diff --git a/.depend b/.depend index 79f7e2ea9e..393fc2a182 100644 --- a/.depend +++ b/.depend @@ -7,6 +7,16 @@ utils/misc.cmi : utils/tbl.cmi : utils/terminfo.cmi : utils/warnings.cmi : +utils/identifiable.cmo : utils/identifiable.cmi +utils/identifiable.cmx : utils/identifiable.cmi +utils/numbers.cmo : utils/numbers.cmi +utils/numbers.cmx : utils/numbers.cmi +utils/timings.cmo : utils/timings.cmi +utils/timings.cmx : utils/timings.cmi +utils/arg_helper.cmo : utils/arg_helper.cmi +utils/arg_helper.cmx : utils/arg_helper.cmi +utils/strongly_connected_components.cmo : utils/strongly_connected_components.cmi +utils/strongly_connected_components.cmx : utils/strongly_connected_components.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 \ @@ -34,6 +44,11 @@ parsing/asttypes.cmi : parsing/location.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 +parsing/ast_iterator.cmo : parsing/ast_iterator.cmi +parsing/ast_invariants.cmo : parsing/ast_invariants.cmi +parsing/attr_helper.cmo : parsing/attr_helper.cmi +parsing/depend.cmo : parsing/depend.cmi +parsing/builtin_attributes.cmo : parsing/builtin_attributes.cmi parsing/longident.cmi : parsing/parse.cmi : parsing/parsetree.cmi parsing/parser.cmi : parsing/parsetree.cmi parsing/location.cmi \ @@ -101,6 +116,8 @@ parsing/printast.cmx : parsing/parsetree.cmi utils/misc.cmx \ parsing/syntaxerr.cmo : parsing/location.cmi parsing/syntaxerr.cmi parsing/syntaxerr.cmx : parsing/location.cmx parsing/syntaxerr.cmi typing/annot.cmi : parsing/location.cmi +typing/tast_mapper.cmo : typing/tast_mapper.cmi +typing/untypeast.cmo : typing/untypeast.cmi typing/btype.cmi : typing/types.cmi typing/path.cmi parsing/asttypes.cmi typing/cmi_format.cmi : typing/types.cmi typing/cmt_format.cmi : typing/types.cmi typing/typedtree.cmi \ @@ -129,7 +146,7 @@ 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 : typing/outcometree.cmi typing/printtyp.cmi : typing/types.cmi typing/path.cmi \ typing/outcometree.cmi parsing/longident.cmi typing/ident.cmi \ typing/env.cmi @@ -420,6 +437,8 @@ bytecomp/printlambda.cmi : bytecomp/lambda.cmi bytecomp/runtimedef.cmi : bytecomp/simplif.cmi : bytecomp/lambda.cmi bytecomp/switch.cmi : +bytecomp/translattribute.cmi : bytecomp/lambda.cmi +bytecomp/translattribute.cmo : bytecomp/translattribute.cmi bytecomp/symtable.cmi : utils/misc.cmi typing/ident.cmi \ bytecomp/cmo_format.cmi bytecomp/translclass.cmi : typing/typedtree.cmi parsing/location.cmi \ @@ -510,6 +529,7 @@ 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.cmi : bytecomp/instruct.cmi bytecomp/meta.cmo : bytecomp/meta.cmi bytecomp/meta.cmx : bytecomp/meta.cmi bytecomp/opcodes.cmo : @@ -604,12 +624,65 @@ asmcomp/asmpackager.cmi : typing/env.cmi asmcomp/branch_relaxation.cmi : asmcomp/linearize.cmi \ asmcomp/branch_relaxation_intf.cmo asmcomp/clambda.cmi : bytecomp/lambda.cmi typing/ident.cmi \ - asmcomp/debuginfo.cmi parsing/asttypes.cmi + asmcomp/debuginfo.cmi parsing/asttypes.cmi middle_end/debuginfo.cmi asmcomp/closure.cmi : bytecomp/lambda.cmi asmcomp/clambda.cmi asmcomp/cmm.cmi : bytecomp/lambda.cmi typing/ident.cmi asmcomp/debuginfo.cmi asmcomp/cmmgen.cmi : asmcomp/cmx_format.cmi asmcomp/cmm.cmi \ asmcomp/clambda.cmi -asmcomp/cmx_format.cmi : asmcomp/clambda.cmi +middle_end/simple_value_approx.cmi : middle_end/base_types/set_of_closures_id.cmi \ + middle_end/base_types/symbol.cmi middle_end/base_types/variable.cmi \ + middle_end/base_types/export_id.cmi middle_end/base_types/closure_id.cmi \ + middle_end/flambda.cmi middle_end/freshening.cmi +middle_end/flambda.cmi : middle_end/base_types/mutable_variable.cmi \ + middle_end/projection.cmi middle_end/base_types/static_exception.cmi \ + middle_end/allocated_const.cmi middle_end/base_types/set_of_closures_origin.cmi +middle_end/projection.cmi : middle_end/base_types/var_within_closure.cmi +middle_end/base_types/closure_id.cmi : middle_end/base_types/closure_element.cmi +middle_end/base_types/id_types.cmo : middle_end/base_types/id_types.cmi +middle_end/pass_wrapper.cmo : middle_end/pass_wrapper.cmi +middle_end/semantics_of_primitives.cmo : middle_end/semantics_of_primitives.cmi +middle_end/flambda_iterators.cmo : middle_end/flambda_iterators.cmi +middle_end/inlining_cost.cmo : middle_end/inlining_cost.cmi +middle_end/closure_conversion.cmo : middle_end/closure_conversion.cmi +middle_end/initialize_symbol_to_let_symbol.cmo : middle_end/initialize_symbol_to_let_symbol.cmi +middle_end/lift_let_to_initialize_symbol.cmo : middle_end/lift_let_to_initialize_symbol.cmi +middle_end/find_recursive_functions.cmo : middle_end/find_recursive_functions.cmi +middle_end/invariant_params.cmo : middle_end/invariant_params.cmi +middle_end/inconstant_idents.cmo : middle_end/inconstant_idents.cmi +middle_end/effect_analysis.cmo : middle_end/effect_analysis.cmi +middle_end/alias_analysis.cmo : middle_end/alias_analysis.cmi +middle_end/lift_constants.cmo : middle_end/lift_constants.cmi +middle_end/share_constants.cmo : middle_end/share_constants.cmi +middle_end/simplify_common.cmo : middle_end/simplify_common.cmi +middle_end/remove_unused_arguments.cmo : middle_end/remove_unused_arguments.cmi +middle_end/remove_unused_closure_vars.cmo : middle_end/remove_unused_closure_vars.cmi +middle_end/remove_unused_program_constructs.cmo : middle_end/remove_unused_program_constructs.cmi +middle_end/lift_code.cmo : middle_end/lift_code.cmi +middle_end/simplify_boxed_integer_ops.cmo : middle_end/simplify_boxed_integer_ops_intf.cmi \ + middle_end/simplify_boxed_integer_ops.cmi +middle_end/closure_conversion_aux.cmo : middle_end/closure_conversion_aux.cmi +middle_end/simplify_primitives.cmo : middle_end/simplify_primitives.cmi +middle_end/inlining_stats_types.cmo : middle_end/inlining_stats_types.cmi +middle_end/inlining_stats.cmo : middle_end/inlining_stats.cmi +middle_end/extract_projections.cmo : middle_end/extract_projections.cmi +middle_end/augment_specialised_args.cmo : middle_end/augment_specialised_args.cmi +middle_end/unbox_free_vars_of_closures.cmo : middle_end/unbox_free_vars_of_closures.cmi +middle_end/unbox_specialised_args.cmo : middle_end/unbox_specialised_args.cmi +middle_end/unbox_closures.cmo : middle_end/unbox_closures.cmi +middle_end/inlining_transforms.cmo : middle_end/inlining_transforms.cmi +middle_end/inlining_transforms.cmi : middle_end/inlining_decision_intf.cmi +middle_end/inlining_decision.cmo : middle_end/inlining_decision.cmi +middle_end/inline_and_simplify.cmo : middle_end/inline_and_simplify.cmi +middle_end/ref_to_variables.cmo : middle_end/ref_to_variables.cmi +middle_end/flambda_invariants.cmo : middle_end/flambda_invariants.cmi +middle_end/middle_end.cmo : middle_end/middle_end.cmi +middle_end/inline_and_simplify_aux.cmo : middle_end/inline_and_simplify_aux.cmi +middle_end/remove_free_vars_equal_to_args.cmo : middle_end/remove_free_vars_equal_to_args.cmi +middle_end/flambda_utils.cmo : middle_end/backend_intf.cmi middle_end/flambda_utils.cmi +middle_end/base_types/compilation_unit.cmi : middle_end/base_types/linkage_name.cmi +middle_end/base_types/set_of_closures_id.cmi : middle_end/base_types/compilation_unit.cmi +asmcomp/export_info.cmi : middle_end/base_types/tag.cmi middle_end/simple_value_approx.cmi +asmcomp/cmx_format.cmi : asmcomp/clambda.cmi asmcomp/export_info.cmi asmcomp/codegen.cmi : asmcomp/cmm.cmi asmcomp/coloring.cmi : asmcomp/comballoc.cmi : asmcomp/mach.cmi @@ -875,6 +948,7 @@ 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 +driver/compplugin.cmo : driver/compplugin.cmi driver/compdynlink.cmi : driver/compenv.cmi : driver/compile.cmi : diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..8920b98826 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,159 @@ +#************************************************************************** +#* * +#* 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 + +/.mailmap ocaml-typo=long-line,missing-header,non-ascii +/.merlin ocaml-typo=missing-header +/Changes ocaml-typo=non-ascii,missing-header +/INSTALL ocaml-typo=missing-header +/LICENSE ocaml-typo=long-line,very-long-line,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/hashbang ocaml-typo=white-at-eol,missing-lf + +testsuite/tests/** ocaml-typo=missing-header +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 + +# Similarly, the docstring tests fail for the same reason on Windows +testsuite/tests/docstrings/empty.ml text eol=lf + +# These are forced to \n to allow the Cygwin testsuite to pass on a +# Windows-checkout +testsuite/tests/formatting/margins.ml text eol=lf +testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml text eol=lf +testsuite/tests/typing-extension-constructor/test.ml text eol=lf +testsuite/tests/typing-extensions/extensions.ml text eol=lf +testsuite/tests/typing-extensions/open_types.ml text eol=lf +testsuite/tests/typing-objects/Exemples.ml text eol=lf +testsuite/tests/typing-objects/pr5619_bad.ml text eol=lf +testsuite/tests/typing-objects/pr6123_bad.ml text eol=lf +testsuite/tests/typing-objects/pr6907_bad.ml text eol=lf +testsuite/tests/typing-objects/Tests.ml text eol=lf +testsuite/tests/typing-pattern_open/pattern_open.ml text eol=lf +testsuite/tests/typing-private/private.ml text eol=lf +testsuite/tests/typing-recordarg/recordarg.ml text eol=lf +testsuite/tests/typing-short-paths/pr5918.ml text eol=lf +testsuite/tests/typing-sigsubst/sigsubst.ml text eol=lf +testsuite/tests/typing-typeparam/newtype.ml text eol=lf +testsuite/tests/typing-unboxed/test.ml text eol=lf +testsuite/tests/typing-unboxed-types/test.ml text eol=lf +testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml text eol=lf +testsuite/tests/typing-warnings/coercions.ml text eol=lf +testsuite/tests/typing-warnings/exhaustiveness.ml text eol=lf +testsuite/tests/typing-warnings/pr6872.ml text eol=lf +testsuite/tests/typing-warnings/pr7085.ml text eol=lf +testsuite/tests/typing-warnings/pr7115.ml text eol=lf +testsuite/tests/typing-warnings/records.ml text eol=lf +testsuite/tests/typing-warnings/unused_types.ml text eol=lf diff --git a/.gitignore b/.gitignore index 1b8bc6f0f3..332ecb8637 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,87 @@ /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/ocamlruni /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 +/driver/compdynlink.mlopt +/driver/compdynlink.mlbyte +/driver/compdynlink.mli -# /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 +143,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 +170,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 +206,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,1965 +216,139 @@ /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/**/*.result +/testsuite/**/*.opt_result +/testsuite/**/*.corrected +/testsuite/**/*.byte +/testsuite/**/*.native +/testsuite/**/program +/testsuite/**/_log -# /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/_retries -# /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/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/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/asmcomp/*.out.manifest -# /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/*.safe-string +/testsuite/tests/basic/pr6322.ml -# /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/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/float-unboxing/*.flambda +/testsuite/tests/float-unboxing/float_inline.ml -# /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/opaque/*/*.mli -# /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/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/self-contained-toplevel/cached_cmi.ml -# /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/tool-ocamldoc-2/ocamldoc.sty -# /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/tool-ocamldoc-html/*.html +/testsuite/tests/tool-ocamldoc-html/style.css -# /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/tool-ocamldoc-man/*.3o -# /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/tool-ocamldoc-open/alias.odoc +/testsuite/tests/tool-ocamldoc-open/inner.odoc +/testsuite/tests/tool-ocamldoc-open/main.odoc +/testsuite/tests/tool-ocamldoc-open/ocamldoc.sty -# /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/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/tool-lexyacc/scanner.ml +/testsuite/tests/tool-lexyacc/grammar.mli +/testsuite/tests/tool-lexyacc/grammar.ml -# /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-multifile/a.ml +/testsuite/tests/typing-multifile/b.ml +/testsuite/tests/typing-multifile/c.ml -# /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/unboxed-primitive-args/main.ml +/testsuite/tests/unboxed-primitive-args/stubs.c -# /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/unwind/unwind_test -# /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/warnings/w55.opt.opt_result +/testsuite/tests/warnings/w58.opt.opt_result -# /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/tools/expect_test -# /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 /tools/ocamlprof +/tools/ocamlprof.opt /tools/opnames.ml /tools/dumpobj +/tools/dumpobj.opt /tools/dumpapprox -/tools/objinfo +/tools/ocamlobjinfo +/tools/ocamlobjinfo.opt /tools/cvt_emit +/tools/cvt_emit.opt /tools/cvt_emit.bak /tools/cvt_emit.ml /tools/ocamlcp +/tools/ocamlcp.opt /tools/ocamloptp +/tools/ocamloptp.opt /tools/ocamlmktop +/tools/ocamlmktop.opt /tools/primreq +/tools/primreq.opt /tools/ocamldumpobj /tools/keywords /tools/lexer299.ml /tools/ocaml299to3 /tools/ocamlmklib +/tools/ocamlmklib.opt /tools/ocamlmklibconfig.ml /tools/lexer301.ml /tools/scrapelabels @@ -2699,88 +356,13 @@ /tools/objinfo_helper /tools/read_cmt /tools/read_cmt.opt +/tools/cmpbyt +/tools/cmpbyt.opt +/tools/stripdebug +/tools/stripdebug.opt -# /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 -/utils/domainstate.ml -/utils/domainstate.mli -# /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 0000000000..dca1e0d28f --- /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 6dce10ee3e..0000000000 --- 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/.mailmap b/.mailmap new file mode 100644 index 0000000000..96b523485f --- /dev/null +++ b/.mailmap @@ -0,0 +1,76 @@ +# The format of this file is generally of the form +# +# for example: +# Proper Name +# +# Proper Name Commit Name +# +# See the MAPPING AUTHORS section of 'man git-shortlog' for more details. + +# Such a remapping may be useful in particular for tracking authorship +# of commits erroneously made under an obscure alias or email adress. +# (Some Name , pour ne pas le citer) + +Alain Frisch alainfrisch + + + + + + + + +cvs2svn +Damien Doligez Some Name +Damien Doligez doligez +Mohamed Iguernelala +Jérémie Dimino + +# The aliases below correspond to preference expressed by +# contributors on the name under which they credited, for example +# if they use an opaque nickname from github or mantis: +# +# Preferred Name nickname +# or +# Preferred Name +# Preferred Name @github.com +# to indicate a preference associated to a Mantis account. + +Florian Angeletti octachron +Gabriel Radanne Drup +Pierre Weis pierreweis +John Christopher McAlpine chrismamo1 +Runhang Li marklrh +Francis Souther FDSouthern +Simon Cruanes +Frederic Bour +David Sheets +David Allsopp +Tim Cuthbertson +Grégoire Henry +Julien Moutinho +Adam Borowski +Mikhail Mandrykin +Maverick Woo +Andi McClure +Michael Grünewald +Michael O'Connor +Florian Angeletti +Kenji Tokudome +Philippe Veber +Valentin Gatien-Baron +Stephen Dolan +Junsong Li +Junsong Li +Christophe Raffali +Anton Bachin +Reed Wilson +David Scott +Martin Neuhäußer +Goswin von Brederlow + +# These contributors prefer to be referred to pseudonymously + + +tkob tkob +ygrek ygrek diff --git a/.merlin b/.merlin index 9977984088..38628a4744 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.yml b/.travis.yml index 9b2dcc5fe4..c04147b02f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,22 @@ +#************************************************************************** +#* * +#* 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 os: - linux diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..23b21107e0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,352 @@ +# 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. + +## Contributing to the standard library + +Contributions to the standard library are very welcome. There is some +widespread belief in the community than the stdlib is somehow "frozen" +and that its evolutions are mostly driven by the need of the OCaml +compiler itself. Let's be clear: this is just plain wrong. The +compiler is happy with its own local utility functions, and many +recent additions to the stdlib are not used by the compiler. + +Another common and wrong idea is that core OCaml maintainers don't +really care about the standard library. This is not true, and won't +be unless one of the "alternative standard" libraries really gains +enough "market share" in the community. + +So: please contribute! + +Obviously, the proposals to evolve the standard library will be +evaluated with very high standards, similar to those applied to the +evolution of the surface langage, and much higher than those for +internal compiler changes (optimizations, etc). + +A key property of the standard library is its stability. Backward +compatibility is not an absolute technical requirement (any addition +to/of a module can break existing code, formally), but breakage should +be limited as much as possible (and assessed, when relevant). A +corollary is that any addition creates a long-term support commitment. +For instance, once a concrete type or function is made public, +changing the exposed definition cannot be done easily. + +There is no plan to extend dramatically the functional domain covered +by the standard library. For instance, proposals to include support +for XML, JSON, or network protocols are very likely to be rejected. Such +domains are better treated by external libraries. Small additions to +existing modules are much simpler to get in, even more so (but not +necessarily) when: + + - they cannot easily be implemented externally, or when + - they facilitate communication between independent external + libraries, or when + - they fill obvious gaps. + +Of course, standard guidelines apply as well: proper documentation, +proper tests, portability (yes, also Windows!), good justification for +why the change is desirable and why it should go into stdlib. + +So: be prepared for some serious review process! But yes, yes, +contributions are welcome and appreciated. Promised. + + +## 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. + +### How to sign the CLA + +If your contribution is large enough, you should sign the CLA. If you +are contributing on your own behalf, you should sign [the individual +CLA](http://caml.inria.fr/pub/docs/CLA-individual.doc). For corporate +contributions, if your employer has not already done so, they should +sign [the corporate +CLA](http://caml.inria.fr/pub/docs/CLA-corporate.doc). Review the CLA, +sign it, and send it -- scanned PDF by email, or postail mail -- to +Xavier Leroy ([contact +info](http://gallium.inria.fr/%7Exleroy/contact.html)). diff --git a/Changes b/Changes index 0822312817..d1c9b65655 100644 --- a/Changes +++ b/Changes @@ -1,26 +1,1908 @@ -OCaml 4.03.0: -------------- +OCaml 4.04.2 (23 Jun 2017): +--------------------------- + +### Security fix: + +- PR#7557: Local privilege escalation issue with ocaml binaries. + (Damien Doligez, report by Eric Milliken, review by Xavier Leroy) + +OCaml 4.04.1 (14 Apr 2017): +--------------------------- + +### Code generation and optimizations: + +- PR#7501, GPR#1089: Consider arrays of length zero as constants + when using Flambda. + (Pierre Chambart, review by Mark Shinwell and Leo White) + +### Standard library: + +- PR#7403, GPR#894: fix a bug in Set.map as introduced in 4.04.0 + (Gabriel Scherer, report by Thomas Leonard) + +### Tools: + +- PR#7411: ocamldoc, avoid nested
 tags in module description.
+  (Florian Angeletti, report by user 'kosik')
+
+- PR#7488: ocamldoc, wrong Latex output for variant types
+  with constructors without arguments.
+  (Florian Angeletti, report by Xavier Leroy)
+
+### Build system:
+
+- PR#7373, GPR#1023: New flexlink target in Makefile.nt to bootstrap the
+  flexlink binary only, rather than the flexlink binary and the FlexDLL C
+  objects.
+  (David Allsopp)
+
+### Bug fixes
+
+- PR#7369: Str.regexp raises "Invalid_argument: index out of bounds"
+  (Damien Doligez, report by John Whitington)
+
+- PR#7373, GPR#1023: Fix ocamlmklib with bootstrapped FlexDLL. Bootstrapped
+  FlexDLL objects are now installed to a subdirectory flexdll of the Standard
+  Library which allows the compilers to pick them up explicitly and also
+  ocamlmklib to include them without unnecessarily adding the entire Standard
+  Library.
+  (David Allsopp)
+
+- PR#7385, GPR#1057: fix incorrect timestamps returned by Unix.stat on Windows
+  when either TZ is set or system date is in DST.
+  (David Allsopp, report and initial fix by Nicolás Ojeda Bär, review and
+   superior implementation suggestion by Xavier Leroy)
+
+- PR#7405, GPR#903: s390x: Fix address of caml_raise_exn in native dynlink modules
+  (Richard Jones, review by Xavier Leroy)
+
+- PR#7417, GPR#930: ensure 16 byte stack alignment inside caml_allocN on x86-64
+  for ocaml build with WITH_FRAME_POINTERS defined
+  (Christoph Cullmann)
+
+- PR#7456, GPR#1092: fix slow compilation on source files containing a lot
+  of similar debugging information location entries
+  (Mark Shinwell)
+
+- PR#7457: a case of double free in the systhreads library (POSIX implementation)
+  (Xavier Leroy, report by Chet Murthy)
+
+- PR#7460, GPR#1011: catch uncaught exception when unknown files are passed
+  as argument (regression in 4.04.0)
+  (Bernhard Schommer, review by Florian Angeletti and Gabriel Scherer,
+   report by Stephen Dolan)
+
+- PR#7505: Memory cannot be released after calling
+    Bigarray.Genarray.change_layout.
+  (Damien Doligez and Xavier Leroy, report by Liang Wang)
+
+- GPR#912: Fix segfault in Unix.create_process on Windows caused by wrong header
+  configuration.
+  (David Allsopp)
+
+- GPR#980: add dynlink options to ocamlbytecomp.cmxa to allow ocamlopt.opt
+  to load plugins. See http://github.com/OCamlPro/ocamlc-plugins for examples.
+  (Fabrice Le Fessant, review by David Allsopp)
+
+- GPR#992: caml-types.el: Fix missing format argument, so that it can show kind
+  of call at point correctly.
+  (Chunhui He)
+
+- GPR#1043: Allow Windows CRLF line-endings in ocamlyacc on Unix and Cygwin.
+  (David Allsopp, review by Damien Doligez and Xavier Leroy)
+
+- GPR#1072: Fix segfault in Sys.runtime_parameters when exception backtraces
+  are enabled.
+  (Olivier Andrieu)
+
+OCaml 4.04.0 (4 Nov 2016):
+--------------------------
+
+(Changes that can break existing programs are marked with a "*")
+
+### Language features:
+
+- PR#7233: Support GADT equations on non-local abstract types
+  (Jacques Garrigue)
+
+- GPR#187, GPR#578: Local opening of modules in a pattern.
+  Syntax: "M.(p)", "M.[p]","M.[| p |]", "M.{p}"
+  (Florian Angeletti, Jacques Garrigue, review by Alain Frisch)
+
+- GPR#301: local exception declarations "let exception ... in"
+  (Alain Frisch)
+
+- GPR#508: Allow shortcut for extension on semicolons: ;%foo
+  (Jérémie Dimino)
+
+- GPR#606: optimized representation for immutable records with a single
+  field, and concrete types with a single constructor with a single argument.
+  This is triggered with a [@@unboxed] attribute on the type definition.
+  Currently mutually recursive datatypes are not well supported, this
+  limitation should be lifted in the future (see MPR#7364).
+  (Damien Doligez)
+
+### Compiler user-interface and warnings:
+
+* PR#6475, GPR#464: interpret all command-line options before compiling any
+  files, changes (improves) the semantics of repeated -o options or -o
+  combined with -c see the super-detailed commit message at
+  https://github.com/ocaml/ocaml/commit/da56cf6dfdc13c09905c2e07f1d4849c8346eec8
+  (whitequark)
+
+- PR#7139: clarify the wording of Warning 38
+  (Unused exception or extension constructor)
+  (Gabriel Scherer)
+
+* PR#7147, GPR#475: add colors when reporting errors generated by ppx rewriters.
+  Remove the `Location.errorf_prefixed` function which is no longer relevant
+  (Simon Cruanes, Jérémie Dimino)
+
+- PR#7169, GPR#501: clarify the wording of Warning 8
+  (Non-exhaustivity warning for pattern matching)
+  (Florian Angeletti, review and report by Gabriel Scherer)
+
+* GPR#591: Improve support for OCAMLPARAM: (i) do not use objects
+  files with -a, -pack, -shared; (ii) use "before" objects in the toplevel
+  (but not "after" objects); (iii) use -I dirs in the toplevel,
+  (iv) fix bug where -I dirs were ignored when using threads
+  (Marc Lasson, review by Damien Doligez and Alain Frisch)
+
+- GPR#648: New -plugin option for ocamlc and ocamlopt, to dynamically extend
+  the compilers at runtime.
+  (Fabrice Le Fessant)
+
+- GPR#684: Detect unused module declarations
+  (Alain Frisch)
+
+- GPR#706: Add a settable Env.Persistent_signature.load function so
+  that cmi files can be loaded from other sources. This can be used to
+  create self-contained toplevels.
+  (Jérémie Dimino)
+
+### Standard library:
+
+- PR#6279, GPR#553: implement Set.map
+  (Gabriel Scherer)
+
+- PR#6820, GPR#560: Add Obj.reachable_words to compute the
+  "transitive" heap size of a value
+  (Alain Frisch, review by Mark Shinwell and Damien Doligez)
+
+- GPR#473: Provide `Sys.backend_type` so that user can write backend-specific
+  code in some cases (for example,  code generator).
+  (Hongbo Zhang)
+
+- GPR#589: Add a non-allocating function to recover the number of
+  allocated minor words.
+  (Pierre Chambart, review by Damien Doligez and Gabriel Scherer)
+
+- GPR#626: String.split_on_char
+  (Alain Frisch)
+
+- GPR#669: Filename.extension and Filename.remove_extension
+  (Alain Frisch, request by Edgar Aroutiounian, review by Daniel Bünzli
+  and Damien Doligez)
+
+- GPR#674: support unknown Sys.os_type in Filename, defaulting to Unix
+  (Filename would previously fail at initialization time for
+   Sys.os_type values other than "Unix", "Win32" and "Cygwin";
+   mirage-os uses "xen")
+  (Anil Madhavapeddy)
+
+- GPR#772 %string_safe_set and %string_unsafe_set are deprecated aliases
+  for %bytes_safe_set and %bytes_unsafe_set.
+  (Hongbo Zhang and Damien Doligez)
+
+### Other libraries
+
+- MPR#4834, GPR#592: Add a Biggarray.Genarray.change_layout function
+  to switch bigarrays between C and fortran layouts.
+  (Guillaume Hennequin, review by Florian Angeletti)
+
+### Code generation and optimizations:
+
+- PR#4747, GPR#328: Optimize Hashtbl by using in-place updates of its
+  internal bucket lists.  All operations run in constant stack size
+  and are usually faster, except Hashtbl.copy which can be much
+  slower
+  (Alain Frisch)
+
+- PR#6217, GPR#538: Optimize performance of record update:
+  no more performance cliff when { foo with t1 = ..; t2 = ...; ... }
+  hits 6 updated fields
+  (Olivier Nicole, review by Thomas Braibant and Pierre Chambart)
+
+- PR#7023, GPR#336: Better unboxing strategy
+  (Alain Frisch, Pierre Chambart)
+
+- PR#7244, GPR#840: Ocamlopt + flambda requires a lot of memory
+  to compile large array literal expressions
+  (Pierre Chambart, review by Mark Shinwell)
+
+- PR#7291, GPR#780: Handle specialisation of recursive function that does
+  not always preserve the arguments
+  (Pierre Chambart, Mark Shinwell, report by Simon Cruanes)
+
+- PR#7328, GPR#702: Do not eliminate boxed int divisions by zero and
+  avoid checking twice if divisor is zero with flambda.
+  (Pierre Chambart, report by Jeremy Yallop)
+
+- GPR#427: Obj.is_block is now an inlined OCaml function instead of a
+  C external.  This should be faster.
+  (Demi Obenour)
+
+- GPR#580: Optimize immutable float records
+  (Pierre Chambart, review by Mark Shinwell)
+
+- GPR#602: Do not generate dummy code to force module linking
+  (Pierre Chambart, reviewed by Jacques Garrigue)
+
+- GPR#703: Optimize some constant string operations when the "-safe-string"
+  configure time option is enabled.
+  (Pierre Chambart)
+
+- GPR#707: Load cross module information during a meet
+  (Pierre Chambart, report by Leo White, review by Mark Shinwell)
+
+- GPR#709: Share a few more equal switch branches
+  (Pierre Chambart, review by Gabriel Scherer)
+
+- GPR#712: Small improvements to type-based optimizations for array
+  and lazy
+  (Alain Frisch, review by Pierre Chambart)
+
+- GPR#714: Prevent warning 59 from triggering on Lazy of constants
+  (Pierre Chambart, review by Leo White)
+
+- GPR#723 Sort emitted functions according to source location
+  (Pierre Chambart, review by Mark Shinwell)
+
+- Lack of type normalization lead to missing simple compilation for "lazy x"
+  (Alain Frisch)
+
+### Runtime system:
+
+- PR#7203, GPR#534: Add a new primitive caml_alloc_float_array to allocate an
+  array of floats
+  (Thomas Braibant)
+
+- PR#7210, GPR#562: Allows to register finalisation function that are
+  called only when a value will never be reachable anymore. The
+  drawbacks compared to the existing one is that the finalisation
+  function is not called with the value as argument. These finalisers
+  are registered with `GC.finalise_last`
+  (François Bobot reviewed by Damien Doligez and Leo White)
+
+- GPR#247: In previous OCaml versions, inlining caused stack frames to
+  disappear from stacktraces. This made debugging harder in presence of
+  optimizations, and flambda was going to make this worse. The debugging
+  information produced by the compiler now enables the reconstruction of the
+  original backtrace. Use `Printexc.get_raw_backtrace_next_slot` to traverse
+  the list of inlined stack frames.
+  (Frédéric Bour, review by Mark Shinwell and Xavier Leroy)
+
+- GPR#590: Do not perform compaction if the real overhead is less than expected
+  (Thomas Braibant)
+
+### Tools:
+
+- PR#7189: toplevel #show, follow chains of module aliases
+  (Gabriel Scherer, report by Daniel Bünzli, review by Thomas Refis)
+
+- PR#7248: have ocamldep interpret -open arguments in left-to-right order
+  (Gabriel Scherer, report by Anton Bachin)
+
+- PR#7272, GPR#798: ocamldoc, missing line breaks in type_*.html files
+  (Florian Angeletti)
+
+- PR#7290: ocamldoc, improved support for inline records
+  (Florian Angeletti)
+
+- PR#7323, GPR#750: ensure "ocamllex -ml" works with -safe-string
+  (Hongbo Zhang)
+
+- PR#7350, GPR#806: ocamldoc, add viewport metadata to generated html pages
+  (Florian Angeletti, request by Daniel Bünzli)
+
+- GPR#452: Make the output of ocamldep more stable
+  (Alain Frisch)
+
+- GPR#548: empty documentation comments
+  (Florian Angeletti)
+
+- GPR#575: Add the -no-version option to the toplevel
+  (Sébastien Hinderer)
+
+- GPR#598: Add a --strict option to ocamlyacc treat conflicts as errors
+  (this option is now used for the compiler's parser)
+  (Jeremy Yallop)
+
+- GPR#613: make ocamldoc use -open arguments
+  (Florian Angeletti)
+
+- GPR#718: ocamldoc, fix order of extensible variant constructors
+  (Florian Angeletti)
+
+### Debugging and profiling:
+
+- GPR#585: Spacetime, a new memory profiler (Mark Shinwell, Leo White)
+
+### Manual and documentation:
+
+- PR#7007, PR#7311: document the existence of OCAMLPARAM and
+  ocaml_compiler_internal_params
+  (Damien Doligez, reports by Wim Lewis and Gabriel Scherer)
+
+- PR#7243: warn users against using WinZip to unpack the source archive
+  (Damien Doligez, report by Shayne Fletcher)
+
+- PR#7245, GPR#565: clarification to the wording and documentation
+  of Warning 52 (fragile constant pattern)
+  (Gabriel Scherer, William, Adrien Nader, Jacques Garrigue)
+
+- #PR7265, GPR#769: Restore 4.02.3 behaviour of Unix.fstat, if the
+  file descriptor doesn't wrap a regular file (win32unix only)
+  (Andreas Hauptmann, review by David Allsopp)
+
+- PR#7288: flatten : Avoid confusion
+  (Damien Doligez, report by user 'tormen')
+
+- PR#7355: Gc.finalise and lazy values
+  (Jeremy Yallop)
+
+- GPR#842: Document that [Store_field] must not be used to populate
+  arrays of values declared using [CAMLlocalN] (Mark Shinwell)
+
+### Compiler distribution build system:
+
+- GPR#324: Compiler developers: Adding new primitives to the
+  standard runtime doesn't require anymore to run `make bootstrap`
+  (François Bobot)
+
+- GPR#384: Fix compilation using old Microsoft C Compilers not
+  supporting secure CRT functions (SDK Visual Studio 2005 compiler and
+  earlier) and standard 64-bit integer literals (Visual Studio .NET
+  2002 and earlier)
+  (David Allsopp)
+
+- GPR#507: More sharing between Unix and Windows makefiles
+  (whitequark, review by Alain Frisch)
+
+* GPR#512, GPR#587: Installed `ocamlc`, `ocamlopt`, and `ocamllex` are
+  now the native-code versions of the tools, if those versions were
+  built.
+  (Demi Obenour)
+
+- GPR#525: fix build on OpenIndiana
+  (Sergey Avseyev, review by Damien Doligez)
+
+- GPR#687: "./configure -safe-string" to get a system where
+  "-unsafe-string" is not allowed, thus giving stronger non-local
+  guarantees about immutability of strings
+  (Alain Frisch, review by Hezekiah M. Carty)
+
+### Bug fixes:
+
+* PR#6505: Missed Type-error leads to a segfault upon record access.
+  (Jacques Garrigue, extra report by Stephen Dolan)
+  Proper fix required a more restrictive approach to recursive types:
+  mutually recursive types are seen as abstract types (i.e. non-contractive)
+  when checking the well-foundedness of the recursion.
+
+* PR#6752: Nominal types and scope escaping.
+  Revert to strict scope for non-generalizable type variables, cf. Mantis.
+  Note that this is actually stricter than the behavior before 4.03,
+  cf. PR#7313, meaning that you may sometimes need to add type annotations
+  to explicitly instantiate non-generalizable type variables.
+  (Jacques Garrigue, following discussion with Jeremy Yallop,
+   Nicolas Ojeda Bar and Alain Frisch)
+
+- PR#7112: Aliased arguments ignored for equality of module types
+  (Jacques Garrigue, report by Leo White)
+
+- PR#7134: compiler forcing aliases it shouldn't while reporting type errors
+  (Jacques Garrigue, report and suggestion by sliquister)
+
+- PR#7153: document that Unix.SOCK_SEQPACKET is not really usable.
+
+- PR#7165, GPR#494: uncaught exception on invalid lexer directive
+  (Gabriel Scherer, report by KC Sivaramakrishnan using afl-fuzz)
+
+- PR#7257, GPR#583: revert a 4.03 change of behavior on (Unix.sleep 0.),
+  it now calls (nano)sleep for 0 seconds as in (< 4.03) versions.
+  (Hannes Mehnert, review by Damien Doligez)
+
+- PR#7260: GADT + subtyping compile time crash
+  (Jacques Garrigue, report by Nicolas Ojeda Bar)
+
+- PR#7269: Segfault from conjunctive constraints in GADT
+  (Jacques Garrigue, report by Stephen Dolan)
+
+- PR#7276: Support more than FD_SETSIZE sockets in Windows' emulation
+  of select
+  (David Scott, review by Alain Frisch)
+
+* PR#7278: Prevent private inline records from being mutated
+  (Alain Frisch, report by Pierre Chambart)
+
+- PR#7284: Bug in mcomp_fields leads to segfault
+  (Jacques Garrigue, report by Leo White)
+
+- PR#7285: Relaxed value restriction broken with principal
+  (Jacques Garrigue, report by Leo White)
+
+- PR#7297: -strict-sequence turns off Warning 21
+  (Jacques Garrigue, report by Valentin Gatien-Baron)
+
+- PR#7299: remove access to OCaml heap inside blocking section in win32unix
+  (David Allsopp, report by Andreas Hauptmann)
+
+- PR#7300: remove access to OCaml heap inside blocking in Unix.sleep on Windows
+  (David Allsopp)
+
+- PR#7305: -principal causes loop in type checker when compiling
+  (Jacques Garrigue, report by Anil Madhavapeddy, analysis by Leo White)
+
+- PR#7330: Missing exhaustivity check for extensible variant
+  (Jacques Garrigue, report by Elarnon *)
+
+- PR#7374: Contractiveness check unsound with constraints
+  (Jacques Garrigue, report by Leo White)
+
+- PR#7378: GADT constructors can be re-exposed with an incompatible type
+  (Jacques Garrigue, report by Alain Frisch)
+
+- PR#7389: Unsoundness in GADT exhaustiveness with existential variables
+  (Jacques Garrigue, report by Stephen Dolan)
+
+* GPR#533: Thread library: fixed [Thread.wait_signal] so that it
+  converts back the signal number returned by [sigwait] to an
+  OS-independent number
+  (Jérémie Dimino)
+
+- GPR#600: (similar to GPR#555) ensure that register typing constraints are
+  respected at N-way join points in the control flow graph
+  (Mark Shinwell)
+
+- GPR#672: Fix float_of_hex parser to correctly reject some invalid forms
+  (Bogdan Tătăroiu, review by Thomas Braibant and Alain Frisch)
+
+- GPR#700: Fix maximum weak bucket size
+  (Nicolas Ojeda Bar, review by François Bobot)
+
+- GPR#708 Allow more module aliases in strengthening (Leo White)
+
+- GPR#713, PR#7301: Fix wrong code generation involving lazy values in Flambda
+  mode
+  (Mark Shinwell, review by Pierre Chambart and Alain Frisch)
+
+- GPR#721: Fix infinite loop in flambda due to [@@specialise] annotations
+
+- GPR#779: Building native runtime on Windows could fail when bootstrapping
+  FlexDLL if there was also a system-installed flexlink
+  (David Allsopp, report Michael Soegtrop)
+
+- GPR#805, GPR#815, GPR#833: check for integer overflow in String.concat
+  (Jeremy Yallop,
+   review by Damien Doligez, Alain Frisch, Daniel Bünzli, Fabrice Le Fessant)
+
+- GPR#810: check for integer overflow in Array.concat
+  (Jeremy Yallop)
+
+- GPR#814: fix the Buffer.add_substring bounds check to handle overflow
+  (Jeremy Yallop)
+
+- GPR#880: Fix [@@inline] with default parameters in flambda (Leo White)
+
+### Internal/compiler-libs changes:
+
+- PR#7200, GPR#539: Improve, fix, and add test for parsing/pprintast.ml
+  (Runhang Li, David Sheets, Alain Frisch)
+
+- GPR#351: make driver/pparse.ml functions type-safe
+  (Gabriel Scherer, Dmitrii Kosarev, review by Jérémie Dimino)
+
+- GPR#516: Improve Texp_record constructor representation, and
+  propagate updated record type information
+  (Pierre Chambart, review by Alain Frisch)
+
+- GPR#678: Graphics.close_graph crashes 64-bit Windows ports (re-implementation
+  of PR#3963)
+  (David Allsopp)
+
+- GPR#679: delay registration of docstring after the mapper is applied
+  (Hugo Heuzard, review by Leo White)
+
+- GPR#872: don't attach (**/**) comments to any particular node
+  (Thomas Refis, review by Leo White)
+
+OCaml 4.03.0 (25 Apr 2016):
+---------------------------
+
+(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 Whitington)
+
+- 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:
+
+* GPR#596: make string/bytes distinguishable in the underlying
+  compiler implementation; caml_fill_string and caml_create_string are
+  deprecated and will be removed in the future, please use
+  caml_fill_bytes and caml_create_bytes for migration
+  (Hongbo Zhang, review by Damien Doligez, Alain Frisch, and Hugo Heuzard)
+
+- 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 François Bobot, Thomas Braibant, Leo White)
+
+- GPR#325: Add v=0x400 flag to OCAMLRUNPARAM to display GC stats on exit
+  (Louis Gesbert, review by Alain Frisch)
+
+### 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 Markus 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
+  A side-effect of the fix is that, for deeply nested non generalizable
+  type variables, having an interface file may no longer be sufficient,
+  and you may have to add a local type annotation (cf PR#7313)
+  (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)
+
+- PR#7324: OCaml 4.03.0 type checker dies with an assert failure when
+  given some cyclic recusive module expression
+  (Jacques Garrigue, report by jmcarthur)
+
+- PR#7368: Manual major GC fails to compact the heap
+  (Krzysztof Pszeniczny)
+
+- GPR#205: Clear caml_backtrace_last_exn before registering as root
+  (report and fix by Frédéric 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)
+- PR#6919: corrupted final_table
+  (ygrek)
+- PR#6926: Regression: ocamldoc lost unattached comment
+  (Damien Doligez, report by François Bobot)
+- PR#6930: Aliased result type of GADT constructor results in assertion failure
+  (Jacques Garrigue)
+
+Feature wishes:
+- PR#6691: install .cmt[i] files for stdlib and compiler-libs
+  (David Sheets, request by Gabriel Radanne)
+- GPR#37: New primitive: caml_alloc_dummy_function
+  (Hugo Heuzard)
+
+OCaml 4.02.2 (17 Jun 2015):
+---------------------------
+
+(Changes that can break existing programs are marked with a "*")
+
+Language features:
+- PR#6583: add a new class of binary operators with the same syntactic
+  precedence as method calls; these operators start with # followed
+  by a non-empty sequence of operator symbols (for instance #+, #!?).
+  It is also possible to use '#' as part of these extra symbols
+  (for instance ##, or #+#); this is rejected by the type-checker,
+  but can be used e.g. by ppx rewriters.
+  (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#6501: harden the native-code generator against certain uses of "%identity"
-  (Xavier Leroy, report by Antoine Miné).
+- 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
+  (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
+  (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
+  (Leo White)
+- GPR#159: Better locations for structure/signature items
+  (Leo White)
 
-Runtime system:
-- PR#6517: use ISO C99 types {,u}int{32,64}_t in preference to our homegrown
-  types {,u}int{32,64}.
+Toplevel and debugger:
+- PR#5958: generalized polymorphic #install_printer
+  (Pierre Chambart and Grégoire Henry)
+
+OCamlbuild:
+- PR#6237: explicit "infer" tag to control or disable menhir --infer
+  (Hugo Heuzard)
+- PR#6625: pass -linkpkg to files built with -output-obj.
+  (whitequark)
+- PR#6702: explicit "linkpkg" and "dontlink(foo)" flags
+  (whitequark, Gabriel Scherer)
+- PR#6712: Ignore common VCS directories
+  (whitequark)
+- PR#6720: pass -g to C compilers when tag 'debug' is set
+  (whitequark, Gabriel Scherer)
+- PR#6733: add .byte.so and .native.so targets to pass
+  -output-obj -cclib -shared.
+  (whitequark)
+- PR#6733: "runtime_variant(X)" to pass -runtime-variant X option.
+  (whitequark)
+- PR#6774: new menhir-specific flags "only_tokens" and "external_tokens(Foo)"
+  (François Pottier)
+
+Libraries:
+- PR#6285: Add support for nanosecond precision in Unix.stat()
+  (Jérémie Dimino, report by user 'gfxmonk')
+- PR#6781: Add higher baud rates to Unix termios
+  (Damien Doligez, report by Berke Durak)
+- PR#6834: Add Obj.{first,last}_non_constant_constructor_tag
+  (Mark Shinwell, request by Gabriel Scherer)
+
+Runtime:
+- PR#6078: Release the runtime system when calling caml_dlopen
+  (Jérémie Dimino)
+- PR#6675: GC hooks
+  (Damien Doligez and Roshan James)
+
+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
+  (whitequark, review by Damien Doligez and Mark Shinwell)
+
+Installation procedure:
+- Update instructions for x86-64 PIC mode and POWER architecture builds
+  (Mark Shinwell)
+
+Bug fixes:
+- PR#5271: Location.prerr_warning is hard-coded to use Format.err_formatter
+  (Damien Doligez, report by Rolf Rolles)
+- PR#5395: OCamlbuild mishandles relative symlinks and include paths
+  (Damien Doligez, report by Didier Le Botlan)
+- PR#5822: wrong value of Options.ext_dll on windows
+  (Damien Doligez and Daniel Weil)
+- PR#5836, PR#6684: printing lazy values in ocamldebug may segfault
+  (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 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
+  backtraces on 32-bit ARM.
+  (Mark Shinwell)
+- PR#6573: extern "C" for systhreads/threads.h
+  (Mickaël Delahaye)
+- PR#6575: Array.init evaluates callback although it should not do so
+  (Alain Frisch, report by Gerd Stolpmann)
+- PR#6607: The manual doesn't mention 0x200 flag for OCAMLRUNPARAM=v
+  (Alain Frisch)
+- PR#6616: allow meaningful use of -use-runtime without -custom.
+  (whitequark)
+- PR#6617: allow android build with pthreads support (since SDK r10c)
+  (whitequark)
+- PR#6626: ocamlbuild on cygwin cannot find ocamlfind
+  (Gergely Szilvasy)
+- PR#6628: Configure script rejects legitimate arguments
+  (Michael Grünewald, Damien Doligez)
+- PR#6630: Failure of tests/prim-bigstring/{big,}string.ml on big-endian
+  architectures
+  (Pierre Chambart, testing by Mark Shinwell)
+- PR#6640: ocamlbuild: wrong "unused tag" warning on "precious"
+  (report by user 'william')
+- PR#6652: ocamlbuild -clean does not print a newline after output
+  (Damien Doligez, report by Andi McClure)
+- PR#6658: cross-compiler: version check not working on OS X
+  (Gerd Stolpmann)
+- PR#6665: Failure of tests/asmcomp on sparc
+  (Stéphane Glondu)
+- PR#6667: wrong implementation of %bswap16 on ARM64
+  (Xavier Leroy)
+- PR#6669: fix 4.02 regression in toplevel printing of lazy values
+  (Leo White, review by Gabriel Scherer)
+- PR#6671: Windows: environment variable 'TZ' affects Unix.gettimeofday
+  (Mickaël Delahaye and Damien Doligez)
+- PR#6680: Missing parentheses in warning about polymorphic variant value
+  (Jacques Garrigue and Gabriel Scherer, report by Philippe Veber)
+- PR#6686: Bug in [subst_boxed_number]
+  (Jérémie Dimino, Mark Shinwell)
+- PR#6690: Uncaught exception (Not_found) with (wrong) wildcard or unification
+  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
+  (whitequark, review by Jacques-Henri Jourdan, Xavier Leroy and Mark Shinwell)
+- PR#6717: Pprintast does not print let-pattern attributes
+  (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
+  (Damien Doligez, Maverick Woo)
+- PR#6749: ocamlopt returns n for (n mod 1) instead of 0
+  (Mark Shinwell and Jérémie Dimino)
+- PR#6753: Num.quo_num and Num.mod_num incorrect for some negative arguments
+  (Xavier Leroy)
+- PR#6758: Ocamldoc "analyse_module: parsetree and typedtree don't match"
+  (Damien Doligez, report by user 'maro')
+- PR#6759: big_int_of_string incorrectly parses some hexa literals
+  (Damien Doligez, report by Pierre-yves Strub)
+- PR#6763: #show with -short-paths doesn't select shortest type paths
+  (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 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 whitequark)
+- PR#6791: "%s@[", "%s@{" regression in Scanf
+  (Benoît Vaugon)
+- PR#6793: ocamlbuild passes nonsensical "-ocamlc ..." commands to menhir
+  (Gabriel Scherer, report by Damien Doligez)
+- PR#6799: include guards missing for unixsupport.h and other files
+  (Andreas Hauptmann)
+- PR#6810: Improve documentation of Bigarray.Genarray.map_file
+  (Mark Shinwell and Daniel Bünzli)
+- PR#6812: -short-paths and -no-alias-deps can create inconsistent assumptions
+  (Jacques Garrigue, report by Valentin Gatien-Baron)
+- PR#6817: GADT exhaustiveness breakage with modules
+  (Leo White, report by Pierre Chambart)
+- PR#6824: fix buffer sharing on partial application of Format.asprintf
+  (Gabriel Scherer, report by Alain Frisch)
+- PR#6831: Build breaks for -aspp gcc on solaris-like OSs
+  (John Tibble)
+- PR#6836: Assertion failure using -short-paths
+  (Jacques Garrigue, report by David Sheets)
+- PR#6837: Build profiling libraries on FreeBSD and NetBSD x86-64
+  (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
+  (Jacques Garrigue, report by Leo White)
+- PR#6857: __MODULE__ doesn't give the current module with -o
+  (Jacques Garrigue, report by Valentin Gatien-Baron)
+- PR#6862: Exhaustiveness check wrong for class constructor arguments
+  (Jacques Garrigue)
+- PR#6869: Improve comment on [Hashtbl.hash_param]
+  (Mark Shinwell, report by Jun Furuse)
+- PR#6870: Unsoundness when -rectypes fails to detect non-contractive type
+  (Jacques Garrigue, report by Stephen Dolan)
+- PR#6872: Type-directed propagation fails to disambiguate variants
+  that are also exception constructors
+  (Jacques Garrigue, report by Romain Beauxis)
+- PR#6878: AArch64 backend generates invalid asm: conditional branch
+  out of range (Mark Shinwell, report by Richard Jones, testing by Richard
+  Jones and Xavier Leroy, code review by Xavier Leroy and Thomas Refis)
+- PR#6879: Wrong optimization of 1 mod n
+  (Mark Shinwell, report by Jean-Christophe Filliâtre)
+- PR#6884: The __CYGWIN32__ #define should be replaced with __CYGWIN__
+  (Adrien Nader)
+- PR#6886: -no-alias-deps allows to build self-referential compilation units
+  (Jacques Garrigue, report by Valentin Gatien-Baron)
+- PR#6889: ast_mapper fails to rewrite class attributes
+  (Sébastien Briais)
+- PR#6893: ocamlbuild:  "tag not used" warning when using (p)dep
+  (Gabriel Scherer, report by Christiano Haesbaert)
+- GPR#143: fix getsockopt behaviour for boolean socket options
+  (Anil Madhavapeddy and Andrew Ray)
+- GPR#190: typo in pervasives
+  (Guillaume Bury)
+- Misplaced assertion in major_gc.c for no-naked-pointers mode
+  (Stephen Dolan, Mark Shinwell)
+
+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
+  (whitequark)
+- PR#6693: also build libasmrun_shared.so and lib{asm,caml}run_pic.a
+  (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#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)
+
+OCaml 4.02.1 (14 Oct 2014):
+---------------------------
+
+(Changes that can break existing programs are marked with a "*")
+
+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
+  (Chen Gang)
+- PR#6207: Configure doesn't detect features correctly on Haiku
+  (Jessica Hamilton)
+- PR#6466: Non-exhaustive matching warning message for open types is confusing
+  (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)
+  (Cristopher Zimmermann)
+- PR#6533: broken semantics of %(%) when substituted by a box
+  (Benoît Vaugon, report by Boris Yakobowski)
+- PR#6534: legacy support for %.10s
+  (Benoît Vaugon, Gabriel Scherer, report by Nick Chapman)
+- PR#6536: better documentation of flag # in format strings
+  (Damien Doligez, report by Nick Chapman)
+- 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 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
+  (Hugo Heuzard, review by Gabriel Scherer)
+- PR#6553: Missing command line options for ocamldoc
+  (Maxence Guesdon)
+- PR#6554: fix race condition when retrieving backtraces
+  (Jérémie Dimino, Mark Shinwell).
+- PR#6557: String.sub throws Invalid_argument("Bytes.sub")
+  (Damien Doligez, report by Oliver Bandel)
+- PR#6562: Fix ocamldebug module source lookup
+  (Leo White)
+- PR#6563: Inclusion of packs failing to run module initializers
+  (Jacques Garrigue, report by Mark Shinwell)
+- PR#6564: infinite loop in Mtype.remove_aliases
+  (Jacques Garrigue, report by Mark Shinwell)
+- PR#6565: compilation fails with Env.Error(_)
+  (Jacques Garrigue and Mark Shinwell)
+- PR#6566: -short-paths and signature inclusion errors
+  (Jacques Garrigue, report by Mark Shinwell)
+- PR#6572: Fatal error with recursive modules
+  (Jacques Garrigue, report by Quentin Stievenart)
+- PR#6575: Array.init evaluates callback although it should not do so
+  (Alain Frisch, report by Gerd Stolpmann)
+- PR#6578: Recursive module containing alias causes Segmentation fault
+  (Jacques Garrigue)
+- PR#6581: Some bugs in generative functors
+  (Jacques Garrigue, report by Mark Shinwell)
+- PR#6584: ocamldep support for "-open M"
+  (Gabriel Scherer, review by Damien Doligez, report by Hezekiah M. Carty)
+- PR#6588: Code generation errors for ARM
+  (Mark Shinwell, Xavier Leroy)
+- PR#6590: Improve Windows (MSVC and mingw) build
+  (Chen Gang)
+- PR#6599: ocamlbuild: add -bin-annot when using -pack
+  (Christopher Zimmermann)
+- PR#6602: Fatal error when tracing a function with abstract type
+  (Jacques Garrigue, report by Hugo Herbelin)
+- ocamlbuild: add an -ocamlmklib option to change the ocamlmklib command
+  (Jérôme Vouillon)
 
-Ocaml 4.02.0:
--------------
+OCaml 4.02.0 (29 Aug 2014):
+---------------------------
 
 (Changes that can break existing programs are marked with a "*")
 
 Language features:
 - Attributes and extension nodes
   (Alain Frisch)
-- PR#5095: Generative functors
+- Generative functors (PR#5905)
   (Jacques Garrigue)
-- Module aliases
+* Module aliases
   (Jacques Garrigue)
 * Alternative syntax for string literals {id|...|id} (can break comments)
   (Alain Frisch)
@@ -51,9 +1933,10 @@ Type system:
   an applicative functor if no types are created
   (Jacques Garrigue, suggestion by Leo White)
 * Module aliases are now typed in a specific way, which remembers their
-  identity. In particular this changes the signature inferred by
-  "module type of"
-  (Jacques Garrigue)
+  identity. Compiled interfaces become smaller, but may depend on the
+  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
   closed objects and fixed polymorphic variants.
@@ -82,29 +1965,26 @@ Compilers:
 - PR#6042: Optimization of integer division and modulus by constant divisors
   (Xavier Leroy and Phil Denys)
 - Add "-open" command line flag for opening a single module before typing
+  (Leo White, Mark Shinwell and Nick Chapman)
 * "-o" now sets module name to the output file name up to the first "."
   (it also applies when "-o" is not given, i.e. the module name is then
    the input file name up to the first ".")
-  (Leo White and Mark Shinwell)
+  (Leo White, Mark Shinwell and Nick Chapman)
 * PR#5779: better sharing of structured constants
   (Alain Frisch)
-- PR#6182: better message for virtual objects and class types
-  (Leo P. White, Stephen Dolan)
 - PR#5817: new flag to keep locations in cmi files
   (Alain Frisch)
 - PR#5854: issue warning 3 when referring to a value marked with
   the [@@ocaml.deprecated] attribute
   (Alain Frisch, suggestion by Pierre-Marie Pédrot)
+- PR#6017: a new format implementation based on GADTs
+  (Benoît Vaugon and Gabriel Scherer)
 * PR#6203: Constant exception constructors no longer allocate
   (Alain Frisch)
-- PR#6311: Improve signature mismatch error messages
-  (Alain Frisch, suggestion by Daniel Bünzli)
+- PR#6260: avoid unnecessary boxing in let
+  (Vladimir Brankov)
 - PR#6345: Better compilation of optional arguments with default values
   (Alain Frisch, review by Jacques Garrigue)
-- PR#6260: Unnecessary boxing in let
-  (Vladimir Brankov)
-- PR#6017: a new format implementation based on GADTs
-  (Benoît Vaugon and Gabriel Scherer)
 - PR#6389: ocamlopt -opaque option for incremental native compilation
   (Pierre Chambart, Gabriel Scherer)
 
@@ -122,13 +2002,13 @@ Runtime system:
 - Fixed bug in native code version of [caml_raise_with_string] that could
   potentially lead to heap corruption.
   (Mark Shinwell)
-- Blocks initialized by [CAMLlocal*] and [caml_alloc] are now filled with
+* Blocks initialized by [CAMLlocal*] and [caml_alloc] are now filled with
   [Val_unit] rather than zero.
   (Mark Shinwell)
 - Fixed a major performance problem on large heaps (~1GB) by making heap
   increments proportional to heap size by default
   (Damien Doligez)
-- PR#4765: Structural equality should treat exception specifically
+- PR#4765: Structural equality treats exception specifically
   (Alain Frisch)
 - PR#5009: efficient comparison/indexing of exceptions
   (Alain Frisch, request by Markus Mottl)
@@ -141,10 +2021,8 @@ Runtime system:
   (Xavier Leroy)
 
 Standard library:
-* Add new modules: Bytes and BytesLabels.
+* Add new modules Bytes and BytesLabels for mutable byte sequences.
   (Damien Doligez)
-- PR#6355: Improve documentation regarding finalisers and multithreading
-  (Daniel Bünzli, Mark Shinwell)
 - PR#4986: add List.sort_uniq and Set.of_list
   (Alain Frisch)
 - PR#5935: a faster version of "raise" which does not maintain the backtrace
@@ -155,7 +2033,9 @@ Standard library:
   (John Whitington)
 - PR#6180: efficient creation of uninitialized float arrays
   (Alain Frisch, request by Markus Mottl)
-- Trigger warning 3 for all values marked as deprected in the documentation.
+- PR#6355: Improve documentation regarding finalisers and multithreading
+  (Daniel Bünzli, Mark Shinwell)
+- Trigger warning 3 for all values marked as deprecated in the documentation.
   (Damien Doligez)
 
 OCamldoc:
@@ -170,53 +2050,30 @@ OCamldoc:
   (Maxence Guesdon, report by Anil Madhavapeddy)
 
 Bug fixes:
-- PR#6507: crash on AArch64 resulting from incorrect setting of
-  [caml_bottom_of_stack].  (Richard Jones, Mark Shinwell)
 - PR#2719: wrong scheduling of bound checks within a
   try...with Invalid_argument -> _ ...  (Xavier Leroy)
-- PR#4771: Clarify documentation of Dynlink.allow_only
-  (Damien Doligez, report by David Allsopp)
-- PR#6232: Don't use [mktemp] on platforms where [mkstemp] is available
-  (Stéphane Glondu, Mark Shinwell)
-- PR#6439: Don't use the deprecated [getpagesize] function
-  (John Whitington, Mark Shinwell)
 - PR#4719: Sys.executable_name wrong if executable name contains dots (Windows)
   (Alain Frisch, report by Bart Jacobs)
-- PR#4855: 'camlp4 -I +dir' accepted, dir is relative to 'camlp4 -where'
-  (Jun Furuse and Hongbo Zhang, report by Dmitry Grebeniuk)
-- PR#5201: ocamlbuild: add --norc to the bash invocation to help performances
-  (user 'daweil')
 - PR#5406 ocamlbuild: "tag 'package' does not expect a parameter"
   (Gabriel Scherer)
-- PR#5598: follow-up fix related to PR#6165
-  (Damien Doligez)
+- PR#5598, PR#6165: Alterations to handling of \013 in source files
+  breaking other tools
+  (David Allsopp and Damien Doligez)
 - PR#5820: Fix camlp4 lexer roll back problem
   (Hongbo Zhang)
-- PR#5851: warn when -r is disabled because no _tags file is present
-  (Gabriel Scherer)
 - PR#5946: CAMLprim taking (void) as argument
   (Benoît Vaugon)
 - PR#6038: on x86-32, enforce 16-byte stack alignment for compatibility
   with recent GCC and Clang.  Win32/MSVC keeps 4-byte stack alignment.
   (Xavier Leroy)
-- PR#6062: Fix a regression bug caused by commit 13047
+- PR#6062: Fix a 4.01 camlp4 DELETE_RULE regression caused by commit 13047
   (Hongbo Zhang, report by Christophe Troestler)
-- PR#6109: Typos in ocamlbuild error messages
-  (Gabriel Kerneis)
-- PR#6116: more efficient implementation of Digest.to_hex
-  (ygrek)
-- PR#6142: add cmt file support to ocamlobjinfo
-  (Anil Madhavapeddy)
-- PR#6165: Alterations to handling of \013 in source files breaking other tools
-  (David Allsopp)
 - PR#6173: Typing error message is worse than before
   (Jacques Garrigue and John Whitington)
 - PR#6174: OCaml compiler loops on an example using GADTs (-rectypes case)
   (Jacques Garrigue and Grégoire Henry, report by Chantal Keller)
-- PR#6175: add open! support to camlp4
+- PR#6175: open! was not suppored by camlp4
   (Hongbo Zhang)
-- PR#6183: enhanced documentation for 'Unix.shutdown_connection'
-  (Anil Madhavapeddy, report by Jun Furuse)
 - PR#6184: ocamlbuild: `ocamlfind ocamldep` does not support -predicate
   (Jacques-Pascal Deplaix)
 - PR#6194: Incorrect unused warning with first-class modules in patterns
@@ -226,6 +2083,8 @@ Bug fixes:
   (Xavier Leroy)
 - PR#6216: inlining of GADT matches generates invalid assembly
   (Xavier Leroy and Alain Frisch, report by Mark Shinwell)
+- PR#6232: Don't use [mktemp] on platforms where [mkstemp] is available
+  (Stéphane Glondu, Mark Shinwell)
 - PR#6233: out-of-bounds exceptions lose their locations on ARM, PowerPC
   (Jacques-Henri Jourdan and Xavier Leroy,
    report and testing by Stéphane Glondu)
@@ -242,8 +2101,6 @@ Bug fixes:
   (Xavier Leroy, report by Pierre-Marie Pédrot)
 - PR#6262: equality of first-class modules take module aliases into account
   (Alain Frisch and Leo White)
-- PR#6267: more information printed by "bt" command of ocamldebug
-  (Josh Watzman)
 - PR#6268: -DMODEL_$(MODEL) not passed when building asmrun/arm.p.o
   (Peter Michael Green)
 - PR#6273: fix Sys.file_exists on large files (Win32)
@@ -280,31 +2137,43 @@ Bug fixes:
   (Jacques Garrigue, report by Gabriel Scherer and Benoît Vaugon)
 - PR#6408: Optional arguments given as ~?arg instead of ?arg in message
   (Michael O'Connor)
-- PR#6418: reimplement parametrized Format tags/indentation with GADTs
-  (Benoît Vaugon)
+- PR#6411: missing libgcc_s_sjlj-1.dll in mingw (add -static-libgcc)
+  (Jun Furuse and Alain Frisch, Jonathan Protzenko and Adrien Nader)
 - PR#6436: Typos in @deprecated text in stdlib/arrayLabels.mli
   (John Whitington)
+- PR#6439: Don't use the deprecated [getpagesize] function
+  (John Whitington, Mark Shinwell)
+- PR#6441: undetected tail-call in some mutually-recursive functions
+  (many arguments, and mutual block mixes functions and non-functions)
+  (Stefan Holdermans, review by Xavier Leroy)
 - PR#6443: ocaml segfault when List.fold_left is traced then executed
-  (Jacques Garrigue, report by Reventlov)
+  (Jacques Garrigue, report by user 'Reventlov')
+- PR#6451: some bugs in untypeast.ml
+  (Jun Furuse, review by Alain Frisch)
 - PR#6460: runtime assertion failure with large [| e1;...eN |]
   float array expressions
   (Leo White)
+- PR#6463: -dtypedtree fails on class fields
+  (Leo White)
+- PR#6469: invalid -dsource printing of "external _pipe = ...", "Pervasives.(!)"
+  (Gabriel Scherer and Damien Doligez, user 'ngunn')
 - PR#6482: ocamlbuild fails when _tags file in unhygienic directory
   (Gabriel Scherer)
+- PR#6502: ocamlbuild spurious warning on "use_menhir" tag
+  (Xavier Leroy)
 - PR#6505: Missed Type-error leads to a segfault upon record access
-  (Jacques Garrigue, report by Christoph Höger)
+  (Jacques Garrigue, Jeremy Yallop, report by Christoph Höger)
+- PR#6507: crash on AArch64 resulting from incorrect setting of
+  [caml_bottom_of_stack].  (Richard Jones, Mark Shinwell)
 - PR#6509: add -linkall flag to ocamlcommon.cma
   (Frédéric Bour)
 - PR#6513: Fatal error Ctype.Unify(_) in functor type
-  (Jacques Garrigue, report by Dario Teixeira)
-- fix -dsource printing of "external _pipe = ..."
-  (Gabriel Scherer)
+- PR#6523: failure upon character bigarray access, and unnecessary change
+  in comparison ordering (Jeremy Yallop, Mark Shinwell)
 - bound-checking bug in caml_string_{get,set}{16,32,64}
   (Pierre Chambart and Gabriel Scherer, report by Nicolas Trangez)
 - sometimes wrong stack alignment at out-of-bounds array access
   (Gabriel Scherer and Xavier Leroy, report by Pierre Chambart)
-- make ocamldebug -I auto-detection work with ocamlbuild
-  (Josh Watzman)
 
 Features wishes:
 - PR#4243: make the Makefiles parallelizable
@@ -312,10 +2181,18 @@ Features wishes:
 - PR#4323: have "of_string" in Num and Big_int work with binary and
            hex representations
   (Zoe Paraskevopoulou, review by Gabriel Scherer)
+- PR#4771: Clarify documentation of Dynlink.allow_only
+  (Damien Doligez, report by David Allsopp)
+- PR#4855: 'camlp4 -I +dir' accepted, dir is relative to 'camlp4 -where'
+  (Jun Furuse and Hongbo Zhang, report by Dmitry Grebeniuk)
+- PR#5201: ocamlbuild: add --norc to the bash invocation to help performances
+  (Daniel Weil)
 - PR#5650: Camlp4FoldGenerator doesn't handle well "abstract" types
   (Hongbo Zhang)
 - PR#5808: allow simple patterns, not just identifiers, in "let p : t = ..."
   (Alain Frisch)
+- PR#5851: warn when -r is disabled because no _tags file is present
+  (Gabriel Scherer)
 - PR#5899: a programmer-friendly access to backtrace information
   (Jacques-Henri Jourdan and Gabriel Scherer)
 - PR#6000 comment 9644: add a warning for non-principal coercions to format
@@ -328,28 +2205,49 @@ Features wishes:
   (David Sheets)
 - PR#6087: ocamlbuild, improve _tags parsing of escaped newlines
   (Gabriel Scherer, request by Daniel Bünzli)
+- PR#6109: Typos in ocamlbuild error messages
+  (Gabriel Kerneis)
+- PR#6116: more efficient implementation of Digest.to_hex
+  (ygrek)
+- PR#6142: add cmt file support to ocamlobjinfo
+  (Anil Madhavapeddy)
 - PR#6166: document -ocamldoc option of ocamlbuild
   (Xavier Clerc)
+- PR#6182: better message for virtual objects and class types
+  (Leo White, Stephen Dolan)
+- PR#6183: enhanced documentation for 'Unix.shutdown_connection'
+  (Anil Madhavapeddy, report by Jun Furuse)
 - PR#6187: ocamlbuild: warn when using -plugin-tag(s) without myocamlbuild.ml
   (Jacques-Pascal Deplaix)
-- PR#6246: allow wilcard _ as for-loop index
+- PR#6246: allow wildcard _ as for-loop index
   (Alain Frisch, request by ygrek)
+- PR#6267: more information printed by "bt" command of ocamldebug
+  (Josh Watzman)
 - PR#6270: remove need for -I directives to ocamldebug in common case
   (Josh Watzman, review by Xavier Clerc and Alain Frisch)
+- PR#6311: Improve signature mismatch error messages
+  (Alain Frisch, suggestion by Daniel Bünzli)
 - 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 whitequark and Jun Furuse)
 - PR#6406: Expose OCaml version in C headers
-  (Peter Zotov and Romain Calascibetta)
-- PR#5899: a programmer-friendly access to backtrace information
-  (Jacques-Henri Jourdan and Gabriel Scherer)
+  (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
+  (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) .. -> .."
   (Thomas Gazagnaire and Jeremy Yallop, review by Gabriel Scherer)
+- make ocamldebug -I auto-detection work with ocamlbuild
+  (Josh Watzman)
 
-
-OCaml 4.01.0:
--------------
+OCaml 4.01.0 (12 Sep 2013):
+---------------------------
 
 (Changes that can break existing programs are marked with a "*")
 
@@ -359,7 +2257,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
@@ -408,7 +2306,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,
@@ -582,7 +2480,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)
@@ -620,7 +2518,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
@@ -648,7 +2546,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
@@ -666,13 +2564,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
@@ -718,7 +2616,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
@@ -767,8 +2665,6 @@ Feature wishes:
   (Anil Madhavapeddy)
 - PR#6060: ocamlbuild tags 'principal', 'strict_sequence' and 'short_paths'
   (Anil Madhavapeddy)
-- PR#6495: ocamlbuild tags 'safe_string', 'unsafe_string'
-  (Anil Madhavapeddy)
 - ocamlbuild tag 'no_alias_deps'
   (Daniel Bünzli)
 
@@ -786,8 +2682,8 @@ Tools:
   (Guillaume Melquiond, Alain Frisch)
 
 
-OCaml 4.00.1:
--------------
+OCaml 4.00.1 (5 Oct 2012):
+--------------------------
 
 Bug fixes:
 - PR#4019: better documentation of Str.matched_string
@@ -816,8 +2712,8 @@ Bug fixes:
 - PR#5761: Incorrect bigarray custom block size
 
 
-OCaml 4.00.0:
--------------
+OCaml 4.00.0 (26 Jul 2012):
+---------------------------
 
 (Changes that can break existing programs are marked with a "*")
 
@@ -1143,8 +3039,8 @@ Other changes:
 - Copy VERSION file to library directory when installing.
 
 
-OCaml 3.12.1:
--------------
+OCaml 3.12.1 (4 Jul 2011):
+--------------------------
 
 Bug fixes:
 - PR#4345, PR#4767: problems with camlp4 printing of float values
@@ -1241,8 +3137,8 @@ Other changes:
   comparing a custom block value with an unboxed integer.
 
 
-Objective Caml 3.12.0:
-----------------------
+Objective Caml 3.12.0 (2 Aug 2010):
+-----------------------------------
 
 (Changes that can break existing programs are marked with a "*"  )
 
@@ -1372,8 +3268,8 @@ Bug Fixes:
 - Small problem with representation of Int32, Int64, and Nativeint constants.
 - Use RTLD_LOCAL for native dynlink in private mode.
 
-Objective Caml 3.11.2:
-----------------------
+Objective Caml 3.11.2 (20 Jan 2010):
+------------------------------------
 
 Bug fixes:
 - PR#4151: better documentation for min and max w.r.t. NaN
@@ -1421,8 +3317,8 @@ Feature wishes:
 - PR#4723: "clear_rules" function to empty the set of ocamlbuild rules
 - PR#4921: configure option to help cross-compilers
 
-Objective Caml 3.11.1:
-----------------------
+Objective Caml 3.11.1 (12 Jun 2009):
+------------------------------------
 
 Bug fixes:
 - PR#4095: ocamldebug: strange behaviour of control-C
@@ -1477,8 +3373,8 @@ Other changes:
 - Support for 64-bit mode in Solaris/x86 (PR#4670).
 
 
-Objective Caml 3.11.0:
-----------------------
+Objective Caml 3.11.0 (03 Dec 2008):
+------------------------------------
 
 (Changes that can break existing programs are marked with a "*"  )
 
@@ -1608,8 +3504,8 @@ Bug fixes:
 - PR#4614: Inconsistent declaration of CamlCBCmd in LablTk library.
 
 
-Objective Caml 3.10.2:
-----------------------
+Objective Caml 3.10.2 (29 Feb 2008):
+------------------------------------
 
 Bug fixes:
 - PR#1217 (partial) Typo in ocamldep man page
@@ -1626,8 +3522,8 @@ Bug fixes:
 - Bug in typing of polymorphic variants (reported on caml-list)
 
 
-Objective Caml 3.10.1:
-----------------------
+Objective Caml 3.10.1 (11 Jan 2008):
+------------------------------------
 
 Bug fixes:
 - PR#3830 small bugs in docs
@@ -1713,8 +3609,8 @@ New features:
   emacs files
 
 
-Objective Caml 3.10.0:
-----------------------
+Objective Caml 3.10.0 (18 May 2007):
+------------------------------------
 
 (Changes that can break existing programs are marked with a "*"  )
 
@@ -1791,8 +3687,8 @@ Lexer generator (ocamllex): improved error reporting.
 License: fixed a typo in the "special exception" to the LGPL.
 
 
-Objective Caml 3.09.3:
-----------------------
+Objective Caml 3.09.3 (15 Sep 2006):
+------------------------------------
 
 Bug fixes:
 - ocamldoc: -using modtype constraint to filter module elements displayed
@@ -1827,8 +3723,8 @@ New features:
 
 
 
-Objective Caml 3.09.2:
-----------------------
+Objective Caml 3.09.2 (14 Apr 2006):
+------------------------------------
 
 Bug fixes:
 - Makefile: problem with "make world.opt" PR#3954
@@ -1858,8 +3754,8 @@ New features:
 - ported to MacOS X on Intel PR#3985
 - configure: added support for GNU Hurd PR#3991
 
-Objective Caml 3.09.1:
-----------------------
+Objective Caml 3.09.1 (4 Jan 2006):
+-----------------------------------
 
 Bug fixes:
 - compilers: raise not_found with -principal PR#3855
@@ -1893,8 +3789,8 @@ Bug fixes:
 New features:
 - otherlibs/labltk: browser uses menu bars instead of menu buttons
 
-Objective Caml 3.09.0:
-----------------------
+Objective Caml 3.09.0 (27 Oct 2006):
+------------------------------------
 
 (Changes that can break existing programs are marked with a "*"  )
 
@@ -1968,8 +3864,8 @@ Miscellaneous:
 - Configuration information is installed in `ocamlc -where`/Makefile.config
   and can be used by client Makefiles or shell scripts.
 
-Objective Caml 3.08.4:
-----------------------
+Objective Caml 3.08.4 (11 Aug 2005):
+------------------------------------
 
 New features:
 - configure: find X11 config in some 64-bit Linux distribs
@@ -2016,8 +3912,8 @@ Bug fixes:
 - yacc: avoid name capture for idents of the Parsing module
 
 
-Objective Caml 3.08.3:
-----------------------
+Objective Caml 3.08.3 (24 Mar 2005):
+------------------------------------
 
 New features:
 - support for ocamlopt -pack under Mac OS X (PR#2634, PR#3320)
@@ -2061,8 +3957,8 @@ Bug fixes:
 - windows: better handling of InterpreterPath registry entry (PR#3334, PR#3432)
 
 
-Objective Caml 3.08.2:
-----------------------
+Objective Caml 3.08.2 (22 Nov 2004):
+------------------------------------
 
 Bug fixes:
 - runtime: memory leak when unmarshalling big data structures (PR#3247)
@@ -2082,8 +3978,8 @@ Misc:
 - unix: added missing #includes (PR#3088)
 
 
-Objective Caml 3.08.1:
-----------------------
+Objective Caml 3.08.1 (19 Aug 2004):
+------------------------------------
 
 Licence:
 - The emacs files are now under GPL
@@ -2107,8 +4003,8 @@ Misc:
 - added -v option to ocamllex
 - ocamldoc: new -intf and -impl options supported (PR#3036)
 
-Objective Caml 3.08.0:
-----------------------
+Objective Caml 3.08.0 (13 Jul 2004):
+------------------------------------
 
 (Changes that can break existing programs are marked with a "*"  )
 
@@ -2209,8 +4105,8 @@ Camlp4:
 - See camlp4/CHANGES and camlp4/ICHANGES for more info.
 
 
-Objective Caml 3.07:
---------------------
+Objective Caml 3.07 (29 Sep 2003):
+----------------------------------
 
 Language features:
 - Experimental support for recursive module definitions
@@ -2369,8 +4265,8 @@ OCamldoc:
 - fix: empty [] in generated HTML indexes
 
 
-Objective Caml 3.06:
---------------------
+Objective Caml 3.06 (20 Aug 2002):
+----------------------------------
 
 Type-checking:
 - Apply value restriction to polymorphic record fields.
@@ -2395,8 +4291,8 @@ Windows ports:
 - Fixed two problems with the Mingw port under Cygwin 1.3.
 
 
-Objective Caml 3.05:
---------------------
+Objective Caml 3.05 (29 Jul 2002):
+----------------------------------
 
 Language features:
 - Support for polymorphic methods and record fields.
@@ -2466,7 +4362,7 @@ Standard library:
 - Module Printf:
     added %S and %C formats (quoted, escaped strings and characters);
     added kprintf (calls user-specified continuation on formatted string).
-- Module Queue: faster implementation (courtesy of Francois Pottier).
+- Module Queue: faster implementation (courtesy of François Pottier).
 - Module Random: added Random.bool.
 - Module Stack: added Stack.is_empty.
 - Module Pervasives:
@@ -2527,8 +4423,8 @@ Windows port:
 - LablTk library: fixed a bug in Fileinput
 
 
-Objective Caml 3.04:
---------------------
+Objective Caml 3.04 (13 Dec 2001):
+----------------------------------
 
 Type-checker:
 - Allowed coercing self to the type of the current class, avoiding
@@ -2595,8 +4491,8 @@ License: added special exception to the LGPL'ed code (libraries and
   runtime system) allowing unrestricted linking, whether static or dynamic.
 
 
-Objective Caml 3.03 ALPHA:
---------------------------
+Objective Caml 3.03 ALPHA (12 Oct 2001):
+----------------------------------------
 
 Language:
 - Removed built-in syntactic sugar for streams and stream patterns
@@ -2676,8 +4572,8 @@ Windows port:
 
 
 
-Objective Caml 3.02:
---------------------
+Objective Caml 3.02 (30 Jul 2001):
+----------------------------------
 
 Both compilers:
 - Fixed embarrassing bug in pattern-matching compilation
@@ -2742,8 +4638,8 @@ MacOS 9 port:
 - Removed the last traces of support for 68k
 
 
-Objective Caml 3.01:
---------------------
+Objective Caml 3.01 (09 Mar 2001):
+----------------------------------
 
 New language features:
 - Variables are allowed in "or" patterns, e.g.
@@ -2860,8 +4756,8 @@ Mac OS ports:
 - Int64.format works on Mac OS 8/9.
 
 
-Objective Caml 3.00:
---------------------
+Objective Caml 3.00 (25 Apr 2000):
+----------------------------------
 
 Language:
 - OCaml/OLabl merger:
@@ -2971,8 +4867,8 @@ Macintosh port:
   program written in O'Caml.
 
 
-Objective Caml 2.04:
---------------------
+Objective Caml 2.04 (26 Nov 1999):
+----------------------------------
 
 - C interface: corrected inconsistent change in the CAMLparam* macros.
 - Fixed internal error in ocamlc -g.
@@ -2985,8 +4881,8 @@ Objective Caml 2.04:
   - Native-code compiler: fixed bug in assembling certain
     floating-point constants (masm doesn't grok 2e5, wants 2.0e5).
 
-Objective Caml 2.03:
---------------------
+Objective Caml 2.03 (19 Nov 1999):
+----------------------------------
 
 New ports:
 - Ported to BeOS / Intel x86 (bytecode and native-code).
@@ -3071,8 +4967,8 @@ Others:
   not loading properly.
 
 
-Objective Caml 2.02:
---------------------
+Objective Caml 2.02 (04 Mar 1999):
+----------------------------------
 
 * Type system:
   - Check that all components of a signature have unique names.
@@ -3154,8 +5050,8 @@ Objective Caml 2.02:
   - Fixed end-of-line bug in ocamlcp causing problems with generated sources.
 
 
-Objective Caml 2.01:
---------------------
+Objective Caml 2.01 (09 Dec 1998):
+----------------------------------
 
 * Typing:
   - Added warning for expressions of the form "a; b" where a does not have
@@ -3232,8 +5128,8 @@ Objective Caml 2.01:
 * Macintosh port: source code for Macintosh application merged in.
 
 
-Objective Caml 2.00:
---------------------
+Objective Caml 2.00 (19 Aug 1998):
+----------------------------------
 
 * Language:
   - New class language.  See http://caml.inria.fr/ocaml/refman/
@@ -3331,8 +5227,8 @@ Objective Caml 2.00:
   - Fixed bug with next-error under Emacs 20.
 
 
-Objective Caml 1.07:
---------------------
+Objective Caml 1.07 (11 Dec 1997):
+----------------------------------
 
 * Native-code compiler:
   - Revised interface between generated code and GC, fixes serious GC
@@ -3356,8 +5252,8 @@ Objective Caml 1.07:
 
 * MS Windows port: better handling of long command lines in Sys.command
 
-Objective Caml 1.06:
---------------------
+Objective Caml 1.06 (18 Nov 1997):
+----------------------------------
 
 * Language:
   - Added two new keywords: "assert" (check assertion) and "lazy"
@@ -3454,8 +5350,8 @@ Objective Caml 1.06:
 
 * Emacs editing mode and debugger interface updated to July '97 version.
 
-Objective Caml 1.05:
---------------------
+Objective Caml 1.05 (21 Mar 1997):
+----------------------------------
 
 * Typing: fixed several bugs causing spurious type errors.
 
@@ -3473,8 +5369,8 @@ handling of checkpoints; various other small fixes.
 
 * Macintosh port: fixed signed division problem in bytecomp/emitcode.ml
 
-Objective Caml 1.04:
---------------------
+Objective Caml 1.04 (11 Mar 1997):
+----------------------------------
 
 * Replay debugger ported from Caml Light; added debugger support in
   compiler (option -g) and runtime system. Debugger is alpha-quality
@@ -3536,8 +5432,8 @@ Objective Caml 1.04:
 * Emacs editing mode and debugger interface included in distribution.
 
 
-Objective Caml 1.03:
---------------------
+Objective Caml 1.03 (29 Oct 1996):
+----------------------------------
 
 * Typing:
   - bug with type names escaping their scope via unification with
@@ -3585,8 +5481,9 @@ Objective Caml 1.03:
 * Perl-free, cpp-free, cholesterol-free installation procedure.
 
 
-Objective Caml 1.02:
---------------------
+Objective Caml 1.02 (27 Sep 1996):
+----------------------------------
+
 * Typing:
   - fixed bug with type names escaping their scope via unification
     with non-generalized type variables '_a;
@@ -3642,8 +5539,9 @@ Objective Caml 1.02:
   and call caml_main() later.
 
 
-Objective Caml 1.01:
---------------------
+Objective Caml 1.01 (12 Jun 1996):
+----------------------------------
+
 * Typing: better report of type incompatibilities;
   non-generalizable type variables in a struct...end no longer flagged
   immediately as an error;
@@ -3694,10 +5592,10 @@ Objective Caml 1.01:
     some error messages have been made clearer;
     several bugs fixes.
 
-Objective Caml 1.00:
---------------------
+Objective Caml 1.00 (9 May 1996):
+---------------------------------
 
-* Merge of Jerome Vouillon and Didier Remy's object-oriented
+* Merge of Jérôme Vouillon and Didier Rémy's object-oriented
 extensions.
 
 * All libraries: all "new" functions renamed to "create" because "new"
@@ -3730,8 +5628,8 @@ marshaling to/from strings.
 
 * Dynlink library: added support for linking libraries (.cma files).
 
-Caml Special Light 1.15:
-------------------------
+Caml Special Light 1.15 (15 Mar 1996):
+--------------------------------------
 
 * Caml Special Light now runs under Windows NT and 95. Many thanks to
 Kevin Gallo (Microsoft Research) who contributed his initial port.
@@ -3761,8 +5659,8 @@ manifest module type specifications.
 * Unix library: bug in gethostbyaddr fixed; bounds checking for read,
 write, etc.
 
-Caml Special Light 1.14:
-------------------------
+Caml Special Light 1.14 (8 Feb 1996):
+-------------------------------------
 
 * cslopt ported to the PowerPC/RS6000 architecture. Better support for
 AIX in the bytecode system as well.
@@ -3775,8 +5673,8 @@ out-of-order pops fixed.
 
 * Several bug fixes in callbacks and signals.
 
-Caml Special Light 1.13:
-------------------------
+Caml Special Light 1.13 (4 Jan 1996):
+-------------------------------------
 
 * Pattern-matching compilation revised to factor out accesses inside
 matched structures.
@@ -3799,13 +5697,13 @@ Intel decided to organize the floating-point registers as a stack).
 * cslopt for the Sparc: don't use Sparc V8 smul and sdiv instructions,
 emulation on V7 processors is abysmal.
 
-Caml Special Light 1.12:
-------------------------
+Caml Special Light 1.12 (30 Nov 1995):
+--------------------------------------
 
 * Fixed an embarrassing bug with references to floats.
 
-Caml Special Light 1.11:
-------------------------
+Caml Special Light 1.11 (29 Nov 1995):
+--------------------------------------
 
 * Streams and stream parsers a la Caml Light are back (thanks to
 Daniel de Rauglaudre).
@@ -3827,8 +5725,8 @@ core on me).
 
 * Lower memory consumption for the native-code compiler.
 
-Caml Special Light 1.10:
-------------------------
+Caml Special Light 1.10 (07 Nov 1995):
+--------------------------------------
 
 * Many bug fixes (too many to list here).
 
@@ -3845,8 +5743,8 @@ arbitrary-precision arithmetic have been ported (thanks to John
 Malecki and Victor Manuel Gulias Fernandez); better docs for the Unix
 and regexp libraries.
 
-Caml Special Light 1.07:
-------------------------
+Caml Special Light 1.07 (20 Sep 1995):
+--------------------------------------
 
 * Syntax: optional ;; allowed in compilation units and structures
 (back by popular demand)
@@ -3862,7 +5760,7 @@ no calls to ranlib in Solaris
 
 * Standard library: added List.memq; documentation of Array fixed.
 
-Caml Special Light 1.06:
-------------------------
+Caml Special Light 1.06 (12 Sep 1995):
+--------------------------------------
 
 * First public release.
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index a83bbd3bda..0000000000
--- 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 0000000000..cdea168dac
--- /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 8209011f9d..3666ebe155 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,627 +1,203 @@
-In the following, "the Library" refers to all files marked "Copyright
-INRIA" in the following directories and their sub-directories:
-
-  asmrun, byterun, config, otherlibs, stdlib, win32caml
-
-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,
-  utils, yacc
-
-The Compiler is distributed under the terms of the Q Public License
-version 1.0 with a change to choice of law (included below).
-
-The Library is distributed under the terms of the GNU Library General
-Public License version 2 (included below).
-
-As a special exception to the Q Public Licence, you may develop
-application programs, reusable components and other software items
-that link with the original or modified versions of the Compiler
-and are not made available to the general public, without any of the
-additional requirements listed in clause 6c of the Q Public licence.
-
-As a special exception to the GNU Library General Public License, you
-may link, statically or dynamically, a "work that uses the Library"
-with a publicly distributed version of the Library to produce an
-executable file containing portions of the Library, and distribute
-that executable file under terms of your choice, without any of the
-additional requirements listed in clause 6 of the GNU Library General
-Public License.  By "a publicly distributed version of the Library",
-we mean either the unmodified Library as distributed by INRIA, or a
-modified version of the Library that is distributed under the
-conditions defined in clause 2 of the GNU Library General Public
-License.  This exception does not however invalidate any other reasons
-why the executable file might be covered by the GNU Library General
-Public License.
+In the following, "the OCaml Core System" refers to all files marked
+"Copyright INRIA" in this distribution.
+
+The OCaml Core System is distributed under the terms of the
+GNU Lesser General Public License (LGPL) version 2.1 (included below).
+
+As a special exception to the GNU Lesser General Public License, you
+may link, statically or dynamically, a "work that uses the OCaml Core
+System" with a publicly distributed version of the OCaml Core System
+to produce an executable file containing portions of the OCaml Core
+System, and distribute that executable file under terms of your
+choice, without any of the additional requirements listed in clause 6
+of the GNU Lesser General Public License.  By "a publicly distributed
+version of the OCaml Core System", we mean either the unmodified OCaml
+Core System as distributed by INRIA, or a modified version of the
+OCaml Core System that is distributed under the conditions defined in
+clause 2 of the GNU Lesser General Public License.  This exception
+does not however invalidate any other reasons why the executable file
+might be covered by the GNU Lesser General Public License.
 
 ----------------------------------------------------------------------
 
-                   THE Q PUBLIC LICENSE version 1.0
+GNU LESSER GENERAL PUBLIC LICENSE
 
-              Copyright (C) 1999 Troll Tech AS, Norway.
-                  Everyone is permitted to copy and
-                  distribute this license document.
+Version 2.1, February 1999
 
-The intent of this license is to establish freedom to share and change
-the software regulated by this license under the open source model.
+Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
 
-This license applies to any software containing a notice placed by the
-copyright holder saying that it may be distributed under the terms of
-the Q Public License version 1.0. Such software is herein referred to
-as the Software. This license covers modification and distribution of
-the Software, use of third-party application programs based on the
-Software, and development of free software which uses the Software.
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
 
-                            Granted Rights
+Preamble
 
-1. You are granted the non-exclusive rights set forth in this license
-provided you agree to and comply with any and all conditions in this
-license. Whole or partial distribution of the Software, or software
-items that link with the Software, in any form signifies acceptance of
-this license.
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
 
-2. You may copy and distribute the Software in unmodified form
-provided that the entire package, including - but not restricted to -
-copyright, trademark notices and disclaimers, as released by the
-initial developer of the Software, is distributed.
+This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
 
-3. You may make modifications to the Software and distribute your
-modifications, in a form that is separate from the Software, such as
-patches. The following restrictions apply to modifications:
+When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
 
-      a. Modifications must not alter or remove any copyright notices
-      in the Software.
+To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
 
-      b. When modifications to the Software are released under this
-      license, a non-exclusive royalty-free right is granted to the
-      initial developer of the Software to distribute your
-      modification in future versions of the Software provided such
-      versions remain available under these terms in addition to any
-      other license(s) of the initial developer.
+For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
 
-4. You may distribute machine-executable forms of the Software or
-machine-executable forms of modified versions of the Software,
-provided that you meet these restrictions:
+We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.
 
-      a. You must include this license document in the distribution.
+To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
 
-      b. You must ensure that all recipients of the machine-executable
-      forms are also able to receive the complete machine-readable
-      source code to the distributed Software, including all
-      modifications, without any charge beyond the costs of data
-      transfer, and place prominent notices in the distribution
-      explaining this.
+Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.
 
-      c. You must ensure that all modifications included in the
-      machine-executable forms are available under the terms of this
-      license.
+Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
 
-5. You may use the original or modified versions of the Software to
-compile, link and run application programs legally developed by you or
-by others.
+When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
 
-6. You may develop application programs, reusable components and other
-software items that link with the original or modified versions of the
-Software. These items, when distributed, are subject to the following
-requirements:
+We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
 
-      a. You must ensure that all recipients of machine-executable
-      forms of these items are also able to receive and use the
-      complete machine-readable source code to the items without any
-      charge beyond the costs of data transfer.
+For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
 
-      b. You must explicitly license all recipients of your items to
-      use and re-distribute original and modified versions of the
-      items in both machine-executable and source code forms. The
-      recipients must be able to do so without any charges whatsoever,
-      and they must be able to re-distribute to anyone they choose.
+In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
 
-      c. If the items are not available to the general public, and the
-      initial developer of the Software requests a copy of the items,
-      then you must supply one.
+Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
 
-                       Limitations of Liability
+The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.
 
-In no event shall the initial developers or copyright holders be
-liable for any damages whatsoever, including - but not restricted to -
-lost revenue or profits or other direct, indirect, special, incidental
-or consequential damages, even if they have been advised of the
-possibility of such damages, except to the extent invariable law, if
-any, provides otherwise.
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
-                             No Warranty
+0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
 
-The Software and this license document are provided AS IS with NO
-WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN,
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
 
-                            Choice of Law
+The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
 
-This license is governed by the Laws of France.
+"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
 
-----------------------------------------------------------------------
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
+
+1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
 
-                  GNU LIBRARY GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
-                  GNU LIBRARY GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
+2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
 
     a) The modified work must itself be a software library.
+    b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
+    c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
+    d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.
+
+Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
+
+This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
+
+4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
+
+If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
+
+5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
+
+However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
+
+When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
+
+If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
+
+Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
+
+6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
+
+You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
+
+    a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
+    b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
+    c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
+    d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
+    e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
+
+For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
+
+It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
+
+7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
 
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-                            NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-     Appendix: How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    
-    Copyright (C)   
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-    MA 02111-1307, USA
+    a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
+    b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
+
+8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
+
+9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
+
+10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
+
+11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
+
+14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
+
+NO WARRANTY
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Libraries
+
+If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).
+
+To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
+
+one line to give the library's name and an idea of what it does.
+Copyright (C) year  name of author
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 Also add information on how to contact you by electronic and paper mail.
 
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
+You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names:
 
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+Yoyodyne, Inc., hereby disclaims all copyright interest in
+the library `Frob' (a library for tweaking knobs) written
+by James Random Hacker.
 
-  , 1 April 1990
-  Ty Coon, President of Vice
+signature of Ty Coon, 1 April 1990
+Ty Coon, President of Vice
 
 That's all there is to it!
+
+--------------------------------------------------
diff --git a/Makefile b/Makefile
index c760746a2d..d54eb45000 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 utils/domainstate.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
@@ -142,6 +48,9 @@ world.opt:
 	$(MAKE) coldstart
 	$(MAKE) opt.opt
 
+reconfigure:
+	./configure $(CONFIGURE_ARGS)
+
 # Hard bootstrap how-to:
 # (only necessary in some cases, for example if you remove some primitive)
 #
@@ -166,7 +75,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
@@ -189,7 +98,8 @@ coldstart:
 	cp byterun/ocamlrun$(EXE) boot/ocamlrun$(EXE)
 	cd yacc; $(MAKE) all
 	cp yacc/ocamlyacc$(EXE) boot/ocamlyacc$(EXE)
-	cd stdlib; $(MAKE) COMPILER=../boot/ocamlc all
+	cd stdlib; \
+	  $(MAKE) COMPILER="../boot/ocamlc -use-prims ../byterun/primitives" all
 	cd stdlib; cp $(LIBFILES) ../boot
 	if test -f boot/libcamlrun.a; then :; else \
 	  ln -s ../byterun/libcamlrun.a boot/libcamlrun.a; fi
@@ -222,10 +132,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 +151,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 +172,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 +182,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 +194,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,13 +220,14 @@ 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 ocamlc $(INSTALL_BINDIR)/ocamlc.byte$(EXE)
 	cp ocaml $(INSTALL_BINDIR)/ocaml$(EXE)
 	cd stdlib; $(MAKE) install
-	cp lex/ocamllex $(INSTALL_BINDIR)/ocamllex$(EXE)
+	cp lex/ocamllex $(INSTALL_BINDIR)/ocamllex.byte$(EXE)
 	cp $(CAMLYACC)$(EXE) $(INSTALL_BINDIR)/ocamlyacc$(EXE)
 	cp utils/*.cmi utils/*.cmt utils/*.cmti \
 	   parsing/*.cmi parsing/*.cmt parsing/*.cmti \
@@ -336,40 +245,58 @@ 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; else \
+	   cd $(INSTALL_BINDIR); \
+	   ln -sf ocamlc.byte$(EXE) ocamlc$(EXE); \
+	   ln -sf ocamllex.byte$(EXE) ocamllex$(EXE); \
+	   fi
 
 # Installation of the native-code compiler
 installopt:
 	cd asmrun; $(MAKE) install
-	cp ocamlopt $(INSTALL_BINDIR)/ocamlopt$(EXE)
+	cp ocamlopt $(INSTALL_BINDIR)/ocamlopt.byte$(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
+	if test -f ocamlopt.opt ; then $(MAKE) installoptopt; else \
+	   cd $(INSTALL_BINDIR); ln -sf ocamlopt.byte$(EXE) ocamlopt$(EXE); fi
 	cd tools; $(MAKE) installopt
 
 installoptopt:
 	cp ocamlc.opt $(INSTALL_BINDIR)/ocamlc.opt$(EXE)
 	cp ocamlopt.opt $(INSTALL_BINDIR)/ocamlopt.opt$(EXE)
 	cp lex/ocamllex.opt $(INSTALL_BINDIR)/ocamllex.opt$(EXE)
+	cd $(INSTALL_BINDIR); \
+	   ln -sf ocamlc.opt$(EXE) ocamlc$(EXE); \
+	   ln -sf ocamlopt.opt$(EXE) ocamlopt$(EXE); \
+	   ln -sf ocamllex.opt$(EXE) ocamllex$(EXE)
+	cp 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,18 +325,22 @@ 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
 
-ocamlopt: compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma $(OPTSTART)
+ocamlopt: compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma \
+          compilerlibs/ocamlbytecomp.cma $(OPTSTART)
 	$(CAMLC) $(LINKFLAGS) -o ocamlopt \
-	  compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma $(OPTSTART)
+	  compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma \
+	  compilerlibs/ocamlbytecomp.cma $(OPTSTART)
 
 partialclean::
 	rm -f ocamlopt
@@ -432,11 +363,37 @@ 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 \
+    compilerlibs/ocamlbytecomp.cmxa \
+    compilerlibs/ocamlopttoplevel.cmxa \
+    $(OPTTOPLEVELSTART:.cmo=.cmx)
+	$(CAMLOPT) $(LINKFLAGS) -linkall -o $@ $^
+
+partialclean::
+	rm -f ocamlnat
 
 toplevel/opttoploop.cmx: otherlibs/dynlink/dynlink.cmxa
 
@@ -452,6 +409,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,17 +422,24 @@ 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|%%STATS%%|$(STATS)|' \
 	    -e 's|%%ASM%%|$(ASM)|' \
 	    -e 's|%%ASM_CFI_SUPPORTED%%|$(ASM_CFI_SUPPORTED)|' \
 	    -e 's|%%WITH_FRAME_POINTERS%%|$(WITH_FRAME_POINTERS)|' \
+	    -e 's|%%WITH_SPACETIME%%|$(WITH_SPACETIME)|' \
+	    -e 's|%%PROFINFO_WIDTH%%|$(PROFINFO_WIDTH)|' \
+	    -e 's|%%LIBUNWIND_AVAILABLE%%|$(LIBUNWIND_AVAILABLE)|' \
+	    -e 's|%%LIBUNWIND_LINK_FLAGS%%|$(LIBUNWIND_LINK_FLAGS)|' \
 	    -e 's|%%MKDLL%%|$(MKDLL)|' \
 	    -e 's|%%MKEXE%%|$(MKEXE)|' \
 	    -e 's|%%MKMAINDLL%%|$(MKMAINDLL)|' \
 	    -e 's|%%HOST%%|$(HOST)|' \
 	    -e 's|%%TARGET%%|$(TARGET)|' \
+	    -e 's|%%FLAMBDA%%|$(FLAMBDA)|' \
+	    -e 's|%%SAFE_STRING%%|$(SAFE_STRING)|' \
+	    -e 's|%%FLEXDLL_DIR%%||' \
 	    utils/config.mlp > utils/config.ml
 
 utils/domainstate.ml: utils/domainstate.ml.c byterun/caml/domain_state.tbl
@@ -518,7 +483,7 @@ partialclean::
 # The bytecode compiler compiled with the native-code compiler
 
 compilerlibs/ocamlbytecomp.cmxa: $(BYTECOMP:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(BYTECOMP:.cmo=.cmx)
+	$(CAMLOPT) -a -ccopt "$(NATDYNLINKOPTS)" -o $@ $(BYTECOMP:.cmo=.cmx)
 partialclean::
 	rm -f compilerlibs/ocamlbytecomp.cmxa compilerlibs/ocamlbytecomp.a
 
@@ -533,26 +498,30 @@ 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
 
 ocamlopt.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
+              compilerlibs/ocamlbytecomp.cmxa  \
               $(OPTSTART:.cmo=.cmx)
 	$(CAMLOPT) $(LINKFLAGS) -o ocamlopt.opt \
 	   compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
+	   compilerlibs/ocamlbytecomp.cmxa  \
 	   $(OPTSTART:.cmo=.cmx)
 
 partialclean::
 	rm -f ocamlopt.opt
 
-$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(ASMCOMP:.cmo=.cmx): ocamlopt
+$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(MIDDLE_END:.cmo=.cmx) \
+$(ASMCOMP:.cmo=.cmx): ocamlopt
 
 # The numeric opcodes
 
 bytecomp/opcodes.ml: byterun/caml/instruct.h
 	sed -n -e '/^enum/p' -e 's/,//g' -e '/^  /p' byterun/caml/instruct.h | \
+	tr -d '\r' | \
 	awk -f tools/make-opcodes > bytecomp/opcodes.ml
 
 partialclean::
@@ -567,11 +536,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/;$$//'; \
+	 cat byterun/caml/fail.h | tr -d '\r' | \
+	 sed -n -e 's|.*/\* \("[A-Za-z_]*"\) \*/$$|  \1;|p'; \
 	 echo '|]'; \
 	 echo 'let builtin_primitives = [|'; \
-	 sed -e 's/.*/  "&";/' -e '$$s/;$$//' byterun/primitives; \
+	 sed -e 's/.*/  "&";/' byterun/primitives; \
 	 echo '|]') > bytecomp/runtimedef.ml
 
 partialclean::
@@ -581,65 +550,32 @@ beforedepend:: bytecomp/runtimedef.ml
 
 # Choose the right machine-dependent files
 
-asmcomp/arch.ml: asmcomp/$(ARCH)/arch.ml
-	ln -s $(ARCH)/arch.ml asmcomp/arch.ml
-
-partialclean::
-	rm -f asmcomp/arch.ml
-
-beforedepend:: asmcomp/arch.ml
-
-asmcomp/proc.ml: asmcomp/$(ARCH)/proc.ml
-	ln -s $(ARCH)/proc.ml asmcomp/proc.ml
+asmcomp/arch.ml: asmcomp/$(ARCH_OCAMLOPT)/arch.ml
+	ln -s $(ARCH_OCAMLOPT)/arch.ml asmcomp/arch.ml
 
-partialclean::
-	rm -f asmcomp/proc.ml
+asmcomp/proc.ml: asmcomp/$(ARCH_OCAMLOPT)/proc.ml
+	ln -s $(ARCH_OCAMLOPT)/proc.ml asmcomp/proc.ml
 
-beforedepend:: asmcomp/proc.ml
+asmcomp/selection.ml: asmcomp/$(ARCH_OCAMLOPT)/selection.ml
+	ln -s $(ARCH_OCAMLOPT)/selection.ml asmcomp/selection.ml
 
-asmcomp/selection.ml: asmcomp/$(ARCH)/selection.ml
-	ln -s $(ARCH)/selection.ml asmcomp/selection.ml
+asmcomp/CSE.ml: asmcomp/$(ARCH_OCAMLOPT)/CSE.ml
+	ln -s $(ARCH_OCAMLOPT)/CSE.ml asmcomp/CSE.ml
 
-partialclean::
-	rm -f asmcomp/selection.ml
+asmcomp/reload.ml: asmcomp/$(ARCH_OCAMLOPT)/reload.ml
+	ln -s $(ARCH_OCAMLOPT)/reload.ml asmcomp/reload.ml
 
-beforedepend:: asmcomp/selection.ml
-
-asmcomp/CSE.ml: asmcomp/$(ARCH)/CSE.ml
-	ln -s $(ARCH)/CSE.ml asmcomp/CSE.ml
-
-partialclean::
-	rm -f asmcomp/CSE.ml
-
-beforedepend:: asmcomp/CSE.ml
-
-asmcomp/reload.ml: asmcomp/$(ARCH)/reload.ml
-	ln -s $(ARCH)/reload.ml asmcomp/reload.ml
-
-partialclean::
-	rm -f asmcomp/reload.ml
-
-beforedepend:: asmcomp/reload.ml
-
-asmcomp/scheduling.ml: asmcomp/$(ARCH)/scheduling.ml
-	ln -s $(ARCH)/scheduling.ml asmcomp/scheduling.ml
-
-partialclean::
-	rm -f asmcomp/scheduling.ml
-
-beforedepend:: asmcomp/scheduling.ml
+asmcomp/scheduling.ml: asmcomp/$(ARCH_OCAMLOPT)/scheduling.ml
+	ln -s $(ARCH_OCAMLOPT)/scheduling.ml 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 \
+asmcomp/emit.ml: asmcomp/$(ARCH_OCAMLOPT)/emit.mlp tools/cvt_emit
+	echo \# 1 \"$(ARCH_OCAMLOPT)/emit.mlp\" > asmcomp/emit.ml
+	$(CAMLRUN) tools/cvt_emit >asmcomp/emit.ml \
 	|| { rm -f asmcomp/emit.ml; exit 2; }
 
-partialclean::
-	rm -f asmcomp/emit.ml
-
-beforedepend:: asmcomp/emit.ml
-
 tools/cvt_emit: tools/cvt_emit.mll
 	cd tools && $(MAKE) cvt_emit
 
@@ -720,25 +656,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
@@ -793,20 +710,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:
@@ -846,14 +749,20 @@ 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
+	$(CAMLDEP) $(DEPFLAGS) -native \
+		-impl driver/compdynlink.mlopt >> .depend
+	$(CAMLDEP) $(DEPFLAGS) -bytecode \
+		-impl driver/compdynlink.mlbyte >> .depend
 
 alldepend:: depend
 
@@ -871,7 +780,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 9666b7bd21..e02fac857e 100644
--- a/Makefile.nt
+++ b/Makefile.nt
@@ -1,118 +1,88 @@
-#########################################################################
-#                                                                       #
-#                                 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=
+  FLEXDLL_DIR=
+else
+  BOOT_FLEXLINK_CMD=FLEXLINK_CMD="../boot/ocamlrun ../flexdll/flexlink.exe"
+  CAMLOPT:=OCAML_FLEXLINK="boot/ocamlrun flexdll/flexlink.exe" $(CAMLOPT)
+  ifeq "$(wildcard flexdll/flexdll_*.$(O))$(filter flexdll,$(MAKECMDGOALS))" ""
+    FLEXDLL_DIR=
+  else
+    FLEXDLL_DIR="+flexdll"
+  endif
+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
+
+flexdll: flexdll/Makefile flexlink
+	$(MAKECMD) -C flexdll \
+             MSVC_DETECT=0 CHAINS=$(FLEXDLL_CHAIN) NATDYNLINK=false support
+
+# Bootstrapping flexlink - leaves a bytecode image of flexlink.exe in flexdll/
+flexlink: 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
+	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 +121,14 @@ 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 -use-prims ../byterun/primitives"\
+	             all
 	cd stdlib ; cp $(LIBFILES) ../boot
 
 # Build the core system: the minimum needed to make depend and bootstrap
@@ -176,10 +149,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 +168,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 +181,18 @@ 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)
 
 # Complete build using fast compilers
 world.opt: coldstart opt.opt
@@ -229,74 +206,115 @@ INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
 INSTALL_COMPLIBDIR=$(DESTDIR)$(COMPLIBDIR)
 INSTALL_STUBLIBDIR=$(DESTDIR)$(STUBLIBDIR)
 INSTALL_MANDIR=$(DESTDIR)$(MANDIR)
+INSTALL_DISTRIB=$(DESTDIR)$(PREFIX)
+INSTALL_FLEXDLL=$(INSTALL_LIBDIR)/flexdll
 
 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"
+	cp ocamlc "$(INSTALL_BINDIR)/ocamlc.byte.exe"
 	cd stdlib ; $(MAKEREC) install
-	cp lex/ocamllex $(INSTALL_BINDIR)/ocamllex.exe
-	cp yacc/ocamlyacc.exe $(INSTALL_BINDIR)/ocamlyacc.exe
+	cp lex/ocamllex "$(INSTALL_BINDIR)/ocamllex.exe"
+	cp yacc/ocamlyacc.exe "$(INSTALL_BINDIR)/ocamlyacc.exe"
+	cp lex/ocamllex "$(INSTALL_BINDIR)/ocamllex.byte.exe"
 	cp utils/*.cmi utils/*.cmt utils/*.cmti \
 	   parsing/*.cmi parsing/*.cmt parsing/*.cmti \
 	   typing/*.cmi typing/*.cmt typing/*.cmti \
 	   bytecomp/*.cmi bytecomp/*.cmt bytecomp/*.cmti \
 	   driver/*.cmi driver/*.cmt driver/*.cmti \
-	   toplevel/*.cmi toplevel/*.cmt toplevel/*.cmti $(INSTALL_COMPLIBDIR)
+	   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"
+	if test -n "$(INSTALL_DISTRIB)"; then \
+	   cp README.adoc "$(INSTALL_DISTRIB)/Readme.general.txt"; \
+	   cp README.win32.adoc "$(INSTALL_DISTRIB)/Readme.windows.txt"; \
+	   cp LICENSE "$(INSTALL_DISTRIB)/License.txt"; \
+	   cp Changes "$(INSTALL_DISTRIB)/Changes.txt"; \
+	fi
+
+install-flexdll:
+	cat stdlib/camlheader flexdll/flexlink.exe > \
+	  "$(INSTALL_BINDIR)/flexlink.exe"
+ifneq "$(filter-out mingw,$(TOOLCHAIN))" ""
+	cp flexdll/default$(filter-out _i386,_$(ARCH)).manifest \
+    "$(INSTALL_BINDIR)/"
+endif
+	if test -n "$(wildcard flexdll/flexdll_*.$(O))" ; then \
+	  mkdir -p "$(INSTALL_FLEXDLL)" ; \
+	  cp flexdll/flexdll_*.$(O) "$(INSTALL_FLEXDLL)" ; \
+	fi
 
 # 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"
+	cp ocamlopt "$(INSTALL_BINDIR)/ocamlopt.byte.exe"
+	cd stdlib && $(MAKEREC) installopt
+	cp middle_end/*.cmi middle_end/*.cmt middle_end/*.cmti \
+		"$(INSTALL_COMPLIBDIR)"
+	cp middle_end/base_types/*.cmi middle_end/base_types/*.cmt \
+		middle_end/base_types/*.cmti "$(INSTALL_COMPLIBDIR)"
+	cp asmcomp/*.cmi asmcomp/*.cmt asmcomp/*.cmti "$(INSTALL_COMPLIBDIR)"
+	cp compilerlibs/ocamloptcomp.cma $(OPTSTART) "$(INSTALL_COMPLIBDIR)"
+	if test -n "$(WITH_OCAMLDOC)"; then \
+	  (cd ocamldoc && $(MAKEREC) installopt); \
+	fi
 	for i in $(OTHERLIBRARIES); do \
 	  $(MAKEREC) -C otherlibs/$$i installopt || exit $$?; \
 	done
 	if test -f ocamlopt.opt ; then $(MAKEREC) installoptopt; fi
-	cd tools; $(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 ocamlc.opt "$(INSTALL_BINDIR)/ocamlc$(EXE)"
+	cp ocamlopt.opt "$(INSTALL_BINDIR)/ocamlopt$(EXE)"
+	cp lex/ocamllex.opt "$(INSTALL_BINDIR)/ocamllex$(EXE)"
+	cp utils/*.cmx parsing/*.cmx typing/*.cmx bytecomp/*.cmx \
+           driver/*.cmx asmcomp/*.cmx "$(INSTALL_COMPLIBDIR)"
 	cp compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlcommon.$(A) \
            compilerlibs/ocamlbytecomp.cmxa compilerlibs/ocamlbytecomp.$(A) \
            compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamloptcomp.$(A) \
            $(BYTESTART:.cmo=.cmx) $(BYTESTART:.cmo=.$(O)) \
            $(OPTSTART:.cmo=.cmx) $(OPTSTART:.cmo=.$(O)) \
-           $(INSTALL_COMPLIBDIR)
+           "$(INSTALL_COMPLIBDIR)"
+
+# Run all tests
+
+tests: opt.opt
+	cd testsuite && $(MAKE) clean && $(MAKE) all
+
+# The clean target
 
 clean:: partialclean
 
@@ -315,7 +333,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,14 +342,16 @@ 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
 
-ocamlopt: compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma $(OPTSTART)
+ocamlopt: compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma \
+          compilerlibs/ocamlbytecomp.cma $(OPTSTART)
 	$(CAMLC) $(LINKFLAGS) -o ocamlopt \
-          compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma $(OPTSTART)
+          compilerlibs/ocamlcommon.cma compilerlibs/ocamloptcomp.cma \
+	  compilerlibs/ocamlbytecomp.cma $(OPTSTART)
 
 partialclean::
 	rm -f ocamlopt
@@ -355,14 +376,21 @@ partialclean::
 
 # 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 \
+    compilerlibs/ocamlbytecomp.cmxa \
+    compilerlibs/ocamlopttoplevel.cmxa \
+    $(OPTTOPLEVELSTART:.cmo=.cmx)
+	$(CAMLOPT) $(LINKFLAGS) -linkall -o $@ $^
 
 toplevel/opttoploop.cmx: otherlibs/dynlink/dynlink.cmxa
 
 otherlibs/dynlink/dynlink.cmxa: otherlibs/dynlink/natdynlink.ml
-	cd otherlibs/dynlink && $(MAKE) -f Makefile.nt allopt
+	cd otherlibs/dynlink && $(MAKEREC) allopt
 
 
 # The configuration file
@@ -393,12 +421,20 @@ utils/config.ml: utils/config.mlp config/Makefile
 	    -e 's|%%ASM%%|$(ASM)|' \
 	    -e 's|%%ASM_CFI_SUPPORTED%%|false|' \
 	    -e 's|%%WITH_FRAME_POINTERS%%|false|' \
-	    -e 's|%%MKDLL%%|$(MKDLL)|' \
-	    -e 's|%%MKEXE%%|$(MKEXE)|' \
-	    -e 's|%%MKMAINDLL%%|$(MKMAINDLL)|' \
+	    -e 's|%%WITH_SPACETIME%%|$(WITH_SPACETIME)|' \
+	    -e 's|%%PROFINFO_WIDTH%%|$(PROFINFO_WIDTH)|' \
+	    -e 's|%%LIBUNWIND_AVAILABLE%%|false|' \
+	    -e 's|%%LIBUNWIND_LINK_FLAGS%%||' \
+	    -e 's|%%MKDLL%%|$(subst \,\\,$(MKDLL))|' \
+	    -e 's|%%MKEXE%%|$(subst \,\\,$(MKEXE))|' \
+	    -e 's|%%MKMAINDLL%%|$(subst \,\\,$(MKMAINDLL))|' \
 	    -e 's|%%CC_PROFILE%%||' \
 	    -e 's|%%HOST%%|$(HOST)|' \
 	    -e 's|%%TARGET%%|$(TARGET)|' \
+	    -e 's|%%FLAMBDA%%|$(FLAMBDA)|' \
+	    -e 's|%%SAFE_STRING%%|$(SAFE_STRING)|' \
+	    -e 's|%%FLEXLINK_FLAGS%%|$(subst \,\\,$(FLEXLINK_FLAGS))|' \
+	    -e 's|%%FLEXDLL_DIR%%|$(FLEXDLL_DIR)|' \
 	    utils/config.mlp > utils/config.ml
 
 partialclean::
@@ -451,26 +487,30 @@ 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)
 
 ocamlopt.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
+              compilerlibs/ocamlbytecomp.cmxa \
               $(OPTSTART:.cmo=.cmx)
 	$(CAMLOPT) $(LINKFLAGS) -o ocamlopt.opt \
            compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
+	  compilerlibs/ocamlbytecomp.cmxa \
            $(OPTSTART:.cmo=.cmx)
 
 partialclean::
 	rm -f ocamlopt.opt
 
-$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(ASMCOMP:.cmo=.cmx): ocamlopt
+$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(MIDDLE_END:.cmo=.cmx) \
+$(ASMCOMP:.cmo=.cmx): ocamlopt
 
 # The numeric opcodes
 
 bytecomp/opcodes.ml: byterun/caml/instruct.h
 	sed -n -e "/^enum/p" -e "s|,||g" -e "/^  /p" byterun/caml/instruct.h | \
+	tr -d '\r' | \
 	gawk -f tools/make-opcodes > bytecomp/opcodes.ml
 
 partialclean::
@@ -485,11 +525,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/;$$//'; \
+	 cat byterun/caml/fail.h | tr -d '\r' | \
+	 sed -n -e 's|.*/\* \("[A-Za-z_]*"\) \*/$$|  \1;|p'; \
 	 echo '|]'; \
 	 echo 'let builtin_primitives = [|'; \
-	 sed -e 's/.*/  "&";/' -e '$$s/;$$//' byterun/primitives; \
+	 sed -e 's/.*/  "&";/' byterun/primitives; \
 	 echo '|]') > bytecomp/runtimedef.ml
 
 partialclean::
@@ -507,12 +547,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 +589,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 +615,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::
@@ -595,7 +629,7 @@ alldepend::
 runtimeopt: makeruntimeopt stdlib/libasmrun.$(A)
 
 makeruntimeopt:
-	cd asmrun ; $(MAKEREC) all
+	cd asmrun ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
 stdlib/libasmrun.$(A): asmrun/libasmrun.$(A)
 	cp asmrun/libasmrun.$(A) stdlib/libasmrun.$(A)
 clean::
@@ -607,15 +641,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 +664,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 +711,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,20 +735,30 @@ 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; \
-	 do $(CAMLDEP) $(DEPFLAGS) $$d/*.mli $$d/*.ml; \
+	(for d in utils parsing typing bytecomp asmcomp middle_end \
+	 middle_end/base_types driver toplevel; \
+	 do $(CAMLDEP) -slash $(DEPFLAGS) $$d/*.mli $$d/*.ml; \
 	 done) > .depend
+	$(CAMLDEP) -slash $(DEPFLAGS) -native \
+		-impl driver/compdynlink.mlopt >> .depend
+	$(CAMLDEP) -slash $(DEPFLAGS) -bytecode \
+		-impl driver/compdynlink.mlbyte >> .depend
 
 alldepend:: depend
 
 distclean:
-	$(MAKE) clean
-	rm -f asmrun/.depend.nt byterun/.depend.nt
+	$(MAKEREC) clean
+	rm -f asmrun/.depend.nt byterun/.depend.nt \
+	            otherlibs/bigarray/.depend.nt  \
+		    otherlibs/str/.depend.nt
 	rm -f boot/ocamlrun boot/ocamlrun.exe boot/camlheader boot/ocamlyacc \
 	      boot/*.cm* boot/libcamlrun.a
 	rm -f config/Makefile config/m.h config/s.h
@@ -757,11 +770,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 0000000000..5ffccb4aa8
--- /dev/null
+++ b/Makefile.shared
@@ -0,0 +1,318 @@
+#**************************************************************************
+#*                                                                        *
+#*                                 OCaml                                  *
+#*                                                                        *
+#*            Xavier Leroy, projet Cristal, INRIA Rocquencourt            *
+#*                                                                        *
+#*   Copyright 1999 Institut National de Recherche en Informatique et     *
+#*     en Automatique.                                                    *
+#*                                                                        *
+#*   All rights reserved.  This file is distributed under the terms of    *
+#*   the GNU Lesser General Public License version 2.1, with the          *
+#*   special exception on linking described in the file LICENSE.          *
+#*                                                                        *
+#**************************************************************************
+
+# For users who don't read the INSTALL file
+defaultentry:
+
+# The main Makefile, fragments shared between Makefile and Makefile.nt
+include config/Makefile
+CAMLRUN ?= boot/ocamlrun
+CAMLYACC ?= boot/ocamlyacc
+include stdlib/StdlibModules
+
+CAMLC=$(CAMLRUN) boot/ocamlc -g -nostdlib -I boot -use-prims byterun/primitives
+CAMLOPT=$(CAMLRUN) ./ocamlopt -g -nostdlib -I stdlib -I otherlibs/dynlink
+COMPFLAGS=-strict-sequence -principal -absname -w +a-4-9-41-42-44-45-48 \
+	  -warn-error A \
+          -bin-annot -safe-string -strict-formats $(INCLUDES)
+LINKFLAGS=
+
+YACCFLAGS=-v --strict
+CAMLLEX=$(CAMLRUN) boot/ocamllex
+CAMLDEP=$(CAMLRUN) tools/ocamldep
+DEPFLAGS=$(INCLUDES)
+
+OCAMLBUILDBYTE=$(WITH_OCAMLBUILD:=.byte)
+OCAMLBUILDNATIVE=$(WITH_OCAMLBUILD:=.native)
+
+OCAMLDOC_OPT=$(WITH_OCAMLDOC:=.opt)
+
+INCLUDES=-I utils -I parsing -I typing -I bytecomp -I middle_end \
+        -I middle_end/base_types -I asmcomp -I driver -I toplevel
+
+UTILS=utils/config.cmo utils/misc.cmo \
+  utils/identifiable.cmo utils/numbers.cmo utils/arg_helper.cmo \
+  utils/clflags.cmo utils/tbl.cmo utils/timings.cmo \
+  utils/terminfo.cmo utils/ccomp.cmo utils/warnings.cmo \
+  utils/consistbl.cmo \
+  utils/strongly_connected_components.cmo
+
+PARSING=parsing/location.cmo parsing/longident.cmo \
+  parsing/docstrings.cmo parsing/ast_helper.cmo \
+  parsing/syntaxerr.cmo parsing/parser.cmo \
+  parsing/lexer.cmo parsing/parse.cmo parsing/printast.cmo \
+  parsing/pprintast.cmo \
+  parsing/ast_mapper.cmo parsing/ast_iterator.cmo parsing/attr_helper.cmo \
+  parsing/builtin_attributes.cmo parsing/ast_invariants.cmo parsing/depend.cmo
+
+TYPING=typing/ident.cmo typing/path.cmo \
+  typing/primitive.cmo typing/types.cmo \
+  typing/btype.cmo typing/oprint.cmo \
+  typing/subst.cmo typing/predef.cmo \
+  typing/datarepr.cmo typing/cmi_format.cmo typing/env.cmo \
+  typing/typedtree.cmo typing/printtyped.cmo typing/ctype.cmo \
+  typing/printtyp.cmo typing/includeclass.cmo \
+  typing/mtype.cmo typing/envaux.cmo typing/includecore.cmo \
+  typing/typedtreeIter.cmo typing/typedtreeMap.cmo \
+  typing/tast_mapper.cmo \
+  typing/cmt_format.cmo typing/untypeast.cmo \
+  typing/includemod.cmo typing/typetexp.cmo typing/parmatch.cmo \
+  typing/stypes.cmo typing/typedecl.cmo typing/typecore.cmo \
+  typing/typeclass.cmo \
+  typing/typemod.cmo
+
+COMP=bytecomp/lambda.cmo bytecomp/printlambda.cmo \
+  bytecomp/typeopt.cmo bytecomp/switch.cmo bytecomp/matching.cmo \
+  bytecomp/translobj.cmo bytecomp/translattribute.cmo \
+  bytecomp/translcore.cmo \
+  bytecomp/translclass.cmo bytecomp/translmod.cmo \
+  bytecomp/simplif.cmo bytecomp/runtimedef.cmo \
+  driver/pparse.cmo driver/main_args.cmo \
+  driver/compenv.cmo driver/compmisc.cmo
+
+COMMON=$(UTILS) $(PARSING) $(TYPING) $(COMP)
+
+BYTECOMP=bytecomp/meta.cmo bytecomp/instruct.cmo bytecomp/bytegen.cmo \
+  bytecomp/printinstr.cmo bytecomp/opcodes.cmo bytecomp/emitcode.cmo \
+  bytecomp/bytesections.cmo bytecomp/dll.cmo bytecomp/symtable.cmo \
+  bytecomp/bytelink.cmo bytecomp/bytelibrarian.cmo bytecomp/bytepackager.cmo \
+  driver/compdynlink.cmo driver/compplugin.cmo \
+  driver/errors.cmo driver/compile.cmo
+
+INTEL_ASM=\
+  asmcomp/x86_proc.cmo \
+  asmcomp/x86_dsl.cmo \
+  asmcomp/x86_gas.cmo \
+  asmcomp/x86_masm.cmo
+
+ARCH_SPECIFIC_ASMCOMP=
+ifeq ($(ARCH),i386)
+ARCH_SPECIFIC_ASMCOMP=$(INTEL_ASM)
+endif
+ifeq ($(ARCH),amd64)
+ARCH_SPECIFIC_ASMCOMP=$(INTEL_ASM)
+endif
+
+ASMCOMP=\
+  $(ARCH_SPECIFIC_ASMCOMP) \
+  asmcomp/arch.cmo \
+  asmcomp/cmm.cmo asmcomp/printcmm.cmo \
+  asmcomp/reg.cmo asmcomp/mach.cmo asmcomp/proc.cmo \
+  asmcomp/clambda.cmo asmcomp/printclambda.cmo \
+  asmcomp/export_info.cmo \
+  asmcomp/export_info_for_pack.cmo \
+  asmcomp/compilenv.cmo \
+  asmcomp/closure.cmo \
+  asmcomp/build_export_info.cmo \
+  asmcomp/closure_offsets.cmo \
+  asmcomp/flambda_to_clambda.cmo \
+  asmcomp/import_approx.cmo \
+  asmcomp/un_anf.cmo \
+  asmcomp/strmatch.cmo asmcomp/cmmgen.cmo \
+  asmcomp/printmach.cmo asmcomp/selectgen.cmo \
+  asmcomp/spacetime_profiling.cmo asmcomp/selection.cmo \
+  asmcomp/comballoc.cmo \
+  asmcomp/CSEgen.cmo asmcomp/CSE.cmo \
+  asmcomp/liveness.cmo \
+  asmcomp/spill.cmo asmcomp/split.cmo \
+  asmcomp/interf.cmo asmcomp/coloring.cmo \
+  asmcomp/reloadgen.cmo asmcomp/reload.cmo \
+  asmcomp/deadcode.cmo \
+  asmcomp/printlinear.cmo asmcomp/linearize.cmo \
+  asmcomp/schedgen.cmo asmcomp/scheduling.cmo \
+  asmcomp/branch_relaxation_intf.cmo \
+  asmcomp/branch_relaxation.cmo \
+  asmcomp/emitaux.cmo asmcomp/emit.cmo asmcomp/asmgen.cmo \
+  asmcomp/asmlink.cmo asmcomp/asmlibrarian.cmo asmcomp/asmpackager.cmo \
+  driver/opterrors.cmo driver/optcompile.cmo
+
+MIDDLE_END=\
+  middle_end/debuginfo.cmo \
+  middle_end/base_types/tag.cmo \
+  middle_end/base_types/linkage_name.cmo \
+  middle_end/base_types/compilation_unit.cmo \
+  middle_end/base_types/variable.cmo \
+  middle_end/base_types/mutable_variable.cmo \
+  middle_end/base_types/id_types.cmo \
+  middle_end/base_types/set_of_closures_id.cmo \
+  middle_end/base_types/set_of_closures_origin.cmo \
+  middle_end/base_types/closure_element.cmo \
+  middle_end/base_types/closure_id.cmo \
+  middle_end/base_types/var_within_closure.cmo \
+  middle_end/base_types/static_exception.cmo \
+  middle_end/base_types/export_id.cmo \
+  middle_end/base_types/symbol.cmo \
+  middle_end/pass_wrapper.cmo \
+  middle_end/semantics_of_primitives.cmo \
+  middle_end/allocated_const.cmo \
+  middle_end/projection.cmo \
+  middle_end/flambda.cmo \
+  middle_end/flambda_iterators.cmo \
+  middle_end/flambda_utils.cmo \
+  middle_end/inlining_cost.cmo \
+  middle_end/effect_analysis.cmo \
+  middle_end/freshening.cmo \
+  middle_end/simple_value_approx.cmo \
+  middle_end/lift_code.cmo \
+  middle_end/closure_conversion_aux.cmo \
+  middle_end/closure_conversion.cmo \
+  middle_end/initialize_symbol_to_let_symbol.cmo \
+  middle_end/lift_let_to_initialize_symbol.cmo \
+  middle_end/find_recursive_functions.cmo \
+  middle_end/invariant_params.cmo \
+  middle_end/inconstant_idents.cmo \
+  middle_end/alias_analysis.cmo \
+  middle_end/lift_constants.cmo \
+  middle_end/share_constants.cmo \
+  middle_end/simplify_common.cmo \
+  middle_end/remove_unused_arguments.cmo \
+  middle_end/remove_unused_closure_vars.cmo \
+  middle_end/remove_unused_program_constructs.cmo \
+  middle_end/simplify_boxed_integer_ops.cmo \
+  middle_end/simplify_primitives.cmo \
+  middle_end/inlining_stats_types.cmo \
+  middle_end/inlining_stats.cmo \
+  middle_end/inline_and_simplify_aux.cmo \
+  middle_end/remove_free_vars_equal_to_args.cmo \
+  middle_end/extract_projections.cmo \
+  middle_end/augment_specialised_args.cmo \
+  middle_end/unbox_free_vars_of_closures.cmo \
+  middle_end/unbox_specialised_args.cmo \
+  middle_end/unbox_closures.cmo \
+  middle_end/inlining_transforms.cmo \
+  middle_end/inlining_decision.cmo \
+  middle_end/inline_and_simplify.cmo \
+  middle_end/ref_to_variables.cmo \
+  middle_end/flambda_invariants.cmo \
+  middle_end/middle_end.cmo
+
+TOPLEVEL=toplevel/genprintval.cmo toplevel/toploop.cmo \
+  toplevel/trace.cmo toplevel/topdirs.cmo toplevel/topmain.cmo
+
+OPTTOPLEVEL=toplevel/genprintval.cmo toplevel/opttoploop.cmo \
+  toplevel/opttopdirs.cmo toplevel/opttopmain.cmo
+BYTESTART=driver/main.cmo
+
+OPTSTART=driver/optmain.cmo
+
+TOPLEVELSTART=toplevel/topstart.cmo
+
+OPTTOPLEVELSTART=toplevel/opttopstart.cmo
+
+PERVASIVES=$(STDLIB_MODULES) outcometree topdirs toploop
+
+
+# The middle end (whose .cma library is currently only used for linking
+# the "ocamlobjinfo" program, since we cannot depend on the whole native code
+# compiler for "make world" and the list of dependencies for
+# asmcomp/export_info.cmo is long).
+
+compilerlibs/ocamlmiddleend.cma: $(MIDDLE_END)
+	$(CAMLC) -a -o $@ $(MIDDLE_END)
+compilerlibs/ocamlmiddleend.cmxa: $(MIDDLE_END:%.cmo=%.cmx)
+	$(CAMLOPT) -a -o $@ $^
+partialclean::
+	rm -f compilerlibs/ocamlmiddleend.cma compilerlibs/ocamlmiddleend.cmxa \
+	      compilerlibs/ocamlmiddleend.$(A)
+
+
+# Tools
+
+ocamltools: ocamlc ocamlyacc ocamllex asmcomp/cmx_format.cmi \
+            asmcomp/printclambda.cmo compilerlibs/ocamlmiddleend.cma \
+            asmcomp/export_info.cmo
+	+cd tools ; $(MAKEREC) all
+
+ocamltoolsopt: ocamlopt
+	+cd tools; $(MAKEREC) opt
+
+ocamltoolsopt.opt: ocamlc.opt ocamlyacc ocamllex.opt asmcomp/cmx_format.cmi \
+                   asmcomp/printclambda.cmx compilerlibs/ocamlmiddleend.cmxa \
+                   asmcomp/export_info.cmx
+	+cd tools; $(MAKEREC) opt.opt
+
+partialclean::
+	+cd tools; $(MAKEREC) clean
+
+alldepend::
+	+cd tools; $(MAKEREC) depend
+
+#config/Makefile: configure
+#	./configure $(CONFIGURE_ARGS)
+
+## Test compilation of backend-specific parts
+
+ARCH_SPECIFIC = \
+  asmcomp/arch.ml asmcomp/proc.ml asmcomp/CSE.ml asmcomp/selection.ml \
+  asmcomp/scheduling.ml asmcomp/reload.ml asmcomp/scheduling.ml \
+  asmcomp/emit.ml
+
+partialclean::
+	rm -f $(ARCH_SPECIFIC)
+
+beforedepend:: $(ARCH_SPECIFIC)
+
+ARCH_OCAMLOPT:=$(ARCH)
+
+.PHONY: check_arch check_all_arches
+
+# This rule provides a quick way to check that machine-dependent
+# files compiles fine for a foreign architecture (passed as ARCH=xxx).
+
+check_arch:
+	@echo "========= CHECKING asmcomp/$(ARCH) =============="
+	@rm -f $(ARCH_SPECIFIC) asmcomp/*.cm*
+	@$(MAKEREC) ARCH_OCAMLOPT=$(ARCH) compilerlibs/ocamloptcomp.cma \
+	            >/dev/null
+	@rm -f $(ARCH_SPECIFIC) asmcomp/*.cm*
+
+ARCHES=amd64 i386 arm arm64 power sparc s390x
+
+check_all_arches:
+	@for i in $(ARCHES); do \
+	  $(MAKEREC) --no-print-directory check_arch ARCH=$$i; \
+	done
+
+# Compiler Plugins
+
+DYNLINK_DIR=otherlibs/dynlink
+
+driver/compdynlink.mlbyte: $(DYNLINK_DIR)/dynlink.ml driver/compdynlink.mli
+	grep -v 'REMOVE_ME for ../../debugger/dynlink.ml' \
+	     $(DYNLINK_DIR)/dynlink.ml >driver/compdynlink.mlbyte
+
+ifeq ($(NATDYNLINK),true)
+driver/compdynlink.mlopt: $(DYNLINK_DIR)/natdynlink.ml driver/compdynlink.mli
+	cp $(DYNLINK_DIR)/natdynlink.ml driver/compdynlink.mlopt
+else
+driver/compdynlink.mlopt: driver/compdynlink.mlno driver/compdynlink.mli
+	cp driver/compdynlink.mlno driver/compdynlink.mlopt
+endif
+
+driver/compdynlink.mli: $(DYNLINK_DIR)/dynlink.mli
+	cp $(DYNLINK_DIR)/dynlink.mli driver/compdynlink.mli
+
+driver/compdynlink.cmo: driver/compdynlink.mlbyte driver/compdynlink.cmi
+	$(CAMLC) $(COMPFLAGS) -c -impl $<
+
+driver/compdynlink.cmx: driver/compdynlink.mlopt driver/compdynlink.cmi
+	$(CAMLOPT) $(COMPFLAGS) -c -impl $<
+
+beforedepend:: driver/compdynlink.mlbyte driver/compdynlink.mlopt \
+               driver/compdynlink.mli
+partialclean::
+	rm -f driver/compdynlink.mlbyte
+	rm -f driver/compdynlink.mli
+	rm -f driver/compdynlink.mlopt
diff --git a/Makefile.tools b/Makefile.tools
new file mode 100644
index 0000000000..9ec9a98dfc
--- /dev/null
+++ b/Makefile.tools
@@ -0,0 +1,109 @@
+#**************************************************************************
+#*                                                                        *
+#*                                 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.          *
+#*                                                                        *
+#**************************************************************************
+
+# This makefile provides variables for using the in-tree compiler,
+# interpreter, lexer and other associated tools. It is intended to be
+# included within other makefiles.
+# See testsuite/makefiles/Makefile.common, manual/tools/Makefile and
+# manual/manual/tutorials/Makefile as examples.
+# Note that these makefile should define the $(TOPDIR) variable on their
+# own.
+
+WINTOPDIR=`cygpath -m "$(TOPDIR)"`
+
+# TOPDIR is the root directory of the OCaml sources, in Unix syntax.
+# WINTOPDIR is the same directory, in Windows syntax.
+
+OTOPDIR=$(TOPDIR)
+CTOPDIR=$(TOPDIR)
+CYGPATH=echo
+DIFF=diff -q
+SORT=sort
+SET_LD_PATH=CAML_LD_LIBRARY_PATH="$(LD_PATH)"
+
+# The variables above may be overridden by .../config/Makefile
+# OTOPDIR is either TOPDIR or WINTOPDIR, whichever is appropriate for
+#   arguments given to the OCaml compiler.
+# CTOPDIR is either TOPDIR or WINTOPDIR, whichever is appropriate for
+#   arguments given to the C and Fortran compilers.
+# CYGPATH is the command that translates unix-style file names into
+#   whichever syntax is appropriate for arguments of OCaml programs.
+# DIFF is a "diff -q" command that ignores trailing CRs under Windows.
+# SORT is the Unix "sort" command. Usually a simple command, but may be an
+#   absolute name if the Windows "sort" command is in the PATH.
+# SET_LD_PATH is a command prefix that sets the path for dynamic libraries
+#   (CAML_LD_LIBRARY_PATH for Unix, PATH for Windows) using the LD_PATH shell
+#   variable. Note that for Windows we add Unix-syntax directory names in
+#   PATH, and Cygwin will translate it to Windows syntax.
+
+include $(TOPDIR)/config/Makefile
+
+ifneq ($(USE_RUNTIME),)
+#Check USE_RUNTIME value
+ifeq ($(findstring $(USE_RUNTIME),d i),)
+$(error If set, USE_RUNTIME must be equal to "d" (debug runtime) \
+        or "i" (instrumented runtime))
+endif
+
+RUNTIME_VARIANT=-I $(OTOPDIR)/asmrun -I $(OTOPDIR)/byterun \
+                -runtime-variant $(USE_RUNTIME)
+export OCAMLRUNPARAM?=v=0
+endif
+
+OCAMLRUN=$(TOPDIR)/byterun/ocamlrun$(USE_RUNTIME)$(EXE)
+
+OCFLAGS=-nostdlib -I $(OTOPDIR)/stdlib $(COMPFLAGS)
+OCOPTFLAGS=
+
+ifeq ($(SUPPORTS_SHARED_LIBRARIES),false)
+  CUSTOM = -custom
+else
+  CUSTOM =
+endif
+
+OCAML=$(OCAMLRUN) $(OTOPDIR)/ocaml $(OCFLAGS) -noinit
+EXPECT_TEST=$(OCAMLRUN) $(OTOPDIR)/testsuite/tools/expect_test$(EXE)
+ifeq "$(FLEXLINK)" ""
+  FLEXLINK_PREFIX=
+else
+  ifeq "$(wildcard $(TOPDIR)/flexdll/Makefile)" ""
+    FLEXLINK_PREFIX=
+  else
+    EMPTY=
+    FLEXLINK_PREFIX=OCAML_FLEXLINK="$(WINTOPDIR)/boot/ocamlrun \
+	                            $(WINTOPDIR)/flexdll/flexlink.exe" $(EMPTY)
+  endif
+endif
+OCAMLC=$(FLEXLINK_PREFIX)$(OCAMLRUN) $(OTOPDIR)/ocamlc $(CUSTOM) $(OCFLAGS) \
+       $(RUNTIME_VARIANT)
+OCAMLOPT=$(FLEXLINK_PREFIX)$(OCAMLRUN) $(OTOPDIR)/ocamlopt $(OCFLAGS) \
+         $(RUNTIME_VARIANT)
+OCAMLDOC=$(OCAMLRUN) $(OTOPDIR)/ocamldoc/ocamldoc
+OCAMLLEX=$(OCAMLRUN) $(OTOPDIR)/lex/ocamllex
+OCAMLMKLIB=$(FLEXLINK_PREFIX)$(OCAMLRUN) $(OTOPDIR)/tools/ocamlmklib \
+           -ocamlc "$(OTOPDIR)/byterun/ocamlrun$(USE_RUNTIME)$(EXE) \
+                    $(OTOPDIR)/ocamlc $(OCFLAGS) $(RUNTIME_VARIANT)" \
+           -ocamlopt "$(OTOPDIR)/byterun/ocamlrun$(USE_RUNTIME)$(EXE) \
+                      $(OTOPDIR)/ocamlopt $(OCFLAGS) $(RUNTIME_VARIANT)"
+OCAMLYACC=$(TOPDIR)/yacc/ocamlyacc$(EXE)
+DUMPOBJ=$(OCAMLRUN) $(OTOPDIR)/tools/dumpobj
+OBJINFO=$(OCAMLRUN) $(OTOPDIR)/tools/ocamlobjinfo
+BYTECODE_ONLY=[ "$(ARCH)" = "none" -o "$(ASM)" = "none" ]
+NATIVECODE_ONLY=false
+
+#FORTRAN_COMPILER=
+#FORTRAN_LIBRARY=
+
+UNIXLIBVAR=`case "$(OTHERLIBRARIES)" in *win32unix*) echo win32;; esac`
diff --git a/README b/README
deleted file mode 100644
index 093ad8edf1..0000000000
--- 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 0000000000..480b0250f7
--- /dev/null
+++ b/README.adoc
@@ -0,0 +1,157 @@
+= 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
+  configure::             configure script
+  CONTRIBUTING.md::       how to contribute to OCaml
+  INSTALL.adoc::          instructions for installation
+  LICENSE::               license and copyright notice
+  Makefile::              main Makefile
+  Makefile.nt::           MS Windows Makefile
+  Makefile.shared::       common Makefile
+  Makefile.tools::        used by manual/ and testsuite/ Makefiles
+  README.adoc::           this file
+  README.win32.adoc::     info on the MS Windows ports of OCaml
+  VERSION::               version string
+  asmcomp/::              native-code compiler and linker
+  asmrun/::               native-code runtime library
+  boot/::                 bootstrap compiler
+  bytecomp/::             bytecode compiler and linker
+  byterun/::              bytecode interpreter and runtime system
+  compilerlibs/::         the OCaml compiler as a library
+  config/::               autoconfiguration stuff
+  debugger/::             source-level replay debugger
+  driver/::               driver code for the compilers
+  emacs/::                editing mode and debugger interface for GNU Emacs
+  experimental/::         experiments not built by default
+  flexdll/::              empty (see README.win32.adoc)
+  lex/::                  lexer generator
+  man/::                  man pages
+  manual/::               system to generate the manual
+  middle_end/::           the flambda optimisation phase
+  ocamldoc/::             documentation generator
+  otherlibs/::            several external libraries
+  parsing/::              syntax analysis
+  stdlib/::               standard library
+  testsuite/::            tests
+  tools/::                various utilities
+  toplevel/::             interactive system
+  typing/::               typechecking
+  utils/::                utility libraries
+  yacc/::                 parser generator
+
+== Copyright
+
+All files marked "Copyright INRIA" in this distribution are copyright 1996,
+1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Institut National de
+Recherche en Informatique et en Automatique (INRIA) and distributed under
+the conditions stated in file LICENSE.
+
+== Installation
+
+See the file link:INSTALL.adoc[] for installation instructions on machines running Unix,
+Linux, OS X and Cygwin.  For native Microsoft Windows, see
+link:README.win32.adoc[].
+
+== 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 information 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.
+
+The OCaml Community website is
+
+http://ocaml.org/
+
+== 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[].
+
+For information on contributing to OCaml, see the file CONTRIBUTING.md.
diff --git a/README.win32 b/README.win32
deleted file mode 100644
index 0f520f466e..0000000000
--- 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 0000000000..ff1177f272
--- /dev/null
+++ b/README.win32.adoc
@@ -0,0 +1,338 @@
+= 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
+https://github.com/alainfrisch/flexdll. 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. Note: if you
+use Visual Studio 2015 or Visual Studio 2017, the binary distribution of
+FlexDLL will not work and you must build it from sources.
+
+The base bytecode system (ocamlc, ocaml, ocamllex, ocamlyacc, ...) of all three
+ports runs without any additional tools.
+
+== 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               |
+| Visual Studio 2017 | 19.10.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.
+(Note: you should use cygwin's `tar` command to unpack this archive. If you
+use WinZip, you will need to deselect "TAR file smart CR/LF conversion" in
+the WinZip Options Window.)
+
+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 and 2017, you
+need to use the shortcuts in the "Windows Desktop Command Prompts" (2015) or
+"VC" (2017) group under the "Visual Studio Tools" group.
+
+Unlike `SetEnv` for the Windows SDK, the architecture is selected by using a
+different shortcut, rather than by running a command.
+
+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 and 2017 make the shortcuts even clearer by including the full name of the
+architecture.
+
+You cannot at present use a cross-compiler to compile 64-bit OCaml on 32-bit
+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.
+(Note: you should use cygwin's `tar` command to unpack this archive. If you
+use WinZip, you will need to deselect "TAR file smart CR/LF conversion" in
+the WinZip Options Window.)
+
+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 OCaml distribution.  This can be
+done in one of three ways:
+
+ * Extracting the sources from a tarball from
+   https://github.com/alainfrisch/flexdll/releases
+ * 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 ab4a744804..5c2529a11f 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-4.02.3+multicore-dev0
+4.04.2+multicore-dev0
 
 # 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 0000000000..649910d731
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,81 @@
+#**************************************************************************
+#*                                                                        *
+#*                                 OCaml                                  *
+#*                                                                        *
+#*                         Christophe Troestler                           *
+#*                                                                        *
+#*   Copyright 2015 Christophe Troestler                                  *
+#*                                                                        *
+#*   All rights reserved.  This file is distributed 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 the 64 bits version
+platform:
+  - x64
+
+image: Visual Studio 2015
+
+branches:
+  only:
+    - trunk
+    - 4.04
+
+# 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
+    OCAMLRUNPARAM: v=0,b
+    OCAMLROOT: "%PROGRAMFILES%/OCaml"
+    OCAMLROOT2: "%PROGRAMFILES%/OCaml-mingw32"
+
+cache:
+  - C:\cygwin\var\cache\setup
+
+install:
+  - mkdir "%OCAMLROOT%/bin/flexdll"
+  - appveyor DownloadFile "http://alain.frisch.fr/flexdll/flexdll-bin-0.35.zip" -FileName "flexdll.zip"
+  - appveyor DownloadFile "http://alain.frisch.fr/flexdll/flexdll-0.35.tar.gz" -FileName "flexdll.tar.gz"
+  - cinst 7zip.commandline
+  - mkdir flexdll-tmp
+  - cd flexdll-tmp
+  - 7za x -y ..\flexdll.zip
+  - for %%F in (flexdll.h flexlink.exe default_amd64.manifest) do copy %%F "%OCAMLROOT%\bin\flexdll"
+  - cd ..
+  # Make sure the Cygwin path comes before the Git one (otherwise
+  # cygpath behaves crazily), but after the MSVC one.
+  - set Path=C:\cygwin\bin;%OCAMLROOT%\bin\flexdll;%Path%
+  - '%CYG_ROOT%\bin\bash -lc "cygcheck -dc cygwin"'
+  - '"%CYG_ROOT%\setup-x86.exe" -qgnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P diffutils -P make -P mingw64-i686-gcc-core >NUL'
+  - '%CYG_ROOT%\bin\bash -lc "cygcheck -dc cygwin"'
+  - set OCAML_PREV_PATH=%PATH%
+  - set OCAML_PREV_LIB=%LIB%
+  - set OCAML_PREV_INCLUDE=%INCLUDE%
+  - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
+
+build_script:
+  - "%CYG_ROOT%/bin/bash -lc \"echo 'eval $($APPVEYOR_BUILD_FOLDER/tools/msvs-promote-path)' >> ~/.bash_profile\""
+  - '%CYG_ROOT%/bin/bash -lc "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh"'
+  - set PATH=%OCAML_PREV_PATH%
+  - set LIB=%OCAML_PREV_LIB%
+  - set INCLUDE=%OCAML_PREV_INCLUDE%
+  - call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x86
+  - '%CYG_ROOT%/bin/bash -lc "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh msvc32-only"'
+
+test_script:
+  - set PATH=%OCAML_PREV_PATH%
+  - set LIB=%OCAML_PREV_LIB%
+  - set INCLUDE=%OCAML_PREV_INCLUDE%
+  - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
+  - '%APPVEYOR_BUILD_FOLDER%\ocamlc.opt -version'
+  - set CAML_LD_LIBRARY_PATH=%OCAMLROOT%/lib/stublibs
+  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER && make -f Makefile.nt tests"'
+  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER/../build-mingw32 && make -f Makefile.nt tests"'
+  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER && make -f Makefile.nt install"'
+  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER/../build-mingw32 && make -f Makefile.nt install"'
diff --git a/appveyor_build.sh b/appveyor_build.sh
new file mode 100644
index 0000000000..1ecede1b03
--- /dev/null
+++ b/appveyor_build.sh
@@ -0,0 +1,95 @@
+#!/bin/bash
+#**************************************************************************
+#*                                                                        *
+#*                                 OCaml                                  *
+#*                                                                        *
+#*                         Christophe Troestler                           *
+#*                                                                        *
+#*   Copyright 2015 Christophe Troestler                                  *
+#*                                                                        *
+#*   All rights reserved.  This file is distributed 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 run {
+    NAME=$1
+    shift
+    echo "-=-=- $NAME -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
+    $@
+    CODE=$?
+    if [ $CODE -ne 0 ]; then
+        echo "-=-=- $NAME failed! -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
+        exit $CODE
+    else
+        echo "-=-=- End of $NAME -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
+    fi
+}
+
+PREFIX="C:/Program Files/OCaml"
+
+wmic cpu get name
+
+if [[ $1 = "msvc32-only" ]] ; then
+  cd $APPVEYOR_BUILD_FOLDER/flexdll-0.35
+  make MSVC_DETECT=0 CHAINS=msvc MSVC_FLAGS="-nologo -MD -D_CRT_NO_DEPRECATE -GS- -WX" support
+  cp flexdll*_msvc.obj "$PREFIX/bin/flexdll"
+
+  cd $APPVEYOR_BUILD_FOLDER/../build-msvc32
+  cp config/m-nt.h config/m.h
+  cp config/s-nt.h config/s.h
+
+  eval $(tools/msvs-promote-path)
+
+  PREFIX="C:/Program Files/OCaml-msmvc32"
+  echo "Edit config/Makefile to set PREFIX=$PREFIX"
+  sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" -e "/\(BYTE\|NATIVE\)CCCOMPOPTS=./s/\r\?$/ -WX\0/" config/Makefile.msvc > config/Makefile
+
+  run "make world" make -f Makefile.nt world
+  run "make runtimeopt" make -f Makefile.nt runtimeopt
+  run "make -C otherlibs/systhreads libthreadsnat.lib" make -C otherlibs/systhreads -f Makefile.nt libthreadsnat.lib
+
+  exit 0
+fi
+
+cd $APPVEYOR_BUILD_FOLDER
+
+git worktree add ../build-mingw32 -b appveyor-build-mingw32
+git worktree add ../build-msvc32 -b appveyor-build-msvc32
+
+cd ../build-mingw32
+git submodule update --init flexdll
+
+cd $APPVEYOR_BUILD_FOLDER
+
+tar -xzf flexdll.tar.gz
+cd flexdll-0.35
+make MSVC_DETECT=0 CHAINS=msvc64 support
+cp flexdll*_msvc64.obj "$PREFIX/bin/flexdll"
+cd ..
+
+cp config/m-nt.h config/m.h
+cp config/s-nt.h config/s.h
+
+echo "Edit config/Makefile to set PREFIX=$PREFIX"
+sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" -e "/\(BYTE\|NATIVE\)CCCOMPOPTS=./s/\r\?$/ -WX\0/" config/Makefile.msvc64 > config/Makefile
+#run "Content of config/Makefile" cat config/Makefile
+
+run "make world" make -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
+
+cd ../build-mingw32
+
+cp config/m-nt.h config/m.h
+cp config/s-nt.h config/s.h
+
+PREFIX="C:/Program Files/OCaml-mingw32"
+echo "Edit config/Makefile to set PREFIX=$PREFIX"
+sed -e "s|PREFIX=.*|PREFIX=$PREFIX|" -e "/\(BYTE\|NATIVE\)CCCOMPOPTS=./s/\r\?$/ -Werror\0/" config/Makefile.mingw > config/Makefile
+#run "Content of config/Makefile" cat config/Makefile
+
+run "make flexdll" make -f Makefile.nt flexdll
+run "make world.opt" make -f Makefile.nt world.opt
diff --git a/asmcomp/.ignore b/asmcomp/.ignore
deleted file mode 100644
index 8c24e74ad1..0000000000
--- 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 eadad7cdc2..92d7bede7b 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,15 +20,52 @@ 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 =
+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 *)
     num_eqs: valnum array Equations.t;  (* mapping rhs -> valnums *)
@@ -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].  *)
 
@@ -161,21 +207,12 @@ let insert_move srcs dsts i =
   match Array.length srcs with
   | 0 -> i
   | 1 -> instr_cons (Iop Imove) srcs dsts i
-  | l -> (* Parallel move: first copy srcs into tmps one by one,
+  | _ -> (* Parallel move: first copy srcs into tmps one by one,
             then copy tmps into dsts one by one *)
          let tmps = Reg.createv_like srcs in
          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
@@ -184,18 +221,17 @@ class cse_generic = object (self)
 method class_of_operation op =
   match op with
   | Imove | Ispill | Ireload -> assert false   (* treated specially *)
-  | Iconst_int _ | Iconst_float _ | Iconst_symbol _
-  | Iconst_blockheader _ -> Op_pure
-  | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+  | Iconst_int _ | Iconst_float _ | Iconst_symbol _ -> Op_pure
+  | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _
   | Iextcall _ -> assert false                 (* treated specially *)
   | Istackoffset _ -> Op_other
   | Iload(_,_) -> Op_load
   | Iloadmut -> assert false                   (* treated speacially *)
   | Istore(_,_,asg) -> Op_store asg
   | Ialloc _ -> assert false                   (* treated specially *)
-  | Iintop(Icheckbound) -> Op_checkbound
+  | Iintop(Icheckbound _) -> Op_checkbound
   | Iintop _ -> Op_pure
-  | Iintop_imm(Icheckbound, _) -> Op_checkbound
+  | Iintop_imm(Icheckbound _, _) -> Op_checkbound
   | Iintop_imm(_, _) -> Op_pure
   | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
   | Ifloatofint | Iintoffloat -> Op_pure
@@ -205,21 +241,21 @@ method class_of_operation op =
 
 method is_cheap_operation op =
   match op with
-  | Iconst_int _ | Iconst_blockheader _ -> true
+  | Iconst_int _ -> true
   | _ -> false
 
 (* Forget all equations involving memory loads.  Performed after a
    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]. *)
 
 method private cse n i =
   match i.desc with
-  | Iend | Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _)
+  | Iend | Ireturn | Iop(Itailcall_ind _) | Iop(Itailcall_imm _)
   | Iexit _ | Iraise _ ->
       i
   | Iop (Imove | Ispill | Ireload) ->
@@ -227,12 +263,13 @@ method private cse n i =
          as to the argument reg. *)
       let n1 = set_move n i.arg.(0) i.res.(0) in
       {i with next = self#cse n1 i.next}
-  | Iop (Icall_ind | Icall_imm _ | Iextcall _) ->
-      (* For function calls and context switches, we should at least forget:
+  | Iop (Icall_ind _ | Icall_imm _ | Iextcall _) ->
+      (* For function calls, we should at least forget:
          - 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
@@ -242,23 +279,28 @@ 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 Iloadmut ->
       let n1 = set_unknown_regs n (Proc.destroyed_at_oper i.desc) 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? *)
@@ -282,7 +324,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 0b375ff571..cd95851556 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 aee43d2bca..34671ba709 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -16,7 +19,7 @@ open Arch
 open Mach
 open CSEgen
 
-class cse = object (self)
+class cse = object
 
 inherit cse_generic as super
 
diff --git a/asmcomp/amd64/NOTES.md b/asmcomp/amd64/NOTES.md
new file mode 100644
index 0000000000..b0adc6985b
--- /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 a4f1abd974..e0436fdecf 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
@@ -45,6 +46,8 @@ type specific_operation =
 and float_operation =
     Ifloatadd | Ifloatsub | Ifloatmul | Ifloatdiv
 
+let spacetime_node_hole_pointer_is_live_before _specific_op = false
+
 (* Sizes, endianness *)
 
 let big_endian = false
@@ -72,11 +75,11 @@ let offset_addressing addr delta =
   | Iindexed2scaled(scale, n) -> Iindexed2scaled(scale, n + delta)
 
 let num_args_addressing = function
-    Ibased(s, n) -> 0
-  | Iindexed n -> 1
-  | Iindexed2 n -> 2
-  | Iscaled(scale, n) -> 1
-  | Iindexed2scaled(scale, n) -> 2
+    Ibased _ -> 0
+  | Iindexed _ -> 1
+  | Iindexed2 _ -> 2
+  | Iscaled _ -> 1
+  | Iindexed2scaled _ -> 2
 
 (* Printing operations and addressing modes *)
 
diff --git a/asmcomp/amd64/emit.mlp b/asmcomp/amd64/emit.mlp
index b25a5314a1..c8911fd59d 100644
--- a/asmcomp/amd64/emit.mlp
+++ b/asmcomp/amd64/emit.mlp
@@ -1,17 +1,22 @@
-(***********************************************************************)
+# 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 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
-(* Emission of x86-64 (AMD 64) assembly code *)
+(* 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
 
@@ -56,7 +89,7 @@ let frame_size () =                     (* includes return address *)
 
 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
@@ -65,139 +98,198 @@ 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 emit_call s =
-  if !Clflags.dlcode && not macosx && not mingw64 && not cygwin
-  then `call	{emit_symbol s}@PLT`
-  else `call	{emit_symbol s}`
+let symbols_defined = ref StringSet.empty
+let symbols_used = ref StringSet.empty
 
-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 add_def_symbol s = symbols_defined := StringSet.add s !symbols_defined
+let add_used_symbol s = symbols_used := StringSet.add s !symbols_used
 
-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 imp_table = Hashtbl.create 16
 
-let locate_domain_state () =
+let reset_imp_table () = Hashtbl.clear imp_table
+
+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
+
+let locate_domain_state tgt =
   let bits = Domainstate.minor_heap_align_bits in
   let dom_mask = Nativeint.(shift_left minus_one bits) in
-  (* CR mshinwell: could do (-1) lsl bits *)
-  `andq	${emit_nativeint dom_mask}`
+  I.and_ (nat dom_mask) tgt
 
-let domain_field f =
-  emit_int (Domainstate.idx_of_field f * 8)
+let domain_field f base_reg =
+  mem64 QWORD (Domainstate.idx_of_field f * 8) base_reg
 
 (* Output a label *)
 
 let emit_label lbl =
-  let l = if macosx then "L" else ".L" in
-  emit_string l; emit_int lbl
-
-let emit_data_label lbl =
-  emit_string ".Ld"; emit_int lbl
+  match system with
+  | S_macosx | S_win64 -> "L" ^ string_of_int lbl
+  | _ -> ".L" ^ 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 *)
 
-let record_frame_label live dbg =
-  let lbl = new_label() in
+let record_frame_label ?label live raise_ dbg =
+  let lbl =
+    match label with
+    | None -> new_label()
+    | Some label -> label
+  in
   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;
       fd_frame_size = frame_size();
       fd_live_offset = !live_offset;
+      fd_raise = raise_;
       fd_debuginfo = dbg } :: !frame_descriptors;
   lbl
 
-let record_frame live dbg =
-  let lbl = record_frame_label live dbg in `{emit_label lbl}:\n`
+let record_frame ?label live raise_ dbg =
+  let lbl = record_frame_label ?label live raise_ dbg in
+  def_label lbl
+
+(* Spacetime instrumentation *)
+
+let spacetime_before_uninstrumented_call ~node_ptr ~index =
+  (* At the moment, [node_ptr] is pointing at the node for the current
+     OCaml function.  Get hold of the node itself and move the pointer
+     forwards, saving it into the distinguished register.  This is used
+     for instrumentation of function calls (e.g. caml_call_gc and bounds
+     check failures) not inserted until this stage of the compiler
+     pipeline. *)
+  I.mov node_ptr (reg Proc.loc_spacetime_node_hole);
+  assert (index >= 2);
+  I.add (int (index * 8)) (reg Proc.loc_spacetime_node_hole)
 
 (* Record calls to the GC -- we've moved them out of the way *)
 
@@ -205,32 +297,49 @@ type gc_call =
   { gc_size : int;                      (* Allocation size, in bytes *)
     gc_lbl: label;                      (* Entry label *)
     gc_return_lbl: label;               (* Where to branch after GC *)
-    gc_frame: label }                   (* Label of frame descriptor *)
+    gc_frame: label;                    (* Label of frame descriptor *)
+    gc_spacetime : (X86_ast.arg * int) option;
+    (* Spacetime node hole pointer and index *)
+  }
 
 let call_gc_sites = ref ([] : gc_call list)
 
 let emit_call_gc gc =
-  `{emit_label gc.gc_lbl}:	addq	${emit_int gc.gc_size}, %r15\n`;
-  `	{emit_call "caml_call_gc"}\n`;
-  `{emit_label gc.gc_frame}:	jmp	{emit_label gc.gc_return_lbl}\n`
+  def_label gc.gc_lbl;
+  (* TODO KC:
+  begin match gc.gc_spacetime with
+  | None -> assert (not Config.spacetime)
+  | Some (node_ptr, index) ->
+    assert Config.spacetime;
+    spacetime_before_uninstrumented_call ~node_ptr ~index
+  end;
+  *)
+  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
-   per bound check site.  Without -g, we can share a single call. *)
+   In -g mode, or when using Spacetime profiling, 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 *)
+    bd_frame: label;                    (* Label of frame descriptor *)
+    bd_spacetime : (X86_ast.arg * int) option;
+    (* As for [gc_call]. *)
+  }
 
 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 bound_error_label ?label dbg ~spacetime =
+  if !Clflags.debug || Config.spacetime then begin
     let lbl_bound_error = new_label() in
-    let lbl_frame = record_frame_label Reg.Set.empty dbg in
+    let lbl_frame = record_frame_label ?label Reg.Set.empty false dbg in
     bound_error_sites :=
-     { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
+      { bd_lbl = lbl_bound_error; bd_frame = lbl_frame;
+        bd_spacetime = spacetime; } :: !bound_error_sites;
    lbl_bound_error
  end else begin
    if !bound_error_call = 0 then bound_error_call := new_label();
@@ -238,13 +347,21 @@ let bound_error_label dbg =
  end
 
 let emit_call_bound_error bd =
-  `{emit_label bd.bd_lbl}:	{emit_call "caml_ml_array_bound_error"}\n`;
-  `{emit_label bd.bd_frame}:\n`
+  def_label bd.bd_lbl;
+  begin match bd.bd_spacetime with
+  | None -> ()
+  | Some (node_ptr, index) ->
+    spacetime_before_uninstrumented_call ~node_ptr ~index
+  end;
+  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
 
 (* read barrier calls *)
 
@@ -270,48 +387,48 @@ let emit_call_read_barrier rb =
 (* 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
@@ -324,52 +441,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`;
+    if n <> 0
+    then begin
+      I.add (int n) rsp;
     cfi_adjust_cfa_offset (-n);
-    if fp then begin
-       `	popq	%rbp\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 ()
@@ -379,18 +490,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 ->
+    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_directive ".quad" cst
+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
+
 
 (* Output the assembly code for an instruction *)
 
@@ -403,168 +520,187 @@ let tailrec_entry_point = ref 0
 let emit_instr fallthrough 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.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`
+      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) ->
+  | Lop(Iconst_int 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`
+        | Reg _ -> I.xor (res i 0) (res i 0)
+        | _     -> I.mov (int 0) (res i 0)
+      end
         else
-          `	movabsq	${emit_nativeint n}, {emit_reg i.res.(0)}\n`
+        I.mov (nat n) (res i 0)
     | Lop(Iconst_float f) ->
-        begin match Int64.bits_of_float f with
+      begin match f with
         | 0x0000_0000_0000_0000L ->       (* +0.0 *)
-          `	xorpd	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
+          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`
+          I.movsd (mem64_rip NONE (emit_label lbl)) (res i 0)
         end
     | Lop(Iconst_symbol s) ->
-        `	{load_symbol_addr s}, {emit_reg i.res.(0)}\n`
+      add_used_symbol s;
+      load_symbol_addr s (res i 0)
     | Lop(Icall_ind) ->
         if Config.stats then begin
-          `	pushq	%r11\n`;
-          `	movq	%r15, %r11\n`;
-          `	{locate_domain_state()}, %r11\n`;
-          `	incq	{domain_field Domainstate.Domain_call_ind}(%r11)\n`;
-          `	popq	%r11\n`;
+          I.push r11;
+          I.mov r15 r11;
+          locate_domain_state r11;
+          I.inc (domain_field Domainstate.Domain_call_ind r11);
+          I.pop r11;
         end;
-        `	call	*{emit_reg i.arg.(0)}\n`;
-        record_frame i.live i.dbg
+        I.call (arg i 0);
+        record_frame i.live false i.dbg ~label:label_after
     | Lop(Icall_imm(s)) ->
         if Config.stats then begin
-          `	movq	%r15, %r11\n`;
-          `	{locate_domain_state()}, %r11\n`;
-          `	incq	{domain_field Domainstate.Domain_call_imm}(%r11)\n`;
+          I.mov r15 r11;
+          locate_domain_state r11;
+          I.inc (domain_field Domainstate.Domain_call_imm r11);
         end;
-        `	{emit_call s}\n`;
-        record_frame i.live i.dbg
+        add_used_symbol func;
+        emit_call func;
+        record_frame i.live false i.dbg ~label:label_after
     | Lop(Itailcall_ind) ->
         output_epilogue begin fun () ->
         if Config.stats then begin
-          `	pushq	%r11\n`;
-          `	movq	%r15, %r11\n`;
-          `	{locate_domain_state()}, %r11\n`;
-          `	incq	{domain_field Domainstate.Domain_tailcall_ind}(%r11)\n`;
-          `	popq	%r11\n`;
+          I.push r11;
+          I.mov r15 r11;
+          locate_domain_state r11;
+          I.inc (domain_field Domainstate.Domain_tailcall_ind r11);
+          I.pop r11;
         end;
-        `	jmp	*{emit_reg i.arg.(0)}\n`
+        I.jmp (arg i 0);
+        (* TODO KC: Spacetime
+        if Config.spacetime then begin
+          record_frame Reg.Set.empty false i.dbg ~label:label_after
+        end
+        *)
         end
     | Lop(Itailcall_imm s) ->
-        if s = !function_name then begin
-          if Config.stats then begin
-            `	movq	%r15, %r11\n`;
-            `	{locate_domain_state()}, %r11\n`;
-            `	incq	{domain_field Domainstate.Domain_tailcall_imm}(%r11)\n`
-          end;
-          `	jmp	{emit_label !tailrec_entry_point}\n`
-        end else begin
-          output_epilogue begin fun () ->
-          if Config.stats then begin
-            `	movq	%r15, %r11\n`;
-            `	{locate_domain_state()}, %r11\n`;
-            `	incq	{domain_field Domainstate.Domain_tailcall_imm}(%r11)\n`;
-          end;
-          `	{emit_jump s}\n`
+        begin
+          if func = !function_name then
+            if Config.stats then begin
+              I.movq r15 r11;
+              locate_domain_state r11;
+              I.inc (domain_field Domainstate.DOmain_tailcall_imm r11);
+            end;
+            I.jmp (label !tailrec_entry_point)
+          else begin
+            output_epilogue begin fun () ->
+              if Config.stats then begin
+                I.movq r15 r11;
+                locate_domain_state r11;
+                I.inc (domain_field Domainstate.Domain_tailcall_imm r11)
+              end;
+              add_used_symbol func;
+              emit_jump func
+            end
           end
+        end;
+        (* FIXME KC:
+          if Config.spacetime then begin
+          record_frame Reg.Set.empty false i.dbg ~label:label_after
         end
-    | Lop(Iextcall(s, alloc, stack_off)) ->
+        *)
+    | Lop(Iextcall {func; alloc; stack_off; label_after}) ->
+        add_used_symbol func;
         if stack_off > 0 then
           begin
-            ` leaq  (%rsp), %r13\n`;
-            ` leaq  {emit_int stack_off}(%rsp), %r12\n`;
-            ` {load_symbol_addr s}, %rax\n`;
-            ` {emit_call "caml_c_call_stack_args"}\n`;
-            record_frame i.live i.dbg;
+            I.lea (mem64 QWORD 0 rsp) r13;
+            I.lea (mem64 QWORD stack_off rsp) r12;
+            load_symbol_addr func rax;
+            emit_call "caml_c_call_stack_args";
+            record_frame i.live false i.dbg ~label:label_after;
           (* caml_c_call preserves the old value of %r15, but this may no longer
              be the correct minor heap pointer, so we reload young_ptr *)
-          `	{locate_domain_state ()}, %r15\n`;
+          locate_domain_state r15;
           if Config.stats then begin
-            `	incq	{domain_field Domainstate.Domain_extcall_alloc_stackargs}(%r15)\n`;
+            I.inc (domain_field Domainstate.Domain_extcall_alloc_stackargs r15)
           end;
-          `	movq	{domain_field Domainstate.Domain_young_ptr}(%r15), %r15\n`;
+          I.mov (domain_field Domainstate.Domain_young_ptr r15) r15;
           end
         else 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 func rax;
+          emit_call "caml_c_call";
+          record_frame i.live false i.dbg ~label:label_after;
           (* caml_c_call preserves the old value of %r15, but this may no longer
              be the correct minor heap pointer, so we reload young_ptr *)
-          `	{locate_domain_state ()}, %r15\n`;
+          locate_domain_state r15;
           if Config.stats then begin
-            `	incq	{domain_field Domainstate.Domain_extcall_alloc}(%r15)\n`;
+            I.inc (domain_field Domainstate.Domain_extcall_alloc r15)
           end;
-          `	movq	{domain_field Domainstate.Domain_young_ptr}(%r15), %r15\n`;
+          I.mov (domain_field Domainstate.Domain_young_ptr r15) r15;
         end else begin
-          `	movq  %rsp, %r10\n`;
-          `	movq  %r15, %r11\n`;
-          `	{locate_domain_state ()}, %r11\n`;
+          I.mov rsp r10;
+          I.mov r15 r11;
+          locate_domain_state r11;
           if Config.stats then begin
-            `	incq	{domain_field Domainstate.Domain_extcall_noalloc}(%r11)\n`;
+            I.inc (domain_field Domainstate.Domain_extcall_noalloc r15);
           end;
-          `	.cfi_remember_state\n`;
-          `	movq	{domain_field Domainstate.Domain_system_sp}(%r11), %rsp\n`;
-          `	.cfi_def_cfa_offset 8\n`;
-          `	pushq %r10\n`;
-          cfi_adjust_cfa_offset (8);
-          `	{emit_call s}\n`;
-          `	popq  %r10\n`;
+          cfi_remember_state ();
+          I.mov (domain_field Domainstate.Domain_system_sp r11) rsp;
+          cfi_def_cfa_offset 8;
+          I.push r10;
+          cfi_adjust_cfa_offset 8;
+          emit_call func;
+          (* FIXME KC:
+          if Config.spacetime then begin
+            record_frame Reg.Set.empty false i.dbg ~label:label_after
+          end
+          *)
+          I.pop r10;
           cfi_adjust_cfa_offset (-8);
-          `	movq  %r10, %rsp\n`;
-          `	.cfi_restore_state\n`;
+          I.mov r10 rsp;
+          cfi_restore_state ();
         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;
+        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 = i.res.(0) in
+        let dest = res i 0 in
         if Config.stats then begin
-          `	push	%r15\n`;
-          `	{locate_domain_state()}, %r15\n`;
-          `	incq	{domain_field Domainstate.Domain_immutable_loads}(%r15)\n`;
-          `	pop	%r15\n`;
+          I.push r15;
+          locate_domain_state r15;
+          I.inc (domain_field Domainstate.Domain_immutable_loads r15);
+          I.pop r15;
         end;
         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
+        | 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 Iloadmut ->
         if Config.stats then begin
-          `	movq	%r15, %rax\n`;
-          `	{locate_domain_state()}, %rax\n`;
-          `	incq  {domain_field Domainstate.Domain_mutable_loads}(%rax)\n`;
+          I.mov r15 rax;
+          locate_domain_state rax;
+          I.inc (domain_field Domainstate.Domain_mutable_loads rax);
         end;
         `	movq	({emit_reg i.arg.(0)},{emit_reg i.arg.(1)},8), {emit_reg i.res.(0)}\n`;
         `	movq	{emit_reg i.res.(0)}, %rax\n`;
@@ -589,191 +725,218 @@ let emit_instr fallthrough i =
             rb_frame = lbl_frame } :: !read_barrier_call_sites
     | Lop(Istore(chunk, addr, is_assignment)) ->
         if Config.stats && is_assignment then begin
-          `	push	%r15\n`;
-          `	{locate_domain_state()}, %r15\n`;
-          `	incq	{domain_field Domainstate.Domain_immutable_stores}(%r15)\n`;
-          `	pop	%r15\n`;
+          I.push r15;
+          locate_domain_state r15;
+          I.inc (domain_field Domainstate.Domain_immutable_stores r15);
+          I.pop r15;
         end;
         begin match chunk with
-          | Word ->
-            `	movq	{emit_reg i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
+        | Word_int | Word_val ->
+          I.mov (arg i 0) (addressing addr QWORD i 1)
           | Byte_unsigned | Byte_signed ->
-            `	movb	{emit_reg8 i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
+          I.mov (arg8 i 0) (addressing addr BYTE i 1)
           | Sixteen_unsigned | Sixteen_signed ->
-            `	movw	{emit_reg16 i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
+          I.mov (arg16 i 0) (addressing addr WORD i 1)
           | Thirtytwo_signed | Thirtytwo_unsigned ->
-            `	movl	{emit_reg32 i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
+          I.mov (arg32 i 0) (addressing addr DWORD i 1)
           | Single ->
-            `	cvtsd2ss {emit_reg i.arg.(0)}, %xmm15\n`;
-            `	movss	%xmm15, {emit_addressing addr i.arg 1}\n`
+          I.cvtsd2ss (arg i 0) xmm15;
+          I.movss xmm15 (addressing addr REAL4 i 1)
           | Double | Double_u ->
-            `	movsd	{emit_reg i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
+          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
-          `{emit_label lbl_redo}:	movq	%r15, %rax\n`;
-          `	subq	${emit_int n}, %r15\n`;
-          `	{locate_domain_state ()}, %rax\n`;
-          if Config.stats then begin
-            `	incq {domain_field Domainstate.Domain_allocations}(%rax)\n`;
-          end;
-          `	cmpq	{domain_field Domainstate.Domain_young_limit}(%rax), %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`;
+  | Lop(Ialloc { words = n; label_after_call_gc; spacetime_index; }) ->
+      (* TODO Spacetime *)
+      if !fastcode_flag then begin
+        let lbl_redo = new_label() in
+        def_label lbl_redo;
+        I.mov r15 rax;
+        I.sub (int n) r15;
+        locate_domain_state rax;
+        if Config.stats then begin
+          I.inc (domain_field Domainstate.Domain_allocations rax);
+        end;
+        I.cmpq (domain_field Domainstate.Domain_young_limit rax) r15;
+        let lbl_call_gc = new_label() in
+        let dbg =
+          if not Config.spacetime then Debuginfo.none
+          else i.dbg
+        in
+        let lbl_frame =
+          record_frame_label ?label:label_after_call_gc i.live false dbg
+        in
+        I.jb (label lbl_call_gc);
+        I.lea (mem64 NONE 8 R15) (res i 0);
+        let gc_spacetime =
+          if not Config.spacetime then None
+          else Some (arg i 0, spacetime_index)
+        in
           call_gc_sites :=
             { gc_size = n;
               gc_lbl = lbl_call_gc;
               gc_return_lbl = lbl_redo;
-              gc_frame = lbl_frame } :: !call_gc_sites
+            gc_frame = lbl_frame;
+            gc_spacetime; } :: !call_gc_sites
         end else begin
           if Config.stats then begin
-            `	movq	%r15, %rax\n`;
-            `	{locate_domain_state ()}, %rax\n`;
-            `	incq {domain_field Domainstate.Domain_allocations}(%rax)\n`;
+            I.mov r15 rax
+            locate_domain_state rax;
+            I.inc (domain_field Domainstate.Domain_allocations rax);
+          end;
+          if Config.spacetime then begin
+            (* spacetime_before_uninstrumented_call ~node_ptr:(arg i 0)
+              ~index:spacetime_index; *)
+            ()
           end;
           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`
+          | 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}	leaq	8(%r15), {emit_reg i.res.(0)}\n`
+          let label =
+            record_frame_label ?label:label_after_call_gc i.live false
+              Debuginfo.none
+          in
+          def_label label;
+          I.lea (mem64 NONE 8 R15) (res i 0)
         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`
+      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)) ->
-        `	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`
+      I.cmp (int n) (arg i 0);
+      I.set (cond cmp) al;
+      I.movzx al (res i 0)
+  | Lop(Iintop (Icheckbound { label_after_error; spacetime_index; } )) ->
+      let spacetime =
+        if not Config.spacetime then None
+        else Some (arg i 2, spacetime_index)
+      in
+      let lbl = bound_error_label ?label:label_after_error i.dbg ~spacetime in
+      I.cmp (arg i 1) (arg i 0);
+      I.jbe (label lbl)
+  | Lop(Iintop_imm(Icheckbound { label_after_error; spacetime_index; }, n)) ->
+      let spacetime =
+        if not Config.spacetime then None
+        else Some (arg i 1, spacetime_index)
+      in
+      let lbl = bound_error_label ?label:label_after_error i.dbg ~spacetime in
+      I.cmp (int n) (arg i 0);
+      I.jbe (label lbl)
     | Lop(Iintop(Idiv | Imod)) ->
-        `	cqto\n`;
-        `	idivq	{emit_reg i.arg.(1)}\n`
+      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 *)
-        `	{emit_string(instr_for_intop op)}	%cl, {emit_reg i.res.(0)}\n`
+      instr_for_intop op cl (res i 0)
     | Lop(Iintop Imulh) ->
-        `	imulq	{emit_reg i.arg.(1)}\n`
+      I.imul (arg i 1) None
     | 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`
+      instr_for_intop op (arg i 1) (res i 0)
     | 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`
+      I.lea (mem64 NONE n (arg64 i 0)) (res i 0)
     | Lop(Iintop_imm(Iadd, 1) | Iintop_imm(Isub, -1)) ->
-        `	incq	{emit_reg i.res.(0)}\n`
+      I.inc (res i 0)
     | Lop(Iintop_imm(Iadd, -1) | Iintop_imm(Isub, 1)) ->
-        `	decq	{emit_reg i.res.(0)}\n`
+      I.dec (res i 0)
     | 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`
+      instr_for_intop op (int n) (res i 0)
     | Lop(Inegf) ->
-        `	xorpd	{emit_symbol "caml_negf_mask"}(%rip), {emit_reg i.res.(0)}\n`
+      I.xorpd (mem64_rip OWORD (emit_symbol "caml_negf_mask")) (res i 0)
     | Lop(Iabsf) ->
-        `	andpd	{emit_symbol "caml_absf_mask"}(%rip), {emit_reg i.res.(0)}\n`
+      I.andpd (mem64_rip OWORD (emit_symbol "caml_absf_mask")) (res i 0)
     | Lop(Iaddf | Isubf | Imulf | Idivf as floatop) ->
-        `	{emit_string(instr_for_floatop floatop)}	{emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n`
+      instr_for_floatop floatop (arg i 1) (res i 0)
     | Lop(Ifloatofint) ->
-        `	cvtsi2sdq	{emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`
+      I.cvtsi2sd  (arg i 0)  (res i 0)
     | Lop(Iintoffloat) ->
-        `	cvttsd2siq	{emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`
+      I.cvttsd2si (arg i 0) (res i 0)
     | Lop(Ispecific(Ilea addr)) ->
-        `	leaq	{emit_addressing addr i.arg 0}, {emit_reg i.res.(0)}\n`
+      I.lea (addressing addr NONE i 0) (res i 0)
     | Lop(Ispecific(Istore_int(n, addr, _))) ->
-        `	movq	${emit_nativeint n}, {emit_addressing addr i.arg 0}\n`
+      I.mov (nat n) (addressing addr QWORD i 0)
     | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
-        assert (not !pic_code && not !Clflags.dlcode);
-        `	movq	${emit_symbol s}, {emit_addressing addr i.arg 0}\n`
+      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))) ->
-        `	addq	${emit_int n}, {emit_addressing addr i.arg 0}\n`
+      I.add (int n) (addressing addr QWORD i 0)
     | 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
+      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) ->
-        `	sqrtsd	{emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`
+      I.sqrtsd (arg i 0) (res i 0)
     | Lop(Ispecific(Ifloatsqrtf addr)) ->
-        `	sqrtsd	{emit_addressing addr i.arg 0}, {emit_reg i.res.(0)}\n`
+      I.sqrtsd (addressing addr REAL8 i 0) (res i 0)
     | Lreloadretaddr ->
         ()
     | Lreturn ->
         output_epilogue begin fun () ->
-        `	ret\n`
+        I.ret ()
         end
     | Llabel lbl ->
-        `{emit_Llabel fallthrough lbl}:\n`
+      emit_Llabel fallthrough lbl
     | Lbranch lbl ->
-        `	jmp	{emit_label lbl}\n`
+      I.jmp (label lbl)
     | Lcondbranch(tst, lbl) ->
+      let lbl = label lbl in
         begin match tst with
-          Itruetest ->
+      | Itruetest ->
             output_test_zero i.arg.(0);
-            `	jne	{emit_label lbl}\n`
+          I.jne lbl
         | Ifalsetest ->
             output_test_zero i.arg.(0);
-            `	je	{emit_label lbl}\n`
+          I.je lbl
         | 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`
+          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);
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
+          I.j (cond cmp) lbl
         | 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`
+          I.cmp (int n) (arg i 0);
+          I.j (cond cmp) lbl
         | Ifloattest(cmp, neg) ->
-            emit_float_test cmp neg i.arg lbl
+          emit_float_test cmp neg i lbl
         | Ioddtest ->
-            `	testb	$1, {emit_reg8 i.arg.(0)}\n`;
-            `	jne	{emit_label lbl}\n`
+          I.test (int 1) (arg8 i 0);
+          I.jne lbl
         | Ieventest ->
-            `	testb	$1, {emit_reg8 i.arg.(0)}\n`;
-            `	je	{emit_label lbl}\n`
+          I.test (int 1) (arg8 i 0);
+          I.je lbl
         end
     | Lcondbranch3(lbl0, lbl1, lbl2) ->
-            `	cmpq	$1, {emit_reg i.arg.(0)}\n`;
+      I.cmp (int 1) (arg i 0);
             begin match lbl0 with
-              None -> ()
-            | Some lbl -> `	jb	{emit_label lbl}\n`
+      | None -> ()
+      | Some lbl -> I.jb (label lbl)
             end;
             begin match lbl1 with
-              None -> ()
-            | Some lbl -> `	je	{emit_label lbl}\n`
+      | None -> ()
+      | Some lbl -> I.je (label lbl)
             end;
             begin match lbl2 with
-              None -> ()
-            | Some lbl -> `	jg	{emit_label lbl}\n`
+      | None -> ()
+      | Some lbl -> I.jg (label lbl)
             end
     | Lswitch jumptbl ->
-        let lbl = new_label() in
+      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
@@ -783,54 +946,56 @@ let emit_instr fallthrough i =
           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 mingw64 || cygwin then
-          `	.section .rdata,\"dr\"\n`
-        else if macosx then ()
-        else
-          `	.section .rodata\n`;
-        emit_align 4;
-        `{emit_label lbl}:`;
+      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
-          `	.long	{emit_label jumptbl.(i)} - {emit_label lbl}\n`
+        D.long (ConstSub (ConstLabel(emit_label jumptbl.(i)),
+                         ConstLabel lbl))
         done;
-        `	.text\n`
+      D.text ()
     | Lsetuptrap lbl ->
-        `	call	{emit_label lbl}\n`
+        I.call (label lbl)
     | Lpushtrap ->
         cfi_adjust_cfa_offset 8;
-        `	pushq	%r14\n`;
+        I.push r14;
         cfi_adjust_cfa_offset 8;
-        ` movq  %r15, %r14\n`;
-        `	{locate_domain_state ()}, %r14\n`;
-        `	movq	{domain_field Domainstate.Domain_stack_high}(%r14), %r14\n`;
-        ` subq  %rsp, %r14\n`;
+        I.mov r15 r14;
+        locate_domain_state r14;
+        I.mov (domain_field Domainstate.Domain_stack_high r14) r14;
+        I.sub rsp r14;
         stack_offset := !stack_offset + 16
     | Lpoptrap ->
-        `	popq	%r14\n`;
+        I.pop r14;
         cfi_adjust_cfa_offset (-8);
-        `	addq	$8, %rsp\n`;
+        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"}\n`;
-          record_frame Reg.Set.empty i.dbg
-        | true, Lambda.Raise_reraise ->
-          `	{emit_call "caml_reraise_exn"}\n`;
-          record_frame Reg.Set.empty i.dbg
-        | false, _
-        | true, Lambda.Raise_notrace ->
-          ` movq  %r15, %rsp\n`;
-          `	{locate_domain_state ()}, %rsp\n`;
-          `	movq	{domain_field Domainstate.Domain_stack_high}(%rsp), %rsp\n`;
-          ` subq  %r14, %rsp\n`;
-          `	popq	%r14\n`;
-          `	ret\n`
+      (* No Spacetime instrumentation is required for [caml_raise_exn] and
+         [caml_reraise_exn].  The only function called that might affect the
+         trie is [caml_stash_backtrace], and it does not. *)
+      begin match k with
+      | Cmm.Raise_withtrace ->
+          emit_call "caml_raise_exn";
+          record_frame Reg.Set.empty true i.dbg
+      | Cmm.Raise_notrace ->
+          I.movq r15 rsp;
+          locate_domain_state rsp;
+          I.mov (domain_field Domainstate.Domain_stack_high rsp) rsp;
+          I.sub r14 rsp;
+          I.pop r14;
+          I.ret ()
         end
 
 let rec emit_all fallthrough i =
@@ -843,20 +1008,21 @@ let rec emit_all fallthrough i =
 (* Emission of the profiling prelude *)
 
 let emit_profile () =
-  match Config.system with
-  | "linux" | "gnu" ->
+  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. *)
-      `	pushq	%r10\n`;
-      if not fp then
-        `	movq	%rsp, %rbp\n`;
-      `	{emit_call "mcount"}\n`;
-      `	popq	%r10\n`
-  | _ ->
-      () (*unsupported yet*)
+    I.push r10;
+    if not fp then I.mov rsp rbp;
+    (* No Spacetime instrumentation needed: [mcount] cannot call anything
+       OCaml-related. *)
+    emit_call "mcount";
+    I.pop r10
+  end
+
+let all_functions = ref []
 
 
 type preproc_fun_result =
@@ -902,32 +1068,37 @@ let fundecl fundecl =
   bound_error_sites := [];
   bound_error_call := 0;
   read_barrier_call_sites := [];
-  `	.text\n`;
-  emit_align 16;
+  all_functions := fundecl :: !all_functions;
+  D.text ();
+  D.align 16;
+  add_def_symbol fundecl.fun_name;
   Emitaux.emit_block_header_for_closure ~word_directive:".quad"
     ~comment_string:"#"
     ~function_entry_points_are_doubleword_aligned:true;
-  if macosx
+  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`;
+    I.push rbp;
        cfi_adjust_cfa_offset 8;
-       `	movq	%rsp, %rbp\n`;
+    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`;
+    if n <> 0
+    then begin
+      I.sub (int n) rsp;
     cfi_adjust_cfa_offset n;
   end;
+<<<<<<< HEAD
 
   let preproc_res = preproc_fun fundecl.fun_body fundecl.fun_name in
   let s = !Clflags.stack_slop + preproc_res.max_stack_size in
@@ -946,7 +1117,7 @@ let fundecl fundecl =
   if not preproc_res.contains_nontail_calls &&
      s < stack_threshold_size + profile_slop
   then begin
-    `{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;
     List.iter emit_call_read_barrier !read_barrier_call_sites;
@@ -962,140 +1133,227 @@ let fundecl fundecl =
     let handle_overflow = new_label() in
     let after_overflow = record_frame_label live_initially Debuginfo.none in
 
-    ` movq %r15, %r11\n`;
-    `	{locate_domain_state ()}, %r11\n`;
+    I.mov r15 r11;
+    locate_domain_state r11;
     if Config.stats then begin
-      `	incq	{domain_field Domainstate.Domain_stackoverflow_checks}(%r11)\n`;
+      I.inc (domain_field Domainstate.Domain_stackoverflow_checks r11);
     end;
-    `	movq	{domain_field Domainstate.Domain_stack_threshold}(%r11), %r11\n`;
-    ` addq ${emit_int s}, %r11\n`;
-    ` cmpq %r11, %rsp\n`;
+    I.mov (domain_field Domainstate.Domain_stack_threshold r11) r11;
+    I.add (int s) r11;
+    I.cmp r11 rsp;
+    I.jb (label handle_overflow);
     ` jb {emit_label handle_overflow}\n`;
-    `{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;
     List.iter emit_call_read_barrier !read_barrier_call_sites;
     emit_call_bound_errors ();
-    `{emit_label handle_overflow}:\n`;
-    ` {emit_call "caml_call_realloc_stack"}\n`;
-    `{emit_label after_overflow}:\n`;
-    ` jmp {emit_label !tailrec_entry_point}\n`;
+    def_label handle_overflow;
+    emit_call "caml_call_realloc_stack";
+    def_label after_overflow;
+    I.jmp (label !tailrec_entry_point);
   end;
 
+  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)
+  | 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))
+  | 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 := [];
+  all_functions := [];
+  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;
+  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 emit_spacetime_shapes () =
+  D.data ();
+  D.align 8;
+  emit_global_label "spacetime_shapes";
+  List.iter (fun fundecl ->
+      (* CR-someday mshinwell: some of this should be platform independent *)
+      begin match fundecl.fun_spacetime_shape with
+      | None -> ()
+      | Some shape ->
+        let funsym = emit_symbol fundecl.fun_name in
+        D.comment ("Shape for " ^ funsym ^ ":");
+        D.qword (ConstLabel funsym);
+        List.iter (fun (part_of_shape, label) ->
+            let tag =
+              match part_of_shape with
+              | Direct_call_point _ -> 1
+              | Indirect_call_point -> 2
+              | Allocation_point -> 3
+            in
+            D.qword (Const (Int64.of_int tag));
+            D.qword (ConstLabel (emit_label label));
+            begin match part_of_shape with
+            | Direct_call_point { callee; } ->
+              D.qword (ConstLabel (emit_symbol callee))
+            | Indirect_call_point -> ()
+            | Allocation_point -> ()
+            end)
+          shape;
+          D.qword (Const 0L)
+      end)
+    !all_functions;
+  D.qword (Const 0L);
+  D.comment "End of Spacetime shapes."
 
 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_code_label = (fun l -> D.qword (ConstLabel (emit_label l)));
+      efa_data_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 ->
+        (fun lbl ofs ->
+           let c =
+             ConstAdd (
+               ConstSub(ConstLabel(emit_label lbl), ConstThis),
+               const_32 ofs
+             ) in
+           if system = S_macosx then begin
             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`
+             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 Config.spacetime then begin
+    emit_spacetime_shapes ()
 	end;
-      efa_def_label = (fun l -> `{emit_label l}:\n`);
-      efa_string = (fun s -> emit_string_directive "	.asciz	" s) };
-  if Config.system = "linux" then
+
+  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 f14e69cd38..0000000000
--- 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 9d0028ee10..945674e40b 100644
--- a/asmcomp/amd64/proc.ml
+++ b/asmcomp/amd64/proc.ml
@@ -1,14 +1,18 @@
-(***********************************************************************)
+# 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 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Description of the AMD64 processor *)
 
@@ -27,13 +31,6 @@ let win64 =
   | "win64" | "mingw64" | "cygwin" -> true
   | _                   -> false
 
-(* Which asm conventions to use *)
-
-let masm =
-  match Config.ccomp_type with
-  | "msvc" -> true
-  | _      -> false
-
 (* Registers available for register allocation *)
 
 (* Register map:
@@ -75,6 +72,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 +98,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 |]
@@ -133,8 +131,8 @@ let phys_reg n =
   if n < 100 then hard_int_reg.(n) else hard_float_reg.(n - 100)
 
 let rax = phys_reg 0
-let rcx = phys_reg 5
 let rdx = phys_reg 4
+let r13 = phys_reg 9
 let rbp = phys_reg 12
 let rxmm15 = phys_reg 115
 
@@ -155,7 +153,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
@@ -176,14 +174,22 @@ let calling_conventions first_int last_int first_float last_float make_stack
 
 let incoming ofs = Incoming ofs
 let outgoing ofs = Outgoing ofs
-let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
+let not_supported _ofs = fatal_error "Proc.loc_results: cannot call"
+
+let max_int_args_in_regs () =
+  if Config.spacetime then 9 else 10
 
 let loc_arguments arg =
-  calling_conventions 0 9 100 109 outgoing arg
+  calling_conventions 0 ((max_int_args_in_regs ()) - 1) 100 109 outgoing arg
 let loc_parameters arg =
-  let (loc, ofs) = calling_conventions 0 9 100 109 incoming arg in loc
+  let (loc, _ofs) =
+    calling_conventions 0 ((max_int_args_in_regs ()) - 1) 100 109 incoming arg
+  in
+  loc
 let loc_results res =
-  let (loc, ofs) = calling_conventions 0 0 100 100 not_supported res in loc
+  let (loc, _ofs) = calling_conventions 0 0 100 100 not_supported res in loc
+
+let loc_spacetime_node_hole = r13
 
 (* C calling conventions under Unix:
      first integer args in rdi, rsi, rdx, rcx, r8, r9
@@ -199,7 +205,7 @@ let loc_results res =
      Return value in rax or xmm0. *)
 
 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 0 100 100 not_supported res in loc
 
 let unix_loc_external_arguments arg =
   calling_conventions 2 7 100 107 outgoing arg
@@ -215,7 +221,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,14 +240,21 @@ 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
 
 (* Volatile registers: none *)
 
-let regs_are_volatile rs = false
+let regs_are_volatile _rs = false
 
 (* Registers destroyed by operations *)
 
@@ -259,16 +272,23 @@ let destroyed_at_c_call =
        108;109;110;111;112;113;114;115])
 
 let destroyed_at_oper = function
-    Iop(Icall_ind | Icall_imm _) -> all_phys_regs
-  | Iop(Iextcall(_, alloc, stack_ofs)) ->
+    Iop(Icall_ind _ | Icall_imm _ ->
+      all_phys_regs
+  | Iop(Iextcall {alloc; stack_ofs; }) ->
       assert (stack_ofs >= 0);
       if alloc || stack_ofs > 0 then all_phys_regs
       else destroyed_at_c_call
   | Iop(Iintop(Idiv | Imod)) | Iop(Iintop_imm((Idiv | Imod), _))
         -> [| rax; rdx |]
   | Iop(Istore(Single, _, _)) -> [| rxmm15 |]
+  | Iop(Ialloc _) when Config.spacetime
+        -> [| rax; loc_spacetime_node_hole |]
   | Iop(Ialloc _ | Iintop(Imulh | Icomp _) | Iintop_imm((Icomp _), _))
         -> [| rax |]
+  | Iop (Iintop (Icheckbound _)) when Config.spacetime ->
+      [| loc_spacetime_node_hole |]
+  | Iop (Iintop_imm(Icheckbound _, _)) when Config.spacetime ->
+      [| loc_spacetime_node_hole |]
   | Iswitch(_, _) -> [| rax; rdx |]
   | Iop Iloadmut -> [| rax; rdx |]
   | _ ->
@@ -285,11 +305,11 @@ let destroyed_at_raise = all_phys_regs
 
 
 let safe_register_pressure = function
-    Iextcall(_,_,_) -> if win64 then if fp then 7 else 8 else 0
+    Iextcall _ -> if win64 then if fp then 7 else 8 else 0
   | _ -> if fp then 10 else 11
 
 let max_register_pressure = function
-    Iextcall(_, _,_) ->
+    Iextcall _ ->
       if win64 then
         if fp then [| 7; 10 |]  else [| 8; 10 |]
         else
@@ -306,9 +326,9 @@ let max_register_pressure = function
    registers). *)
 
 let op_is_pure = function
-  | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+  | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _
   | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _ | Iloadmut
-  | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) -> false
+  | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _) -> false
   | Ispecific(Ilea _) -> true
   | Ispecific _ -> false
   | _ -> true
@@ -321,13 +341,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 49070d299f..2e29de4c19 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
 
@@ -22,8 +24,7 @@ open Mach
    Operation                    Res     Arg1    Arg2
      Imove                      R       S
                              or S       R
-     Iconst_int         ]       S if 32-bit signed, R otherwise
-     Iconst_blockheader ]
+     Iconst_int                 S if 32-bit signed, R otherwise
      Iconst_float               R
      Iconst_symbol (not PIC)    S
      Iconst_symbol (PIC)        R
@@ -64,7 +65,7 @@ inherit Reloadgen.reload_generic as super
 
 method! reload_operation op arg res =
   match op with
-  | Iintop(Iadd|Isub|Iand|Ior|Ixor|Icomp _|Icheckbound) ->
+  | Iintop(Iadd|Isub|Iand|Ior|Ixor|Icomp _|Icheckbound _) ->
       (* One of the two arguments can reside in the stack, but not both *)
       if stackp arg.(0) && stackp arg.(1)
       then ([|arg.(0); self#makereg arg.(1)|], res)
@@ -88,12 +89,12 @@ method! reload_operation op arg res =
   | Ifloatofint | Iintoffloat ->
       (* Result must be in register, but argument can be on stack *)
       (arg, (if stackp res.(0) then [| self#makereg res.(0) |] else res))
-  | Iconst_int n | Iconst_blockheader n ->
+  | Iconst_int n ->
       if n <= 0x7FFFFFFFn && n >= -0x80000000n
       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 *)
@@ -101,7 +102,7 @@ method! reload_operation op arg res =
 
 method! reload_test tst arg =
   match tst with
-    Iinttest cmp ->
+    Iinttest _ ->
       (* One of the two arguments can reside on stack *)
       if stackp arg.(0) && stackp arg.(1)
       then [| self#makereg arg.(0); arg.(1) |]
diff --git a/asmcomp/amd64/scheduling.ml b/asmcomp/amd64/scheduling.ml
index e234431bfa..ad146c5063 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 fa7fe66c05..fb50bc150a 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)
@@ -120,25 +123,27 @@ let inline_ops =
 
 class selector = object (self)
 
-inherit Selectgen.selector_generic as super
+inherit Spacetime_profiling.instruction_selection as super
 
-method is_immediate n = n <= 0x7FFFFFFF && n >= -0x80000000
+method is_immediate n = n <= 0x7FFF_FFFF && n >= (-1-0x7FFF_FFFF)
+  (* -1-.... : hack so that this can be compiled on 32-bit
+     (cf 'make check_all_arches') *)
 
 method is_immediate_natint n = n <= 0x7FFFFFFFn && n >= -0x80000000n
 
 method! is_simple_expr e =
   match e with
-  | Cop(Cextcall(fn, _, _, _), args)
+  | Cop(Cextcall (fn, _, _, _, _), args)
     when List.mem fn inline_ops ->
       (* inlined ops are simple if their arguments are *)
       List.for_all self#is_simple_expr args
   | _ ->
       super#is_simple_expr e
 
-method select_addressing chunk exp =
+method select_addressing _chunk exp =
   let (a, d) = select_addr exp in
   (* PR#4625: displacement must be a signed 32-bit immediate *)
-  if d < -0x8000_0000 || d > 0x7FFF_FFFF
+  if not (self # is_immediate d)
   then (Iindexed 0, exp)
   else match a with
     | Asymbol s ->
@@ -156,13 +161,16 @@ method! select_store is_assign addr exp =
   match exp with
     Cconst_int n when self#is_immediate n ->
       (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
-  | (Cconst_natint n | Cconst_blockheader n) when self#is_immediate_natint n ->
+  | (Cconst_natint n) when self#is_immediate_natint n ->
+      (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
+  | (Cblockheader(n, _dbg))
+      when self#is_immediate_natint n && not Config.spacetime ->
       (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
   | Cconst_pointer n when self#is_immediate n ->
       (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,9 +178,9 @@ 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
-        (Iindexed d, _) -> super#select_operation op args
+    Caddi | Caddv | Cadda | Csubi ->
+      begin match self#select_addressing Word_int (Cop(op, args)) with
+        (Iindexed _, _)
       | (Iindexed2 0, _) -> super#select_operation op args
       | (addr, arg) -> (Ispecific(Ilea addr), [arg])
       end
@@ -185,7 +193,7 @@ method! select_operation op args =
       self#select_floatarith true Imulf Ifloatmul args
   | Cdivf ->
       self#select_floatarith false Idivf Ifloatdiv args
-  | Cextcall("sqrt", _, false, _) ->
+  | Cextcall("sqrt", _, false, _, _) ->
      begin match args with
        [Cop(Cload (Double|Double_u as chunk), [loc])] ->
          let (addr, arg) = self#select_addressing chunk loc in
@@ -196,21 +204,21 @@ 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
       end
-  | Cextcall("caml_bswap16_direct", _, _, _) ->
+  | Cextcall("caml_bswap16_direct", _, _, _, _) ->
       (Ispecific (Ibswap 16), args)
-  | Cextcall("caml_int32_direct_bswap", _, _, _) ->
+  | Cextcall("caml_int32_direct_bswap", _, _, _, _) ->
       (Ispecific (Ibswap 32), args)
-  | Cextcall("caml_int64_direct_bswap", _, _, _)
-  | Cextcall("caml_nativeint_direct_bswap", _, _, _) ->
+  | Cextcall("caml_int64_direct_bswap", _, _, _, _)
+  | Cextcall("caml_nativeint_direct_bswap", _, _, _, _) ->
       (Ispecific (Ibswap 64), args)
   (* AMD64 does not support immediate operands for multiply high signed *)
   | Cmulhi ->
diff --git a/asmcomp/arm/CSE.ml b/asmcomp/arm/CSE.ml
index bea333dc42..54c6c093d1 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -16,7 +19,7 @@ open Arch
 open Mach
 open CSEgen
 
-class cse = object (self)
+class cse = object
 
 inherit cse_generic as super
 
@@ -28,7 +31,7 @@ method! class_of_operation op =
 
 method! is_cheap_operation op =
   match op with
-  | Iconst_int n | Iconst_blockheader n -> n <= 255n && n >= 0n
+  | Iconst_int n -> n <= 255n && n >= 0n
   | _ -> false
 
 end
diff --git a/asmcomp/arm/NOTES.md b/asmcomp/arm/NOTES.md
new file mode 100644
index 0000000000..7a8ae671b5
--- /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 d93c1e0e46..1ab0e0b108 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.                                      *)
+(*   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"
@@ -134,6 +137,8 @@ and shift_operation =
   | Ishiftlogicalright
   | Ishiftarithmeticright
 
+let spacetime_node_hole_pointer_is_live_before _specific_op = false
+
 (* Sizes, endianness *)
 
 let big_endian = false
@@ -154,7 +159,7 @@ let identity_addressing = Iindexed 0
 
 let offset_addressing (Iindexed n) delta = Iindexed(n + delta)
 
-let num_args_addressing (Iindexed n) = 1
+let num_args_addressing (Iindexed _) = 1
 
 (* Printing operations and addressing modes *)
 
diff --git a/asmcomp/arm/emit.mlp b/asmcomp/arm/emit.mlp
index 4948fb2b1b..caf28077bc 100644
--- a/asmcomp/arm/emit.mlp
+++ b/asmcomp/arm/emit.mlp
@@ -1,15 +1,19 @@
-(***********************************************************************)
+#2 "asmcomp/arm/emit.mlp"
+(**************************************************************************)
 (*                                                                     *)
 (*                                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.                                      *)
+(*   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 *)
 
@@ -31,21 +35,18 @@ let fastcode_flag = ref true
 let emit_label lbl =
   emit_string ".L"; emit_int lbl
 
-let emit_data_label lbl =
-  emit_string ".Ld"; emit_int lbl
-
 (* Symbols *)
 
 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}`
 
@@ -98,26 +99,33 @@ let emit_addressing addr r n =
 
 (* Record live pointers at call points *)
 
-let record_frame_label live dbg =
-  let lbl = new_label() in
+let record_frame_label ?label live raise_ dbg =
+  let lbl =
+    match label with
+    | None -> new_label()
+    | Some label -> label
+  in
   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;
       fd_frame_size = frame_size();
       fd_live_offset = !live_offset;
+      fd_raise = raise_;
       fd_debuginfo = dbg } :: !frame_descriptors;
   lbl
 
-let record_frame live dbg =
-  let lbl = record_frame_label live dbg in `{emit_label lbl}:`
+let record_frame ?label live raise_ dbg =
+  let lbl = record_frame_label ?label live raise_ dbg in `{emit_label lbl}:`
 
 (* Record calls to the GC -- we've moved them out of the way *)
 
@@ -142,10 +150,10 @@ type bound_error_call =
 
 let bound_error_sites = ref ([] : bound_error_call list)
 
-let bound_error_label dbg =
+let bound_error_label ?label dbg =
   if !Clflags.debug || !bound_error_sites = [] then begin
     let lbl_bound_error = new_label() in
-    let lbl_frame = record_frame_label Reg.Set.empty dbg in
+    let lbl_frame = record_frame_label ?label Reg.Set.empty false dbg in
     bound_error_sites :=
       { bd_lbl = lbl_bound_error;
         bd_frame_lbl = lbl_frame } :: !bound_error_sites;
@@ -283,13 +291,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 +328,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 +346,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
@@ -388,12 +395,11 @@ let emit_instr i =
               `	ldr	{emit_reg dst}, {emit_stack src}\n`
           end; 1
         end
-    | Lop(Iconst_int n | Iconst_blockheader n) ->
+    | Lop(Iconst_int 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 +431,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`
@@ -434,40 +440,40 @@ let emit_instr i =
         end; 1
     | Lop(Iconst_symbol s) ->
         emit_load_symbol_addr i.res.(0) s
-    | Lop(Icall_ind) ->
+    | Lop(Icall_ind { label_after; }) ->
         if !arch >= ARMv5 then begin
           `	blx	{emit_reg i.arg.(0)}\n`;
-          `{record_frame i.live i.dbg}\n`; 1
+          `{record_frame i.live false i.dbg ~label:label_after}\n`; 1
         end else begin
           `	mov	lr, pc\n`;
           `	bx	{emit_reg i.arg.(0)}\n`;
-          `{record_frame i.live i.dbg}\n`; 2
+          `{record_frame i.live false i.dbg ~label:label_after}\n`; 2
         end
-    | Lop(Icall_imm s) ->
-        `	{emit_call s}\n`;
-        `{record_frame i.live i.dbg}\n`; 1
-    | Lop(Itailcall_ind) ->
+    | Lop(Icall_imm { func; label_after; }) ->
+        `	{emit_call func}\n`;
+        `{record_frame i.live false i.dbg ~label:label_after}\n`; 1
+    | Lop(Itailcall_ind { label_after = _; }) ->
         output_epilogue begin fun () ->
           if !contains_calls then
             `	ldr	lr, [sp, #{emit_int (-4)}]\n`;
           `	bx	{emit_reg i.arg.(0)}\n`; 2
         end
-    | Lop(Itailcall_imm s) ->
-        if s = !function_name then begin
+    | Lop(Itailcall_imm { func; label_after = _; }) ->
+        if func = !function_name then begin
           `	b	{emit_label !tailrec_entry_point}\n`; 1
         end else begin
           output_epilogue begin fun () ->
             if !contains_calls then
               `	ldr	lr, [sp, #{emit_int (-4)}]\n`;
-            `	{emit_jump s}\n`; 2
+            `	{emit_jump func}\n`; 2
           end
         end
-    | Lop(Iextcall(s, false)) ->
-        `	{emit_call s}\n`; 1
-    | Lop(Iextcall(s, true)) ->
-        let ninstr = emit_load_symbol_addr (phys_reg 7 (* r7 *)) s in
+    | Lop(Iextcall { func; alloc = false; }) ->
+        `	{emit_call func}\n`; 1
+    | Lop(Iextcall { func; alloc = true; label_after; }) ->
+        let ninstr = emit_load_symbol_addr (phys_reg 7 (* r7 *)) func in
         `	{emit_call "caml_c_call"}\n`;
-        `{record_frame i.live i.dbg}\n`;
+        `{record_frame i.live false i.dbg ~label:label_after}\n`;
         1 + ninstr
     | Lop(Istackoffset n) ->
         assert (n mod 8 = 0);
@@ -537,8 +543,10 @@ let emit_instr i =
           | Double_u -> "fstd"
           | _ (* 32-bit quantities *) -> "str" in
         `	{emit_string instr}	{emit_reg r}, {emit_addressing addr i.arg 1}\n`; 1
-    | Lop(Ialloc n) ->
-        let lbl_frame = record_frame_label i.live i.dbg in
+    | Lop(Ialloc { words = n; label_after_call_gc; }) ->
+        let lbl_frame =
+          record_frame_label i.live false i.dbg ?label:label_after_call_gc
+        in
         if !fastcode_flag then begin
           let lbl_redo = new_label() in
           `{emit_label lbl_redo}:`;
@@ -581,12 +589,12 @@ let emit_instr i =
         `	ite	{emit_string compthen}\n`;
         `	mov{emit_string	compthen}	{emit_reg i.res.(0)}, #1\n`;
         `	mov{emit_string compelse}	{emit_reg i.res.(0)}, #0\n`; 4
-    | Lop(Iintop Icheckbound) ->
-        let lbl = bound_error_label i.dbg in
+    | Lop(Iintop (Icheckbound { label_after_error; } )) ->
+        let lbl = bound_error_label ?label:label_after_error i.dbg in
         `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
         `	bls	{emit_label lbl}\n`; 2
-    | Lop(Iintop_imm(Icheckbound, n)) ->
-        let lbl = bound_error_label i.dbg in
+    | Lop(Iintop_imm(Icheckbound { label_after_error; }, n)) ->
+        let lbl = bound_error_label ?label:label_after_error i.dbg in
         `	cmp	{emit_reg i.arg.(0)}, #{emit_int n}\n`;
         `	bls	{emit_label lbl}\n`; 2
     | Lop(Ispecific(Ishiftcheckbound(shiftop, n))) ->
@@ -651,7 +659,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 +764,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
@@ -782,12 +791,11 @@ let emit_instr i =
         cfi_adjust_cfa_offset (-8);
         stack_offset := !stack_offset - 8; 1
     | Lraise k ->
-        begin match !Clflags.debug, k with
-        | true, (Lambda.Raise_regular | Lambda.Raise_reraise) ->
+        begin match k with
+        | Cmm.Raise_withtrace ->
           `	{emit_call "caml_raise_exn"}\n`;
-          `{record_frame Reg.Set.empty i.dbg}\n`; 1
-        | false, _
-        | true, Lambda.Raise_notrace ->
+          `{record_frame Reg.Set.empty true i.dbg}\n`; 1
+        | Cmm.Raise_notrace ->
           `	mov	sp, trap_ptr\n`;
           `	pop	\{trap_ptr, pc}\n`; 2
         end
@@ -820,7 +828,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`
   | _ -> ()
@@ -871,7 +879,6 @@ let fundecl fundecl =
 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 -> `	.short	{emit_int n}\n`
   | Cint32 n -> `	.long	{emit_int32 (Nativeint.to_int32 n)}\n`
@@ -879,7 +886,6 @@ let emit_item = function
   | 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 -> `	.word	{emit_symbol s}\n`
-  | Clabel_address lbl -> `	.word	{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 -> `	.align	{emit_int(Misc.log2 n)}\n`
@@ -892,6 +898,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`
@@ -933,9 +940,12 @@ let end_assembly () =
   `	.globl	{emit_symbol lbl}\n`;
   `{emit_symbol lbl}:\n`;
   emit_frames
-    { efa_label = (fun lbl ->
+    { efa_code_label = (fun lbl ->
                        `	.type	{emit_label lbl}, %function\n`;
                        `	.word	{emit_label lbl}\n`);
+      efa_data_label = (fun lbl ->
+                       `	.type	{emit_label lbl}, %object\n`;
+                       `	.word	{emit_label lbl}\n`);
       efa_16 = (fun n -> `	.short	{emit_int n}\n`);
       efa_32 = (fun n -> `	.long	{emit_int32 n}\n`);
       efa_word = (fun n -> `	.word	{emit_int n}\n`);
@@ -947,7 +957,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 58bfa427b3..4e63f1308d 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.                                      *)
+(*   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,7 +66,7 @@ let num_register_classes = 3
 
 let register_class r =
   match (r.typ, !fpu) with
-    (Int | Addr), _  -> 0
+  | (Val | Int | Addr), _  -> 0
   | Float, VFPv2     -> 1
   | Float, VFPv3_D16 -> 1
   | Float, _         -> 2
@@ -104,41 +107,77 @@ let phys_reg n =
 let stack_slot slot ty =
   Reg.at_location ty (Stack slot)
 
+let loc_spacetime_node_hole = Reg.dummy  (* Spacetime unsupported *)
+
 (* 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 ->
+    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;
+            loc.(i) <- [| phys_reg !int |];
           incr int
         end else begin
-          loc.(i) <- stack_slot (make_stack !ofs) ty;
+            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;
+            loc.(i) <- [| phys_reg !float |];
           incr float
         end else begin
           ofs := Misc.align !ofs size_float;
-          loc.(i) <- stack_slot (make_stack !ofs) 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 *)
 
 let incoming ofs = Incoming ofs
 let outgoing ofs = Outgoing ofs
-let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
+let not_supported _ofs = fatal_error "Proc.loc_results: cannot call"
 
 (* OCaml calling convention:
      first integer args in r0...r7
@@ -146,12 +185,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,13 +217,16 @@ 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
 
 (* Volatile registers: none *)
 
-let regs_are_volatile rs = false
+let regs_are_volatile _rs = false
 
 (* Registers destroyed by operations *)
 
@@ -196,14 +254,14 @@ let destroyed_at_c_call =
                          124;125;126;127;128;129;130;131]))
 
 let destroyed_at_oper = function
-    Iop(Icall_ind | Icall_imm _)
-  | Iop(Iextcall(_, true)) ->
+    Iop(Icall_ind _ | Icall_imm _)
+  | Iop(Iextcall { alloc = true; _ }) ->
       all_phys_regs
-  | Iop(Iextcall(_, false)) ->
+  | Iop(Iextcall { alloc = false; _}) ->
       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 *)
@@ -216,16 +274,16 @@ let destroyed_at_raise = all_phys_regs
 (* Maximal register pressure *)
 
 let safe_register_pressure = function
-    Iextcall(_, _) -> if abi = EABI then 0 else 4
+    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 |]
+    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 |]
@@ -235,9 +293,9 @@ let max_register_pressure = function
    registers). *)
 
 let op_is_pure = function
-  | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+  | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _
   | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
-  | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _)
+  | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _)
   | Ispecific(Ishiftcheckbound _) -> false
   | _ -> true
 
diff --git a/asmcomp/arm/reload.ml b/asmcomp/arm/reload.ml
index bd783acb82..f6d9b881db 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 0d6618ab9e..4039eaac8b 100644
--- a/asmcomp/arm/scheduling.ml
+++ b/asmcomp/arm/scheduling.ml
@@ -1,22 +1,25 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                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
 
 (* Instruction scheduling for the ARM *)
 
-class scheduler = object(self)
+class scheduler = object
 
 inherit Schedgen.scheduler_generic as super
 
@@ -55,8 +58,8 @@ method oper_issue_cycles = function
   | Iintop(Ilsl | Ilsr | Iasr) -> 2
   | Iintop(Icomp _)
   | Iintop_imm(Icomp _, _) -> 3
-  | Iintop(Icheckbound)
-  | Iintop_imm(Icheckbound, _) -> 2
+  | Iintop(Icheckbound _)
+  | Iintop_imm(Icheckbound _, _) -> 2
   | Ispecific(Ishiftcheckbound _) -> 3
   | Iintop(Imul | Imulh)
   | Ispecific(Imuladd | Imulsub | Imulhadd) -> 2
diff --git a/asmcomp/arm/selection.ml b/asmcomp/arm/selection.ml
index 4725942b72..ee64c9bf39 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.                                      *)
+(*   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 *)
@@ -76,7 +79,7 @@ let pseudoregs_for_operation op arg res =
       (arg', res)
   (* We use __aeabi_idivmod for Cmodi only, and hence we care only
      for the remainder in r1, so fix up the destination register. *)
-  | Iextcall("__aeabi_idivmod", false) ->
+  | Iextcall { func = "__aeabi_idivmod"; alloc = false; } ->
       (arg, [|r1|])
   (* Other instructions are regular *)
   | _ -> raise Use_default
@@ -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
@@ -103,22 +108,24 @@ method is_immediate n =
 
 method! is_simple_expr = function
   (* inlined floating-point ops are simple if their arguments are *)
-  | Cop(Cextcall("sqrt", _, _, _), args) when !fpu >= VFPv2 ->
+  | Cop(Cextcall("sqrt", _, _, _, _), args) when !fpu >= VFPv2 ->
       List.for_all self#is_simple_expr args
   (* inlined byte-swap ops are simple if their arguments are *)
-  | Cop(Cextcall("caml_bswap16_direct", _, _, _), args) when !arch >= ARMv6T2 ->
+  | Cop(Cextcall("caml_bswap16_direct", _, _, _, _), args)
+    when !arch >= ARMv6T2 ->
       List.for_all self#is_simple_expr args
-  | Cop(Cextcall("caml_int32_direct_bswap", _,_,_), args) when !arch >= ARMv6 ->
+  | Cop(Cextcall("caml_int32_direct_bswap", _,_,_,_), args)
+    when !arch >= ARMv6 ->
       List.for_all self#is_simple_expr args
   | e -> super#is_simple_expr e
 
 method 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)
 
@@ -160,21 +167,24 @@ method select_shift_arith op arithop arithrevop args =
       | op_args -> op_args
       end
 
+method private iextcall (func, alloc) =
+  Iextcall { func; alloc; label_after = Cmm.new_label (); }
+
 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
@@ -192,15 +202,16 @@ method! select_operation op args =
       (Iintop Imulh, args)
   (* Turn integer division/modulus into runtime ABI calls *)
   | (Cdivi, args) ->
-      (Iextcall("__aeabi_idiv", false), args)
+      (self#iextcall("__aeabi_idiv", false), args)
   | (Cmodi, args) ->
       (* See above for fix up of return register *)
-      (Iextcall("__aeabi_idivmod", false), args)
+      (self#iextcall("__aeabi_idivmod", false), args)
   (* Recognize 16-bit bswap instruction (ARMv6T2 because we need movt) *)
-  | (Cextcall("caml_bswap16_direct", _, _, _), args) when !arch >= ARMv6T2 ->
+  | (Cextcall("caml_bswap16_direct", _, _, _, _), args) when !arch >= ARMv6T2 ->
       (Ispecific(Ibswap 16), args)
   (* Recognize 32-bit bswap instructions (ARMv6 and above) *)
-  | (Cextcall("caml_int32_direct_bswap", _, _, _), args) when !arch >= ARMv6 ->
+  | (Cextcall("caml_int32_direct_bswap", _, _, _, _), args)
+    when !arch >= ARMv6 ->
       (Ispecific(Ibswap 32), args)
   (* Turn floating-point operations into runtime ABI calls for softfp *)
   | (op, args) when !fpu = Soft -> self#select_operation_softfp op args
@@ -210,12 +221,12 @@ method! select_operation op args =
 method private select_operation_softfp op args =
   match (op, args) with
   (* Turn floating-point operations into runtime ABI calls *)
-  | (Caddf, args) -> (Iextcall("__aeabi_dadd", false), args)
-  | (Csubf, args) -> (Iextcall("__aeabi_dsub", false), args)
-  | (Cmulf, args) -> (Iextcall("__aeabi_dmul", false), args)
-  | (Cdivf, args) -> (Iextcall("__aeabi_ddiv", false), args)
-  | (Cfloatofint, args) -> (Iextcall("__aeabi_i2d", false), args)
-  | (Cintoffloat, args) -> (Iextcall("__aeabi_d2iz", false), args)
+  | (Caddf, args) -> (self#iextcall("__aeabi_dadd", false), args)
+  | (Csubf, args) -> (self#iextcall("__aeabi_dsub", false), args)
+  | (Cmulf, args) -> (self#iextcall("__aeabi_dmul", false), args)
+  | (Cdivf, args) -> (self#iextcall("__aeabi_ddiv", false), args)
+  | (Cfloatofint, args) -> (self#iextcall("__aeabi_i2d", false), args)
+  | (Cintoffloat, args) -> (self#iextcall("__aeabi_d2iz", false), args)
   | (Ccmpf comp, args) ->
       let func = (match comp with
                     Cne    (* there's no __aeabi_dcmpne *)
@@ -228,15 +239,15 @@ method private select_operation_softfp op args =
                     Cne -> Ceq (* eq 0 => false *)
                   | _   -> Cne (* ne 0 => true *)) in
       (Iintop_imm(Icomp(Iunsigned comp), 0),
-       [Cop(Cextcall(func, typ_int, false, Debuginfo.none), args)])
+       [Cop(Cextcall(func, typ_int, false, Debuginfo.none, 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]) ->
+      (self#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),
+        Cop(Cextcall("__aeabi_d2f", typ_int, false, Debuginfo.none, 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
 
@@ -260,7 +271,7 @@ method private select_operation_vfpv3 op args =
   | (Csubf, [Cop(Cmulf, args); arg]) ->
       (Ispecific Imulsubf, arg :: args)
   (* Recognize floating-point square root *)
-  | (Cextcall("sqrt", _, false, _), args) ->
+  | (Cextcall("sqrt", _, false, _, _), args) ->
       (Ispecific Isqrtf, args)
   (* Other operations are regular *)
   | (op, args) -> super#select_operation op args
diff --git a/asmcomp/arm64/CSE.ml b/asmcomp/arm64/CSE.ml
index f9e03e487e..b85eb16464 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -16,7 +19,7 @@ open Arch
 open Mach
 open CSEgen
 
-class cse = object (self)
+class cse = object
 
 inherit cse_generic as super
 
@@ -28,7 +31,7 @@ method! class_of_operation op =
 
 method! is_cheap_operation op =
   match op with
-  | Iconst_int n | Iconst_blockheader n -> n <= 65535n && n >= 0n
+  | Iconst_int n -> n <= 65535n && n >= 0n
   | _ -> false
 
 end
diff --git a/asmcomp/arm64/NOTES.md b/asmcomp/arm64/NOTES.md
new file mode 100644
index 0000000000..e2134eb18e
--- /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 3e62da89ff..2da57a466c 100644
--- a/asmcomp/arm64/arch.ml
+++ b/asmcomp/arm64/arch.ml
@@ -1,18 +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.                                      *)
+(*   Copyright 2013 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
 (*                                                                     *)
-(***********************************************************************)
-
-let command_line_options = []
+(*   All rights reserved.  This file is distributed 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, 64-bit mode *)
 
@@ -33,13 +34,18 @@ type addressing_mode =
 
 (* Specific operations *)
 
+type cmm_label = int
+  (* Do not introduce a dependency to Cmm *)
+
 type specific_operation =
-  | Ifar_alloc of int
-  | Ifar_intop_checkbound
-  | Ifar_intop_imm_checkbound of int
+  | Ifar_alloc of { words : int; label_after_call_gc : cmm_label option; }
+  | Ifar_intop_checkbound of { label_after_error : cmm_label option; }
+  | Ifar_intop_imm_checkbound of
+      { bound : int; label_after_error : cmm_label option; }
   | Ishiftarith of arith_operation * int
-  | Ishiftcheckbound of int
-  | Ifar_shiftcheckbound of int
+  | Ishiftcheckbound of { shift : int; label_after_error : cmm_label option; }
+  | Ifar_shiftcheckbound of
+      { shift : int; label_after_error : cmm_label option; }
   | Imuladd       (* multiply and add *)
   | Imulsub       (* multiply and subtract *)
   | Inegmulf      (* floating-point negate and multiply *)
@@ -54,6 +60,12 @@ and arith_operation =
     Ishiftadd
   | Ishiftsub
 
+let spacetime_node_hole_pointer_is_live_before = function
+  | Ifar_alloc _ | Ifar_intop_checkbound _ | Ifar_intop_imm_checkbound _
+  | Ishiftarith _ | Ishiftcheckbound _ | Ifar_shiftcheckbound _ -> false
+  | Imuladd | Imulsub | Inegmulf | Imuladdf | Inegmuladdf | Imulsubf
+  | Inegmulsubf | Isqrtf | Ibswap _ -> false
+
 (* Sizes, endianness *)
 
 let big_endian = false
@@ -78,8 +90,8 @@ let offset_addressing addr delta =
   | Ibased(s, n) -> Ibased(s, n + delta)
 
 let num_args_addressing = function
-  | Iindexed n -> 1
-  | Ibased(s, n) -> 0
+  | Iindexed _ -> 1
+  | Ibased _ -> 0
 
 (* Printing operations and addressing modes *)
 
@@ -95,12 +107,12 @@ let print_addressing printreg addr ppf arg =
 
 let print_specific_operation printreg op ppf arg =
   match op with
-  | Ifar_alloc n ->
-    fprintf ppf "(far) alloc %i" n
-  | Ifar_intop_checkbound ->
+  | Ifar_alloc { words; label_after_call_gc = _; } ->
+    fprintf ppf "(far) alloc %i" words
+  | Ifar_intop_checkbound _ ->
     fprintf ppf "%a (far) check > %a" printreg arg.(0) printreg arg.(1)
-  | Ifar_intop_imm_checkbound n ->
-    fprintf ppf "%a (far) check > %i" printreg arg.(0) n
+  | Ifar_intop_imm_checkbound { bound; _ } ->
+    fprintf ppf "%a (far) check > %i" printreg arg.(0) bound
   | Ishiftarith(op, shift) ->
       let op_name = function
       | Ishiftadd -> "+"
@@ -111,11 +123,12 @@ let print_specific_operation printreg op ppf arg =
        else sprintf ">> %i" (-shift) in
       fprintf ppf "%a %s %a %s"
        printreg arg.(0) (op_name op) printreg arg.(1) shift_mark
-  | Ishiftcheckbound n ->
-      fprintf ppf "check %a >> %i > %a" printreg arg.(0) n printreg arg.(1)
-  | Ifar_shiftcheckbound n ->
+  | Ishiftcheckbound { shift; _ } ->
+      fprintf ppf "check %a >> %i > %a" printreg arg.(0) shift
+        printreg arg.(1)
+  | Ifar_shiftcheckbound { shift; _ } ->
       fprintf ppf
-        "(far) check %a >> %i > %a" printreg arg.(0) n printreg arg.(1)
+        "(far) check %a >> %i > %a" printreg arg.(0) shift printreg arg.(1)
   | Imuladd ->
       fprintf ppf "(%a * %a) + %a"
         printreg arg.(0)
diff --git a/asmcomp/arm64/emit.mlp b/asmcomp/arm64/emit.mlp
index eafc8af2a2..9de1d6afe5 100644
--- a/asmcomp/arm64/emit.mlp
+++ b/asmcomp/arm64/emit.mlp
@@ -1,16 +1,20 @@
-(***********************************************************************)
+#2 "asmcomp/arm64/emit.mlp"
+(**************************************************************************)
 (*                                                                     *)
 (*                                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.                                      *)
+(*   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 *)
 
@@ -40,15 +44,11 @@ let reg_x20 = phys_reg 17           (* x20 *)
 let reg_x0 = phys_reg 0             (* x19 *)
 let reg_x1 = phys_reg 1             (* x20 *)
 
-
 (* Output a label *)
 
 let emit_label lbl =
   emit_string ".L"; emit_int lbl
 
-let emit_data_label lbl =
-  emit_string ".Ld"; emit_int lbl
-
 (* Symbols *)
 
 let emit_symbol s =
@@ -125,26 +125,33 @@ let emit_addressing addr r =
 
 (* Record live pointers at call points *)
 
-let record_frame_label live dbg =
-  let lbl = new_label() in
+let record_frame_label ?label live raise_ dbg =
+  let lbl =
+    match label with
+    | None -> new_label()
+    | Some label -> label
+  in
   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;
       fd_frame_size = frame_size();
       fd_live_offset = !live_offset;
+      fd_raise = raise_;
       fd_debuginfo = dbg } :: !frame_descriptors;
   lbl
 
-let record_frame live dbg =
-  let lbl = record_frame_label live dbg in `{emit_label lbl}:`
+let record_frame ?label live raise_ dbg =
+  let lbl = record_frame_label ?label live raise_ dbg in `{emit_label lbl}:`
 
 (* Record calls to the GC -- we've moved them out of the way *)
 
@@ -171,10 +178,10 @@ type bound_error_call =
 
 let bound_error_sites = ref ([] : bound_error_call list)
 
-let bound_error_label dbg =
+let bound_error_label ?label dbg =
   if !Clflags.debug || !bound_error_sites = [] then begin
     let lbl_bound_error = new_label() in
-    let lbl_frame = record_frame_label Reg.Set.empty dbg in
+    let lbl_frame = record_frame_label ?label Reg.Set.empty false dbg in
     bound_error_sites :=
       { bd_lbl = lbl_bound_error;
         bd_frame_lbl = lbl_frame } :: !bound_error_sites;
@@ -368,8 +375,8 @@ let num_call_gc_and_check_bound_points instr =
     | Lend -> totals
     | Lop (Ialloc _) when !fastcode_flag ->
       loop instr.next (call_gc + 1, check_bound)
-    | Lop (Iintop Icheckbound)
-    | Lop (Iintop_imm (Icheckbound, _))
+    | Lop (Iintop Icheckbound _)
+    | Lop (Iintop_imm (Icheckbound _, _))
     | Lop (Ispecific (Ishiftcheckbound _)) ->
       let check_bound =
         (* When not in debug mode, there is at most one check-bound point. *)
@@ -380,14 +387,14 @@ let num_call_gc_and_check_bound_points instr =
     (* The following four should never be seen, since this function is run
        before branch relaxation. *)
     | Lop (Ispecific (Ifar_alloc _))
-    | Lop (Ispecific Ifar_intop_checkbound)
+    | Lop (Ispecific Ifar_intop_checkbound _)
     | Lop (Ispecific (Ifar_intop_imm_checkbound _))
     | Lop (Ispecific (Ifar_shiftcheckbound _)) -> assert false
     | _ -> loop instr.next totals
   in
   loop instr (0, 0)
 
-let max_out_of_line_code_offset instr ~num_call_gc ~num_check_bound =
+let max_out_of_line_code_offset ~num_call_gc ~num_check_bound =
   if num_call_gc < 1 && num_check_bound < 1 then 0
   else begin
     let size_of_call_gc = 2 in
@@ -426,8 +433,8 @@ module BR = Branch_relaxation.Make (struct
 
     let classify_instr = function
       | Lop (Ialloc _)
-      | Lop (Iintop Icheckbound)
-      | Lop (Iintop_imm (Icheckbound, _))
+      | Lop (Iintop Icheckbound _)
+      | Lop (Iintop_imm (Icheckbound _, _))
       | Lop (Ispecific (Ishiftcheckbound _)) -> Some Bcc
       (* The various "far" variants in [specific_operation] don't need to
          return [Some] here, since their code sequences never contain any
@@ -451,16 +458,16 @@ module BR = Branch_relaxation.Make (struct
   let instr_size = function
     | Lend -> 0
     | Lop (Imove | Ispill | Ireload) -> 1
-    | Lop (Iconst_int n | Iconst_blockheader n) ->
+    | Lop (Iconst_int n) ->
       num_instructions_for_intconst n
     | Lop (Iconst_float _) -> 2
     | Lop (Iconst_symbol _) -> 2
-    | Lop (Icall_ind) -> 1
+    | Lop (Icall_ind _) -> 1
     | Lop (Icall_imm _) -> 1
-    | Lop (Itailcall_ind) -> epilogue_size ()
-    | Lop (Itailcall_imm s) ->
-      if s = !function_name then 1 else epilogue_size ()
-    | Lop (Iextcall (_, alloc, stack_off)) ->
+    | Lop (Itailcall_ind _) -> epilogue_size ()
+    | Lop (Itailcall_imm { func; _ }) ->
+      if func = !function_name then 1 else epilogue_size ()
+    | Lop (Iextcall { alloc ; stack_off; }) -> 1
       if stack_off > 0 then 5
       else if alloc then 3
       else 8
@@ -471,16 +478,17 @@ module BR = Branch_relaxation.Make (struct
     | Lop Iloadmut -> 6
     | Lop (Ialloc _) when !fastcode_flag -> 4
     | Lop (Ispecific (Ifar_alloc _)) when !fastcode_flag -> 5
-    | Lop (Ialloc num_words) | Lop (Ispecific (Ifar_alloc num_words)) ->
+    | Lop (Ialloc { words = num_words; _ })
+    | Lop (Ispecific (Ifar_alloc { words = num_words; _ })) ->
       begin match num_words with
       | 16 | 24 | 32 -> 1
       | _ -> 1 + num_instructions_for_intconst (Nativeint.of_int num_words)
       end
     | Lop (Iintop (Icomp _)) -> 2
     | Lop (Iintop_imm (Icomp _, _)) -> 2
-    | Lop (Iintop Icheckbound) -> 2
-    | Lop (Ispecific Ifar_intop_checkbound) -> 3
-    | Lop (Iintop_imm (Icheckbound, _)) -> 2
+    | Lop (Iintop (Icheckbound _)) -> 2
+    | Lop (Ispecific (Ifar_intop_checkbound _)) -> 3
+    | Lop (Iintop_imm (Icheckbound _, _)) -> 2
     | Lop (Ispecific (Ifar_intop_imm_checkbound _)) -> 3
     | Lop (Ispecific (Ishiftcheckbound _)) -> 2
     | Lop (Ispecific (Ifar_shiftcheckbound _)) -> 3
@@ -518,30 +526,32 @@ module BR = Branch_relaxation.Make (struct
     | Lpushtrap -> 3
     | Lpoptrap -> 1
     | Lraise k ->
-      begin match !Clflags.debug, k with
-      | true, (Lambda.Raise_regular | Lambda.Raise_reraise) -> 1
-      | false, _
-      | true, Lambda.Raise_notrace -> 4
+      begin match k with
+      | Cmm.Raise_withtrace -> 1
+      | Cmm.Raise_notrace -> 5
       end
 
-  let relax_allocation ~num_words =
-    Lop (Ispecific (Ifar_alloc num_words))
+  let relax_allocation ~num_words ~label_after_call_gc =
+    Lop (Ispecific (Ifar_alloc { words = num_words; label_after_call_gc; }))
 
-  let relax_intop_checkbound () =
-    Lop (Ispecific Ifar_intop_checkbound)
+  let relax_intop_checkbound ~label_after_error =
+    Lop (Ispecific (Ifar_intop_checkbound { label_after_error; }))
 
-  let relax_intop_imm_checkbound ~bound =
-    Lop (Ispecific (Ifar_intop_imm_checkbound bound))
+  let relax_intop_imm_checkbound ~bound ~label_after_error =
+    Lop (Ispecific (Ifar_intop_imm_checkbound { bound; label_after_error; }))
 
   let relax_specific_op = function
-    | Ishiftcheckbound shift -> Lop (Ispecific (Ifar_shiftcheckbound shift))
+    | Ishiftcheckbound { shift; label_after_error; } ->
+      Lop (Ispecific (Ifar_shiftcheckbound { shift; label_after_error; }))
     | _ -> assert false
 end)
 
 (* Output the assembly code for allocation. *)
 
-let assembly_code_for_allocation i ~n ~far =
-  let lbl_frame = record_frame_label i.live i.dbg in
+let assembly_code_for_allocation ?label_after_call_gc i ~n ~far =
+  let lbl_frame =
+    record_frame_label ?label:label_after_call_gc i.live false i.dbg
+  in
   if !fastcode_flag then begin
     let lbl_redo = new_label() in
     let lbl_call_gc = new_label() in
@@ -558,8 +568,7 @@ let assembly_code_for_allocation i ~n ~far =
       `{emit_label lbl}:\n`
     end;
     call_gc_sites :=
-      { gc_size = n;
-        gc_lbl = lbl_call_gc;
+      { gc_lbl = lbl_call_gc;
         gc_return_lbl = lbl_redo;
         gc_frame_lbl = lbl_frame } :: !call_gc_sites
   end else begin
@@ -601,45 +610,44 @@ let emit_instr i =
           | _ ->
               assert false
         end
-    | Lop(Iconst_int n | Iconst_blockheader n) ->
+    | Lop(Iconst_int 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
     | Lop(Iconst_symbol s) ->
         emit_load_symbol_addr i.res.(0) s
-    | Lop(Icall_ind) ->
+    | Lop(Icall_ind { label_after; }) ->
         `	blr	{emit_reg i.arg.(0)}\n`;
-        `{record_frame i.live i.dbg}\n`
-    | Lop(Icall_imm s) ->
-        `	bl	{emit_symbol s}\n`;
-        `{record_frame i.live i.dbg}\n`
-    | Lop(Itailcall_ind) ->
+        `{record_frame i.live false i.dbg ~label:label_after}\n`
+    | Lop(Icall_imm { func; label_after; }) ->
+        `	bl	{emit_symbol func}\n`;
+        `{record_frame i.live false i.dbg ~label:label_after}\n`
+    | Lop(Itailcall_ind { label_after = _; }) ->
         output_epilogue (fun () -> `	br	{emit_reg i.arg.(0)}\n`)
-    | Lop(Itailcall_imm s) ->
-        if s = !function_name then
+    | Lop(Itailcall_imm { func; label_after = _; }) ->
+        if func = !function_name then
           `	b	{emit_label !tailrec_entry_point}\n`
         else
           output_epilogue (fun () -> `	b	{emit_symbol s}\n`)
-    | Lop(Iextcall(s, alloc, stack_off)) ->
+    | Lop(Iextcall {func; alloc; stack_off; label_after}) ->
         if stack_off > 0 then begin
           `	mov {emit_reg reg_x19}, sp\n`;
           `	add {emit_reg reg_x20}, sp, #{emit_int (Misc.align stack_off 16)}\n`;
           emit_load_symbol_addr reg_x15 s;
           `	bl	{emit_symbol "caml_c_call_stack_args"}\n`;
-          `{record_frame i.live i.dbg}\n`;
+          `{record_frame i.live false i.dbg ~label:label_after}\n`;
         end else if alloc then begin
           emit_load_symbol_addr reg_x15 s;
           `	bl	{emit_symbol "caml_c_call"}\n`;
-          `{record_frame i.live i.dbg}\n`;
+          `{record_frame i.live false i.dbg ~label:label_after}\n`;
         end else begin
           `	mov {emit_reg reg_tmp1}, sp\n`;
           `{load_domain_field Domainstate.Domain_system_sp reg_tmp2}\n`;
@@ -659,7 +667,7 @@ let emit_instr i =
         let dst = i.res.(0) in
         let base =
           match addr with
-          | Iindexed ofs -> i.arg.(0)
+          | Iindexed _ -> i.arg.(0)
           | Ibased(s, ofs) ->
               `	adrp	{emit_reg reg_tmp1}, {emit_symbol_offset s ofs}\n`;
               reg_tmp1
@@ -680,7 +688,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 Iloadmut ->
@@ -708,7 +716,7 @@ let emit_instr i =
         let src = i.arg.(0) in
         let base =
           match addr with
-          | Iindexed ofs -> i.arg.(1)
+          | Iindexed _ -> i.arg.(1)
           | Ibased(s, ofs) ->
               `	adrp	{emit_reg reg_tmp1}, {emit_symbol_offset s ofs}\n`;
               reg_tmp1 in
@@ -722,47 +730,48 @@ 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) ->
-        assembly_code_for_allocation i ~n ~far:false
-    | Lop(Ispecific (Ifar_alloc n)) ->
-        assembly_code_for_allocation i ~n ~far:true
+    | Lop(Ialloc { words = n; label_after_call_gc; }) ->
+        assembly_code_for_allocation i ~n ~far:false ?label_after_call_gc
+    | Lop(Ispecific (Ifar_alloc { words = n; label_after_call_gc; })) ->
+        assembly_code_for_allocation i ~n ~far:true ?label_after_call_gc
     | Lop(Iintop(Icomp cmp)) ->
         `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
         `	cset	{emit_reg i.res.(0)}, {emit_string (name_for_comparison cmp)}\n`
     | Lop(Iintop_imm(Icomp cmp, n)) ->
         `	cmp	{emit_reg i.arg.(0)}, #{emit_int n}\n`;
         `	cset	{emit_reg i.res.(0)}, {emit_string (name_for_comparison cmp)}\n`
-    | Lop(Iintop Icheckbound) ->
-        let lbl = bound_error_label i.dbg in
+    | Lop(Iintop (Icheckbound { label_after_error; })) ->
+        let lbl = bound_error_label i.dbg ?label:label_after_error in
         `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
         `	b.ls	{emit_label lbl}\n`
-    | Lop(Ispecific Ifar_intop_checkbound) ->
-        let lbl = bound_error_label i.dbg in
+    | Lop(Ispecific Ifar_intop_checkbound { label_after_error; }) ->
+        let lbl = bound_error_label i.dbg ?label:label_after_error in
         let lbl2 = new_label () in
         `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
         `	b.hi	{emit_label lbl2}\n`;
         `	b	{emit_label lbl}\n`;
         `{emit_label lbl2}:\n`;
-    | Lop(Iintop_imm(Icheckbound, n)) ->
-        let lbl = bound_error_label i.dbg in
+    | Lop(Iintop_imm(Icheckbound { label_after_error; }, n)) ->
+        let lbl = bound_error_label i.dbg ?label:label_after_error in
         `	cmp	{emit_reg i.arg.(0)}, #{emit_int n}\n`;
         `	b.ls	{emit_label lbl}\n`
-    | Lop(Ispecific(Ifar_intop_imm_checkbound bound)) ->
-        let lbl = bound_error_label i.dbg in
+    | Lop(Ispecific(
+          Ifar_intop_imm_checkbound { bound; label_after_error; })) ->
+        let lbl = bound_error_label i.dbg ?label:label_after_error in
         let lbl2 = new_label () in
         `	cmp	{emit_reg i.arg.(0)}, #{emit_int bound}\n`;
         `	b.hi	{emit_label lbl2}\n`;
         `	b	{emit_label lbl}\n`;
         `{emit_label lbl2}:\n`;
-    | Lop(Ispecific(Ishiftcheckbound shift)) ->
-        let lbl = bound_error_label i.dbg in
+    | Lop(Ispecific(Ishiftcheckbound { shift; label_after_error; })) ->
+        let lbl = bound_error_label i.dbg ?label:label_after_error in
         `	cmp	{emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}, lsr #{emit_int shift}\n`;
         `	b.cs	{emit_label lbl}\n`
-    | Lop(Ispecific(Ifar_shiftcheckbound shift)) ->
-        let lbl = bound_error_label i.dbg in
+    | Lop(Ispecific(Ifar_shiftcheckbound { shift; label_after_error; })) ->
+        let lbl = bound_error_label i.dbg ?label:label_after_error in
         let lbl2 = new_label () in
         `	cmp	{emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}, lsr #{emit_int shift}\n`;
         `	b.lo	{emit_label lbl2}\n`;
@@ -924,12 +933,11 @@ let emit_instr i =
         cfi_adjust_cfa_offset (-16);
         stack_offset := !stack_offset - 16
     | Lraise k ->
-        begin match !Clflags.debug, k with
-        | true, (Lambda.Raise_regular | Lambda.Raise_reraise) ->
-          `	bl	{emit_symbol "caml_raise_exn"}\n`;
-          `{record_frame Reg.Set.empty i.dbg}\n`
-        | false, _
-        | true, Lambda.Raise_notrace ->
+        begin match k with
+        | Cmm.Raise_withtrace ->
+            `	bl	{emit_symbol "caml_raise_exn"}\n`;
+            `{record_frame Reg.Set.empty true i.dbg}\n`
+        | Cmm.Raise_notrace ->
             `{load_domain_field Domainstate.Domain_stack_high reg_tmp1}\n`;
             `	sub sp, {emit_reg reg_tmp1}, {emit_reg reg_trap_off}\n`;
             `	ldr	{emit_reg reg_tmp1}, [sp, #8]\n`;
@@ -947,7 +955,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`
   | _ -> ()
@@ -997,9 +1005,6 @@ let fundecl fundecl =
   read_barrier_call_sites := [];
   `	.text\n`;
   `	.align	3\n`;
-  Emitaux.emit_block_header_for_closure ~word_directive:".quad"
-    ~comment_string:"//"
-    ~function_entry_points_are_doubleword_aligned:false;
   `	.globl	{emit_symbol fundecl.fun_name}\n`;
   `	.type	{emit_symbol fundecl.fun_name}, %function\n`;
   `{emit_symbol fundecl.fun_name}:\n`;
@@ -1083,7 +1088,6 @@ let fundecl fundecl =
 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 -> `	.short	{emit_int n}\n`
   | Cint32 n -> `	.long	{emit_nativeint n}\n`
@@ -1091,7 +1095,6 @@ let emit_item = function
   | 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 -> `	.align	{emit_int(Misc.log2 n)}\n`
@@ -1105,6 +1108,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`;
@@ -1128,9 +1132,12 @@ let end_assembly () =
   `	.globl	{emit_symbol lbl}\n`;
   `{emit_symbol lbl}:\n`;
   emit_frames
-    { efa_label = (fun lbl ->
+    { efa_code_label = (fun lbl ->
                        `	.type	{emit_label lbl}, %function\n`;
                        `	.quad	{emit_label lbl}\n`);
+      efa_data_label = (fun lbl ->
+                       `	.type	{emit_label lbl}, %object\n`;
+                       `	.quad	{emit_label lbl}\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`);
diff --git a/asmcomp/arm64/proc.ml b/asmcomp/arm64/proc.ml
index 188ce8cb2b..17e77c3f2c 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.                                      *)
+(*   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,7 +62,7 @@ let num_register_classes = 2
 
 let register_class r =
   match r.typ with
-  | (Int | Addr)  -> 0
+  | Val | Int | Addr  -> 0
   | Float         -> 1
 
 let num_available_registers =
@@ -103,6 +106,8 @@ let reg_d7 = phys_reg 107
 let stack_slot slot ty =
   Reg.at_location ty (Stack slot)
 
+let loc_spacetime_node_hole = Reg.dummy  (* Spacetime unsupported *)
+
 (* Calling conventions *)
 
 let calling_conventions
@@ -113,7 +118,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
@@ -134,7 +139,7 @@ let calling_conventions
 
 let incoming ofs = Incoming ofs
 let outgoing ofs = Outgoing ofs
-let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
+let not_supported _ofs = fatal_error "Proc.loc_results: cannot call"
 
 (* OCaml calling convention:
      first integer args in x0...x15
@@ -142,6 +147,8 @@ let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
      remaining args on stack.
    Return values in x0...x15 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 =
@@ -156,7 +163,11 @@ let loc_results res =
    Return values in x0...x1 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
 
@@ -164,7 +175,7 @@ let loc_exn_bucket = phys_reg 0
 
 (* Volatile registers: none *)
 
-let regs_are_volatile rs = false
+let regs_are_volatile _rs = false
 
 (* Registers destroyed by operations *)
 
@@ -177,9 +188,9 @@ let destroyed_at_c_call =
      124;125;126;127;128;129;130;131])
 
 let destroyed_at_oper = function
-  | Iop(Icall_ind | Icall_imm _) ->
+  | Iop(Icall_ind _ | Icall_imm _) ->
       all_phys_regs
-  | Iop(Iextcall(_, alloc, stack_ofs)) ->
+  | Iop(Iextcall { alloc ; stack_ofs; }) ->
       assert (stack_ofs >= 0);
       if alloc || stack_ofs > 0 then all_phys_regs
       else destroyed_at_c_call
@@ -195,12 +206,12 @@ let destroyed_at_raise = all_phys_regs
 (* Maximal register pressure *)
 
 let safe_register_pressure = function
-  | Iextcall(_, _, _) -> 8
+  | Iextcall _ -> 8
   | Ialloc _ -> 25
   | _ -> 26
 
 let max_register_pressure = function
-  | Iextcall(_, _, _) -> [| 10; 8 |]
+  | Iextcall _ -> [| 10; 8 |]
   | Ialloc _ -> [| 25; 32 |]
   | Iintoffloat | Ifloatofint
   | Iload(Single, _) | Istore(Single, _, _) -> [| 26; 31 |]
@@ -210,9 +221,9 @@ let max_register_pressure = function
    registers). *)
 
 let op_is_pure = function
-  | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+  | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _
   | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _ | Iloadmut
-  | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _)
+  | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _)
   | Ispecific(Ishiftcheckbound _) -> false
   | _ -> true
 
diff --git a/asmcomp/arm64/reload.ml b/asmcomp/arm64/reload.ml
index ff9214ef26..0d6cacd0bb 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 cc244be71a..04f514e91d 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 e7ded8fb43..719c5ec223 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* )
@@ -73,10 +76,6 @@ let rec run_automata nbits state input =
 let is_logical_immediate n =
   n <> 0 && n <> -1 && run_automata 64 0 n
 
-let is_intconst = function
-    Cconst_int _ -> true
-  | _ -> false
-
 let inline_ops =
   [ "sqrt"; "caml_bswap16_direct"; "caml_int32_direct_bswap";
     "caml_int64_direct_bswap"; "caml_nativeint_direct_bswap" ]
@@ -97,20 +96,20 @@ method is_immediate n =
 
 method! is_simple_expr = function
   (* inlined floating-point ops are simple if their arguments are *)
-  | Cop(Cextcall(fn, _, _, _), args) when List.mem fn inline_ops ->
+  | Cop(Cextcall (fn, _, _, _, _), args) when List.mem fn inline_ops ->
       List.for_all self#is_simple_expr args
   | e -> super#is_simple_expr e
 
 method 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 +119,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 +151,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 ->
@@ -177,7 +179,8 @@ method! select_operation op args =
   | Ccheckbound _ ->
       begin match args with
       | [Cop(Clsr, [arg1; Cconst_int n]); arg2] when n > 0 && n < 64 ->
-          (Ispecific(Ishiftcheckbound n), [arg1; arg2])
+          (Ispecific(Ishiftcheckbound { shift = n; label_after_error = None; }),
+            [arg1; arg2])
       | _ ->
           super#select_operation op args
       end
@@ -216,15 +219,15 @@ method! select_operation op args =
           super#select_operation op args
       end
   (* Recognize floating-point square root *)
-  | Cextcall("sqrt", _, _, _) ->
+  | Cextcall("sqrt", _, _, _, _) ->
       (Ispecific Isqrtf, args)
   (* Recognize bswap instructions *)
-  | Cextcall("caml_bswap16_direct", _, _, _) ->
+  | Cextcall("caml_bswap16_direct", _, _, _, _) ->
       (Ispecific(Ibswap 16), args)
-  | Cextcall("caml_int32_direct_bswap", _, _, _) ->
+  | Cextcall("caml_int32_direct_bswap", _, _, _, _) ->
       (Ispecific(Ibswap 32), args)
   | Cextcall(("caml_int64_direct_bswap"|"caml_nativeint_direct_bswap"),
-              _, _, _) ->
+              _, _, _, _) ->
       (Ispecific (Ibswap 64), args)
   (* Other operations are regular *)
   | _ ->
diff --git a/asmcomp/asmgen.ml b/asmcomp/asmgen.ml
index 311bb029b2..020732dd66 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 || !dump_clambda then
+    begin
+      Format.fprintf ppf "@.clambda:@.";
+      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,123 @@ 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
+    ~required_globals 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 () ->
+        Ident.Set.iter Compilenv.require_global required_globals;
+        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
+    ~required_globals:program.Lambda.required_globals
+    ppf lambda_gen_implementation program
+
+let compile_implementation_flambda ?toplevel ~source_provenance prefixname
+    ~required_globals ~backend ppf (program:Flambda.program) =
+  compile_implementation_gen ?toplevel ~source_provenance prefixname
+    ~required_globals ppf (flambda_gen_implementation ~backend) program
 
 (* Error report *)
 
diff --git a/asmcomp/asmgen.mli b/asmcomp/asmgen.mli
index 33582af4a7..cc79edf9af 100644
--- a/asmcomp/asmgen.mli
+++ b/asmcomp/asmgen.mli
@@ -1,23 +1,44 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA 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 ->
+    required_globals:Ident.Set.t ->
+    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 f7331cb59c..ca3f5740f7 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 c1a6a4788b..4d66827c0f 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 cea7b568cc..11d27d01dc 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
 
@@ -130,7 +135,7 @@ let is_required name =
   try ignore (Hashtbl.find missing_globals name); true
   with Not_found -> false
 
-let add_required by (name, crc) =
+let add_required by (name, _crc) =
   try
     let rq = Hashtbl.find missing_globals name in
     rq := by :: !rq
@@ -198,12 +203,11 @@ 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 *)
+  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
@@ -229,18 +233,17 @@ let make_startup_file ppf filename units_list =
           units_list));
   compile_phrase(Cmmgen.data_segment_table ("_startup" :: name_list));
   compile_phrase(Cmmgen.code_segment_table ("_startup" :: name_list));
-  compile_phrase
-    (Cmmgen.frame_table("_startup" :: "_system" :: name_list));
-
-  Emit.end_assembly();
-  close_out oc
+  let all_names = "_startup" :: "_system" :: name_list in
+  compile_phrase (Cmmgen.frame_table all_names);
+  if Config.spacetime then begin
+    compile_phrase (Cmmgen.spacetime_shapes all_names);
+  end;
+  Emit.end_assembly ()
 
-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";
+  Compilenv.reset ~source_provenance:Timings.Startup "_shared_startup";
   Emit.begin_assembly();
   List.iter compile_phrase
     (Cmmgen.generic_functions true (List.map fst units));
@@ -250,10 +253,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 +270,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
 
@@ -288,10 +289,16 @@ let call_linker file_list startup_file output_name =
   and main_obj_runtime = !Clflags.output_complete_object
   in
   let files = startup_file :: (List.rev file_list) in
+  let libunwind =
+    if not Config.spacetime then []
+    else if not Config.libunwind_available then []
+    else String.split_on_char ' ' Config.libunwind_link_flags
+  in
   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)
+      files @ (List.rev !Clflags.ccobjs) @ runtime_lib () @ libunwind,
+      (if !Clflags.nopervasives || main_obj_runtime
+       then "" else Config.native_c_libraries)
     else
       files, ""
   in
@@ -327,19 +334,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 60a2111e1c..55310bd901 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 d92aa4835f..6f0db063c6 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. *)
@@ -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 Filename.remove_extension targetobj ^ ".pack" ^ Config.ext_obj
@@ -91,10 +95,31 @@ 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
-    (Filename.remove_extension 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 = Filename.remove_extension objtemp in
+  if Config.flambda then begin
+    let size, lam = Translmod.transl_package_flambda components 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 ~required_globals:Ident.Set.empty 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;
+                       module_ident; required_globals = Ident.Set.empty }
+  end;
   let objfiles =
     List.map
       (fun m -> Filename.remove_extension m.pm_file ^ Config.ext_obj)
@@ -107,11 +132,23 @@ 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
   let filter lst =
-    List.filter (fun (name, crc) -> not (List.mem name unit_names)) lst in
+    List.filter (fun (name, _crc) -> not (List.mem name unit_names)) lst in
   let union lst =
     List.fold_left
       (List.fold_left
@@ -122,7 +159,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 +206,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 +214,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 ->
@@ -175,11 +247,13 @@ let package_files ppf initial_env files targetcmx =
   (* 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 4d47f5c283..203fc301ea 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 d4609e4a8e..6486d19cbc 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
@@ -48,8 +51,8 @@ module Make (T : Branch_relaxation_intf.S) = struct
       in
       match instr.desc with
       | Lop (Ialloc _)
-      | Lop (Iintop Icheckbound)
-      | Lop (Iintop_imm (Icheckbound, _))
+      | Lop (Iintop (Icheckbound _))
+      | Lop (Iintop_imm (Icheckbound _, _))
       | Lop (Ispecific _) ->
         (* We assume that any branches eligible for relaxation generated
            by these instructions only branch forward.  We further assume
@@ -83,20 +86,21 @@ module Make (T : Branch_relaxation_intf.S) = struct
           fixup did_fix (pc + T.instr_size instr.desc) instr.next
         else
           match instr.desc with
-          | Lop (Ialloc num_words) ->
-            instr.desc <- T.relax_allocation ~num_words;
+          | Lop (Ialloc { words = num_words; label_after_call_gc; }) ->
+            instr.desc <- T.relax_allocation ~num_words ~label_after_call_gc;
             fixup true (pc + T.instr_size instr.desc) instr.next
-          | Lop (Iintop Icheckbound) ->
-            instr.desc <- T.relax_intop_checkbound ();
+          | Lop (Iintop (Icheckbound { label_after_error; })) ->
+            instr.desc <- T.relax_intop_checkbound ~label_after_error;
             fixup true (pc + T.instr_size instr.desc) instr.next
-          | Lop (Iintop_imm (Icheckbound, bound)) ->
-            instr.desc <- T.relax_intop_imm_checkbound ~bound;
+          | Lop (Iintop_imm (Icheckbound { label_after_error; }, bound)) ->
+            instr.desc
+              <- T.relax_intop_imm_checkbound ~bound ~label_after_error;
             fixup true (pc + T.instr_size instr.desc) instr.next
           | Lop (Ispecific specific) ->
             instr.desc <- T.relax_specific_op specific;
             fixup true (pc + T.instr_size instr.desc) instr.next
           | Lcondbranch (test, lbl) ->
-            let lbl2 = new_label() in
+            let lbl2 = Cmm.new_label() in
             let cont =
               instr_cons (Lbranch lbl) [||] [||]
                 (instr_cons (Llabel lbl2) [||] [||] instr.next)
diff --git a/asmcomp/branch_relaxation.mli b/asmcomp/branch_relaxation.mli
index e2a93f83d1..170f306d82 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 0812c7c1b8..3b1fbac5db 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
@@ -57,8 +60,16 @@ module type S = sig
   (* Insertion of target-specific code to relax operations that cannot be
      relaxed generically.  It is assumed that these rewrites do not change
      the size of out-of-line code (cf. branch_relaxation.mli). *)
-  val relax_allocation : num_words:int -> Linearize.instruction_desc
-  val relax_intop_checkbound : unit -> Linearize.instruction_desc
-  val relax_intop_imm_checkbound : bound:int -> Linearize.instruction_desc
+  val relax_allocation
+     : num_words:int
+    -> label_after_call_gc:Cmm.label option
+    -> Linearize.instruction_desc
+  val relax_intop_checkbound
+     : label_after_error:Cmm.label option
+    -> Linearize.instruction_desc
+  val relax_intop_imm_checkbound
+     : bound:int
+    -> label_after_error:Cmm.label option
+    -> Linearize.instruction_desc
   val relax_specific_op : Arch.specific_operation -> Linearize.instruction_desc
 end
diff --git a/asmcomp/build_export_info.ml b/asmcomp/build_export_info.ml
new file mode 100644
index 0000000000..80f97f055f
--- /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 { 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, _value_kind), 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 0000000000..2a824ea392
--- /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 ed96f218bf..4b261a385d 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,20 +29,21 @@ 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
   | Ugeneric_apply of ulambda * ulambda list * Debuginfo.t
   | Uclosure of ufunction list * ulambda list
   | Uoffset of ulambda * int
-  | Ulet of Ident.t * ulambda * ulambda
+  | Ulet of mutable_flag * value_kind * Ident.t * ulambda * ulambda
   | Uletrec of (Ident.t * ulambda) list * ulambda
   | Uprim of primitive * ulambda list * Debuginfo.t
   | Uswitch of ulambda * ulambda_switch
@@ -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) *)
 
@@ -104,7 +124,7 @@ let rec compare_float_lists l1 l2 =
 
 let compare_constants c1 c2 =
   match c1, c2 with
-  | Uconst_ref(lbl1, c1), Uconst_ref(lbl2, c2) -> String.compare lbl1 lbl2
+  | Uconst_ref(lbl1, _c1), Uconst_ref(lbl2, _c2) -> String.compare lbl1 lbl2
       (* Same labels -> same constants.
          Different labels -> different constants, even if the contents
            match, because of string constants that must not be
@@ -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 fc7a14d1e2..847152b32a 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,20 +29,21 @@ 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
   | Ugeneric_apply of ulambda * ulambda list * Debuginfo.t
   | Uclosure of ufunction list * ulambda list
   | Uoffset of ulambda * int
-  | Ulet of Ident.t * ulambda * ulambda
+  | Ulet of mutable_flag * value_kind * Ident.t * ulambda * ulambda
   | Uletrec of (Ident.t * ulambda) list * ulambda
   | Uprim of primitive * ulambda list * Debuginfo.t
   | Uswitch of ulambda * ulambda_switch
@@ -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 526f0924ec..e532c7aa9c 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -48,9 +51,9 @@ let rec build_closure_env env_param pos = function
    and no longer in Cmmgen so that approximations stored in .cmx files
    contain the right names if the -for-pack option is active. *)
 
-let getglobal id =
+let getglobal dbg id =
   Uprim(Pgetglobal (Ident.create_persistent (Compilenv.symbol_for_global id)),
-        [], Debuginfo.none)
+        [], dbg)
 
 (* Check if a variable occurs in a [clambda] term. *)
 
@@ -58,14 +61,14 @@ let occurs_var var u =
   let rec occurs = function
       Uvar v -> v = var
     | Uconst _ -> false
-    | Udirect_apply(lbl, args, _) -> List.exists occurs args
+    | Udirect_apply(_lbl, args, _) -> List.exists occurs args
     | Ugeneric_apply(funct, args, _) -> occurs funct || List.exists occurs args
-    | Uclosure(fundecls, clos) -> List.exists occurs clos
-    | Uoffset(u, ofs) -> occurs u
-    | Ulet(id, def, body) -> occurs def || occurs body
+    | Uclosure(_fundecls, clos) -> List.exists occurs clos
+    | Uoffset(u, _ofs) -> occurs u
+    | Ulet(_str, _kind, _id, def, body) -> occurs def || occurs body
     | Uletrec(decls, body) ->
-        List.exists (fun (id, u) -> occurs u) decls || occurs body
-    | Uprim(p, args, _) -> List.exists occurs args
+        List.exists (fun (_id, u) -> occurs u) decls || occurs body
+    | Uprim(_p, args, _) -> List.exists occurs args
     | Uswitch(arg, s) ->
         occurs arg ||
         occurs_array s.us_actions_consts || occurs_array s.us_actions_blocks
@@ -75,15 +78,16 @@ let occurs_var var u =
         (match d with None -> false | Some d -> occurs d)
     | Ustaticfail (_, args) -> List.exists occurs args
     | Ucatch(_, _, body, hdlr) -> occurs body || occurs hdlr
-    | Utrywith(body, exn, hdlr) -> occurs body || occurs hdlr
+    | Utrywith(body, _exn, hdlr) -> occurs body || occurs hdlr
     | Uifthenelse(cond, ifso, ifnot) ->
         occurs cond || occurs ifso || occurs ifnot
     | Usequence(u1, u2) -> occurs u1 || occurs u2
     | Uwhile(cond, body) -> occurs cond || occurs body
-    | Ufor(id, lo, hi, dir, body) -> occurs lo || occurs hi || occurs body
+    | Ufor(_id, lo, hi, _dir, body) -> occurs lo || occurs hi || occurs body
     | 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
@@ -94,72 +98,35 @@ 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 *)
 
 let prim_size prim args =
   match prim with
-    Pidentity -> 0
-  | Pgetglobal id -> 1
-  | Psetglobal id -> 1
-  | Pmakeblock(tag, mut) -> 5 + List.length args
-  | Pfield(f, isptr, Mutable) -> if isptr then 2 else 1
-  | Pfield(f, isptr, Immutable) -> 1
-  | Psetfield(f, isptr, mut) -> if isptr then 4 else 1
-  | Pfloatfield f -> 1
-  | Psetfloatfield f -> 1
+    Pidentity | Pbytes_to_string | Pbytes_of_string -> 0
+  | Pgetglobal _ -> 1
+  | Psetglobal _ -> 1
+  | Pmakeblock _ -> 5 + List.length args
+  | Pfield(_, isptr, Mutable) -> if isptr then 2 else 1
+  | Pfield(_, _, Immutable) -> 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 _ -> 1
+  | Psetfloatfield _ -> 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
+  | Pbyteslength -> 5
+  | Pstringrefs  -> 6
+  | Pbytesrefs | Pbytessets -> 6
+  | 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
@@ -177,19 +144,19 @@ let lambda_smaller lam threshold =
   let rec lambda_size lam =
     if !size > threshold then raise Exit;
     match lam with
-      Uvar v -> ()
+      Uvar _ -> ()
     | Uconst _ -> incr size
-    | Udirect_apply(fn, args, _) ->
+    | Udirect_apply(_, args, _) ->
         size := !size + 4; lambda_list_size args
     | Ugeneric_apply(fn, args, _) ->
         size := !size + 6; lambda_size fn; lambda_list_size args
-    | Uclosure(defs, vars) ->
+    | Uclosure _ ->
         raise Exit (* inlining would duplicate function definitions *)
-    | Uoffset(lam, ofs) ->
+    | Uoffset(lam, _ofs) ->
         incr size; lambda_size lam
-    | Ulet(id, lam, body) ->
+    | Ulet(_str, _kind, _id, lam, body) ->
         lambda_size lam; lambda_size body
-    | Uletrec(bindings, body) ->
+    | Uletrec _ ->
         raise Exit (* usually too large *)
     | Uprim(prim, args, _) ->
         size := !size + prim_size prim args;
@@ -212,7 +179,7 @@ let lambda_smaller lam threshold =
     | Ustaticfail (_,args) -> lambda_list_size args
     | Ucatch(_, _, body, handler) ->
         incr size; lambda_size body; lambda_size handler
-    | Utrywith(body, id, handler) ->
+    | Utrywith(body, _id, handler) ->
         size := !size + 8; lambda_size body; lambda_size handler
     | Uifthenelse(cond, ifso, ifnot) ->
         size := !size + 2;
@@ -221,13 +188,14 @@ let lambda_smaller lam threshold =
         lambda_size lam1; lambda_size lam2
     | Uwhile(cond, body) ->
         size := !size + 2; lambda_size cond; lambda_size body
-    | Ufor(id, low, high, dir, body) ->
+    | Ufor(_id, low, high, _dir, body) ->
         size := !size + 4; lambda_size low; lambda_size high; lambda_size body
-    | Uassign(id, lam) ->
+    | Uassign(_id, lam) ->
         incr size;  lambda_size lam
     | 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
@@ -239,19 +207,20 @@ let lambda_smaller lam threshold =
    that is without side-effects *and* not containing function definitions *)
 
 let rec is_pure_clambda = function
-    Uvar v -> true
+    Uvar _ -> true
   | Uconst _ -> true
   | Uprim((Psetglobal _ | Psetfield _ | Psetfloatfield _ | Pduprecord _ |
-           Pccall _ | Praise _ | Poffsetref _ | Pstringsetu | Pstringsets |
+           Pccall _ | Praise _ | Poffsetref _ |  Pbytessetu | Pbytessets |
            Parraysetu _ | Parraysets _ | Pbigarrayset _), _, _) -> false
-  | Uprim(p, args, _) -> List.for_all is_pure_clambda args
+  | Uprim(_, args, _) -> List.for_all is_pure_clambda args
   | _ -> false
 
 (* Simplify primitive operations on known arguments *)
 
 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)
@@ -298,8 +267,8 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | Paddint -> make_const_int (n1 + n2)
       | Psubint -> make_const_int (n1 - n2)
       | Pmulint -> make_const_int (n1 * n2)
-      | Pdivint when n2 <> 0 -> make_const_int (n1 / n2)
-      | Pmodint when n2 <> 0 -> make_const_int (n1 mod n2)
+      | Pdivint _ when n2 <> 0 -> make_const_int (n1 / n2)
+      | Pmodint _ when n2 <> 0 -> make_const_int (n1 mod n2)
       | Pandint -> make_const_int (n1 land n2)
       | Porint -> make_const_int (n1 lor n2)
       | Pxorint -> make_const_int (n1 lxor n2)
@@ -313,7 +282,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)
@@ -321,8 +290,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)
@@ -332,7 +301,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)
@@ -341,15 +310,15 @@ 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)
       | Pmulbint Pnativeint -> make_const_natint (Nativeint.mul n1 n2)
-      | Pdivbint Pnativeint when n2 <> 0n ->
+      | Pdivbint {size=Pnativeint} when n2 <> 0n ->
           make_const_natint (Nativeint.div n1 n2)
-      | Pmodbint Pnativeint when n2 <> 0n ->
+      | Pmodbint {size=Pnativeint} when n2 <> 0n ->
           make_const_natint (Nativeint.rem n1 n2)
       | Pandbint Pnativeint -> make_const_natint (Nativeint.logand n1 n2)
       | Porbint Pnativeint ->  make_const_natint (Nativeint.logor n1 n2)
@@ -358,7 +327,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 ->
@@ -370,7 +339,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)
@@ -379,14 +348,16 @@ 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)
       | Pmulbint Pint32 -> make_const_int32 (Int32.mul n1 n2)
-      | Pdivbint Pint32 when n2 <> 0l -> make_const_int32 (Int32.div n1 n2)
-      | Pmodbint Pint32 when n2 <> 0l -> make_const_int32 (Int32.rem n1 n2)
+      | Pdivbint {size=Pint32} when n2 <> 0l ->
+          make_const_int32 (Int32.div n1 n2)
+      | Pmodbint {size=Pint32} when n2 <> 0l ->
+          make_const_int32 (Int32.rem n1 n2)
       | Pandbint Pint32 -> make_const_int32 (Int32.logand n1 n2)
       | Porbint Pint32 -> make_const_int32 (Int32.logor n1 n2)
       | Pxorbint Pint32 -> make_const_int32 (Int32.logxor n1 n2)
@@ -394,7 +365,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 ->
@@ -406,7 +377,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)
@@ -415,14 +386,16 @@ 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)
       | Pmulbint Pint64 -> make_const_int64 (Int64.mul n1 n2)
-      | Pdivbint Pint64 when n2 <> 0L -> make_const_int64 (Int64.div n1 n2)
-      | Pmodbint Pint64 when n2 <> 0L -> make_const_int64 (Int64.rem n1 n2)
+      | Pdivbint {size=Pint64} when n2 <> 0L ->
+          make_const_int64 (Int64.div n1 n2)
+      | Pmodbint {size=Pint64} when n2 <> 0L ->
+          make_const_int64 (Int64.rem n1 n2)
       | Pandbint Pint64 -> make_const_int64 (Int64.logand n1 n2)
       | Porbint Pint64 -> make_const_int64 (Int64.logor n1 n2)
       | Pxorbint Pint64 -> make_const_int64 (Int64.logxor n1 n2)
@@ -430,7 +403,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 ->
@@ -448,14 +421,15 @@ 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
 
 let simplif_prim_pure fpc p (args, approxs) dbg =
   match p, args, approxs with
   (* Block construction *)
-  | Pmakeblock(tag, Immutable), _, _ ->
+  | Pmakeblock(tag, Immutable, _kind), _, _ ->
       let field = function
         | Value_const c -> c
         | _ -> raise Exit
@@ -465,22 +439,24 @@ 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 | Pbyteslength),
+     _,
+     [ Value_const(Uconst_ref(_, Some (Uconst_string s))) ] ->
       make_const_int (String.length s)
   (* Identity *)
-  | Pidentity, [arg1], [app1] ->
+  | (Pidentity | Pbytes_to_string | Pbytes_of_string), [arg1], [app1] ->
       (arg1, app1)
   (* Kind test *)
   | Pisint, _, [a1] ->
@@ -495,9 +471,13 @@ 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")
+        | Backend_type ->
+            make_const_ptr 0 (* tag 0 is the same as Native here *)
       end
   (* Catch-all *)
   | _ ->
@@ -510,7 +490,7 @@ let simplif_prim fpc p (args, approxs as args_approxs) dbg =
     (* XXX : always return the same approxs as simplif_prim_pure? *)
     let approx =
       match p with
-      | Pmakeblock(_, Immutable) ->
+      | Pmakeblock(_, Immutable, _kind) ->
           Value_tuple (Array.of_list approxs)
       | _ ->
           Value_unknown
@@ -530,16 +510,33 @@ let approx_ulam = function
     Uconst c -> Value_const c
   | _ -> Value_unknown
 
-let rec substitute fpc sb ulam =
+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 subst_debuginfo loc dbg =
+  if !Clflags.debug then
+    Debuginfo.inline loc dbg
+  else
+    dbg
+
+let rec substitute loc fpc sb ulam =
   match ulam with
     Uvar v ->
       begin try Tbl.find v sb with Not_found -> ulam end
   | Uconst _ -> ulam
   | Udirect_apply(lbl, args, dbg) ->
-      Udirect_apply(lbl, List.map (substitute fpc sb) args, dbg)
+      let dbg = subst_debuginfo loc dbg in
+      Udirect_apply(lbl, List.map (substitute loc fpc sb) args, dbg)
   | Ugeneric_apply(fn, args, dbg) ->
-      Ugeneric_apply(substitute fpc sb fn,
-                     List.map (substitute fpc sb) args, dbg)
+      let dbg = subst_debuginfo loc dbg in
+      Ugeneric_apply(substitute loc fpc sb fn,
+                     List.map (substitute loc fpc sb) args, dbg)
   | Uclosure(defs, env) ->
       (* Question: should we rename function labels as well?  Otherwise,
          there is a risk that function labels are not globally unique.
@@ -549,12 +546,12 @@ let rec substitute fpc sb ulam =
          - When we substitute offsets for idents bound by let rec
            in [close], case [Lletrec], we discard the original
            let rec body and use only the substituted term. *)
-      Uclosure(defs, List.map (substitute fpc sb) env)
-  | Uoffset(u, ofs) -> Uoffset(substitute fpc sb u, ofs)
-  | Ulet(id, u1, u2) ->
+      Uclosure(defs, List.map (substitute loc fpc sb) env)
+  | Uoffset(u, ofs) -> Uoffset(substitute loc fpc sb u, ofs)
+  | Ulet(str, kind, id, u1, u2) ->
       let id' = Ident.rename id in
-      Ulet(id', substitute fpc sb u1,
-           substitute fpc (Tbl.add id (Uvar id') sb) u2)
+      Ulet(str, kind, id', substitute loc fpc sb u1,
+           substitute loc fpc (Tbl.add id (Uvar id') sb) u2)
   | Uletrec(bindings, body) ->
       let bindings1 =
         List.map (fun (id, rhs) -> (id, Ident.rename id, rhs)) bindings in
@@ -564,63 +561,91 @@ let rec substitute fpc sb ulam =
           bindings1 sb in
       Uletrec(
         List.map
-           (fun (id, id', rhs) -> (id', substitute fpc sb' rhs))
+           (fun (_id, id', rhs) -> (id', substitute loc fpc sb' rhs))
            bindings1,
-        substitute fpc sb' body)
+        substitute loc fpc sb' body)
   | Uprim(p, args, dbg) ->
-      let sargs =
-        List.map (substitute fpc sb) args in
+      let sargs = List.map (substitute loc fpc sb) args in
+      let dbg = subst_debuginfo loc dbg in
       let (res, _) =
         simplif_prim fpc p (sargs, List.map approx_ulam sargs) dbg in
       res
   | Uswitch(arg, sw) ->
-      Uswitch(substitute fpc sb arg,
+      let sarg = substitute loc 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 loc fpc sb u
+      | None ->
+          Uswitch(sarg,
               { sw with
                 us_actions_consts =
-                  Array.map (substitute fpc sb) sw.us_actions_consts;
+                      Array.map (substitute loc fpc sb) sw.us_actions_consts;
                 us_actions_blocks =
-                  Array.map (substitute fpc sb) sw.us_actions_blocks;
+                      Array.map (substitute loc fpc sb) sw.us_actions_blocks;
                })
+      end
   | Ustringswitch(arg,sw,d) ->
       Ustringswitch
-        (substitute fpc sb arg,
-         List.map (fun (s,act) -> s,substitute fpc sb act) sw,
-         Misc.may_map (substitute fpc sb) d)
+        (substitute loc fpc sb arg,
+         List.map (fun (s,act) -> s,substitute loc fpc sb act) sw,
+         Misc.may_map (substitute loc fpc sb) d)
   | Ustaticfail (nfail, args) ->
-      Ustaticfail (nfail, List.map (substitute fpc sb) args)
+      Ustaticfail (nfail, List.map (substitute loc 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 loc fpc sb u1, substitute loc fpc sb' u2)
   | Utrywith(u1, id, u2) ->
       let id' = Ident.rename id in
-      Utrywith(substitute fpc sb u1, id',
-               substitute fpc (Tbl.add id (Uvar id') sb) u2)
+      Utrywith(substitute loc fpc sb u1, id',
+               substitute loc fpc (Tbl.add id (Uvar id') sb) u2)
   | Uifthenelse(u1, u2, u3) ->
-      begin match substitute fpc sb u1 with
+      begin match substitute loc fpc sb u1 with
         Uconst (Uconst_ptr n) ->
-          if n <> 0 then substitute fpc sb u2 else substitute fpc sb u3
+          if n <> 0 then substitute loc fpc sb u2 else substitute loc fpc sb u3
       | Uprim(Pmakeblock _, _, _) ->
-          substitute fpc sb u2
+          substitute loc fpc sb u2
       | su1 ->
-          Uifthenelse(su1, substitute fpc sb u2, substitute fpc sb u3)
+          Uifthenelse(su1, substitute loc fpc sb u2, substitute loc fpc sb u3)
       end
   | Usequence(u1, u2) ->
-      Usequence(substitute fpc sb u1, substitute fpc sb u2)
+      Usequence(substitute loc fpc sb u1, substitute loc fpc sb u2)
   | Uwhile(u1, u2) ->
-      Uwhile(substitute fpc sb u1, substitute fpc sb u2)
+      Uwhile(substitute loc fpc sb u1, substitute loc fpc sb u2)
   | Ufor(id, u1, u2, dir, u3) ->
       let id' = Ident.rename id in
-      Ufor(id', substitute fpc sb u1, substitute fpc sb u2, dir,
-           substitute fpc (Tbl.add id (Uvar id') sb) u3)
+      Ufor(id', substitute loc fpc sb u1, substitute loc fpc sb u2, dir,
+           substitute loc fpc (Tbl.add id (Uvar id') sb) u3)
   | Uassign(id, u) ->
       let id' =
         try
           match Tbl.find id sb with Uvar i -> i | _ -> assert false
         with Not_found ->
           id in
-      Uassign(id', substitute fpc sb u)
+      Uassign(id', substitute loc fpc sb u)
   | Usend(k, u1, u2, ul, dbg) ->
-      Usend(k, substitute fpc sb u1, substitute fpc sb u2,
-            List.map (substitute fpc sb) ul, dbg)
+      let dbg = subst_debuginfo loc dbg in
+      Usend(k, substitute loc fpc sb u1, substitute loc fpc sb u2,
+            List.map (substitute loc fpc sb) ul, dbg)
+  | Uunreachable ->
+      Uunreachable
 
 (* Perform an inline expansion *)
 
@@ -632,58 +657,67 @@ let no_effects = function
   | Uclosure _ -> true
   | u -> is_simple_argument u
 
-let rec bind_params_rec fpc subst params args body =
+let rec bind_params_rec loc fpc subst params args body =
   match (params, args) with
-    ([], []) -> substitute fpc subst body
+    ([], []) -> substitute loc fpc subst body
   | (p1 :: pl, a1 :: al) ->
       if is_simple_argument a1 then
-        bind_params_rec fpc (Tbl.add p1 a1 subst) pl al body
+        bind_params_rec loc fpc (Tbl.add p1 a1 subst) pl al body
       else begin
         let p1' = Ident.rename p1 in
         let u1, u2 =
           match Ident.name p1, a1 with
-          | "*opt*", Uprim(Pmakeblock(0, Immutable), [a], dbg) ->
-              a, Uprim(Pmakeblock(0, Immutable), [Uvar p1'], dbg)
+          | "*opt*", Uprim(Pmakeblock(0, Immutable, kind), [a], dbg) ->
+              a, Uprim(Pmakeblock(0, Immutable, kind), [Uvar p1'], dbg)
           | _ ->
               a1, Uvar p1'
         in
         let body' =
-          bind_params_rec fpc (Tbl.add p1 u2 subst) pl al body in
-        if occurs_var p1 body then Ulet(p1', u1, body')
+          bind_params_rec loc fpc (Tbl.add p1 u2 subst) pl al body in
+        if occurs_var p1 body then Ulet(Immutable, Pgenval, p1', u1, body')
         else if no_effects a1 then body'
         else Usequence(a1, body')
       end
   | (_, _) -> assert false
 
-let bind_params fpc params args body =
+let bind_params loc fpc params args body =
   (* Reverse parameters and arguments to preserve right-to-left
      evaluation order (PR#2910). *)
-  bind_params_rec fpc Tbl.empty (List.rev params) (List.rev args) body
+  bind_params_rec loc fpc Tbl.empty (List.rev params) (List.rev args) body
 
 (* Check if a lambda term is ``pure'',
    that is without side-effects *and* not containing function definitions *)
 
 let rec is_pure = function
-    Lvar v -> true
-  | Lconst cst -> true
+    Lvar _ -> true
+  | Lconst _ -> true
   | Lprim((Psetglobal _ | Psetfield _ | Psetfloatfield _ | Pduprecord _ |
-           Pccall _ | Praise _ | Poffsetref _ | Pstringsetu | Pstringsets |
-           Parraysetu _ | Parraysets _ | Pbigarrayset _), _) -> false
-  | Lprim(p, args) -> List.for_all is_pure args
-  | Levent(lam, ev) -> is_pure lam
+           Pccall _ | Praise _ | Poffsetref _  | Pbytessetu | Pbytessets |
+           Parraysetu _ | Parraysets _ | Pbigarrayset _), _,_) -> false
+  | Lprim(_, args,_) -> List.for_all is_pure args
+  | 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 ->
-        Udirect_apply(fundesc.fun_label, app_args, Debuginfo.none)
-    | Some(params, body) ->
-        bind_params fundesc.fun_float_const_prop params app_args body in
+    match fundesc.fun_inline, attribute with
+    | _, Never_inline | None, _ ->
+      let dbg = Debuginfo.from_location loc in
+        warning_if_forced_inline ~loc ~attribute
+          "Function information unavailable";
+        Udirect_apply(fundesc.fun_label, app_args, dbg)
+    | Some(params, body), _  ->
+        bind_params loc 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
@@ -734,32 +768,6 @@ let global_approx = ref([||] : value_approximation array)
 let function_nesting_depth = ref 0
 let excessive_function_nesting_depth = 5
 
-(* Decorate clambda term with debug information *)
-
-let rec add_debug_info ev u =
-  match ev.lev_kind with
-  | Lev_after _ ->
-      begin match u with
-      | Udirect_apply(lbl, args, dinfo) ->
-          Udirect_apply(lbl, args, Debuginfo.from_call ev)
-      | Ugeneric_apply(Udirect_apply(lbl, args1, dinfo1),
-                       args2, dinfo2) ->
-          Ugeneric_apply(Udirect_apply(lbl, args1, Debuginfo.from_call ev),
-                         args2, Debuginfo.from_call ev)
-      | Ugeneric_apply(fn, args, dinfo) ->
-          Ugeneric_apply(fn, args, Debuginfo.from_call ev)
-      | Uprim(Praise k, args, dinfo) ->
-          Uprim(Praise k, args, Debuginfo.from_call ev)
-      | Uprim(p, args, dinfo) ->
-          Uprim(p, args, Debuginfo.from_call ev)
-      | Usend(kind, u1, u2, args, dinfo) ->
-          Usend(kind, u1, u2, args, Debuginfo.from_call ev)
-      | Usequence(u1, u2) ->
-          Usequence(u1, add_debug_info ev u2)
-      | _ -> u
-      end
-  | _ -> u
-
 let prim_promote =
   Pccall { Primitive.prim_name = "caml_obj_promote_to"; prim_arity = 2;
            prim_alloc = true; prim_native_name = "";
@@ -783,7 +791,7 @@ let close_approx_var fenv cenv id =
       (subst, approx)
 
 let close_var fenv cenv id =
-  let (ulam, app) = close_approx_var fenv cenv id in ulam
+  let (ulam, _app) = close_approx_var fenv cenv id in ulam
 
 let rec close fenv cenv = function
     Lvar id ->
@@ -793,7 +801,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
@@ -807,34 +815,41 @@ let rec close fenv cenv = function
         | Const_immstring s ->
             str (Uconst_string s)
         | Const_base (Const_string (s, _)) ->
-              (* strings (even literal ones) are mutable! *)
-              (* of course, the empty string is really immutable *)
-            str ~shared:false(*(String.length s = 0)*) (Uconst_string s)
+              (* Strings (even literal ones) must be assumed to be mutable...
+                 except when OCaml has been configured with
+                 -safe-string.  Passing -safe-string at compilation
+                 time is not enough, since the unit could be linked
+                 with another one compiled without -safe-string, and
+                 that one could modify our string literal.  *)
+            str ~shared:Config.safe_string (Uconst_string s)
         | Const_base(Const_float x) -> str (Uconst_float (float_of_string x))
         | Const_base(Const_int32 x) -> str (Uconst_int32 x)
         | Const_base(Const_int64 x) -> str (Uconst_int64 x)
         | Const_base(Const_nativeint x) -> str (Uconst_nativeint x)
       in
       make_const (transl cst)
-  | Lfunction(kind, params, body) as funct ->
+  | Lfunction _ as funct ->
       close_one_function fenv cenv (Ident.create "fun") funct
 
     (* We convert [f a] to [let a' = a in fun b c -> f a' b c]
        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, _)])
+         [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)
+      | ((_ufunct, Value_closure(fundesc, _approx_res)), uargs)
           when nargs < fundesc.fun_arity ->
         let first_args = List.map (fun arg ->
           (Ident.create "arg", arg) ) uargs in
@@ -846,49 +861,65 @@ let rec close fenv cenv = function
               [] -> body
             | (arg1, arg2) :: args ->
               iter args
-                (Ulet ( arg1, arg2, body))
+                (Ulet (Immutable, Pgenval, arg1, arg2, body))
         in
         let internal_args =
-          (List.map (fun (arg1, arg2) -> Lvar arg1) first_args)
+          (List.map (fun (arg1, _arg2) -> Lvar arg1) first_args)
           @ (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};
+               loc;
+               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)
+      | ((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),
+          let dbg = Debuginfo.from_location loc in
+          warning_if_forced_inline ~loc ~attribute "Over-application";
+          (Ugeneric_apply(direct_apply ~loc ~attribute
+                            fundesc funct ufunct first_args,
+                          rem_args, dbg),
            Value_unknown)
       | ((ufunct, _), uargs) ->
-          (Ugeneric_apply(ufunct, uargs, Debuginfo.none), Value_unknown)
+          let dbg = Debuginfo.from_location loc in
+          warning_if_forced_inline ~loc ~attribute "Unknown function";
+          (Ugeneric_apply(ufunct, uargs, dbg), Value_unknown)
       end
-  | Lsend(kind, met, obj, args, _) ->
+  | Lsend(kind, met, obj, args, loc) ->
       let (umet, _) = close fenv cenv met in
       let (uobj, _) = close fenv cenv obj in
-      (Usend(kind, umet, uobj, close_list fenv cenv args, Debuginfo.none),
+      let dbg = Debuginfo.from_location loc in
+      (Usend(kind, umet, uobj, close_list fenv cenv args, dbg),
        Value_unknown)
-  | Llet(str, id, lam, body) ->
+  | Llet(str, kind, id, lam, body) ->
       let (ulam, alam) = close_named fenv cenv id lam in
       begin match (str, alam) with
         (Variable, _) ->
           let (ubody, abody) = close fenv cenv body in
-          (Ulet(id, ulam, ubody), abody)
+          (Ulet(Mutable, kind, id, ulam, ubody), abody)
       | (_, Value_const _)
         when str = Alias || is_pure lam ->
           close (Tbl.add id alam fenv) cenv body
       | (_, _) ->
           let (ubody, abody) = close (Tbl.add id alam fenv) cenv body in
-          (Ulet(id, ulam, ubody), abody)
+          (Ulet(Immutable, kind, id, ulam, ubody), abody)
       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 *)
@@ -896,15 +927,16 @@ let rec close fenv cenv = function
         let clos_ident = Ident.create "clos" in
         let fenv_body =
           List.fold_right
-            (fun (id, pos, approx) fenv -> Tbl.add id approx fenv)
+            (fun (id, _pos, approx) fenv -> Tbl.add id approx fenv)
             infos fenv in
         let (ubody, approx) = close fenv_body cenv body in
         let sb =
           List.fold_right
-            (fun (id, pos, approx) sb ->
+            (fun (id, pos, _approx) sb ->
               Tbl.add id (Uoffset(Uvar clos_ident, pos)) sb)
             infos Tbl.empty in
-        (Ulet(clos_ident, clos, substitute !Clflags.float_const_prop sb ubody),
+        (Ulet(Immutable, Pgenval, clos_ident, clos,
+              substitute Location.none !Clflags.float_const_prop sb ubody),
          approx)
       end else begin
         (* General case: recursive definition of values *)
@@ -918,49 +950,60 @@ let rec close fenv cenv = function
         let (ubody, approx) = close fenv_body cenv body in
         (Uletrec(udefs, ubody), approx)
       end
-  | Lprim(Pdirapply loc,[funct;arg])
-  | Lprim(Prevapply loc,[arg;funct]) ->
-      close fenv cenv (Lapply(funct, [arg], loc))
-  | Lprim(Pgetglobal id, []) as lam ->
+  | Lprim(Pdirapply,[funct;arg], loc)
+  | Lprim(Prevapply,[arg;funct], 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, [], loc) as lam ->
+      let dbg = Debuginfo.from_location loc in
       check_constant_result lam
-                            (getglobal id)
+                            (getglobal dbg id)
                             (Compilenv.global_approx id)
-  | Lprim(Pfield(n, ptr, mut), [lam]) ->
+  | Lprim(Pfield (n, ptr, mut), [lam], loc) ->
       let (ulam, approx) = close fenv cenv lam in
-      check_constant_result lam (Uprim(Pfield(n, ptr, mut), [ulam], Debuginfo.none))
+      let dbg = Debuginfo.from_location loc in
+      check_constant_result lam (Uprim(Pfield (n, ptr, mut), [ulam], dbg))
                             (field_approx n approx)
-  | Lprim(Psetfield(n, _, _), [Lprim(Pgetglobal id, []); lam]) ->
+  | Lprim(Psetfield(n, is_ptr, init), [Lprim(Pgetglobal id, [], _); lam], loc)->
       let (ulam, approx) = close fenv cenv lam in
       if approx <> Value_unknown then
         (!global_approx).(n) <- approx;
+      let dbg = Debuginfo.from_location loc in
       let promoted = Uprim(prim_promote, [ulam; Uconst (Uconst_int 0)], Debuginfo.none) in
-      (Uprim(Psetfield(n, false, Mutable), [getglobal id; promoted], Debuginfo.none),
+      (Uprim(Psetfield(n, is_ptr, init), [getglobal dbg id; promoted], dbg),
        Value_unknown)
-  | Lprim(Praise k, [Levent(arg, ev)]) ->
-      let (ulam, approx) = close fenv cenv arg in
-      (Uprim(Praise k, [ulam], Debuginfo.from_raise ev),
+  | Lprim(Praise k, [arg], loc) ->
+      let (ulam, _approx) = close fenv cenv arg in
+      let dbg = Debuginfo.from_location loc in
+      (Uprim(Praise k, [ulam], dbg),
        Value_unknown)
-  | Lprim(Pperform loc, args) ->
+  | Lprim(Pperform _, args, loc) ->
       let args = close_list fenv cenv args in
-      let dinfo = Debuginfo.(from_location Dinfo_call loc) in
-      (Udirect_apply ("caml_perform", args, dinfo), Value_unknown)
-  | Lprim(Presume loc, args) ->
+      let dbg = Debuginfo.from_location loc in
+      (Udirect_apply ("caml_perform", args, dbg), Value_unknown)
+  | Lprim(Presume _, args, loc) ->
       let args = close_list fenv cenv args in
-      let dinfo = Debuginfo.(from_location Dinfo_call loc) in
-      (Udirect_apply ("caml_resume", args, dinfo), Value_unknown)
-  | Lprim(Preperform, args) ->
+      let dbg = Debuginfo.from_location loc in
+      (Udirect_apply ("caml_resume", args, dbg), Value_unknown)
+  | Lprim(Preperform, args, loc) ->
       let args = close_list fenv cenv args in
-      (Udirect_apply ("caml_reperform", args, Debuginfo.none), Value_unknown)
-  | Lprim(p, args) ->
+      let dbg = Debuginfo.from_location loc in
+      (Udirect_apply ("caml_reperform", args, dbg), Value_unknown)
+  | Lprim(p, args, loc) ->
+      let dbg = Debuginfo.from_location loc in
       simplif_prim !Clflags.float_const_prop
-                   p (close_list_approx fenv cenv args) Debuginfo.none
+                   p (close_list_approx fenv cenv args) dbg
   | Lswitch(arg, sw) ->
       let fn fail =
         let (uarg, _) = close fenv cenv arg in
         let const_index, const_actions, fconst =
-          close_switch arg fenv cenv sw.sw_consts sw.sw_numconsts fail
+          close_switch fenv cenv sw.sw_consts sw.sw_numconsts fail
         and block_index, block_actions, fblock =
-          close_switch arg fenv cenv sw.sw_blocks sw.sw_numblocks fail in
+          close_switch fenv cenv sw.sw_blocks sw.sw_numblocks fail in
         let ulam =
           Uswitch
             (uarg,
@@ -984,7 +1027,7 @@ let rec close fenv cenv = function
             Ucatch (i,[],ubody,uhandler),Value_unknown
           else fn fail
       end
-  | Lstringswitch(arg,sw,d) ->
+  | Lstringswitch(arg,sw,d,_) ->
       let uarg,_ = close fenv cenv arg in
       let usw =
         List.map
@@ -1034,9 +1077,8 @@ let rec close fenv cenv = function
   | Lassign(id, lam) ->
       let (ulam, _) = close fenv cenv lam in
       (Uassign(id, ulam), Value_unknown)
-  | Levent(lam, ev) ->
-      let (ulam, approx) = close fenv cenv lam in
-      (add_debug_info ev ulam, approx)
+  | Levent(lam, _) ->
+      close fenv cenv lam
   | Lifused _ ->
       assert false
 
@@ -1054,7 +1096,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 _ as funct ->
       close_one_function fenv cenv id funct
   | lam ->
       close fenv cenv lam
@@ -1066,12 +1108,17 @@ 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; loc}) ->
+               Simplif.split_default_wrapper ~id ~kind ~params
+                 ~body ~attr ~wrapper_attr:attr ~loc ()
            | _ -> assert false
          )
          fun_defs)
   in
+  let inline_attribute = match fun_defs with
+    | [_, Lfunction{attr = { inline }}] -> inline
+    | _ -> Default_inline (* recursive functions can't be inlined *)
+  in
 
   (* Update and check nesting depth *)
   incr function_nesting_depth;
@@ -1086,7 +1133,7 @@ and close_functions fenv cenv fun_defs =
   let uncurried_defs =
     List.map
       (function
-          (id, Lfunction(kind, params, body)) ->
+          (id, Lfunction{kind; params; body; loc}) ->
             let label = Compilenv.make_symbol (Some (Ident.unique_name id)) in
             let arity = List.length params in
             let fundesc =
@@ -1095,20 +1142,21 @@ and close_functions fenv cenv fun_defs =
                fun_closed = initially_closed;
                fun_inline = None;
                fun_float_const_prop = !Clflags.float_const_prop } in
-            (id, params, body, fundesc)
+            let dbg = Debuginfo.from_location loc in
+            (id, params, body, fundesc, dbg)
         | (_, _) -> fatal_error "Closure.close_functions")
       fun_defs in
   (* Build an approximate fenv for compiling the functions *)
   let fenv_rec =
     List.fold_right
-      (fun (id, params, body, fundesc) fenv ->
+      (fun (id, _params, _body, fundesc, _dbg) fenv ->
         Tbl.add id (Value_closure(fundesc, Value_unknown)) fenv)
       uncurried_defs fenv in
   (* Determine the offsets of each function's closure in the shared block *)
   let env_pos = ref (-1) in
   let clos_offsets =
     List.map
-      (fun (id, params, body, fundesc) ->
+      (fun (_id, _params, _body, fundesc, _dbg) ->
         let pos = !env_pos + 1 in
         env_pos := !env_pos + 1 + (if fundesc.fun_arity <> 1 then 3 else 2);
         pos)
@@ -1118,16 +1166,13 @@ and close_functions fenv cenv fun_defs =
      does not use its environment parameter is invalidated. *)
   let useless_env = ref initially_closed in
   (* Translate each function definition *)
-  let clos_fundef (id, params, body, fundesc) env_pos =
-    let dbg = match body with
-      | Levent (_,({lev_kind=Lev_function} as ev)) -> Debuginfo.from_call ev
-      | _ -> Debuginfo.none in
+  let clos_fundef (id, params, body, fundesc, dbg) env_pos =
     let env_param = Ident.create "env" in
     let cenv_fv =
       build_closure_env env_param (fv_pos - env_pos) fv in
     let cenv_body =
       List.fold_right2
-        (fun (id, params, body, fundesc) pos env ->
+        (fun (id, _params, _body, _fundesc, _dbg) pos env ->
           Tbl.add id (Uoffset(Uvar env_param, pos - env_pos)) env)
         uncurried_defs clos_offsets cenv_fv in
     let (ubody, approx) = close fenv_rec cenv_body body in
@@ -1150,8 +1195,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
@@ -1166,7 +1222,7 @@ and close_functions fenv cenv fun_defs =
          recompile *)
         Compilenv.backtrack snap; (* PR#6337 *)
         List.iter
-          (fun (id, params, body, fundesc) ->
+          (fun (_id, _params, _body, fundesc, _dbg) ->
              fundesc.fun_closed <- false;
              fundesc.fun_inline <- None;
           )
@@ -1194,7 +1250,7 @@ and close_one_function fenv cenv id funct =
 
 (* Close a switch *)
 
-and close_switch arg fenv cenv cases num_keys default =
+and close_switch fenv cenv cases num_keys default =
   let ncases = List.length cases in
   let index = Array.make num_keys 0
   and store = Storer.mk_store () in
@@ -1257,15 +1313,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
@@ -1275,7 +1333,7 @@ let collect_exported_structured_constants a =
         List.iter (fun f -> ulam f.body) fl;
         List.iter ulam ul
     | Uoffset(u, _) -> ulam u
-    | Ulet (_, u1, u2) -> ulam u1; ulam u2
+    | Ulet (_str, _kind, _, u1, u2) -> ulam u1; ulam u2
     | Uletrec (l, u) -> List.iter (fun (_, u) -> ulam u) l; ulam u
     | Uprim (_, ul, _) -> List.iter ulam ul
     | Uswitch (u, sl) ->
@@ -1295,6 +1353,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
 
@@ -1309,8 +1368,12 @@ let intro size lam =
   let id = Compilenv.make_symbol None in
   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 (ulam, _approx) = close Tbl.empty Tbl.empty lam in
+  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 2db6e16336..f930e0fe52 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 0000000000..94eb4a1fa3
--- /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 0000000000..7acb844902
--- /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 c739b8ce9b..b9bac75bb2 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
@@ -52,6 +107,16 @@ let swap_comparison = function
   | Clt -> Cgt | Cle -> Cge
   | Cgt -> Clt | Cge -> Cle
 
+type label = int
+
+let label_counter = ref 99
+
+let new_label() = incr label_counter; !label_counter
+
+type raise_kind =
+  | Raise_withtrace
+  | Raise_notrace
+
 type memory_chunk =
     Byte_unsigned
   | Byte_signed
@@ -59,28 +124,31 @@ type memory_chunk =
   | Sixteen_signed
   | Thirtytwo_unsigned
   | Thirtytwo_signed
-  | Word
+  | Word_int
+  | Word_val
   | Single
   | Double
   | Double_u
 
-type operation =
+and operation =
     Capply of machtype * Debuginfo.t
-  | Cextcall of string * machtype * bool * Debuginfo.t
+  | Cextcall of string * machtype * bool * Debuginfo.t * label option
+    (** If specified, the given label will be placed immediately after the
+        call (at the same place as any frame descriptor would reference). *)
   | Cload of memory_chunk
   | Cloadmut
-  | Calloc
-  | Cstore of memory_chunk
+  | Calloc of Debuginfo.t
+  | 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
   | Cfloatofint | Cintoffloat
   | Ccmpf of comparison
-  | Craise of Lambda.raise_kind * Debuginfo.t
+  | Craise of raise_kind * Debuginfo.t
   | Ccheckbound of Debuginfo.t
 
 type expression =
@@ -90,7 +158,7 @@ type expression =
   | Cconst_symbol of string
   | Cconst_pointer of int
   | Cconst_natpointer of nativeint
-  | Cconst_blockheader of nativeint
+  | Cblockheader of nativeint * Debuginfo.t
   | Cvar of Ident.t
   | Clet of Ident.t * expression * expression
   | Cassign of Ident.t * expression
@@ -109,11 +177,11 @@ type fundecl =
     fun_args: (Ident.t * machtype) list;
     fun_body: expression;
     fun_fast: bool;
-    fun_dbg : Debuginfo.t; }
+    fun_dbg : Debuginfo.t;
+  }
 
 type data_item =
     Cdefine_symbol of string
-  | Cdefine_label of int
   | Cglobal_symbol of string
   | Cint8 of int
   | Cint16 of int
@@ -122,7 +190,6 @@ type data_item =
   | Csingle of float
   | Cdouble of float
   | Csymbol_address of string
-  | Clabel_address of int
   | Cstring of string
   | Cskip of int
   | Calign of int
@@ -130,3 +197,6 @@ type data_item =
 type phrase =
     Cfunction of fundecl
   | Cdata of data_item list
+
+let reset () =
+  label_counter := 99
diff --git a/asmcomp/cmm.mli b/asmcomp/cmm.mli
index ec9bc43fd3..e268050de7 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 =
@@ -38,6 +83,13 @@ type comparison =
 val negate_comparison: comparison -> comparison
 val swap_comparison: comparison -> comparison
 
+type label = int
+val new_label: unit -> label
+
+type raise_kind =
+  | Raise_withtrace
+  | Raise_notrace
+
 type memory_chunk =
     Byte_unsigned
   | Byte_signed
@@ -45,38 +97,40 @@ 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 *)
 
-type operation =
+and operation =
     Capply of machtype * Debuginfo.t
-  | Cextcall of string * machtype * bool * Debuginfo.t
+  | Cextcall of string * machtype * bool * Debuginfo.t * label option
   | Cload of memory_chunk
   | Cloadmut
-  | Calloc
-  | Cstore of memory_chunk
+  | Calloc of Debuginfo.t
+  | 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
   | Cfloatofint | Cintoffloat
   | Ccmpf of comparison
-  | Craise of Lambda.raise_kind * Debuginfo.t
+  | Craise of raise_kind * Debuginfo.t
   | Ccheckbound of Debuginfo.t
 
-type expression =
+and expression =
     Cconst_int of int
   | Cconst_natint of nativeint
   | Cconst_float of float
   | Cconst_symbol of string
   | Cconst_pointer of int
   | Cconst_natpointer of nativeint
-  | Cconst_blockheader of nativeint
+  | Cblockheader of nativeint * Debuginfo.t
   | Cvar of Ident.t
   | Clet of Ident.t * expression * expression
   | Cassign of Ident.t * expression
@@ -95,11 +149,11 @@ type fundecl =
     fun_args: (Ident.t * machtype) list;
     fun_body: expression;
     fun_fast: bool;
-    fun_dbg : Debuginfo.t; }
+    fun_dbg : Debuginfo.t;
+  }
 
 type data_item =
     Cdefine_symbol of string
-  | Cdefine_label of int
   | Cglobal_symbol of string
   | Cint8 of int
   | Cint16 of int
@@ -108,7 +162,6 @@ type data_item =
   | Csingle of float
   | Cdouble of float
   | Csymbol_address of string
-  | Clabel_address of int
   | Cstring of string
   | Cskip of int
   | Calign of int
@@ -116,3 +169,5 @@ type data_item =
 type phrase =
     Cfunction of fundecl
   | Cdata of data_item list
+
+val reset : unit -> unit
diff --git a/asmcomp/cmmgen.ml b/asmcomp/cmmgen.ml
index 9f6221331f..224555620c 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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-- *)
 
@@ -28,14 +31,19 @@ let bind name arg fn =
   match arg with
     Cvar _ | Cconst_int _ | Cconst_natint _ | Cconst_symbol _
   | Cconst_pointer _ | Cconst_natpointer _
-  | Cconst_blockheader _ -> fn arg
+  | Cblockheader _ -> 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 _
   | Cconst_pointer _ | Cconst_natpointer _
-  | Cconst_blockheader _ -> fn arg
+  | Cblockheader _ -> fn arg
   | _ -> let id = Ident.create name in Clet(id, arg, fn (Cvar id))
 
 let caml_black = Nativeint.shift_left (Nativeint.of_int 3) 8
@@ -64,14 +72,13 @@ 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)
-let alloc_infix_header ofs = Cconst_blockheader(infix_header ofs)
-let alloc_boxedint32_header = Cconst_blockheader(boxedint32_header)
-let alloc_boxedint64_header = Cconst_blockheader(boxedint64_header)
-let alloc_boxedintnat_header = Cconst_blockheader(boxedintnat_header)
+let alloc_float_header dbg = Cblockheader(float_header, dbg)
+let alloc_floatarray_header len dbg = Cblockheader(floatarray_header len, dbg)
+let alloc_closure_header sz dbg = Cblockheader(white_closure_header sz, dbg)
+let alloc_infix_header ofs dbg = Cblockheader(infix_header ofs, dbg)
+let alloc_boxedint32_header dbg = Cblockheader(boxedint32_header, dbg)
+let alloc_boxedint64_header dbg = Cblockheader(boxedint64_header, dbg)
+let alloc_boxedintnat_header dbg = Cblockheader(boxedintnat_header, dbg)
 
 (* Integers *)
 
@@ -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) ->
+  | (_, Cconst_int 0) | (Cconst_int 0, _) ->
       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. *)
@@ -294,11 +320,19 @@ let validate d m p =
   ucompare2 twoszp md < 0 && ucompare2 md (add2 twoszp twop1) <= 0
 *)
 
-let rec div_int c1 c2 dbg =
+let raise_regular dbg exc =
+  Csequence(
+    Cop(Cstore (Thirtytwo_signed, Assignment),
+        [(Cconst_symbol "caml_backtrace_pos"); Cconst_int 0]),
+      Cop(Craise (Raise_withtrace, dbg),[exc]))
+
+let raise_symbol dbg symb =
+  raise_regular dbg (Cconst_symbol symb)
+
+let rec div_int c1 c2 is_safe dbg =
   match (c1, c2) with
     (c1, Cconst_int 0) ->
-      Csequence(c1, Cop(Craise (Raise_regular, dbg),
-                        [Cconst_symbol "caml_exn_Division_by_zero"]))
+      Csequence(c1, raise_symbol dbg "caml_exn_Division_by_zero")
   | (c1, Cconst_int 1) ->
       c1
   | (Cconst_int 0 as c1, c2) ->
@@ -320,7 +354,7 @@ let rec div_int c1 c2 dbg =
                      add_int c1 t);
                    Cconst_int l])
       else if n < 0 then
-        sub_int (Cconst_int 0) (div_int c1 (Cconst_int (-n)) dbg)
+        sub_int (Cconst_int 0) (div_int c1 (Cconst_int (-n)) is_safe dbg)
       else begin
         let (m, p) = divimm_parameters (Nativeint.of_int n) in
         (* Algorithm:
@@ -335,20 +369,18 @@ let rec div_int c1 c2 dbg =
           let t = if p > 0 then Cop(Casr, [t; Cconst_int p]) else t in
           add_int t (lsr_int c1 (Cconst_int (Nativeint.size - 1))))
       end
-  | (c1, c2) when !Clflags.fast ->
+  | (c1, c2) when !Clflags.fast || is_safe = Lambda.Unsafe ->
       Cop(Cdivi, [c1; c2])
   | (c1, c2) ->
       bind "divisor" c2 (fun c2 ->
         Cifthenelse(c2,
                     Cop(Cdivi, [c1; c2]),
-                    Cop(Craise (Raise_regular, dbg),
-                        [Cconst_symbol "caml_exn_Division_by_zero"])))
+                    raise_symbol dbg "caml_exn_Division_by_zero"))
 
-let mod_int c1 c2 dbg =
+let mod_int c1 c2 is_safe dbg =
   match (c1, c2) with
     (c1, Cconst_int 0) ->
-      Csequence(c1, Cop(Craise (Raise_regular, dbg),
-                        [Cconst_symbol "caml_exn_Division_by_zero"]))
+      Csequence(c1, raise_symbol dbg "caml_exn_Division_by_zero")
   | (c1, Cconst_int (1 | (-1))) ->
       Csequence(c1, Cconst_int 0)
   | (Cconst_int 0, c2) ->
@@ -373,15 +405,15 @@ let mod_int c1 c2 dbg =
           sub_int c1 t)
       else
         bind "dividend" c1 (fun c1 ->
-          sub_int c1 (mul_int (div_int c1 c2 dbg) c2))
-  | (c1, c2) when !Clflags.fast ->
+          sub_int c1 (mul_int (div_int c1 c2 is_safe dbg) c2))
+  | (c1, c2) when !Clflags.fast || is_safe = Lambda.Unsafe ->
+      (* Flambda already generates that test *)
       Cop(Cmodi, [c1; c2])
   | (c1, c2) ->
       bind "divisor" c2 (fun c2 ->
         Cifthenelse(c2,
                     Cop(Cmodi, [c1; c2]),
-                    Cop(Craise (Raise_regular, dbg),
-                        [Cconst_symbol "caml_exn_Division_by_zero"])))
+                    raise_symbol dbg "caml_exn_Division_by_zero"))
 
 (* Division or modulo on boxed integers.  The overflow case min_int / -1
    can occur, in which case we force x / -1 = -x and x mod -1 = 0. (PR#5513). *)
@@ -391,35 +423,39 @@ let is_different_from x = function
   | Cconst_natint n -> n <> Nativeint.of_int x
   | _ -> false
 
-let safe_divmod_bi mkop mkm1 c1 c2 bi dbg =
+let safe_divmod_bi mkop is_safe mkm1 c1 c2 bi dbg =
   bind "dividend" c1 (fun c1 ->
   bind "divisor" c2 (fun c2 ->
-    let c = mkop c1 c2 dbg in
+    let c = mkop c1 c2 is_safe dbg in
     if Arch.division_crashes_on_overflow
     && (size_int = 4 || bi <> Pint32)
     && not (is_different_from (-1) c2)
     then Cifthenelse(Cop(Ccmpi Cne, [c2; Cconst_int(-1)]), c, mkm1 c1)
     else c))
 
-let safe_div_bi =
-  safe_divmod_bi div_int (fun c1 -> Cop(Csubi, [Cconst_int 0; c1]))
+let safe_div_bi is_safe =
+  safe_divmod_bi div_int is_safe (fun c1 -> Cop(Csubi, [Cconst_int 0; c1]))
 
-let safe_mod_bi =
-  safe_divmod_bi mod_int (fun c1 -> Cconst_int 0)
+let safe_mod_bi is_safe =
+  safe_divmod_bi mod_int is_safe (fun _ -> Cconst_int 0)
 
 (* Bool *)
 
 let test_bool = function
     Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1]) -> c
-  | 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 *)
 
-let box_float c = Cop(Calloc, [alloc_float_header; c])
+let box_float dbg c = Cop(Calloc dbg, [alloc_float_header dbg; c])
 
 let rec unbox_float = function
-    Cop(Calloc, [header; c]) -> c
+    Cop(Calloc _, [_header; c]) -> c
   | Clet(id, exp, body) -> Clet(id, exp, unbox_float body)
   | Cifthenelse(cond, e1, e2) ->
       Cifthenelse(cond, unbox_float e1, unbox_float e2)
@@ -431,8 +467,8 @@ let rec unbox_float = function
 
 (* Complex *)
 
-let box_complex c_re c_im =
-  Cop(Calloc, [alloc_floatarray_header 2; c_re; c_im])
+let box_complex dbg c_re c_im =
+  Cop(Calloc dbg, [alloc_floatarray_header 2 dbg; c_re; c_im])
 
 let complex_re c = Cop(Cload Double_u, [c])
 let complex_im c = Cop(Cload Double_u,
@@ -457,10 +493,10 @@ let rec remove_unit = function
       Ctrywith(remove_unit body, exn, remove_unit handler)
   | Clet(id, c1, c2) ->
       Clet(id, c1, remove_unit c2)
-  | Cop(Capply (mty, dbg), args) ->
+  | Cop(Capply (_mty, dbg), args) ->
       Cop(Capply (typ_void, dbg), args)
-  | Cop(Cextcall(proc, mty, alloc, dbg), args) ->
-      Cop(Cextcall(proc, typ_void, alloc, dbg), args)
+  | Cop(Cextcall(proc, _mty, alloc, dbg, label_after), args) ->
+      Cop(Cextcall(proc, typ_void, alloc, dbg, label_after), args)
   | Cexit (_,_) as c -> c
   | Ctuple [] as c -> c
   | c -> Csequence(c, Ctuple [])
@@ -472,13 +508,8 @@ let field_address ptr n =
   then ptr
   else Cop(Cadda, [ptr; Cconst_int(n * size_addr)])
 
-let float_field_address ptr n =
-  if n = 0
-  then ptr
-  else Cop(Cadda, [ptr; Cconst_int(n * size_float)])
-
-let get_field base n =
-  Cop(Cload Word, [field_address base n])
+let get_field ptr n =
+  Cop(Cload Word_val, [field_address ptr n])
 
 let get_mut_field base n =
   Cop(Cloadmut, [base; n])
@@ -487,20 +518,24 @@ let set_addr_field base n newval =
   Cop(Cextcall("caml_modify_field", typ_void, false, Debuginfo.none),
       [base; Cconst_int n; newval])
 
-let set_int_field base n newval =
-  Cop(Cstore Word, [field_address base n; newval])
-
-let set_float_field base n newval =
-  Cop(Cstore Double_u, [float_field_address base n; newval])
+let set_int_field init base n newval =
+  Cop(Cstore (Word_val, init), [field_address base n; newval])
 
 let init_field base n newval =
   let promoted = Cop (Cextcall("caml_obj_promote_to", typ_addr,
                                true, Debuginfo.none),
                       [newval; base]) in
-  set_addr_field base n promoted
+  set_int_field Initialization base n promoted
 
 let header ptr =
-  Cop(Cload Word, [Cop(Cadda, [ptr; Cconst_int(-size_int)])])
+  if Config.spacetime then
+    let non_profinfo_mask = (1 lsl (64 - Config.profinfo_width)) - 1 in
+    Cop(Cand, [Cop (Cload Word_int,
+        [Cop(Cadda, [ptr; Cconst_int(-size_int)])]);
+      Cconst_int non_profinfo_mask;
+    ])
+  else
+    Cop(Cload Word_int, [Cop(Cadda, [ptr; Cconst_int(-size_int)])])
 
 let tag_offset =
   if big_endian then -1 else -size_int
@@ -533,38 +568,58 @@ 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 =
   get_mut_field arr (untag_int ofs)
 let int_array_ref arr ofs =
-  Cop(Cload Word, [array_indexing log2_size_addr 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 =
-  box_float(unboxed_float_array_ref arr ofs)
+let float_array_ref dbg arr ofs =
+  box_float dbg (unboxed_float_array_ref arr ofs)
 
 let addr_array_set arr ofs newval =
   Cop(Cextcall("caml_modify_field", typ_void, false, Debuginfo.none),
       [arr; untag_int 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 *)
 
@@ -588,27 +643,28 @@ 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,
+          None),
         [obj; tag]))
 
 let lookup_label obj lab =
   bind "lab" lab (fun lab ->
-    let table = get_mut_field obj (Cconst_int 0) 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)
 
 (* Allocation *)
 
-let make_alloc_generic set_fn tag wordsize args =
+let make_alloc_generic set_fn dbg tag wordsize args =
   if wordsize <= Config.max_young_wosize then
-    Cop(Calloc, Cconst_blockheader(block_header tag wordsize) :: args)
+    Cop(Calloc dbg, Cblockheader(block_header tag wordsize, dbg) :: args)
   else begin
     let id = Ident.create "alloc" in
     let rec fill_fields idx = function
@@ -616,22 +672,22 @@ let make_alloc_generic set_fn tag wordsize args =
     | e1::el -> Csequence(set_fn (Cvar id) idx e1,
                           fill_fields (idx + 1) el) in
     Clet(id,
-         Cop(Cextcall("caml_alloc", typ_addr, true, Debuginfo.none),
+         Cop(Cextcall("caml_alloc", typ_val, true, Debuginfo.none, None),
                  [Cconst_int wordsize; Cconst_int tag]),
          fill_fields 0 args)
   end
 
-let make_alloc tag args =
-  make_alloc_generic init_field tag (List.length args) args
+let make_alloc dbg tag args =
+  make_alloc_generic init_field dbg tag (List.length args) args
 
-let make_addr_array_alloc args =
-  make_alloc_generic set_addr_field 0 (List.length args) args
+let make_addr_array_alloc dbg args =
+  make_alloc_generic set_addr_field dbg 0 (List.length args) args
 
-let make_int_array_alloc args =
-  make_alloc_generic set_int_field 0 (List.length args) args
+let make_int_array_alloc dbg args =
+  make_alloc_generic set_int_field dbg 0 (List.length args) args
 
-let make_float_array_alloc args =
-  make_alloc_generic set_float_field Obj.double_array_tag
+let make_float_array_alloc dbg tag args =
+  make_alloc_generic float_array_set dbg tag
                      (List.length args * size_float / size_addr) args
 
 (* Bounds checking *)
@@ -647,7 +703,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
 
@@ -661,21 +728,29 @@ let rec expr_size env = function
       begin try Ident.find_same id env with Not_found -> RHS_nonrec end
   | Uclosure(fundecls, clos_vars) ->
       RHS_block (fundecls_size fundecls + List.length clos_vars)
-  | Ulet(id, exp, body) ->
+  | Ulet(_str, _kind, id, exp, body) ->
       expr_size (Ident.add id (expr_size env exp) env) body
-  | Uletrec(bindings, body) ->
+  | Uletrec(_bindings, body) ->
       expr_size env body
-  | Uprim(Pmakeblock(tag, mut), args, _) ->
+  | Uprim(Pmakeblock _, 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_unboxed _, _), _, _) ->
+      assert false
+  | Uprim (Pduprecord (Record_extension, sz), _, _) ->
+      RHS_block (sz + 1)
   | Uprim (Pduprecord (Record_float, sz), _, _) ->
       RHS_floatblock sz
-  | Usequence(exp, exp') ->
+  | 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
 
@@ -718,8 +793,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 *)
 
@@ -741,7 +818,7 @@ let alloc_header_boxed_int bi =
   | Pint32 -> alloc_boxedint32_header
   | Pint64 -> alloc_boxedint64_header
 
-let box_int bi arg =
+let box_int dbg bi arg =
   match arg with
     Cconst_int n ->
       transl_structured_constant (box_int_constant bi (Nativeint.of_int n))
@@ -752,21 +829,28 @@ let box_int bi arg =
         if bi = Pint32 && size_int = 8 && big_endian
         then Cop(Clsl, [arg; Cconst_int 32])
         else arg in
-      Cop(Calloc, [alloc_header_boxed_int bi;
+      Cop(Calloc dbg, [alloc_header_boxed_int bi dbg;
                    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])])
+    Cop(Calloc _, [_hdr; _ops; Cop(Clsl, [contents; Cconst_int 32])])
     when bi = Pint32 && size_int = 8 && big_endian ->
       (* Force sign-extension of low 32 bits *)
       Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32]); Cconst_int 32])
-  | Cop(Calloc, [hdr; ops; contents])
+  | Cop(Calloc _, [_hdr; _ops; contents])
     when bi = Pint32 && size_int = 8 && not big_endian ->
       (* Force sign-extension of low 32 bits *)
       Cop(Casr, [Cop(Clsl, [contents; Cconst_int 32]); Cconst_int 32])
-  | Cop(Calloc, [hdr; ops; contents]) ->
+  | Cop(Calloc _, [_hdr; _ops; contents]) ->
       contents
   | Clet(id, exp, body) -> Clet(id, exp, unbox_int bi body)
   | Cifthenelse(cond, e1, e2) ->
@@ -776,7 +860,10 @@ 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),
+      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 =
@@ -784,6 +871,50 @@ let make_unsigned_int bi arg =
   then Cop(Cand, [arg; Cconst_natint 0xFFFFFFFFn])
   else arg
 
+(* Boxed numbers *)
+
+type boxed_number =
+  | Boxed_float of Debuginfo.t
+  | Boxed_integer of boxed_integer * Debuginfo.t
+
+let equal_unboxed_integer ui1 ui2 =
+  match ui1, ui2 with
+  | Pnativeint, Pnativeint -> true
+  | Pint32, Pint32 -> true
+  | Pint64, Pint64 -> true
+  | _, _ -> false
+
+let equal_boxed_number bn1 bn2 =
+  match bn1, bn2 with
+  | Boxed_float _, Boxed_float _ -> true
+  | Boxed_integer(ui1, _), Boxed_integer(ui2, _) ->
+    equal_unboxed_integer ui1 ui2
+  | _, _ -> false
+
+let box_number bn arg =
+  match bn with
+  | Boxed_float dbg -> box_float dbg arg
+  | Boxed_integer (bi, dbg) -> box_int dbg bi arg
+
+type env = {
+  unboxed_ids : (Ident.t * boxed_number) Ident.tbl;
+}
+
+let empty_env =
+  {
+    unboxed_ids =Ident.empty;
+  }
+
+let is_unboxed_id id env =
+  try Some (Ident.find_same id env.unboxed_ids)
+  with Not_found -> None
+
+let add_unboxed_id id unboxed_id bn env =
+  {
+    unboxed_ids = Ident.add id (unboxed_id, bn) env.unboxed_ids;
+  }
+
+
 (* Big arrays *)
 
 let bigarray_elt_size = function
@@ -801,22 +932,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 ->
@@ -827,11 +976,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
@@ -842,9 +989,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
 
@@ -856,7 +1003,7 @@ let bigarray_get unsafe elt_kind layout b args dbg =
         let sz = bigarray_elt_size elt_kind / 2 in
         bind "addr" (bigarray_indexing unsafe elt_kind layout b args dbg)
           (fun addr ->
-          box_complex
+          box_complex dbg
             (Cop(Cload kind, [addr]))
             (Cop(Cload kind, [Cop(Cadda, [addr; Cconst_int sz])])))
     | _ ->
@@ -873,11 +1020,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 =
@@ -892,14 +1039,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 =
@@ -923,7 +1070,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
@@ -938,19 +1085,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,
@@ -986,7 +1133,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
@@ -1009,24 +1156,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 =
@@ -1049,8 +1196,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")
@@ -1065,8 +1211,8 @@ let simplif_primitive_32bits = function
   | Paddbint Pint64 -> Pccall (default_prim "caml_int64_add")
   | Psubbint Pint64 -> Pccall (default_prim "caml_int64_sub")
   | Pmulbint Pint64 -> Pccall (default_prim "caml_int64_mul")
-  | Pdivbint Pint64 -> Pccall (default_prim "caml_int64_div")
-  | Pmodbint Pint64 -> Pccall (default_prim "caml_int64_mod")
+  | Pdivbint {size=Pint64} -> Pccall (default_prim "caml_int64_div")
+  | Pmodbint {size=Pint64} -> Pccall (default_prim "caml_int64_mod")
   | Pandbint Pint64 -> Pccall (default_prim "caml_int64_and")
   | Porbint Pint64 ->  Pccall (default_prim "caml_int64_or")
   | Pxorbint Pint64 -> Pccall (default_prim "caml_int64_xor")
@@ -1079,9 +1225,9 @@ let simplif_primitive_32bits = function
   | Pbintcomp(Pint64, Lambda.Cgt) -> Pccall (default_prim "caml_greaterthan")
   | Pbintcomp(Pint64, Lambda.Cle) -> Pccall (default_prim "caml_lessequal")
   | Pbintcomp(Pint64, Lambda.Cge) -> Pccall (default_prim "caml_greaterequal")
-  | Pbigarrayref(unsafe, n, Pbigarray_int64, layout) ->
+  | Pbigarrayref(_unsafe, n, Pbigarray_int64, _layout) ->
       Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
-  | Pbigarrayset(unsafe, n, Pbigarray_int64, layout) ->
+  | Pbigarrayset(_unsafe, n, Pbigarray_int64, _layout) ->
       Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
   | Pstring_load_64(_) -> Pccall (default_prim "caml_string_get64")
   | Pstring_set_64(_) -> Pccall (default_prim "caml_string_set64")
@@ -1094,13 +1240,13 @@ let simplif_primitive p =
   match p with
   | Pduprecord _ ->
       Pccall (default_prim "caml_obj_dup")
-  | Pbigarrayref(unsafe, n, Pbigarray_unknown, layout) ->
+  | Pbigarrayref(_unsafe, n, Pbigarray_unknown, _layout) ->
       Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
-  | Pbigarrayset(unsafe, n, Pbigarray_unknown, layout) ->
+  | Pbigarrayset(_unsafe, n, Pbigarray_unknown, _layout) ->
       Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
-  | Pbigarrayref(unsafe, n, kind, Pbigarray_unknown_layout) ->
+  | Pbigarrayref(_unsafe, n, _kind, Pbigarray_unknown_layout) ->
       Pccall (default_prim ("caml_ba_get_" ^ string_of_int n))
-  | Pbigarrayset(unsafe, n, kind, Pbigarray_unknown_layout) ->
+  | Pbigarrayset(_unsafe, n, _kind, Pbigarray_unknown_layout) ->
       Pccall (default_prim ("caml_ba_set_" ^ string_of_int n))
   | p ->
       if size_int = 8 then p else simplif_primitive_32bits p
@@ -1124,7 +1270,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
@@ -1221,99 +1366,110 @@ 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 * bool (* true: boxed form available at no cost *)
+  | No_result (* expression never returns a result *)
+
+let unboxed_number_kind_of_unbox dbg = function
+  | Same_as_ocaml_repr -> No_unboxing
+  | Unboxed_float -> Boxed (Boxed_float dbg, false)
+  | Unboxed_integer bi -> Boxed (Boxed_integer (bi, dbg), false)
+  | Untagged_int -> No_unboxing
+
+let rec is_unboxed_number ~strict env e =
+  (* Given unboxed_number_kind from two branches of the code, returns the
+     resulting unboxed_number_kind.
+
+     If [strict=false], one knows that the type of the expression
+     is an unboxable number, and we decide to return an unboxed value
+     if this indeed eliminates at least one allocation.
+
+     If [strict=true], we need to ensure that all possible branches
+     return an unboxable number (of the same kind).  This could not
+     be the case in presence of GADTs.
+ *)
+  let join k1 e =
+    match k1, is_unboxed_number ~strict env e with
+    | Boxed (b1, c1), Boxed (b2, c2) when equal_boxed_number b1 b2 ->
+        Boxed (b1, c1 && c2)
+    | No_result, k | k, No_result ->
+        k (* if a branch never returns, it is safe to unbox it *)
+    | No_unboxing, k | k, No_unboxing when not strict ->
+        k
+    | _, _ -> No_unboxing
+  in
+  match e with
+  | Uvar id ->
+      begin match is_unboxed_id id env with
+      | None -> No_unboxing
+      | Some (_, bn) -> Boxed (bn, false)
+      end
 
-let rec is_unboxed_number = function
-    Uconst(Uconst_ref(_, Uconst_float _)) ->
-      Boxed_float
-  | Uprim(p, _, _) ->
+  | Uconst(Uconst_ref(_, Some (Uconst_float _))) ->
+      Boxed (Boxed_float Debuginfo.none, true)
+  | Uconst(Uconst_ref(_, Some (Uconst_int32 _))) ->
+      Boxed (Boxed_integer (Pint32, Debuginfo.none), true)
+  | Uconst(Uconst_ref(_, Some (Uconst_int64 _))) ->
+      Boxed (Boxed_integer (Pint64, Debuginfo.none), true)
+  | Uconst(Uconst_ref(_, Some (Uconst_nativeint _))) ->
+      Boxed (Boxed_integer (Pnativeint, Debuginfo.none), true)
+  | Uprim(p, _, dbg) ->
       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 dbg p.prim_native_repr_res
+        | Pfloatfield _
+        | Pfloatofint
+        | Pnegfloat
+        | Pabsfloat
+        | Paddfloat
+        | Psubfloat
+        | Pmulfloat
+        | Pdivfloat
+        | Parrayrefu Pfloatarray
+        | Parrayrefs Pfloatarray -> Boxed (Boxed_float dbg, false)
+        | Pbintofint bi
+        | Pcvtbint(_, bi)
+        | Pnegbint bi
+        | Paddbint bi
+        | Psubbint bi
+        | Pmulbint bi
+        | Pdivbint {size=bi}
+        | Pmodbint {size=bi}
+        | Pandbint bi
+        | Porbint bi
+        | Pxorbint bi
+        | Plslbint bi
+        | Plsrbint bi
+        | Pasrbint bi
+        | Pbbswap bi -> Boxed (Boxed_integer (bi, dbg), false)
         | 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 dbg, false)
+        | Pbigarrayref(_, _, Pbigarray_int32, _) ->
+            Boxed (Boxed_integer (Pint32, dbg), false)
+        | Pbigarrayref(_, _, Pbigarray_int64, _) ->
+            Boxed (Boxed_integer (Pint64, dbg), false)
+        | Pbigarrayref(_, _, Pbigarray_native_int,_) ->
+            Boxed (Boxed_integer (Pnativeint, dbg), false)
+        | Pstring_load_32(_) -> Boxed (Boxed_integer (Pint32, dbg), false)
+        | Pstring_load_64(_) -> Boxed (Boxed_integer (Pint64, dbg), false)
+        | Pbigstring_load_32(_) -> Boxed (Boxed_integer (Pint32, dbg), false)
+        | Pbigstring_load_64(_) -> Boxed (Boxed_integer (Pint64, dbg), false)
+        | 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
-      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
+  | Ulet (_, _, _, _, e) | Uletrec (_, e) | Usequence (_, e) ->
+      is_unboxed_number ~strict 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(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 ~strict env e1) e2
+  | _ -> No_unboxing
 
 (* Translate an expression *)
 
@@ -1328,14 +1484,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) ->
@@ -1343,17 +1504,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
+              then alloc_closure_header block_size f.dbg
+              else alloc_infix_header pos f.dbg in
+            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 ::
@@ -1361,131 +1522,118 @@ let rec transl = function
               int_const f.arity ::
               Cconst_symbol f.label ::
               transl_fundecls (pos + 4) rem in
-      Cop(Calloc, transl_fundecls 0 fundecls)
+      Cop(Calloc Debuginfo.none, 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))
-  | 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
+            bind "met" (lookup_tag obj (transl env met)) (call_met obj args))
+  | Ulet(str, kind, id, exp, body) ->
+      transl_let env str kind id exp body
   | Uletrec(bindings, body) ->
-      transl_letrec bindings (transl body)
+      transl_letrec env bindings (transl env body)
 
   (* Primitives *)
   | Uprim(prim, args, dbg) ->
       begin match (simplif_primitive prim, args) with
         (Pgetglobal id, []) ->
           Cconst_symbol (Ident.name id)
-      | (Pmakeblock(tag, mut), []) ->
+      | (Pmakeblock _, []) ->
           assert false
-      | (Pmakeblock(tag, mut), args) ->
-          make_alloc tag (List.map transl args)
+      | (Pmakeblock(tag, _mut, _kind), args) ->
+          make_alloc dbg 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 dbg 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 _, []) ->
           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_addr_array_alloc (List.map transl args)])
-          | Paddrarray ->
-              make_addr_array_alloc (List.map transl args)
-          | Pintarray ->
-              make_int_array_alloc (List.map transl args)
-          | Pfloatarray ->
-              make_float_array_alloc (List.map transl_unbox_float args)
-          end
-      | (Pbigarrayref(unsafe, num_dims, elt_kind, layout), arg1 :: argl) ->
+      | (Pmakearray (kind, _), args) -> transl_make_array dbg 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_float32 | Pbigarray_float64 -> box_float dbg elt
           | Pbigarray_complex32 | Pbigarray_complex64 -> elt
-          | Pbigarray_int32 -> box_int Pint32 elt
-          | Pbigarray_int64 -> box_int Pint64 elt
-          | Pbigarray_native_int -> box_int Pnativeint elt
+          | Pbigarray_int32 -> box_int dbg Pint32 elt
+          | Pbigarray_int64 -> box_int dbg Pint64 elt
+          | Pbigarray_native_int -> box_int dbg Pnativeint elt
           | Pbigarray_caml_int -> force_tag_int elt
           | _ -> tag_int elt
           end
-      | (Pbigarrayset(unsafe, num_dims, elt_kind, layout), arg1 :: argl) ->
+      | (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
-      | (p, [arg1; arg2; arg3; arg4]) ->
-          transl_prim_4 p arg1 arg2 arg3 arg4 dbg
-      | (prim, _) ->
-        let (_ : string) = Format.flush_str_formatter () in
-        Printlambda.primitive Format.str_formatter prim;
-        fatal_error (Printf.sprintf "Cmmgen.transl_prim %s"
-            (Format.flush_str_formatter ()))
+          transl_prim_3 env p arg1 arg2 arg3 dbg
+      | (_, _) ->
+          fatal_error "Cmmgen.transl:prim"
       end
 
   (* Control structures *)
@@ -1494,73 +1642,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
@@ -1569,15 +1719,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,
@@ -1587,246 +1737,336 @@ 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 dbg env kind args =
+  match kind with
+    Pgenarray ->
+      Cop(Cextcall("caml_make_array", typ_addr, true, Debuginfo.none),
+          [make_addr_array_alloc dbg (List.map (transl env) args)])
+  | Paddrarray ->
+      make_addr_array_alloc dbg (List.map (transl env) args)
+  | Pintarray ->
+      make_int_array_alloc dbg (List.map (transl env) args)
+  | Pfloatarray ->
+      make_float_array_alloc dbg (List.map transl_unbox_float 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 dbg)
+    | Unboxed_integer Pint64 when size_int = 4 ->
+        ([|Int; Int|], box_int dbg Pint64)
+    | Unboxed_integer bi -> (typ_int, box_int dbg bi)
+    | Untagged_int -> (typ_int, tag_int)
+  in
+  let args = transl_args prim.prim_native_repr_args args in
+  wrap_result
+    (Cop(Cextcall(Primitive.native_name prim,
+                  typ_res, prim.prim_alloc, dbg, None), args))
 
-and transl_prim_1 p arg dbg =
+and transl_prim_1 env p arg dbg =
   match p with
   (* Generic operations *)
-    Pidentity ->
-      transl arg
+    Pidentity | Pbytes_to_string | Pbytes_of_string | Popaque ->
+      transl env arg
   | Pignore ->
-      return_unit(remove_unit (transl arg))
+      return_unit(remove_unit (transl env arg))
   (* Heap operations *)
   | Pfield(n, is_ptr, mut) ->
-      if is_ptr && (mut = Mutable) then get_mut_field (transl arg) (Cconst_int n)
-      else get_field (transl arg) n
+      if is_ptr && (mut = Mutable)
+      then get_mut_field (transl env arg) (Cconst_int n)
+      else get_field (transl env arg) n
   | Pfloatfield n ->
-      let ptr = transl arg in
-      box_float(
+      let ptr = transl env arg in
+      box_float dbg (
         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])
+  | Praise _ when not (!Clflags.debug) ->
+      Cop(Craise (Cmm.Raise_notrace, dbg), [transl env arg])
+  | Praise Lambda.Raise_notrace ->
+      Cop(Craise (Cmm.Raise_notrace, dbg), [transl env arg])
+  | Praise Lambda.Raise_reraise ->
+      Cop(Craise (Cmm.Raise_withtrace, dbg), [transl env arg])
+  | Praise Lambda.Raise_regular ->
+      raise_regular 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")
+        | Backend_type ->
+            tag_int (Cconst_int 0) (* tag 0 is the same as Native here *)
       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 dbg (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 dbg (Cop(Cnegf, [transl_unbox_float env arg]))
   | Pabsfloat ->
-      box_float(Cop(Cabsf, [transl_unbox_float arg]))
+      box_float dbg (Cop(Cabsf, [transl_unbox_float env arg]))
   (* String operations *)
-  | Pstringlength ->
-      tag_int(string_length (transl arg))
+  | Pstringlength | Pbyteslength ->
+      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 dbg 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 dbg bi2 (transl_unbox_int env bi1 arg)
   | Pnegbint bi ->
-      box_int bi (Cop(Csubi, [Cconst_int 0; transl_unbox_int bi arg]))
+      box_int dbg bi (Cop(Csubi, [Cconst_int 0; transl_unbox_int env bi arg]))
   | Pbbswap bi ->
       let prim = match bi with
         | Pnativeint -> "nativeint"
         | Pint32 -> "int32"
         | 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]))
+      box_int dbg bi (Cop(Cextcall(Printf.sprintf "caml_%s_direct_bswap" prim,
+                               typ_int, false, Debuginfo.none, None),
+                      [transl_unbox_int env bi arg]))
   | Pbswap16 ->
       tag_int (Cop(Cextcall("caml_bswap16_direct", typ_int, false,
-                            Debuginfo.none),
-                   [untag_int (transl arg)]))
+                            Debuginfo.none, None),
+                   [untag_int (transl env arg)]))
   | Patomic_load ->
      Cop (Cextcall("caml_atomic_load", typ_addr, true, Debuginfo.none),
-          [transl arg])
+          [transl env arg])
   | prim ->
-      let (_ : string) = Format.flush_str_formatter () in
-      Printlambda.primitive Format.str_formatter prim;
-      fatal_error (Printf.sprintf "Cmmgen.transl_prim_1 %s"
-          (Format.flush_str_formatter ()))
+      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, is_ptr, mut) ->
-      let set =
-        if not (is_ptr) then set_int_field
-        else if mut = Mutable then set_addr_field
-        else init_field
-      in
-        return_unit (set (transl arg1) n (transl arg2))
-  | Psetfloatfield n ->
-      return_unit (set_float_field (transl arg1) n (transl_unbox_float arg2))
+    Psetfield(n, ptr, init) ->
+      begin match init, ptr with
+      | _, Immediate ->
+          return_unit (set_int_field init (transl env arg1) n (transl env arg2))
+      | Assignment, Pointer ->
+          return_unit (set_addr_field (transl env arg1) n (transl env arg2))
+      | Initialization, Pointer ->
+          return_unit (init_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, init),
+            [if n = 0 then ptr
+                       else Cop(Cadda, [ptr; Cconst_int(n * size_float)]);
+                   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)))
-  | Pdivint ->
-      tag_int(div_int (untag_int(transl arg1)) (untag_int(transl arg2)) dbg)
-  | Pmodint ->
-      tag_int(mod_int (untag_int(transl arg1)) (untag_int(transl arg2)) dbg)
+     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 is_safe ->
+      tag_int(div_int (untag_int(transl env arg1))
+        (untag_int(transl env arg2)) is_safe dbg)
+  | Pmodint is_safe ->
+      tag_int(mod_int (untag_int(transl env arg1))
+        (untag_int(transl env arg2)) is_safe 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]))
+      box_float dbg (Cop(Caddf,
+                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
   | Psubfloat ->
-      box_float(Cop(Csubf,
-                    [transl_unbox_float arg1; transl_unbox_float arg2]))
+      box_float dbg (Cop(Csubf,
+                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
   | Pmulfloat ->
-      box_float(Cop(Cmulf,
-                    [transl_unbox_float arg1; transl_unbox_float arg2]))
+      box_float dbg (Cop(Cmulf,
+                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
   | Pdivfloat ->
-      box_float(Cop(Cdivf,
-                    [transl_unbox_float arg1; transl_unbox_float arg2]))
+      box_float dbg (Cop(Cdivf,
+                    [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 ->
+  | Pstringrefu | Pbytesrefu ->
       tag_int(Cop(Cload Byte_unsigned,
-                  [add_int (transl arg1) (untag_int(transl arg2))]))
-  | Pstringrefs ->
+                  [add_int (transl env arg1) (untag_int(transl env arg2))]))
+  | Pstringrefs | Pbytesrefs ->
       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 ->
+     box_int dbg Pint32
+       (bind "str" (transl env arg1) (fun str ->
+        bind "index" (untag_int (transl env arg2)) (fun idx ->
           check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 3))
                       idx (unaligned_load_32 str idx))))
 
   | 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]))
+     box_int dbg Pint32
+       (bind "ba" (transl env arg1) (fun ba ->
+        bind "index" (untag_int (transl env arg2)) (fun idx ->
+        bind "ba_data" (Cop(Cload Word_int, [field_address ba 1]))
+         (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 ->
+     box_int dbg Pint64
+       (bind "str" (transl env arg1) (fun str ->
+        bind "index" (untag_int (transl env arg2)) (fun idx ->
           check_bound unsafe dbg (sub_int (string_length str) (Cconst_int 7))
                       idx (unaligned_load_64 str idx))))
 
   | 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]))
+     box_int dbg Pint64
+       (bind "ba" (transl env arg1) (fun ba ->
+        bind "index" (untag_int (transl env arg2)) (fun idx ->
+        bind "ba_data" (Cop(Cload Word_int, [field_address ba 1]))
+         (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)))))
 
@@ -1834,49 +2074,49 @@ 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)))
+                          float_array_ref dbg arr idx)))
       | Paddrarray ->
-          addr_array_ref (transl arg1) (transl arg2)
+          addr_array_ref (transl env arg1) (transl env arg2)
       | Pintarray ->
-          int_array_ref (transl arg1) (transl arg2)
+          int_array_ref (transl env arg1) (transl env arg2)
       | Pfloatarray ->
-          float_array_ref (transl arg1) (transl arg2)
+          float_array_ref dbg (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],
                         Cifthenelse(is_addr_array_hdr hdr,
                                     addr_array_ref arr idx,
-                                    float_array_ref arr idx))
+                                    float_array_ref dbg arr idx))
             else
               Cifthenelse(is_addr_array_hdr hdr,
                 Csequence(make_checkbound dbg [addr_array_length hdr; idx],
                           addr_array_ref arr idx),
                 Csequence(make_checkbound dbg [float_array_length hdr; idx],
-                          float_array_ref arr idx)))))
+                          float_array_ref dbg arr idx)))))
       | Paddrarray ->
-          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 [addr_array_length(header arr); idx],
                       addr_array_ref arr idx)))
       | Pintarray ->
-          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 [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 ->
+          box_float dbg (
+            bind "index" (transl env arg2) (fun idx ->
+            bind "arr" (transl env arg1) (fun arr ->
               Csequence(make_checkbound dbg
                                         [float_array_length(header arr); idx],
                         unboxed_float_array_ref arr idx))))
@@ -1884,104 +2124,113 @@ 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])))
 
   (* Boxed integers *)
   | Paddbint bi ->
-      box_int bi (Cop(Caddi,
-                      [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
+      box_int dbg bi (Cop(Caddi,
+                      [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]))
+      box_int dbg bi (Cop(Csubi,
+                      [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]))
-  | Pdivbint bi ->
-      box_int bi (safe_div_bi
-                      (transl_unbox_int bi arg1) (transl_unbox_int bi arg2)
+      box_int dbg bi (Cop(Cmuli,
+                      [transl_unbox_int env bi arg1;
+                       transl_unbox_int env bi arg2]))
+  | Pdivbint { size = bi; is_safe } ->
+      box_int dbg bi (safe_div_bi is_safe
+                      (transl_unbox_int env bi arg1)
+                      (transl_unbox_int env bi arg2)
                       bi dbg)
-  | Pmodbint bi ->
-      box_int bi (safe_mod_bi
-                      (transl_unbox_int bi arg1) (transl_unbox_int bi arg2)
+  | Pmodbint { size = bi; is_safe } ->
+      box_int dbg bi (safe_mod_bi is_safe
+                      (transl_unbox_int env bi arg1)
+                      (transl_unbox_int env bi arg2)
                       bi dbg)
   | Pandbint bi ->
-      box_int bi (Cop(Cand,
-                     [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
+      box_int dbg bi (Cop(Cand,
+                     [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]))
+      box_int dbg bi (Cop(Cor,
+                     [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]))
+      box_int dbg bi (Cop(Cxor,
+                     [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)]))
+      box_int dbg bi (Cop(Clsl,
+                     [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)]))
+      box_int dbg bi (Cop(Clsr,
+                     [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)]))
+      box_int dbg bi (Cop(Casr,
+                     [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]))
+                     [transl_unbox_int env bi arg1;
+                      transl_unbox_int env bi arg2]))
 
   | Patomic_store ->
      Cop (Cextcall ("caml_atomic_store", typ_int, true, Debuginfo.none),
-          [transl arg1; transl arg2])
+          [transl env arg1; transl env arg2])
 
   | prim ->
-      let (_ : string) = Format.flush_str_formatter () in
-      Printlambda.primitive Format.str_formatter prim;
-      fatal_error (Printf.sprintf "Cmmgen.transl_prim_2 %s"
-          (Format.flush_str_formatter ()))
+      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)]))
-  | Pstringsets ->
+  | Pbytessetu ->
+      return_unit(Cop(Cstore (Byte_unsigned, Assignment),
+                      [add_int (transl env arg1) (untag_int(transl env arg2));
+                        untag_int(transl env arg3)]))
+  | Pbytessets ->
       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],
@@ -1997,122 +2246,157 @@ 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))))))
 
   | Patomic_cas ->
-     Cop (Cextcall ("caml_atomic_cas", typ_int, true, Debuginfo.none),
-          [transl arg1; transl arg2; transl arg3])
+     return_unit(Cop (Cextcall ("caml_atomic_cas", typ_int, true, Debuginfo.none),
+          [transl env arg1; transl env arg2; transl env arg3]))
 
-  | _ ->
-    fatal_error "Cmmgen.transl_prim_3"
-
-and transl_prim_4 prim arg1 arg2 arg3 arg4 dbg =
-  match prim with
   | prim ->
-      let (_ : string) = Format.flush_str_formatter () in
-      Printlambda.primitive Format.str_formatter prim;
-      fatal_error (Printf.sprintf "Cmmgen.transl_prim_4 %s"
-          (Format.flush_str_formatter ()))
+      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 =
+  | 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 str kind id exp body =
+  let unboxing =
+    (* If [id] is a mutable variable (introduced to eliminate a local
+       reference) and it contains a type of unboxable numbers, then
+       force unboxing.  Indeed, if not boxed, each assignment to the variable
+       might require some boxing, but such local references are often
+       used in loops and we really want to avoid repeated boxing. *)
+    match str, kind with
+    | Mutable, Pfloatval ->
+        Boxed (Boxed_float Debuginfo.none, false)
+    | Mutable, Pboxedintval bi ->
+        Boxed (Boxed_integer (bi, Debuginfo.none), false)
+    | _, (Pfloatval | Pboxedintval _) ->
+        (* It would be safe to always unbox in this case, but
+           we do it only if this indeed allows us to get rid of
+           some allocations in the bound expression. *)
+        is_unboxed_number ~strict:false env exp
+    | _, Pgenval ->
+        (* Here we don't know statically that the bound expression
+           evaluates to an unboxable number type.  We need to be stricter
+           and ensure that all possible branches in the expression
+           return a boxed value (of the same kind).  Indeed, with GADTs,
+           different branches could return different types. *)
+        is_unboxed_number ~strict:true env exp
+    | _, Pintval ->
+        No_unboxing
+  in
+  match unboxing with
+  | No_unboxing | Boxed (_, true) ->
+      Clet(id, transl env exp, transl env body)
+  | No_result ->
+      (* the let-bound expression never returns a value, we can ignore
+         the body *)
+      transl env exp
+  | Boxed (boxed_number, _false) ->
   let unboxed_id = Ident.create (Ident.name id) in
-  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)
+      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
@@ -2128,71 +2412,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
@@ -2225,42 +2513,49 @@ 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, None), [int_const sz]) in
   let rec init_blocks = function
     | [] -> fill_nonrec bsz
-    | (id, exp, RHS_block sz) :: rem ->
+    | (id, _exp, RHS_block sz) :: rem ->
         Clet(id, op_alloc "caml_alloc_dummy" sz, init_blocks rem)
-    | (id, exp, RHS_floatblock sz) :: rem ->
+    | (id, _exp, RHS_floatblock sz) :: rem ->
         Clet(id, op_alloc "caml_alloc_dummy_float" sz, init_blocks rem)
-    | (id, exp, RHS_nonrec) :: rem ->
+    | (id, _exp, RHS_nonrec) :: rem ->
         Clet (id, Cconst_int 0, init_blocks rem)
   and fill_nonrec = function
     | [] -> fill_blocks bsz
-    | (id, exp, (RHS_block _ | RHS_floatblock _)) :: rem ->
+    | (_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
+          Cop(Cextcall("caml_update_dummy", typ_void, false, Debuginfo.none,
+                None),
+              [Cvar id; transl env exp]) in
         Csequence(op, fill_blocks rem)
-    | (id, exp, RHS_nonrec) :: rem ->
+    | (_id, _exp, RHS_nonrec) :: rem ->
         fill_blocks rem
   in init_blocks bsz
 
 (* 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; }
 
@@ -2280,10 +2575,15 @@ let rec transl_all_functions already_translated cont =
     else begin
       transl_all_functions
         (StringSet.add f.label already_translated)
-        (transl_function f :: cont)
+        ((f.dbg, 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 *)
 
@@ -2292,7 +2592,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->
@@ -2315,11 +2615,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
@@ -2352,66 +2657,112 @@ 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 translated_functions =
+    if Compilenv.structured_constants () = [] &&
+       Queue.is_empty functions
+    then cont, translated_functions
+    else
+      let translated_functions, already_translated =
+        transl_all_functions already_translated translated_functions
+      in
+      let cont = emit_all_constants cont in
+      aux already_translated cont translated_functions
+  in
+  let cont, translated_functions =
+    aux StringSet.empty cont []
+  in
+  let translated_functions =
+    (* Sort functions according to source position *)
+    List.map snd
+      (List.sort (fun (dbg1, _) (dbg2, _) ->
+           Debuginfo.compare dbg1 dbg2) translated_functions)
+  in
+  translated_functions @ 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
@@ -2421,9 +2772,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)
@@ -2446,7 +2823,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, [],
@@ -2460,7 +2837,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])),
@@ -2472,7 +2849,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:
@@ -2492,12 +2869,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
@@ -2507,7 +2884,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))
 
@@ -2524,11 +2901,11 @@ 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, get_mut_field obj (Cconst_int 0),
     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]),
@@ -2540,8 +2917,8 @@ let send_function arity =
   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;
@@ -2554,7 +2931,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 }
@@ -2572,9 +2949,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 }
@@ -2613,7 +2990,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
@@ -2633,7 +3010,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 }
@@ -2647,18 +3024,18 @@ 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,
-               [alloc_closure_header 5;
+           Cop(Calloc Debuginfo.none,
+               [alloc_closure_header 5 Debuginfo.none;
                 Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1));
                 int_const (arity - num - 1);
                 Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1) ^ "_app");
                 Cvar arg; Cvar clos])
          else
-           Cop(Calloc,
-                     [alloc_closure_header 4;
+           Cop(Calloc Debuginfo.none,
+                     [alloc_closure_header 4 Debuginfo.none;
                       Cconst_symbol(name1 ^ "_" ^ string_of_int (num+1));
                       int_const 1; Cvar arg; Cvar clos]);
       fun_fast = true;
@@ -2668,13 +3045,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
@@ -2685,7 +3062,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;
@@ -2697,7 +3074,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)]
 
@@ -2730,9 +3109,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
@@ -2754,7 +3133,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" ::
@@ -2766,8 +3145,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
@@ -2783,6 +3161,18 @@ let frame_table namelist =
         List.map mksym namelist
         @ [cint_zero])
 
+(* Generate the master table of Spacetime shapes *)
+
+let spacetime_shapes namelist =
+  let mksym name =
+    Csymbol_address (
+      Compilenv.make_symbol ~unitname:name (Some "spacetime_shapes"))
+  in
+  Cdata(Cglobal_symbol "caml_spacetime_shapes" ::
+        Cdefine_symbol "caml_spacetime_shapes" ::
+        List.map mksym namelist
+        @ [cint_zero])
+
 (* Generate the table of module data and code segments *)
 
 let segment_table namelist symbol begname endname =
@@ -2807,19 +3197,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 46f9496655..8104afabea 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
@@ -24,7 +31,9 @@ val reference_symbols: string list -> Cmm.phrase
 val globals_map: (string * Digest.t * Digest.t * string list) list ->
   Cmm.phrase
 val frame_table: string list -> Cmm.phrase
+val spacetime_shapes: string list -> Cmm.phrase
 val data_segment_table: string list -> Cmm.phrase
 val code_segment_table: string list -> Cmm.phrase
 val predef_exception: int -> string -> Cmm.phrase
 val plugin_header: (Cmx_format.unit_infos * Digest.t) list -> Cmm.phrase
+val black_block_header: (*tag:*)int -> (*size:*)int -> nativeint
diff --git a/asmcomp/cmx_format.mli b/asmcomp/cmx_format.mli
index 51aa044083..0e3cf28590 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 a318246289..0000000000
--- 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 5dab12fc92..0000000000
--- 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 aff4ad626c..13d647a537 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 b0cd0437a0..874a6f98e1 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 f59f26a144..8f9490462f 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -23,35 +26,41 @@ type allocation_state =
 
 let allocated_size = function
     No_alloc -> 0
-  | Pending_alloc(reg, totalsz) -> totalsz
+  | Pending_alloc(_, ofs) -> ofs
 
 let rec combine i allocstate =
   match i.desc with
     Iend | Ireturn | Iexit _ | Iraise _ ->
       (i, allocated_size allocstate)
-  | Iop(Ialloc sz) ->
+  | Iop(Ialloc { words = sz; _ }) ->
       begin match allocstate with
       | Pending_alloc(reg, totalsz)
           when totalsz + sz < Config.max_young_wosize * Arch.size_addr ->
          let (newnext, newsz) =
-              combine i.next (Pending_alloc(i.res.(0), totalsz + sz)) in
-            (instr_cons (Iop(Iintop_imm(Iadd, -sz))) [| reg |] i.res newnext,
+            combine i.next (Pending_alloc(i.res.(0), sz)) in
+          (instr_cons_debug (Iop(Ialloc {words = newsz; spacetime_index = 0;
+              label_after_call_gc = None; }))
+            i.arg i.res i.dbg newnext, 0)
+      | Pending_alloc(reg, ofs) ->
+          if ofs + sz < Config.max_young_wosize * Arch.size_addr then begin
+            let (newnext, newsz) =
+              combine i.next (Pending_alloc(reg, ofs + sz)) in
+            (instr_cons (Iop(Iintop_imm(Iadd, ofs))) [| reg |] i.res newnext,
              newsz)
       | _ ->
          let (newnext, newsz) =
             combine i.next (Pending_alloc(i.res.(0), sz)) in
-         let newnext =
-           if newsz = sz then newnext else
-             instr_cons (Iop(Iintop_imm(Iadd, newsz - sz))) i.res i.res newnext in
-         (instr_cons (Iop(Ialloc newsz)) i.arg i.res newnext,
-          allocated_size allocstate)
+            (instr_cons_debug (Iop(Ialloc { words = newsz; spacetime_index = 0;
+                label_after_call_gc = None; }))
+              i.arg i.res i.dbg newnext, ofs)
+          end
       end
-  | Iop(Icall_ind | Icall_imm _ | Iextcall _ |
-        Itailcall_ind | Itailcall_imm _) ->
+  | Iop(Icall_ind _ | Icall_imm _ | Iextcall _ |
+        Itailcall_ind _ | Itailcall_imm _) ->
       let newnext = combine_restart i.next in
       (instr_cons_debug i.desc i.arg i.res i.dbg newnext,
        allocated_size allocstate)
-  | Iop op ->
+  | Iop _ ->
       let (newnext, sz) = combine i.next allocstate in
       (instr_cons_debug i.desc i.arg i.res i.dbg newnext, sz)
   | Iifthenelse(test, ifso, ifnot) ->
@@ -84,4 +93,5 @@ and combine_restart i =
   let (newi, _) = combine i No_alloc in newi
 
 let fundecl f =
-  {f with fun_body = combine_restart f.fun_body}
+  if Config.spacetime then f
+  else {f with fun_body = combine_restart f.fun_body}
diff --git a/asmcomp/comballoc.mli b/asmcomp/comballoc.mli
index ee04c16b3a..19d8fdee02 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 a313b97202..1e91fb65e0 100644
--- a/asmcomp/compilenv.ml
+++ b/asmcomp/compilenv.ml
@@ -1,20 +1,28 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                OCaml                                *)
 (*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, 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.               *)
+(*   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 option 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,6 +205,8 @@ let get_global_info global_ident = (
       Hashtbl.find global_infos_table modname
     with Not_found ->
       let (infos, crc) =
+        if Env.is_imported_opaque modname then (None, None)
+        else begin
         try
           let filename =
             find_in_path_uncap !load_path (modname ^ ".cmx") in
@@ -160,7 +215,11 @@ let get_global_info global_ident = (
             raise(Error(Illegal_renaming(modname, ui.ui_name, filename)));
           (Some ui, Some crc)
         with Not_found ->
-          (None, None) in
+            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,40 @@ 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))
+
+let require_global global_ident =
+  if not (Ident.is_predef_exn global_ident) then
+    ignore (get_global_info global_ident : Cmx_format.unit_infos option)
 
 (* Error report *)
 
diff --git a/asmcomp/compilenv.mli b/asmcomp/compilenv.mli
index 7fae3bade6..fa3cfc3430 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 option 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. *)
@@ -79,6 +142,10 @@ val cache_unit_info: unit_infos -> unit
            honored by [symbol_for_global] and [global_approx]
            without looking at the corresponding .cmx file. *)
 
+val require_global: Ident.t -> unit
+        (* Enforce a link dependency of the current compilation
+           unit to the required module *)
+
 val read_library_info: string -> library_infos
 
 type error =
diff --git a/asmcomp/deadcode.ml b/asmcomp/deadcode.ml
index cb93c2869d..28ed13bc86 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
@@ -19,32 +22,38 @@ open Mach
    and a set of registers live "before" instruction [i]. *)
 
 let rec deadcode i =
+  let arg =
+    if Config.spacetime
+      && Mach.spacetime_node_hole_pointer_is_live_before i
+    then Array.append i.arg [| Proc.loc_spacetime_node_hole |]
+    else i.arg
+  in
   match i.desc with
-  | Iend | Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _) | Iraise _ ->
-      (i, Reg.add_set_array i.live i.arg)
+  | Iend | Ireturn | Iop(Itailcall_ind _) | Iop(Itailcall_imm _) | Iraise _ ->
+      (i, Reg.add_set_array i.live arg)
   | Iop op ->
       let (s, before) = deadcode i.next in
       if Proc.op_is_pure op                     (* no side effects *)
       && Reg.disjoint_set_array before i.res    (* results are not used after *)
-      && not (Proc.regs_are_volatile i.arg)    (* no stack-like hard reg *)
+      && not (Proc.regs_are_volatile arg)      (* no stack-like hard reg *)
       && not (Proc.regs_are_volatile i.res)    (*            is involved *)
       then begin
         assert (Array.length i.res > 0);  (* sanity check *)
         (s, before)
       end else begin
-        ({i with next = s}, Reg.add_set_array i.live i.arg)
+        ({i with next = s}, Reg.add_set_array i.live arg)
       end
   | Iifthenelse(test, ifso, ifnot) ->
       let (ifso', _) = deadcode ifso in
       let (ifnot', _) = deadcode ifnot in
       let (s, _) = deadcode i.next in
       ({i with desc = Iifthenelse(test, ifso', ifnot'); next = s},
-       Reg.add_set_array i.live i.arg)
+       Reg.add_set_array i.live arg)
   | Iswitch(index, cases) ->
       let cases' = Array.map (fun c -> fst (deadcode c)) cases in
       let (s, _) = deadcode i.next in
       ({i with desc = Iswitch(index, cases'); next = s},
-       Reg.add_set_array i.live i.arg)
+       Reg.add_set_array i.live arg)
   | Iloop(body) ->
       let (body', _) = deadcode body in
       let (s, _) = deadcode i.next in
@@ -54,7 +63,7 @@ let rec deadcode i =
       let (handler', _) = deadcode handler in
       let (s, _) = deadcode i.next in
       ({i with desc = Icatch(nfail, body', handler'); next = s}, i.live)
-  | Iexit nfail ->
+  | Iexit _ ->
       (i, i.live)
   | Itrywith(body, handler) ->
       let (body', _) = deadcode body in
diff --git a/asmcomp/deadcode.mli b/asmcomp/deadcode.mli
index 6aafae0540..c566cfbd3e 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 3f96049eee..0000000000
--- 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 ef4d55ad91..0000000000
--- 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 ab9442efc1..cab5083375 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 dff83bfa58..a29d8a5ca9 100644
--- a/asmcomp/emitaux.ml
+++ b/asmcomp/emitaux.ml
@@ -1,19 +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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
-open Debuginfo
-
 let output_channel = ref stdout
 
 let emit_string s = output_string !output_channel s
@@ -108,12 +109,14 @@ type frame_descr =
   { fd_lbl: int;                        (* Return address *)
     fd_frame_size: int;                 (* Size of stack frame *)
     fd_live_offset: int list;           (* Offsets/regs of live addresses *)
+    fd_raise: bool;                     (* Is frame for a raise? *)
     fd_debuginfo: Debuginfo.t }         (* Location, if any *)
 
 let frame_descriptors = ref([] : frame_descr list)
 
 type emit_frame_actions =
-  { efa_label: int -> unit;
+  { efa_code_label: int -> unit;
+    efa_data_label: int -> unit;
     efa_16: int -> unit;
     efa_32: int32 -> unit;
     efa_word: int -> unit;
@@ -128,11 +131,41 @@ let emit_frames a =
     try
       Hashtbl.find filenames name
     with Not_found ->
-      let lbl = Linearize.new_label () in
+      let lbl = Cmm.new_label () in
       Hashtbl.add filenames name lbl;
-      lbl in
+      lbl
+  in
+  let module Label_table =
+    Hashtbl.Make (struct
+      type t = bool * Debuginfo.t
+
+      let equal ((rs1 : bool), dbg1) (rs2, dbg2) =
+        rs1 = rs2 && Debuginfo.compare dbg1 dbg2 = 0
+
+      let hash (rs, dbg) =
+        Hashtbl.hash (rs, Debuginfo.hash dbg)
+    end)
+  in
+  let debuginfos = Label_table.create 7 in
+  let rec label_debuginfos rs rdbg =
+    let key = (rs, rdbg) in
+    try fst (Label_table.find debuginfos key)
+    with Not_found ->
+      let lbl = Cmm.new_label () in
+      let next =
+        match rdbg with
+        | [] -> assert false
+        | _ :: [] -> None
+        | _ :: ((_ :: _) as rdbg') -> Some (label_debuginfos false rdbg')
+      in
+      Label_table.add debuginfos key (lbl, next);
+      lbl
+  in
+  let emit_debuginfo_label rs rdbg =
+    a.efa_data_label (label_debuginfos rs rdbg)
+  in
   let emit_frame fd =
-    a.efa_label fd.fd_lbl;
+    a.efa_code_label fd.fd_lbl;
     a.efa_16 (if Debuginfo.is_none fd.fd_debuginfo
               then fd.fd_frame_size
               else fd.fd_frame_size + 1);
@@ -142,28 +175,42 @@ let emit_frames a =
     a.efa_16 (List.length uniq_fd_live_offset);
     List.iter a.efa_16 uniq_fd_live_offset;
     a.efa_align Arch.size_addr;
-    if not (Debuginfo.is_none fd.fd_debuginfo) then begin
-      let d = fd.fd_debuginfo in
-      let line = min 0xFFFFF d.dinfo_line
-      and char_start = min 0xFF d.dinfo_char_start
-      and char_end = min 0x3FF d.dinfo_char_end
-      and kind = match d.dinfo_kind with Dinfo_call -> 0 | Dinfo_raise -> 1 in
-      let info =
-        Int64.add (Int64.shift_left (Int64.of_int line) 44) (
-        Int64.add (Int64.shift_left (Int64.of_int char_start) 36) (
-        Int64.add (Int64.shift_left (Int64.of_int char_end) 26)
-                  (Int64.of_int kind))) in
-      a.efa_label_rel
-        (label_filename d.dinfo_file)
-        (Int64.to_int32 info);
-      a.efa_32 (Int64.to_int32 (Int64.shift_right info 32))
-    end in
+    match List.rev fd.fd_debuginfo with
+    | [] -> ()
+    | _ :: _ as rdbg -> emit_debuginfo_label fd.fd_raise rdbg
+  in
   let emit_filename name lbl =
     a.efa_def_label lbl;
     a.efa_string name;
-    a.efa_align Arch.size_addr in
+    a.efa_align Arch.size_addr
+  in
+  let pack_info fd_raise d =
+    let line = min 0xFFFFF d.Debuginfo.dinfo_line
+    and char_start = min 0xFF d.Debuginfo.dinfo_char_start
+    and char_end = min 0x3FF d.Debuginfo.dinfo_char_end
+    and kind = if fd_raise then 1 else 0 in
+    Int64.(add (shift_left (of_int line) 44)
+             (add (shift_left (of_int char_start) 36)
+                (add (shift_left (of_int char_end) 26)
+                   (of_int kind))))
+  in
+  let emit_debuginfo (rs, rdbg) (lbl,next) =
+    let d = List.hd rdbg in
+    a.efa_align Arch.size_addr;
+    a.efa_def_label lbl;
+    let info = pack_info rs d in
+    a.efa_label_rel
+      (label_filename d.Debuginfo.dinfo_file)
+      (Int64.to_int32 info);
+    a.efa_32 (Int64.to_int32 (Int64.shift_right info 32));
+    begin match next with
+    | Some next -> a.efa_data_label next
+    | None -> a.efa_word 0
+    end
+  in
   a.efa_word (List.length !frame_descriptors);
   List.iter emit_frame !frame_descriptors;
+  Label_table.iter emit_debuginfo debuginfos;
   Hashtbl.iter emit_filename filenames;
   frame_descriptors := []
 
@@ -192,12 +239,26 @@ let cfi_endproc () =
   if is_cfi_enabled () then
     emit_string "\t.cfi_endproc\n"
 
+let cfi_remember_state () =
+  if is_cfi_enabled () then
+    emit_string "\t.cfi_remember_state\n"
+
+let cfi_restore_state () =
+  if is_cfi_enabled () then
+    emit_string "\t.cfi_restore_state\n"
+
 let cfi_adjust_cfa_offset n =
   if is_cfi_enabled () then
   begin
     emit_string "\t.cfi_adjust_cfa_offset\t"; emit_int n; emit_string "\n";
   end
 
+let cfi_def_cfa_offset n =
+  if is_cfi_enabled () then
+  begin
+    emit_string "\t.cfi_def_cfa_offset\t"; emit_int n; emit_string "\n";
+  end
+
 let cfi_offset ~reg ~offset =
   if is_cfi_enabled () then begin
     emit_string "\t.cfi_offset ";
@@ -223,27 +284,37 @@ 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
+    (!Clflags.debug || Config.with_frame_pointers) then begin
+    match List.rev dbg with
+    | [] -> ()
+    | { Debuginfo.dinfo_line = line;
+        dinfo_char_start = col;
+        dinfo_file = file_name; } :: _ ->
+      if line > 0 then begin (* PR#6243 *)
     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
+        loc_emitter ~file_num ~line ~col;
+      end
+  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'
-  end
+       emit_int line; emit_char '\n')
 
 (* Emission of block headers immediately prior to function entry points *)
 
@@ -285,3 +356,6 @@ let emit_block_header_for_closure ~word_directive ~comment_string
 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 aa9c9ff0c5..ff2dc8fe6c 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,17 +33,23 @@ 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 *)
     fd_frame_size: int;                 (* Size of stack frame *)
     fd_live_offset: int list;           (* Offsets/regs of live addresses *)
+    fd_raise: bool;                     (* Is frame for a raise? *)
     fd_debuginfo: Debuginfo.t }         (* Location, if any *)
 
 val frame_descriptors : frame_descr list ref
 
 type emit_frame_actions =
-  { efa_label: int -> unit;
+  { efa_code_label: int -> unit;
+    efa_data_label: int -> unit;
     efa_16: int -> unit;
     efa_32: int32 -> unit;
     efa_word: int -> unit;
@@ -57,9 +66,14 @@ 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 cfi_def_cfa_offset : int -> unit
+val cfi_remember_state : unit -> unit
+val cfi_restore_state : unit -> unit
 
-val emit_block_header_for_closure
-   : word_directive:string
-  -> comment_string:string
-  -> function_entry_points_are_doubleword_aligned:bool
-  -> 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 0000000000..3c342fde75
--- /dev/null
+++ b/asmcomp/export_info.ml
@@ -0,0 +1,356 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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 ~print:Export_id.print t1.symbol_id t2.symbol_id;
+    offset_fun = Closure_id.Map.disjoint_union
+        ~eq:int_eq t1.offset_fun t2.offset_fun;
+    offset_fv = Var_within_closure.Map.disjoint_union
+        ~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
+        ~print:(Variable.Map.print Variable.Set.print)
+        ~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; results } =
+    if Set_of_closures_id.Set.mem set_of_closures_id !printed_set_of_closures
+    then fprintf ppf "%a" Set_of_closures_id.print set_of_closures_id
+    else begin
+      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 => %a}"
+        Set_of_closures_id.print set_of_closures_id
+        print_binding bound_vars
+        print_alias aliased_symbol
+        (Closure_id.Map.print print_approx) results
+    end
+  and print_binding ppf bound_vars =
+    Var_within_closure.Map.iter (fun clos_id approx ->
+        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 0000000000..9d6bc0f6b3
--- /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 0000000000..da413408e6
--- /dev/null
+++ b/asmcomp/export_info_for_pack.ml
@@ -0,0 +1,211 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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
+let rename_set_of_closures_id_state = Set_of_closures_id.Tbl.create 10
+let imported_function_declarations_table =
+  (Set_of_closures_id.Tbl.create 10
+   : Flambda.function_declarations Set_of_closures_id.Tbl.t)
+
+(* Rename export identifiers' compilation units to denote that they now
+   live within a pack. *)
+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_id_for_pack units pack
+    (set_of_closures_id : Set_of_closures_id.t)
+      : Set_of_closures_id.t =
+  let compilation_unit =
+    Set_of_closures_id.get_compilation_unit set_of_closures_id
+  in
+  if Compilation_unit.Set.mem compilation_unit units then
+    Set_of_closures_id.Tbl.memoize
+      rename_set_of_closures_id_state
+      (fun _ ->
+         Set_of_closures_id.create
+           ?name:(Set_of_closures_id.name set_of_closures_id)
+           pack)
+      set_of_closures_id
+  else set_of_closures_id
+
+let import_set_of_closures_origin_for_pack units pack
+    (set_of_closures_origin : Set_of_closures_origin.t)
+    : Set_of_closures_origin.t =
+  Set_of_closures_origin.rename
+    (import_set_of_closures_id_for_pack units pack)
+    set_of_closures_origin
+
+let import_set_of_closures units pack
+      (set_of_closures : Export_info.value_set_of_closures)
+      : Export_info.value_set_of_closures =
+  { set_of_closures_id =
+      import_set_of_closures_id_for_pack units pack
+        set_of_closures.set_of_closures_id;
+    bound_vars =
+      Var_within_closure.Map.map (import_approx_for_pack units pack)
+        set_of_closures.bound_vars;
+    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 rec import_code_for_pack units pack expr =
+  Flambda_iterators.map_named (function
+      | Symbol sym -> Symbol (import_symbol_for_pack units pack sym)
+      | Read_symbol_field (sym, field) ->
+        Read_symbol_field (import_symbol_for_pack units pack sym, field)
+      | Set_of_closures set_of_closures ->
+        let set_of_closures =
+          Flambda.create_set_of_closures
+            ~free_vars:set_of_closures.free_vars
+            ~specialised_args:set_of_closures.specialised_args
+            ~direct_call_surrogates:set_of_closures.direct_call_surrogates
+            ~function_decls:
+              (import_function_declarations_for_pack units pack
+                 set_of_closures.function_decls)
+        in
+        Set_of_closures set_of_closures
+      | e -> e)
+    expr
+
+and import_function_declarations_for_pack_aux units pack
+      (function_decls : Flambda.function_declarations) =
+  let funs =
+    Variable.Map.map (fun (function_decl : Flambda.function_declaration) ->
+        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.import_function_declarations_for_pack
+    (Flambda.update_function_declarations function_decls ~funs)
+    (import_set_of_closures_id_for_pack units pack)
+    (import_set_of_closures_origin_for_pack units pack)
+
+and import_function_declarations_for_pack units pack
+    (function_decls:Flambda.function_declarations) =
+  let original_set_of_closures_id = function_decls.set_of_closures_id in
+  try
+    Set_of_closures_id.Tbl.find imported_function_declarations_table
+      original_set_of_closures_id
+  with Not_found ->
+    let function_decls =
+      import_function_declarations_for_pack_aux units pack function_decls
+    in
+    Set_of_closures_id.Tbl.add
+      imported_function_declarations_table
+      original_set_of_closures_id
+      function_decls;
+    function_decls
+
+let import_eidmap_for_pack units pack f map =
+  Export_info.nest_eid_map
+    (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 import_set_of_closures_id =
+    import_set_of_closures_id_for_pack pack_units pack
+  in
+  let import_function_declarations =
+    import_function_declarations_for_pack pack_units pack
+  in
+  let sets_of_closures =
+    Set_of_closures_id.Map.map_keys import_set_of_closures_id
+      (Set_of_closures_id.Map.map
+         import_function_declarations
+         exp.sets_of_closures)
+  in
+  Export_info.create ~sets_of_closures
+    ~closures:(Flambda_utils.make_closure_map' sets_of_closures)
+    ~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:
+      (Set_of_closures_id.Set.map import_set_of_closures_id
+         exp.constant_sets_of_closures)
+    ~invariant_params:
+      (Set_of_closures_id.Map.map_keys import_set_of_closures_id
+         exp.invariant_params)
+
+let clear_import_state () =
+  Set_of_closures_id.Tbl.clear imported_function_declarations_table;
+  Set_of_closures_id.Tbl.clear rename_set_of_closures_id_state;
+  Export_id.Tbl.clear rename_id_state
diff --git a/asmcomp/export_info_for_pack.mli b/asmcomp/export_info_for_pack.mli
new file mode 100644
index 0000000000..2ba3a35d8b
--- /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 0000000000..9ae0ecf957
--- /dev/null
+++ b/asmcomp/flambda_to_clambda.ml
@@ -0,0 +1,692 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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
+
+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; _ } ->
+    (* TODO: synthesize proper value_kind *)
+    let id, env_body = Env.add_fresh_ident env var in
+    Ulet (Immutable, Pgenval, id, to_clambda_named t env var defining_expr,
+      to_clambda t env_body body)
+  | Let_mutable { var = mut_var; initial_value = var; body; contents_kind } ->
+    let id, env_body = Env.add_fresh_mutable_ident env mut_var in
+    let def = subst_var env var in
+    Ulet (Mutable, contents_kind, 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) ->
+    Uprim (Pfield index, [check_field (subst_var env block) index None], dbg)
+  | Prim (Psetfield (index, maybe_ptr, init), [block; new_value], dbg) ->
+    Uprim (Psetfield (index, maybe_ptr, init), [
+        check_field (subst_var env block) index None;
+        subst_var env new_value;
+      ], dbg)
+  | Prim (Popaque, args, dbg) ->
+    Uprim (Pidentity, subst_vars env args, dbg)
+  | Prim (p, args, dbg) ->
+    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 0000000000..39cbc40f8c
--- /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 6bea76f1a1..f727e6e813 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -17,7 +20,7 @@ open Arch
 open Mach
 open CSEgen
 
-class cse = object (self)
+class cse = object
 
 inherit cse_generic as super
 
@@ -37,7 +40,7 @@ method! class_of_operation op =
 
 method! is_cheap_operation op =
   match op with
-  | Iconst_int _ | Iconst_blockheader _ -> true
+  | Iconst_int _ -> true
   | Iconst_symbol _ -> true
   | _ -> false
 
diff --git a/asmcomp/i386/NOTES.md b/asmcomp/i386/NOTES.md
new file mode 100644
index 0000000000..6f1e183978
--- /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 1d486db3ec..baa047ecf4 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -49,6 +52,8 @@ type specific_operation =
 and float_operation =
     Ifloatadd | Ifloatsub | Ifloatsubrev | Ifloatmul | Ifloatdiv | Ifloatdivrev
 
+let spacetime_node_hole_pointer_is_live_before _specific_op = false
+
 (* Sizes, endianness *)
 
 let big_endian = false
@@ -76,11 +81,11 @@ let offset_addressing addr delta =
   | Iindexed2scaled(scale, n) -> Iindexed2scaled(scale, n + delta)
 
 let num_args_addressing = function
-    Ibased(s, n) -> 0
-  | Iindexed n -> 1
-  | Iindexed2 n -> 2
-  | Iscaled(scale, n) -> 1
-  | Iindexed2scaled(scale, n) -> 2
+    Ibased _ -> 0
+  | Iindexed _ -> 1
+  | Iindexed2 _ -> 2
+  | Iscaled _ -> 1
+  | Iindexed2scaled _ -> 2
 
 (* Printing operations and addressing modes *)
 
diff --git a/asmcomp/i386/emit.mlp b/asmcomp/i386/emit.mlp
index 98df5f958b..d3325e1d0c 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,152 +74,150 @@ 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 = string_of_symbol symbol_prefix s
+
+let immsym s = sym (emit_symbol s)
 
-let emit_symbol s =
-  emit_string symbol_prefix; Emitaux.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
-
-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 "%s%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 *)
 
-let record_frame_label live dbg =
-  let lbl = new_label() in
+let record_frame_label ?label live raise_ dbg =
+  let lbl =
+    match label with
+    | None -> new_label()
+    | Some label -> label
+  in
   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;
       fd_frame_size = frame_size();
       fd_live_offset = !live_offset;
+      fd_raise = raise_;
       fd_debuginfo = dbg } :: !frame_descriptors;
   lbl
 
-let record_frame live dbg =
-  let lbl = record_frame_label live dbg in `{emit_label lbl}:\n`
+let record_frame ?label live raise_ dbg =
+  let lbl = record_frame_label ?label live raise_ dbg in
+  def_label lbl
 
 (* Record calls to the GC -- we've moved them out of the way *)
 
@@ -207,8 +229,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
@@ -221,105 +245,112 @@ type bound_error_call =
 let bound_error_sites = ref ([] : bound_error_call list)
 let bound_error_call = ref 0
 
-let bound_error_label dbg =
+let bound_error_label ?label dbg =
   if !Clflags.debug then begin
     let lbl_bound_error = new_label() in
-    let lbl_frame = record_frame_label Reg.Set.empty dbg in
+    let lbl_frame = record_frame_label ?label Reg.Set.empty false dbg in
     bound_error_sites :=
-     { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
-   lbl_bound_error
- 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 +363,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 +444,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 +475,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) ->
+      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 { label_after; }) ->
+      I.call (reg i.arg.(0));
+      record_frame i.live false i.dbg ~label:label_after
+  | Lop(Icall_imm { func; label_after; }) ->
+      add_used_symbol func;
+      emit_call func;
+      record_frame i.live false i.dbg ~label:label_after
+  | Lop(Itailcall_ind { label_after = _; }) ->
+      output_epilogue begin fun () ->
+        I.jmp (reg i.arg.(0))
+      end
+  | Lop(Itailcall_imm { func; label_after = _; }) ->
+      if func = !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 func;
+          I.jmp (immsym func)
         end
-    | Lop(Itailcall_imm s) ->
-        if s = !function_name then
-          `	jmp	{emit_label !tailrec_entry_point}\n`
+      end
+  | Lop(Iextcall { func; alloc; label_after; }) ->
+      add_used_symbol func;
+      if alloc then begin
+        if system <> S_macosx then
+          I.mov (immsym func) eax
         else begin
-          output_epilogue begin fun () ->
-          `	jmp	{emit_symbol s}\n`
-          end
+          external_symbols_indirect :=
+            StringSet.add func !external_symbols_indirect;
+          I.mov (mem_sym DWORD (Printf.sprintf "L%s$non_lazy_ptr"
+                              (emit_symbol func))) eax
+        end;
+        emit_call "caml_c_call";
+        record_frame i.live false i.dbg ~label:label_after
+      end else begin
+        if system <> S_macosx then
+          emit_call func
+        else begin
+          external_symbols_direct :=
+            StringSet.add func !external_symbols_direct;
+          I.call (sym (Printf.sprintf "L%s$stub" (emit_symbol func)))
         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 { words = n; label_after_call_gc; }) ->
+      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 false 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;
+        let label =
+          record_frame_label ?label:label_after_call_gc i.live false
+            Debuginfo.none
+        in
+        def_label label;
+        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 { label_after_error; } )) ->
+      let lbl = bound_error_label ?label:label_after_error i.dbg in
+      I.cmp (reg i.arg.(1)) (reg i.arg.(0));
+      I.jbe (label lbl)
+  | Lop(Iintop_imm(Icheckbound { label_after_error; }, n)) ->
+      let lbl = bound_error_label ?label:label_after_error 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`;
-          record_frame Reg.Set.empty i.dbg
-        | true, Lambda.Raise_reraise ->
-          `	call    {emit_symbol "caml_reraise_exn"}\n`;
-          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`;
+            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 k with
+      | Cmm.Raise_withtrace ->
+          emit_call "caml_raise_exn";
+          record_frame Reg.Set.empty true i.dbg
+      | Cmm.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 +893,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 +951,150 @@ 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)
+  | 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))
+  | 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;
+  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_code_label = (fun l -> D.long (ConstLabel (emit_label l)));
+      efa_data_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 ef5205ef8f..0000000000
--- 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 0b010d248f..f50b8adf9d 100644
--- a/asmcomp/i386/proc.ml
+++ b/asmcomp/i386/proc.ml
@@ -1,14 +1,18 @@
-(***********************************************************************)
+# 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 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* 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,11 +90,12 @@ 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)
 
+let loc_spacetime_node_hole = Reg.dummy  (* Spacetime unsupported *)
+
 (* Instruction selection *)
 
 let word_addressed = false
@@ -117,7 +121,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
@@ -138,19 +142,24 @@ let calling_conventions first_int last_int first_float last_float make_stack
 
 let incoming ofs = Incoming ofs
 let outgoing ofs = Outgoing ofs
-let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
+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, _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 =
+  let (loc, _ofs) = calling_conventions 0 5 100 100 not_supported res in loc
+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
 
@@ -175,8 +184,9 @@ let destroyed_at_c_call =               (* ebx, esi, edi, ebp preserved *)
   [|eax; ecx; edx|]
 
 let destroyed_at_oper = function
-    Iop(Icall_ind | Icall_imm _ | Iextcall(_, true)) -> all_phys_regs
-  | Iop(Iextcall(_, false)) -> destroyed_at_c_call
+    Iop(Icall_ind _ | Icall_imm _ | Iextcall { alloc = true; _}) ->
+    all_phys_regs
+  | Iop(Iextcall { alloc = false; }) -> destroyed_at_c_call
   | Iop(Iintop(Idiv | Imod)) -> [| eax; edx |]
   | Iop(Ialloc _ | Iintop Imulh) -> [| eax |]
   | Iop(Iintop(Icomp _) | Iintop_imm(Icomp _, _)) -> [| eax |]
@@ -188,10 +198,10 @@ let destroyed_at_raise = all_phys_regs
 
 (* Maximal register pressure *)
 
-let safe_register_pressure op = 4
+let safe_register_pressure _op = 4
 
 let max_register_pressure = function
-    Iextcall(_, _) -> [| 4; max_int |]
+    Iextcall _ -> [| 4; max_int |]
   | Iintop(Idiv | Imod) -> [| 5; max_int |]
   | Ialloc _ | Iintop(Icomp _) | Iintop_imm(Icomp _, _) |
     Iintoffloat -> [| 6; max_int |]
@@ -201,9 +211,9 @@ let max_register_pressure = function
    registers).  *)
 
 let op_is_pure = function
-  | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+  | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _
   | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
-  | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) -> false
+  | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _) -> false
   | Ispecific(Ilea _) -> true
   | Ispecific _ -> false
   | _ -> true
@@ -216,12 +226,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 bc1b08f597..511b7f1bd6 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
@@ -37,7 +40,7 @@ method! makereg r =
 
 method! reload_operation op arg res =
   match op with
-    Iintop(Iadd|Isub|Iand|Ior|Ixor|Icomp _|Icheckbound) ->
+    Iintop(Iadd|Isub|Iand|Ior|Ixor|Icomp _|Icheckbound _) ->
       (* One of the two arguments can reside in the stack *)
       if stackp arg.(0) && stackp arg.(1)
       then ([|arg.(0); self#makereg arg.(1)|], res)
@@ -68,7 +71,7 @@ method! reload_operation op arg res =
 
 method! reload_test tst arg =
   match tst with
-    Iinttest cmp ->
+    Iinttest _ ->
       (* One of the two arguments can reside on stack *)
       if stackp arg.(0) && stackp arg.(1)
       then [| self#makereg arg.(0); arg.(1) |]
diff --git a/asmcomp/i386/scheduling.ml b/asmcomp/i386/scheduling.ml
index b166a05a34..05627b0405 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 10d2d40e37..16199ca641 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)
@@ -85,7 +88,7 @@ let rec float_needs = function
       let n1 = float_needs arg1 in
       let n2 = float_needs arg2 in
       if n1 = n2 then 1 + n1 else if n1 > n2 then n1 else n2
-  | Cop(Cextcall(fn, ty_res, alloc, dbg), args)
+  | Cop(Cextcall(fn, _ty_res, _alloc, _dbg, _label), args)
     when !fast_math && List.mem fn inline_float_ops ->
       begin match args with
         [arg] -> float_needs arg
@@ -135,7 +138,7 @@ let pseudoregs_for_operation op arg res =
   (* For storing a byte, the argument must be in eax...edx.
      (But for a short, any reg will do!)
      Keep it simple, just force the argument to be in edx. *)
-  | Istore((Byte_unsigned | Byte_signed), addr, _) ->
+  | Istore((Byte_unsigned | Byte_signed), _, _) ->
       let newarg = Array.copy arg in
       newarg.(0) <- edx;
       (newarg, res, false)
@@ -154,18 +157,18 @@ class selector = object (self)
 
 inherit Selectgen.selector_generic as super
 
-method is_immediate (n : int) = true
+method is_immediate (_n : int) = true
 
 method! is_simple_expr e =
   match e with
-  | Cop(Cextcall(fn, _, alloc, _), args)
+  | Cop(Cextcall(fn, _, _, _, _), args)
     when !fast_math && List.mem fn inline_float_ops ->
       (* inlined float ops are simple if their arguments are *)
       List.for_all self#is_simple_expr args
   | _ ->
       super#is_simple_expr e
 
-method select_addressing chunk exp =
+method select_addressing _chunk exp =
   match select_addr exp with
     (Asymbol s, d) ->
       (Ibased(s, d), Ctuple [])
@@ -182,7 +185,7 @@ method! select_store is_assign addr exp =
   match exp with
     Cconst_int n ->
       (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
-  | (Cconst_natint n | Cconst_blockheader n) ->
+  | (Cconst_natint n | Cblockheader (n, _)) ->
       (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
   | Cconst_pointer n ->
       (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
@@ -196,9 +199,9 @@ 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
-        (Iindexed d, _) -> super#select_operation op args
+    Caddi | Caddv | Cadda | Csubi ->
+      begin match self#select_addressing Word_int (Cop(op, args)) with
+        (Iindexed _, _)
       | (Iindexed2 0, _) -> super#select_operation op args
       | (addr, arg) -> (Ispecific(Ilea addr), [arg])
       end
@@ -215,17 +218,17 @@ 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
       end
   (* Recognize inlined floating point operations *)
-  | Cextcall(fn, ty_res, false, dbg)
+  | Cextcall(fn, _ty_res, false, _dbg, _label)
     when !fast_math && List.mem fn inline_float_ops ->
       (Ispecific(Ifloatspecial fn), args)
   (* i386 does not support immediate operands for multiply high signed *)
@@ -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 0000000000..0ab09ca05e
--- /dev/null
+++ b/asmcomp/import_approx.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 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 =
+    ignore (Compilenv.approx_for_global
+      (Set_of_closures_id.get_compilation_unit set_of_closures_id));
+    let ex_info = Compilenv.approx_env () in
+    let function_declarations =
+      try
+        Some (Set_of_closures_id.Map.find set_of_closures_id
+          ex_info.sets_of_closures)
+      with Not_found ->
+        None
+    in
+    match function_declarations with
+    | None -> None
+    | Some function_declarations ->
+      Some (import_function_declarations function_declarations)
+  in
+  Set_of_closures_id.Tbl.memoize Compilenv.imported_sets_of_closures_table aux
+
+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 option =
+    let bound_vars = Var_within_closure.Map.map import_approx bound_vars in
+    match
+      Set_of_closures_id.Map.find set_of_closures_id ex_info.invariant_params
+    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 ->
+      match import_set_of_closures set_of_closures_id with
+      | None -> None
+      | Some function_decls ->
+        Some (A.create_value_set_of_closures
+          ~function_decls
+          ~bound_vars
+          ~invariant_params:(lazy invariant_params)
+          ~specialised_args:Variable.Map.empty
+          ~freshening:Freshening.Project_var.empty
+          ~direct_call_surrogates:Closure_id.Map.empty)
+  in
+  match Export_info.find_description ex_info ex with
+  | exception Not_found -> A.value_unknown Other
+  | 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
+        (Array.map (function
+           | None -> A.value_any_float
+           | Some f -> A.value_float f)
+           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
+    begin match value_set_of_closures with
+    | None -> A.value_unresolved (Set_of_closures_id set_of_closures_id)
+    | Some value_set_of_closures ->
+      A.value_closure ?set_of_closures_symbol:aliased_symbol
+        value_set_of_closures closure_id
+    end
+  | Value_set_of_closures { set_of_closures_id; bound_vars; aliased_symbol } ->
+    let value_set_of_closures =
+      import_value_set_of_closures ~set_of_closures_id ~bound_vars ~ex_info
+        ~what:"Value_set_of_closures"
+    in
+    match value_set_of_closures with
+    | None ->
+      A.value_unresolved (Set_of_closures_id set_of_closures_id)
+    | Some value_set_of_closures ->
+      let approx = A.value_set_of_closures value_set_of_closures in
+      match aliased_symbol with
+      | None -> approx
+      | Some symbol -> A.augment_with_symbol approx symbol
+
+and import_approx (ap : Export_info.approx) =
+  match ap with
+  | 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 (Symbol 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 0000000000..23d9d29482
--- /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 6d61894896..d185dc0ee6 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
@@ -98,9 +101,9 @@ let build_graph fundecl =
     | Iop(Imove | Ispill | Ireload) ->
         add_interf_move i.arg.(0) i.res.(0) i.live;
         interf i.next
-    | Iop(Itailcall_ind) -> ()
-    | Iop(Itailcall_imm lbl) -> ()
-    | Iop op ->
+    | Iop(Itailcall_ind _) -> ()
+    | Iop(Itailcall_imm _) -> ()
+    | Iop _ ->
         begin match op with
         | Iloadmut ->
             add_interf_arr i.arg i.res;
@@ -110,11 +113,11 @@ let build_graph fundecl =
         add_interf_set i.res i.live;
         add_interf_self i.res;
         interf i.next
-    | Iifthenelse(tst, ifso, ifnot) ->
+    | Iifthenelse(_tst, ifso, ifnot) ->
         interf ifso;
         interf ifnot;
         interf i.next
-    | Iswitch(index, cases) ->
+    | Iswitch(_index, cases) ->
         for i = 0 to Array.length cases - 1 do
           interf cases.(i)
         done;
@@ -176,15 +179,15 @@ let build_graph fundecl =
     | Iop(Ireload) ->
         add_pref (weight / 4) i.res.(0) i.arg.(0);
         prefer weight i.next
-    | Iop(Itailcall_ind) -> ()
-    | Iop(Itailcall_imm lbl) -> ()
-    | Iop op ->
+    | Iop(Itailcall_ind _) -> ()
+    | Iop(Itailcall_imm _) -> ()
+    | Iop _ ->
         prefer weight i.next
-    | Iifthenelse(tst, ifso, ifnot) ->
+    | Iifthenelse(_tst, ifso, ifnot) ->
         prefer (weight / 2) ifso;
         prefer (weight / 2) ifnot;
         prefer weight i.next
-    | Iswitch(index, cases) ->
+    | Iswitch(_index, cases) ->
         for i = 0 to Array.length cases - 1 do
           prefer (weight / 2) cases.(i)
         done;
diff --git a/asmcomp/interf.mli b/asmcomp/interf.mli
index a9b0b63090..13549a1d78 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 fba5460835..3a28d172d3 100644
--- a/asmcomp/linearize.ml
+++ b/asmcomp/linearize.ml
@@ -1,25 +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 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Transformation of Mach code into a list of pseudo-instructions. *)
 
 open Reg
 open Mach
 
-type label = int
-
-let label_counter = ref 99
-
-let new_label() = incr label_counter; !label_counter
+type label = Cmm.label
 
 type instruction =
   { mutable desc: instruction_desc;
@@ -42,11 +41,11 @@ and instruction_desc =
   | Lsetuptrap of label
   | Lpushtrap
   | Lpoptrap
-  | Lraise of Lambda.raise_kind
+  | Lraise of Cmm.raise_kind
 
 let has_fallthrough = function
   | Lreturn | Lbranch _ | Lswitch _ | Lraise _
-  | Lop Itailcall_ind | Lop (Itailcall_imm _) -> false
+  | Lop Itailcall_ind _ | Lop (Itailcall_imm _) -> false
   | _ -> true
 
 type fundecl =
@@ -54,7 +53,9 @@ type fundecl =
     fun_args: Reg.Set.t;
     fun_body: instruction;
     fun_fast: bool;
-    fun_dbg : Debuginfo.t }
+    fun_dbg : Debuginfo.t;
+    fun_spacetime_shape : Mach.spacetime_shape option;
+  }
 
 (* Invert a test *)
 
@@ -111,7 +112,7 @@ let get_label n = match n.desc with
     Lbranch lbl -> (lbl, n)
   | Llabel lbl -> (lbl, n)
   | Lend -> (-1, n)
-  | _ -> let lbl = new_label() in (lbl, cons_instr (Llabel lbl) n)
+  | _ -> let lbl = Cmm.new_label() in (lbl, cons_instr (Llabel lbl) n)
 
 (* Check the fallthrough label *)
 let check_label n = match n.desc with
@@ -178,8 +179,11 @@ let local_exit k =
 let rec linear i n =
   match i.Mach.desc with
     Iend -> n
-  | Iop(Itailcall_ind | Itailcall_imm _ as op) ->
+  | Iop(Itailcall_ind _ | Itailcall_imm _ as op) ->
+      if not Config.spacetime then
       copy_instr (Lop op) i (discard_dead_code n)
+      else
+        copy_instr (Lop op) i (linear i.Mach.next n)
   | Iop(Imove | Ireload | Ispill)
     when i.Mach.arg.(0).loc = i.Mach.res.(0).loc ->
       linear i.Mach.next n
@@ -246,7 +250,7 @@ let rec linear i n =
       end else
         copy_instr (Lswitch(Array.map (fun n -> lbl_cases.(n)) index)) i !n2
   | Iloop body ->
-      let lbl_head = new_label() in
+      let lbl_head = Cmm.new_label() in
       let n1 = linear i.Mach.next n in
       let n2 = linear body (cons_instr (Lbranch lbl_head) n1) in
       cons_instr (Llabel lbl_head) n2
@@ -278,22 +282,21 @@ let rec linear i n =
   | Itrywith(body, handler) ->
       let (lbl_join, n1) = get_label (linear i.Mach.next n) in
       incr try_depth;
+      assert (i.Mach.arg = [| |] || Config.spacetime);
       let (lbl_body, n2) =
-        get_label (cons_instr Lpushtrap
+        get_label (instr_cons Lpushtrap i.Mach.arg [| |]
                     (linear body (cons_instr Lpoptrap n1))) in
       decr try_depth;
-      cons_instr (Lsetuptrap lbl_body)
+      instr_cons (Lsetuptrap lbl_body) i.Mach.arg [| |]
         (linear handler (add_branch lbl_join n2))
   | Iraise k ->
       copy_instr (Lraise k) i (discard_dead_code n)
 
-let reset () =
-  label_counter := 99;
-  exit_label := []
-
 let fundecl f =
   { fun_name = f.Mach.fun_name;
     fun_args = Reg.set_of_array f.Mach.fun_args;
     fun_body = linear f.Mach.fun_body end_instr;
     fun_fast = f.Mach.fun_fast;
-    fun_dbg  = f.Mach.fun_dbg }
+    fun_dbg  = f.Mach.fun_dbg;
+    fun_spacetime_shape = f.Mach.fun_spacetime_shape;
+  }
diff --git a/asmcomp/linearize.mli b/asmcomp/linearize.mli
index e3d49d9f16..f385ddf333 100644
--- a/asmcomp/linearize.mli
+++ b/asmcomp/linearize.mli
@@ -1,19 +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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
 
-type label = int
-val new_label: unit -> label
+type label = Cmm.label
 
 type instruction =
   { mutable desc: instruction_desc;
@@ -36,7 +38,7 @@ and instruction_desc =
   | Lsetuptrap of label
   | Lpushtrap
   | Lpoptrap
-  | Lraise of Lambda.raise_kind
+  | Lraise of Cmm.raise_kind
 
 val has_fallthrough :  instruction_desc -> bool
 val end_instr: instruction
@@ -49,7 +51,8 @@ type fundecl =
     fun_args: Reg.Set.t;
     fun_body: instruction;
     fun_fast: bool;
-    fun_dbg : Debuginfo.t }
+    fun_dbg : Debuginfo.t;
+    fun_spacetime_shape : Mach.spacetime_shape option;
+  }
 
-val reset : unit -> unit
 val fundecl: Mach.fundecl -> fundecl
diff --git a/asmcomp/liveness.ml b/asmcomp/liveness.ml
index 2ef322ef3e..9f96eb07a9 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
@@ -32,18 +35,24 @@ let rec live i finally =
      before the instruction sequence.
      The instruction i is annotated by the set of registers live across
      the instruction. *)
+  let arg =
+    if Config.spacetime
+      && Mach.spacetime_node_hole_pointer_is_live_before i
+    then Array.append i.arg [| Proc.loc_spacetime_node_hole |]
+    else i.arg
+  in
   match i.desc with
     Iend ->
       i.live <- finally;
       finally
-  | Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _) ->
+  | Ireturn | Iop(Itailcall_ind _) | Iop(Itailcall_imm _) ->
       i.live <- Reg.Set.empty; (* no regs are live across *)
-      Reg.set_of_array i.arg
+      Reg.set_of_array arg
   | Iop op ->
       let after = live i.next finally in
       if Proc.op_is_pure op                    (* no side effects *)
       && Reg.disjoint_set_array after i.res    (* results are not used after *)
-      && not (Proc.regs_are_volatile i.arg)    (* no stack-like hard reg *)
+      && not (Proc.regs_are_volatile arg)      (* no stack-like hard reg *)
       && not (Proc.regs_are_volatile i.res)    (*            is involved *)
       then begin
         (* This operation is dead code.  Ignore its arguments. *)
@@ -53,8 +62,8 @@ let rec live i finally =
         let across_after = Reg.diff_set_array after i.res in
         let across =
           match op with
-          | Icall_ind | Icall_imm _ | Iextcall _
-          | Iintop Icheckbound | Iintop_imm(Icheckbound, _) ->
+          | Icall_ind _ | Icall_imm _ | Iextcall _
+          | Iintop (Icheckbound _) | Iintop_imm(Icheckbound _, _) ->
               (* The function call may raise an exception, branching to the
                  nearest enclosing try ... with. Similarly for bounds checks.
                  Hence, everything that must be live at the beginning of
@@ -63,21 +72,21 @@ let rec live i finally =
            | _ ->
                across_after in
         i.live <- across;
-        Reg.add_set_array across i.arg
+        Reg.add_set_array across arg
       end
-  | Iifthenelse(test, ifso, ifnot) ->
+  | Iifthenelse(_test, ifso, ifnot) ->
       let at_join = live i.next finally in
       let at_fork = Reg.Set.union (live ifso at_join) (live ifnot at_join) in
       i.live <- at_fork;
-      Reg.add_set_array at_fork i.arg
-  | Iswitch(index, cases) ->
+      Reg.add_set_array at_fork arg
+  | Iswitch(_index, cases) ->
       let at_join = live i.next finally in
       let at_fork = ref Reg.Set.empty in
       for i = 0 to Array.length cases - 1 do
         at_fork := Reg.Set.union !at_fork (live cases.(i) at_join)
       done;
       i.live <- !at_fork;
-      Reg.add_set_array !at_fork i.arg
+      Reg.add_set_array !at_fork arg
   | Iloop(body) ->
       let at_top = ref Reg.Set.empty in
       (* Yes, there are better algorithms, but we'll just iterate till
@@ -117,7 +126,7 @@ let rec live i finally =
       before_body
   | Iraise _ ->
       i.live <- !live_at_raise;
-      Reg.add_set_array !live_at_raise i.arg
+      Reg.add_set_array !live_at_raise arg
 
 let reset () =
   live_at_raise := Reg.Set.empty;
@@ -125,8 +134,13 @@ let reset () =
 
 let fundecl ppf f =
   let initially_live = live f.fun_body Reg.Set.empty in
-  (* Sanity check: only function parameters can be live at entrypoint *)
+  (* Sanity check: only function parameters (and the Spacetime node hole
+     register, if profiling) can be live at entrypoint *)
   let wrong_live = Reg.Set.diff initially_live (Reg.set_of_array f.fun_args) in
+  let wrong_live =
+    if not Config.spacetime then wrong_live
+    else Reg.Set.remove Proc.loc_spacetime_node_hole wrong_live
+  in
   if not (Reg.Set.is_empty wrong_live) then begin
     Format.fprintf ppf "%a@." Printmach.regset wrong_live;
     Misc.fatal_error "Liveness.fundecl"
diff --git a/asmcomp/liveness.mli b/asmcomp/liveness.mli
index ed2f1a8aeb..7a8fae6270 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 29b1b81f28..0dca317a13 100644
--- a/asmcomp/mach.ml
+++ b/asmcomp/mach.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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
+type label = Cmm.label
+
 type integer_comparison =
     Isigned of Cmm.comparison
   | Iunsigned of Cmm.comparison
@@ -20,7 +25,8 @@ type integer_operation =
     Iadd | Isub | Imul | Imulh | Idiv | Imod
   | Iand | Ior | Ixor | Ilsl | Ilsr | Iasr
   | Icomp of integer_comparison
-  | Icheckbound
+  | Icheckbound of { label_after_error : label option;
+        spacetime_index : int; }
 
 type test =
     Itruetest
@@ -36,19 +42,19 @@ 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
-  | Icall_imm of string
-  | Itailcall_ind
-  | Itailcall_imm of string
-  | Iextcall of string * bool * int
+  | Icall_ind of { label_after : label; }
+  | Icall_imm of { func : string; label_after : label; }
+  | Itailcall_ind of { label_after : label; }
+  | Itailcall_imm of { func : string; label_after : label; }
+  | Iextcall of { func : string; alloc : bool; label_after : label; stack_ofs : int; }
   | Istackoffset of int
   | Iload of Cmm.memory_chunk * Arch.addressing_mode
   | Iloadmut
   | Istore of Cmm.memory_chunk * Arch.addressing_mode * bool
-  | Ialloc of int
+  | Ialloc of { words : int; label_after_call_gc : label option;
+        spacetime_index : int; }
   | Iintop of integer_operation
   | Iintop_imm of integer_operation * int
   | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
@@ -73,14 +79,23 @@ and instruction_desc =
   | Icatch of int * instruction * instruction
   | Iexit of int
   | Itrywith of instruction * instruction
-  | Iraise of Lambda.raise_kind
+  | Iraise of Cmm.raise_kind
+
+type spacetime_part_of_shape =
+  | Direct_call_point of { callee : string; }
+  | Indirect_call_point
+  | Allocation_point
+
+type spacetime_shape = (spacetime_part_of_shape * Cmm.label) list
 
 type fundecl =
   { fun_name: string;
     fun_args: Reg.t array;
     fun_body: instruction;
     fun_fast: bool;
-    fun_dbg : Debuginfo.t }
+    fun_dbg : Debuginfo.t;
+    fun_spacetime_shape : spacetime_shape option;
+  }
 
 let rec dummy_instr =
   { desc = Iend;
@@ -112,10 +127,10 @@ let rec instr_iter f i =
       f i;
       match i.desc with
         Iend -> ()
-      | Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _) -> ()
-      | Iifthenelse(tst, ifso, ifnot) ->
+      | Ireturn | Iop(Itailcall_ind _) | Iop(Itailcall_imm _) -> ()
+      | Iifthenelse(_tst, ifso, ifnot) ->
           instr_iter f ifso; instr_iter f ifnot; instr_iter f i.next
-      | Iswitch(index, cases) ->
+      | Iswitch(_index, cases) ->
           for i = 0 to Array.length cases - 1 do
             instr_iter f cases.(i)
           done;
@@ -130,3 +145,36 @@ let rec instr_iter f i =
       | Iraise _ -> ()
       | _ ->
           instr_iter f i.next
+
+let spacetime_node_hole_pointer_is_live_before insn =
+  match insn.desc with
+  | Iop op ->
+    begin match op with
+    | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _ -> true
+    | Iextcall { alloc; } -> alloc
+    | Ialloc _ ->
+      (* Allocations are special: the call to [caml_call_gc] requires some
+         instrumentation code immediately prior, but this is not inserted until
+         the emitter (since the call is not visible prior to that in any IR).
+         As such, none of the Mach / Linearize analyses will ever see that
+         we use the node hole pointer for these, and we do not need to say
+         that it is live at such points. *)
+      false
+    | Iintop op | Iintop_imm (op, _) ->
+      begin match op with
+      | Icheckbound _
+        (* [Icheckbound] doesn't need to return [true] for the same reason as
+           [Ialloc]. *)
+      | Iadd | Isub | Imul | Imulh | Idiv | Imod
+      | Iand | Ior | Ixor | Ilsl | Ilsr | Iasr
+      | Icomp _ -> false
+      end
+    | Ispecific specific_op ->
+      Arch.spacetime_node_hole_pointer_is_live_before specific_op
+    | Imove | Ispill | Ireload | Iconst_int _ | Iconst_float _
+    | Iconst_symbol _ | Istackoffset _ | Iload _ | Istore _
+    | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
+    | Ifloatofint | Iintoffloat -> false
+    end
+  | Iend | Ireturn | Iifthenelse _ | Iswitch _ | Iloop _ | Icatch _
+  | Iexit _ | Itrywith _ | Iraise _ -> false
diff --git a/asmcomp/mach.mli b/asmcomp/mach.mli
index 24d6ce5fef..97ed64293b 100644
--- a/asmcomp/mach.mli
+++ b/asmcomp/mach.mli
@@ -1,17 +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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
+(** N.B. Backends vary in their treatment of call gc and checkbound
+    points.  If the positioning of any labels associated with these is
+    important for some new feature in the compiler, the relevant backends'
+    behaviour should be checked. *)
+type label = Cmm.label
+
 type integer_comparison =
     Isigned of Cmm.comparison
   | Iunsigned of Cmm.comparison
@@ -20,7 +29,11 @@ type integer_operation =
     Iadd | Isub | Imul | Imulh | Idiv | Imod
   | Iand | Ior | Ixor | Ilsl | Ilsr | Iasr
   | Icomp of integer_comparison
-  | Icheckbound
+  | Icheckbound of { label_after_error : label option;
+        spacetime_index : int; }
+    (** For Spacetime only, [Icheckbound] operations take two arguments, the
+        second being the pointer to the trie node for the current function
+        (and the first being as per non-Spacetime mode). *)
 
 type test =
     Itruetest
@@ -36,20 +49,23 @@ 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
-  | Icall_imm of string
-  | Itailcall_ind
-  | Itailcall_imm of string
-  | Iextcall of string * bool * int (* false = noalloc, true = alloc, n = stack_args *)
+  | Icall_ind of { label_after : label; }
+  | Icall_imm of { func : string; label_after : label; }
+  | Itailcall_ind of { label_after : label; }
+  | Itailcall_imm of { func : string; label_after : label; }
+  | Iextcall of { func : string; alloc : bool; label_after : label;
+                  stack_ofs : int}
   | Istackoffset of int
   | Iload of Cmm.memory_chunk * Arch.addressing_mode
   | Iloadmut
   | Istore of Cmm.memory_chunk * Arch.addressing_mode * bool
                                  (* false = initialization, true = assignment *)
-  | Ialloc of int
+  | Ialloc of { words : int; label_after_call_gc : label option;
+      spacetime_index : int; }
+    (** For Spacetime only, Ialloc instructions take one argument, being the
+        pointer to the trie node for the current function. *)
   | Iintop of integer_operation
   | Iintop_imm of integer_operation * int
   | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
@@ -74,14 +90,29 @@ and instruction_desc =
   | Icatch of int * instruction * instruction
   | Iexit of int
   | Itrywith of instruction * instruction
-  | Iraise of Lambda.raise_kind
+  | Iraise of Cmm.raise_kind
+
+type spacetime_part_of_shape =
+  | Direct_call_point of { callee : string; (* the symbol *) }
+  | Indirect_call_point
+  | Allocation_point
+
+(** A description of the layout of a Spacetime profiling node associated with
+    a given function.  Each call and allocation point instrumented within
+    the function is marked with a label in the code and assigned a place
+    within the node.  This information is stored within the executable and
+    extracted when the user saves a profile.  The aim is to minimise runtime
+    memory usage within the nodes and increase performance. *)
+type spacetime_shape = (spacetime_part_of_shape * Cmm.label) list
 
 type fundecl =
   { fun_name: string;
     fun_args: Reg.t array;
     fun_body: instruction;
     fun_fast: bool;
-    fun_dbg : Debuginfo.t }
+    fun_dbg : Debuginfo.t;
+    fun_spacetime_shape : spacetime_shape option;
+  }
 
 val dummy_instr: instruction
 val end_instr: unit -> instruction
@@ -92,3 +123,5 @@ val instr_cons_debug:
       instruction_desc -> Reg.t array -> Reg.t array -> Debuginfo.t ->
         instruction -> instruction
 val instr_iter: (instruction -> unit) -> instruction -> unit
+
+val spacetime_node_hole_pointer_is_live_before : instruction -> bool
diff --git a/asmcomp/power/CSE.ml b/asmcomp/power/CSE.ml
index ec10d2df4c..7b619cf642 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -16,7 +19,7 @@ open Arch
 open Mach
 open CSEgen
 
-class cse = object (self)
+class cse = object
 
 inherit cse_generic as super
 
@@ -28,7 +31,7 @@ method! class_of_operation op =
 
 method! is_cheap_operation op =
   match op with
-  | Iconst_int n | Iconst_blockheader n -> n <= 32767n && n >= -32768n
+  | Iconst_int n -> n <= 32767n && n >= -32768n
   | _ -> false
 
 end
diff --git a/asmcomp/power/NOTES.md b/asmcomp/power/NOTES.md
new file mode 100644
index 0000000000..d54c08691c
--- /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 cbeba916b5..289f33ca36 100644
--- a/asmcomp/power/arch.ml
+++ b/asmcomp/power/arch.ml
@@ -1,29 +1,60 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA 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 *)
 
 type specific_operation =
     Imultaddf                           (* multiply and add *)
   | Imultsubf                           (* multiply and subtract *)
-  | Ialloc_far of int                   (* allocation in large functions *)
+  | Ialloc_far of                       (* allocation in large functions *)
+      { words : int; label_after_call_gc : int (*Cmm.label*) option; }
+
+(* note: we avoid introducing a dependency to Cmm since this dep
+   is not detected when "make depend" is run under amd64 *)
+
+let spacetime_node_hole_pointer_is_live_before = function
+  | Imultaddf | Imultsubf -> false
+  | Ialloc_far _ -> true
 
 (* Addressing modes *)
 
@@ -34,16 +65,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 *)
 
@@ -60,8 +93,8 @@ let offset_addressing addr delta =
   | Iindexed2 -> assert false
 
 let num_args_addressing = function
-    Ibased(s, n) -> 0
-  | Iindexed n -> 1
+    Ibased _ -> 0
+  | Iindexed _ -> 1
   | Iindexed2 -> 2
 
 (* Printing operations and addressing modes *)
@@ -85,5 +118,5 @@ let print_specific_operation printreg op ppf arg =
   | Imultsubf ->
       fprintf ppf "%a *f %a -f %a"
         printreg arg.(0) printreg arg.(1) printreg arg.(2)
-  | Ialloc_far n ->
-      fprintf ppf "alloc_far %d" n
+  | Ialloc_far { words; _ } ->
+      fprintf ppf "alloc_far %d" words
diff --git a/asmcomp/power/emit.mlp b/asmcomp/power/emit.mlp
index 434408524d..33b9768614 100644
--- a/asmcomp/power/emit.mlp
+++ b/asmcomp/power/emit.mlp
@@ -1,20 +1,21 @@
-(***********************************************************************)
+#2 "asmcomp/power/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 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* 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,68 +25,83 @@ 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
 
-let emit_data_label lbl =
-  emit_string label_prefix; emit_string "d"; emit_int 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 +111,56 @@ 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 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 nativelow n = Nativeint.to_int n land 0xFFFF
-let nativehigh n = Nativeint.to_int (Nativeint.shift_right n 16)
+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 +168,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
 
 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
 
 (* 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,55 +252,89 @@ 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 =
-  let lbl = new_label() in
+let record_frame ?label live raise_ dbg =
+  let lbl =
+    match label with
+    | None -> new_label()
+    | Some label -> 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 ->
+      | {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_raise = raise_;
       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) *)
+(* 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 pic_externals = (Config.system = "rhapsody")
-
-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 +394,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,179 +422,286 @@ module BR = Branch_relaxation.Make (struct
 
   let offset_pc_at_branch = 1
 
+  let size =
+    match abi with
+    | ELF32 -> (fun a _ _ -> a)
+    | ELF64v1 -> (fun _ b _ -> b)
+    | ELF64v2 -> (fun _ _ 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
 
   let instr_size = function
     | 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
-    | Lop(Istackoffset n) -> 1
+    | Lop(Iconst_int n) ->
+      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 _) -> if abi = ELF32 then 2 else tocload_size()
+    | Lop(Iconst_symbol _) -> if abi = ELF32 then 2 else tocload_size()
+    | Lop(Icall_ind _) -> size 2 5 4
+    | Lop(Icall_imm _) -> size 1 3 3
+    | Lop(Itailcall_ind _) -> size 5 7 6
+    | Lop(Itailcall_imm { func; _ }) ->
+        if func = !function_name
+        then 1
+        else size 4 (7 + tocload_size()) (6 + tocload_size())
+    | Lop(Iextcall { alloc = true; _ }) ->
+      size 3 (2 + tocload_size()) (2 + tocload_size())
+    | Lop(Iextcall { alloc = false; _}) -> size 1 2 2
+    | Lop(Istackoffset _) -> 1
     | Lop(Iload(chunk, addr)) ->
       if chunk = Byte_signed
       then load_store_size addr + 1
       else load_store_size addr
-    | Lop(Istore(chunk, addr, _)) -> load_store_size addr
-    | Lop(Ialloc n) -> 4
-    | Lop(Ispecific(Ialloc_far n)) -> 5
+    | Lop(Istore(_chunk, addr, _)) -> load_store_size addr
+    | Lop(Ialloc _) -> 4
+    | Lop(Ispecific(Ialloc_far _)) -> 5
     | Lop(Iintop Imod) -> 3
-    | Lop(Iintop(Icomp cmp)) -> 4
-    | Lop(Iintop op) -> 1
-    | Lop(Iintop_imm(Icomp cmp, n)) -> 4
-    | Lop(Iintop_imm(op, n)) -> 1
+    | Lop(Iintop(Icomp _)) -> 4
+    | Lop(Iintop _) -> 1
+    | Lop(Iintop_imm(Icomp _, _)) -> 4
+    | Lop(Iintop_imm _) -> 1
     | Lop(Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf) -> 1
     | Lop(Ifloatofint) -> 9
     | Lop(Iintoffloat) -> 4
-    | Lop(Ispecific sop) -> 1
+    | Lop(Ispecific _) -> 1
     | Lreloadretaddr -> 2
     | Lreturn -> 2
-    | Llabel lbl -> 0
-    | Lbranch lbl -> 1
-    | Lcondbranch(tst, lbl) -> 2
+    | Llabel _ -> 0
+    | Lbranch _ -> 1
+    | Lcondbranch _ -> 2
     | Lcondbranch3(lbl0, lbl1, lbl2) ->
       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 _ -> size 7 (5 + tocload_size()) (5 + tocload_size())
+    | Lsetuptrap _ -> size 1 2 2
+    | Lpushtrap -> size 4 5 5
     | Lpoptrap -> 2
     | Lraise _ -> 6
 
-  let relax_allocation ~num_words = Lop (Ispecific (Ialloc_far num_words))
+  let relax_allocation ~num_words:words ~label_after_call_gc =
+    Lop (Ispecific (Ialloc_far { words; label_after_call_gc; }))
 
   (* [classify_addr], above, never identifies these instructions as needing
      relaxing.  As such, these functions should never be called. *)
   let relax_specific_op _ = assert false
-  let relax_intop_checkbound () = assert false
-  let relax_intop_imm_checkbound ~bound:_ = assert false
+  let relax_intop_checkbound ~label_after_error:_ = assert false
+  let relax_intop_imm_checkbound ~bound:_ ~label_after_error:_ = assert false
 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 _; typ = (Val | Int | Addr)}, {loc = Reg _} ->
                 `	mr	{emit_reg dst}, {emit_reg src}\n`
-            | {loc = Reg rs; typ = Float}, {loc = Reg rd; typ = Float} ->
+            | {loc = Reg _; typ = Float}, {loc = Reg _; typ = Float} ->
                 `	fmr	{emit_reg dst}, {emit_reg src}\n`
-            | {loc = Reg rs; typ = (Int | Addr)}, {loc = Stack sd} ->
+            | {loc = Reg _; typ = (Val | Int | Addr)}, {loc = Stack _} ->
                 `	{emit_string stg}	{emit_reg src}, {emit_stack dst}\n`
-            | {loc = Reg rs; typ = Float}, {loc = Stack sd} ->
+            | {loc = Reg _; typ = Float}, {loc = Stack _} ->
                 `	stfd	{emit_reg src}, {emit_stack dst}\n`
-            | {loc = Stack ss; typ = (Int | Addr)}, {loc = Reg rd} ->
+            | {loc = Stack _; typ = (Val | Int | Addr)}, {loc = Reg _} ->
                 `	{emit_string lg}	{emit_reg dst}, {emit_stack src}\n`
-            | {loc = Stack ss; typ = Float}, {loc = Reg rd} ->
+            | {loc = Stack _; typ = Float}, {loc = Reg _} ->
                 `	lfd	{emit_reg dst}, {emit_stack src}\n`
             | (_, _) ->
                 fatal_error "Emit: Imove"
         end
-    | Lop(Iconst_int n | Iconst_blockheader n) ->
+    | Lop(Iconst_int 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
-          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`
-        end
+        (* 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
-        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`
+          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_symbol s) ->
+        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`
-    | Lop(Icall_ind) ->
+        | ELF64v1 | ELF64v2 ->
+          emit_tocload emit_reg i.res.(0) (TocSym s)
+        end
+    | Lop(Icall_ind { label_after; }) ->
+        begin match abi with
+        | ELF32 ->
         `	mtctr	{emit_reg i.arg.(0)}\n`;
         `	bctrl\n`;
-        record_frame i.live i.dbg
-    | Lop(Icall_imm s) ->
-        `	bl	{emit_symbol s}\n`;
-        record_frame i.live i.dbg
-    | Lop(Itailcall_ind) ->
-        let n = frame_size() in
+          record_frame i.live false i.dbg ~label:label_after
+        | 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 false i.dbg ~label:label_after;
+          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 false i.dbg ~label:label_after;
+          emit_reload_toc()
+        end
+    | Lop(Icall_imm { func; label_after; }) ->
+        begin match abi with
+        | ELF32 ->
+            emit_call func;
+            record_frame i.live false i.dbg ~label:label_after
+        | 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 func;
+            record_frame i.live false i.dbg ~label:label_after;
+            `	nop\n`;
+            emit_reload_toc()
+        end
+    | Lop(Itailcall_ind { label_after = _; }) ->
+        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
+    | Lop(Itailcall_imm { func; label_after = _; }) ->
+        if func = !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 func);
+            `	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 func); (* 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 func}\n`
+          | ELF64v1 | ELF64v2 ->
+            `	bctr\n`
         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
+        end
+    | Lop(Iextcall { func; alloc; }) ->
+        if not alloc then begin
+          emit_call func;
+          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 func}\n`;
+            `	addi	28, 28, {emit_lower emit_symbol func}\n`;
+            emit_call "caml_c_call";
+            record_frame i.live false i.dbg
+          | ELF64v1 | ELF64v2 ->
+            emit_tocload emit_gpr 28 (TocSym func);
+            emit_call "caml_c_call";
+            record_frame i.live false 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 +710,45 @@ 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`;
+    | Lop(Ialloc { words = n; label_after_call_gc; }) ->
+        if !call_gc_label = 0 then begin
+          match label_after_call_gc with
+          | None -> call_gc_label := new_label ()
+          | Some label -> call_gc_label := label
+        end;
+        `	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`;
-        record_frame i.live Debuginfo.none
-    | Lop(Ispecific(Ialloc_far n)) ->
-        if !call_gc_label = 0 then call_gc_label := new_label();
+        (* Exactly 4 instructions after the beginning of the alloc sequence *)
+        record_frame i.live false Debuginfo.none
+    | Lop(Ispecific(Ialloc_far { words = n; label_after_call_gc; })) ->
+        if !call_gc_label = 0 then begin
+          match label_after_call_gc with
+          | None -> call_gc_label := new_label ()
+          | Some label -> call_gc_label := label
+        end;
         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`;
-        record_frame i.live Debuginfo.none;
-        `{emit_label lbl}:	addi	{emit_reg i.res.(0)}, {emit_gpr 31}, {emit_int size_addr}\n`
+        (* Exactly 4 instructions after the beginning of the alloc sequence *)
+        record_frame i.live false Debuginfo.none;
+        `{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 ->
@@ -550,9 +758,9 @@ let rec emit_instr i dslot =
             `	{emit_string cmplg}	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
             emit_set_comp c i.res.(0)
         end
-    | Lop(Iintop Icheckbound) ->
+    | Lop(Iintop (Icheckbound { label_after_error; })) ->
         if !Clflags.debug then
-          record_frame Reg.Set.empty i.dbg;
+          record_frame Reg.Set.empty false i.dbg ?label:label_after_error;
         `	{emit_string tglle}   {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`
     | Lop(Iintop op) ->
         let instr = name_for_intop op in
@@ -568,9 +776,9 @@ let rec emit_instr i dslot =
             `	{emit_string cmplg}i	{emit_reg i.arg.(0)}, {emit_int n}\n`;
             emit_set_comp c i.res.(0)
         end
-    | Lop(Iintop_imm(Icheckbound, n)) ->
+    | Lop(Iintop_imm(Icheckbound { label_after_error; }, n)) ->
         if !Clflags.debug then
-          record_frame Reg.Set.empty i.dbg;
+          record_frame Reg.Set.empty false i.dbg ?label:label_after_error;
         `	{emit_string tglle}i   {emit_reg i.arg.(0)}, {emit_int n}\n`
     | Lop(Iintop_imm(op, n)) ->
         let instr = name_for_intop_imm op in
@@ -583,40 +791,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 +837,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 +862,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 +888,157 @@ 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`;
+        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
-        | true, Lambda.Raise_reraise ->
-          `	bl	{emit_symbol "caml_reraise_exn"}\n`;
-          record_frame Reg.Set.empty i.dbg
-        | 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`;
+        begin match k with
+        | Cmm.Raise_withtrace ->
+            emit_call "caml_raise_exn";
+            record_frame Reg.Set.empty true i.dbg;
+            emit_call_nop()
+        | Cmm.Raise_notrace ->
+            `	{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
+  jumptables := []; jumptables_lbl := -1;
+  begin match abi with
+  | ELF32 ->
+    emit_string code_space;
   `	.globl	{emit_symbol fundecl.fun_name}\n`;
-  begin match Config.system with
-  | "elf" | "bsd" | "bsd_elf" ->
-      `	.type	{emit_symbol fundecl.fun_name}, @function\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,42 +1049,63 @@ let fundecl fundecl =
   (* Emit the glue code to call the GC *)
   if !call_gc_label > 0 then begin
     `{emit_label !call_gc_label}:\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
 
 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 ->
@@ -869,8 +1122,6 @@ let emit_item = function
       else emit_float64_split_directive ".long" (Int64.bits_of_float f)
   | Csymbol_address s ->
       `	{emit_string datag}	{emit_symbol s}\n`
-  | Clabel_address lbl ->
-      `	{emit_string datag}	{emit_data_label lbl}\n`
   | Cstring s ->
       emit_bytes_directive "	.byte	" s
   | Cskip n ->
@@ -880,33 +1131,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;
@@ -918,13 +1205,25 @@ let end_assembly() =
   declare_global_data lbl;
   `{emit_symbol lbl}:\n`;
   emit_frames
-    { efa_label = (fun l -> `	{emit_string datag}	{emit_label l}\n`);
+    { efa_code_label =
+         (fun l -> `	{emit_string datag}	{emit_label l}\n`);
+      efa_data_label =
+         (fun l -> `	{emit_string datag}	{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 -> `	{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 934d2cbfeb..36e2ff9b64 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,22 +45,11 @@ 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" |]
 
 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";
@@ -67,8 +59,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 = [| 23; 31 |]
@@ -99,102 +90,168 @@ let phys_reg n =
 let stack_slot slot ty =
   Reg.at_location ty (Stack slot)
 
+let loc_spacetime_node_hole = Reg.dummy  (* Spacetime unsupported *)
+
 (* 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 ->
+    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
+            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;
+            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
+            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
-          loc.(i) <- stack_slot (make_stack !ofs) Float;
+            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. *)
 
 let incoming ofs = Incoming ofs
 let outgoing ofs = Outgoing ofs
-let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
+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
-
-let extcall_use_push = 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)
 
 (* 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 *)
 
@@ -202,7 +259,7 @@ let loc_exn_bucket = phys_reg 0
 
 (* Volatile registers: none *)
 
-let regs_are_volatile rs = false
+let regs_are_volatile _rs = false
 
 (* Registers destroyed by operations *)
 
@@ -212,8 +269,9 @@ let destroyed_at_c_call =
      100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; 112])
 
 let destroyed_at_oper = function
-    Iop(Icall_ind | Icall_imm _ | Iextcall(_, true)) -> all_phys_regs
-  | Iop(Iextcall(_, false)) -> destroyed_at_c_call
+    Iop(Icall_ind _ | Icall_imm _ | Iextcall { alloc = true; _ }) ->
+    all_phys_regs
+  | Iop(Iextcall { alloc = false; _ }) -> destroyed_at_c_call
   | _ -> [||]
 
 let destroyed_at_raise = all_phys_regs
@@ -221,20 +279,20 @@ let destroyed_at_raise = all_phys_regs
 (* Maximal register pressure *)
 
 let safe_register_pressure = function
-    Iextcall(_, _) -> 15
+    Iextcall _ -> 15
   | _ -> 23
 
 let max_register_pressure = function
-    Iextcall(_, _) -> [| 15; 18 |]
+    Iextcall _ -> [| 15; 18 |]
   | _ -> [| 23; 30 |]
 
 (* Pure operations (without any side effect besides updating their result
    registers). *)
 
 let op_is_pure = function
-  | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+  | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _
   | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
-  | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) -> false
+  | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _) -> false
   | Ispecific(Imultaddf | Imultsubf) -> true
   | Ispecific _ -> false
   | _ -> true
diff --git a/asmcomp/power/reload.ml b/asmcomp/power/reload.ml
index 98f747a81a..040c793915 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 7adaa2eed3..dcbfca79f0 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 *)
 
@@ -35,7 +38,7 @@ method oper_latency = function
   | Ispecific(Imultaddf | Imultsubf) -> 5
   | _ -> 1
 
-method reload_retaddr_latency = 12
+method! reload_retaddr_latency = 12
   (* If we can have that many cycles between the reloadretaddr and the
      return, we can expect that the blr branch will be completely folded. *)
 
@@ -53,7 +56,7 @@ method oper_issue_cycles = function
   | Iintoffloat -> 4
   | _ -> 1
 
-method reload_retaddr_issue_cycles = 3
+method! reload_retaddr_issue_cycles = 3
   (* load then stalling mtlr *)
 
 end
diff --git a/asmcomp/power/selection.ml b/asmcomp/power/selection.ml
index 86aea05f46..71c474906e 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)
@@ -48,7 +51,7 @@ inherit Selectgen.selector_generic as super
 
 method is_immediate n = (n <= 32767) && (n >= -32768)
 
-method select_addressing chunk exp =
+method select_addressing _chunk exp =
   match select_addr exp with
     (Asymbol s, d) ->
       (Ibased(s, d), Ctuple [])
diff --git a/asmcomp/printclambda.ml b/asmcomp/printclambda.ml
index b28d749e24..c4a790a2aa 100644
--- a/asmcomp/printclambda.ml
+++ b/asmcomp/printclambda.ml
@@ -1,20 +1,37 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA 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
 open Clambda
 
+let mutable_flag = function
+  | Mutable-> "[mut]"
+  | Immutable -> ""
+
+let value_kind =
+  let open Lambda in
+  function
+  | Pgenval -> ""
+  | Pintval -> ":int"
+  | Pfloatval -> ":float"
+  | Pboxedintval Pnativeint -> ":nativeint"
+  | Pboxedintval Pint32 -> ":int32"
+  | Pboxedintval Pint64 -> ":int64"
+
 let rec structured_constant ppf = function
   | Uconst_float x -> fprintf ppf "%F" x
   | Uconst_int32 x -> fprintf ppf "%ldl" x
@@ -31,14 +48,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
@@ -62,13 +92,15 @@ let rec lam ppf = function
         List.iter (fprintf ppf "@ %a" lam) in
       fprintf ppf "@[<2>(closure@ %a %a)@]" funs clos lams fv
   | Uoffset(l,i) -> fprintf ppf "@[<2>(offset %a %d)@]" lam l i
-  | Ulet(id, arg, body) ->
+  | Ulet(mut, kind, id, arg, body) ->
       let rec letbody ul = match ul with
-        | Ulet(id, arg, body) ->
-            fprintf ppf "@ @[<2>%a@ %a@]" Ident.print id lam arg;
+        | Ulet(mut, kind, id, arg, body) ->
+            fprintf ppf "@ @[<2>%a%s%s@ %a@]"
+              Ident.print id (mutable_flag mut) (value_kind kind) lam arg;
             letbody body
         | _ -> ul in
-      fprintf ppf "@[<2>(let@ @[(@[<2>%a@ %a@]" Ident.print id lam arg;
+      fprintf ppf "@[<2>(let@ @[(@[<2>%a%s%s@ %a@]"
+        Ident.print id (mutable_flag mut) (value_kind kind) lam arg;
       let expr = letbody body in
       fprintf ppf ")@]@ %a)@]" lam expr
   | Uletrec(id_arg_list, body) ->
@@ -157,6 +189,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 d138b958ac..3b1ff58f53 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 088e782050..5a6c0897bd 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,21 +47,30 @@ 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"
 
+let raise_kind fmt = function
+  | Raise_withtrace -> Format.fprintf fmt "raise_withtrace"
+  | Raise_notrace -> Format.fprintf fmt "raise_notrace"
+
 let operation = function
-  | Capply(ty, d) -> "app" ^ Debuginfo.to_string d
-  | Cextcall(lbl, ty, alloc, d) ->
+  | 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"
-  | Cloadmut -> "load_mut"
   | Cload c -> Printf.sprintf "load %s" (chunk c)
-  | Calloc -> "alloc"
-  | Cstore Word -> "store"
-  | Cstore c -> Printf.sprintf "store %s" (chunk c)
+  | Cloadmut -> "load_mut"
+  | Calloc d -> "alloc" ^ Debuginfo.to_string d
+  | 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 -> "*"
@@ -71,8 +84,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"
@@ -83,13 +96,16 @@ let operation = function
   | Cfloatofint -> "floatofint"
   | Cintoffloat -> "intoffloat"
   | Ccmpf c -> Printf.sprintf "%sf" (comparison c)
-  | Craise (k, d) -> Lambda.raise_kind k ^ Debuginfo.to_string d
+  | Craise (k, d) -> Format.asprintf "%a%s" raise_kind k (Debuginfo.to_string d)
   | Ccheckbound d -> "checkbound" ^ Debuginfo.to_string d
 
 let rec expr ppf = function
   | Cconst_int n -> fprintf ppf "%i" n
-  | Cconst_natint n | Cconst_blockheader n ->
+  | Cconst_natint n ->
     fprintf ppf "%s" (Nativeint.to_string n)
+  | Cblockheader(n, d) ->
+    fprintf ppf "block-hdr(%s)%s"
+      (Nativeint.to_string n) (Debuginfo.to_string d)
   | Cconst_float n -> fprintf ppf "%F" n
   | Cconst_symbol s -> fprintf ppf "\"%s\"" s
   | Cconst_pointer n -> fprintf ppf "%ia" n
@@ -126,7 +142,7 @@ let rec expr ppf = function
       List.iter (fun e -> fprintf ppf "@ %a" expr e) el;
       begin match op with
       | Capply (mty, _) -> fprintf ppf "@ %a" machtype mty
-      | Cextcall(_, mty, _, _) -> fprintf ppf "@ %a" machtype mty
+      | Cextcall(_, mty, _, _, _) -> fprintf ppf "@ %a" machtype mty
       | _ -> ()
       end;
       fprintf ppf ")@]"
@@ -183,7 +199,6 @@ let fundecl ppf f =
 
 let data_item ppf = function
   | Cdefine_symbol s -> fprintf ppf "\"%s\":" s
-  | Cdefine_label l -> fprintf ppf "L%i:" l
   | Cglobal_symbol s -> fprintf ppf "global \"%s\"" s
   | Cint8 n -> fprintf ppf "byte %i" n
   | Cint16 n -> fprintf ppf "int16 %i" n
@@ -192,7 +207,6 @@ let data_item ppf = function
   | Csingle f -> fprintf ppf "single %F" f
   | Cdouble f -> fprintf ppf "double %F" f
   | Csymbol_address s -> fprintf ppf "addr \"%s\"" s
-  | Clabel_address l -> fprintf ppf "addr L%i" l
   | Cstring s -> fprintf ppf "string \"%s\"" s
   | Cskip n -> fprintf ppf "skip %i" n
   | Calign n -> fprintf ppf "align %i" n
diff --git a/asmcomp/printcmm.mli b/asmcomp/printcmm.mli
index 1c97c4a001..86ec11fe68 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 *)
 
@@ -23,3 +26,4 @@ val expression : formatter -> Cmm.expression -> unit
 val fundecl : formatter -> Cmm.fundecl -> unit
 val data : formatter -> Cmm.data_item list -> unit
 val phrase : formatter -> Cmm.phrase -> unit
+val raise_kind: formatter -> Cmm.raise_kind -> unit
diff --git a/asmcomp/printlinear.ml b/asmcomp/printlinear.ml
index f99ffac919..0096dcce72 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -25,7 +28,7 @@ let instr ppf i =
   | Lend -> ()
   | Lop op ->
       begin match op with
-      | Ialloc _ | Icall_ind | Icall_imm _ | Iextcall _ ->
+      | Ialloc _ | Icall_ind _ | Icall_imm _ | Iextcall _ ->
           fprintf ppf "@[<1>{%a}@]@," regsetaddr i.live
       | _ -> ()
       end;
@@ -61,7 +64,7 @@ let instr ppf i =
   | Lpoptrap ->
       fprintf ppf "pop trap"
   | Lraise k ->
-      fprintf ppf "%s %a" (Lambda.raise_kind k) reg i.arg.(0)
+      fprintf ppf "%a %a" Printcmm.raise_kind k reg i.arg.(0)
   end;
   if not (Debuginfo.is_none i.dbg) then
     fprintf ppf " %s" (Debuginfo.to_string i.dbg)
diff --git a/asmcomp/printlinear.mli b/asmcomp/printlinear.mli
index 68eda9c1d3..b598868e0e 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 e4bcfbf476..16efd644da 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
@@ -80,7 +87,16 @@ let intop = function
   | Ilsr -> " >>u "
   | Iasr -> " >>s "
   | Icomp cmp -> intcomp cmp
-  | Icheckbound -> " check > "
+  | Icheckbound { label_after_error; spacetime_index; } ->
+    if not Config.spacetime then " check > "
+    else
+      Printf.sprintf "check[lbl=%s,index=%d] > "
+        begin
+          match label_after_error with
+          | None -> ""
+          | Some lbl -> string_of_int lbl
+        end
+        spacetime_index
 
 let test tst ppf arg =
   match tst with
@@ -103,17 +119,16 @@ let operation op arg ppf res =
   | Imove -> regs ppf arg
   | Ispill -> fprintf ppf "%a (spill)" regs arg
   | 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_int n -> fprintf ppf "%s" (Nativeint.to_string n)
+  | 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
-  | Itailcall_ind -> fprintf ppf "tailcall %a" regs arg
-  | Itailcall_imm lbl -> fprintf ppf "tailcall \"%s\" %a" lbl regs arg
-  | Iextcall(lbl, alloc, stack_args) ->
-      fprintf ppf "extcall \"%s\" %a%s (stackargs=%d)" lbl regs arg
-      (if alloc then "" else " (noalloc)") stack_args
+  | Icall_ind _ -> fprintf ppf "call %a" regs arg
+  | Icall_imm { func; _ } -> fprintf ppf "call \"%s\" %a" func regs arg
+  | Itailcall_ind _ -> fprintf ppf "tailcall %a" regs arg
+  | Itailcall_imm { func; } -> fprintf ppf "tailcall \"%s\" %a" func regs arg
+  | Iextcall { func; alloc; _ } ->
+      fprintf ppf "extcall \"%s\" %a%s" func regs arg
+      (if alloc then "" else " (noalloc)")
   | Istackoffset n ->
       fprintf ppf "offset stack %i" n
   | Iload(chunk, addr) ->
@@ -128,7 +143,11 @@ let operation op arg ppf res =
        (Array.sub arg 1 (Array.length arg - 1))
        reg arg.(0)
        (if is_assign then "(assign)" else "(init)")
-  | Ialloc n -> fprintf ppf "alloc %i" n
+  | Ialloc { words = n; _ } ->
+    fprintf ppf "alloc %i" n;
+    if Config.spacetime then begin
+      fprintf ppf "(spacetime node = %a)" reg arg.(0)
+    end
   | Iintop(op) -> fprintf ppf "%a%s%a" reg arg.(0) (intop op) reg arg.(1)
   | Iintop_imm(op, n) -> fprintf ppf "%a%s%i" reg arg.(0) (intop op) n
   | Inegf -> fprintf ppf "-f %a" reg arg.(0)
@@ -183,7 +202,7 @@ let rec instr ppf i =
       fprintf ppf "@[try@,%a@;<0 -2>with@,%a@;<0 -2>endtry@]"
              instr body instr handler
   | Iraise k ->
-      fprintf ppf "%s %a" (Lambda.raise_kind k) reg i.arg.(0)
+      fprintf ppf "%a %a" Printcmm.raise_kind k reg i.arg.(0)
   end;
   if not (Debuginfo.is_none i.dbg) then
     fprintf ppf "%s" (Debuginfo.to_string i.dbg);
diff --git a/asmcomp/printmach.mli b/asmcomp/printmach.mli
index bfb0dbefab..fb7411a6a2 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 cabac4db7c..ee0089fd6c 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,9 +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
+val loc_spacetime_node_hole: 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
diff --git a/asmcomp/reg.ml b/asmcomp/reg.ml
index c0c0e16090..9254e11804 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 68755da5f9..a1b84e9816 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 cecacbd4a4..f636877ba5 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 30f23a8254..4ef9bcf096 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
@@ -79,7 +73,7 @@ method reload_operation op arg res =
   | _ ->
       (self#makeregs arg, self#makeregs res)
 
-method reload_test tst args =
+method reload_test _tst args =
   self#makeregs args
 
 method private reload i =
@@ -89,13 +83,13 @@ method private reload i =
        However, something needs to be done for the function pointer in
        indirect calls. *)
     Iend | Ireturn | Iop(Itailcall_imm _) | Iraise _ -> i
-  | Iop(Itailcall_ind) ->
+  | Iop(Itailcall_ind _) ->
       let newarg = self#makereg1 i.arg in
       insert_moves i.arg newarg
         {i with arg = newarg}
   | Iop(Icall_imm _ | Iextcall _) ->
       {i with next = self#reload i.next}
-  | Iop(Icall_ind) ->
+  | Iop(Icall_ind _) ->
       let newarg = self#makereg1 i.arg in
       insert_moves i.arg newarg
         {i with arg = newarg; next = self#reload i.next}
@@ -133,7 +127,6 @@ method fundecl f =
   let new_body = self#reload f.fun_body in
   ({fun_name = f.fun_name; fun_args = f.fun_args;
     fun_body = new_body; fun_fast = f.fun_fast;
-    fun_dbg  = f.fun_dbg},
+    fun_dbg  = f.fun_dbg; fun_spacetime_shape = f.fun_spacetime_shape},
    redo_regalloc)
-
 end
diff --git a/asmcomp/reloadgen.mli b/asmcomp/reloadgen.mli
index 45c68d1c3d..75e870fb1c 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 0000000000..360a4f1372
--- /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
+
+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 ->
+      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 0000000000..679e77f284
--- /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 0000000000..84d52d644c
--- /dev/null
+++ b/asmcomp/s390x/arch.ml
@@ -0,0 +1,91 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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 *)
+
+let spacetime_node_hole_pointer_is_live_before _specific_op = false
+
+(* 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 _ -> 1
+  | Iindexed2 _ -> 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 0000000000..f99380aee0
--- /dev/null
+++ b/asmcomp/s390x/emit.mlp
@@ -0,0 +1,763 @@
+#2 "asmcomp/s390x/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 Linux on Z 64-bit assembly code *)
+
+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
+
+(* 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"
+
+
+(* 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 ?label live raise_ dbg =
+  let lbl =
+    match label with
+    | None -> new_label()
+    | Some label -> 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_raise = raise_;
+      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 ?label dbg =
+  if !Clflags.debug then begin
+    let lbl_bound_error = new_label() in
+    let lbl_frame = record_frame ?label Reg.Set.empty false dbg in
+    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 _; typ = (Val | Int | Addr)}, {loc = Reg _} ->
+                `	lgr	{emit_reg dst}, {emit_reg src}\n`
+            | {loc = Reg _; typ = Float}, {loc = Reg _; typ = Float} ->
+                `	ldr	{emit_reg dst}, {emit_reg src}\n`
+            | {loc = Reg _; typ = (Val | Int | Addr)}, {loc = Stack _} ->
+                `	stg	{emit_reg src}, {emit_stack dst}\n`
+            | {loc = Reg _; typ = Float}, {loc = Stack _} ->
+                `	std	{emit_reg src}, {emit_stack dst}\n`
+            | {loc = Stack _; typ = (Val | Int | Addr)}, {loc = Reg _} ->
+                `	lg	{emit_reg dst}, {emit_stack src}\n`
+            | {loc = Stack _; typ = Float}, {loc = Reg _} ->
+                `	ldy	{emit_reg dst}, {emit_stack src}\n`
+            | (_, _) ->
+                fatal_error "Emit: Imove"
+        end
+    | Lop(Iconst_int 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 { label_after; }) ->
+        `	basr	%r14, {emit_reg i.arg.(0)}\n`;
+        let lbl = record_frame i.live false i.dbg ~label:label_after in
+         `{emit_label lbl}:\n`
+
+    | Lop(Icall_imm { func; label_after; }) ->
+        if !pic_code then
+        `	brasl	%r14, {emit_symbol func}@PLT\n`
+        else
+        `	brasl	%r14, {emit_symbol func}\n`;
+        let lbl = record_frame i.live false i.dbg ~label:label_after in
+         `{emit_label lbl}:\n`;
+    | Lop(Itailcall_ind { label_after = _; }) ->
+        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 { func; label_after = _; }) ->
+        if func = !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 func}@PLT\n`
+          else
+            `	brcl	15, {emit_symbol func}\n`
+        end
+
+     | Lop(Iextcall { func; alloc; label_after; }) ->
+        if alloc then begin
+          if !pic_code then begin
+          `	lgrl	%r7, {emit_symbol func}@GOTENT\n`;
+          `	brasl	%r14, {emit_symbol "caml_c_call"}@PLT\n`
+          end else begin
+          `	larl	%r7, {emit_symbol func}\n`;
+          `	brasl	%r14, {emit_symbol "caml_c_call"}\n`
+          end;
+          let lbl = record_frame i.live false i.dbg ~label:label_after in
+           `{emit_label lbl}:\n`;
+        end else begin
+          if !pic_code then
+          `	brasl	%r14, {emit_symbol func}@PLT\n`
+          else
+          `	brasl	%r14, {emit_symbol func}\n`
+       end
+
+     | 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 { words = n; label_after_call_gc; }) ->
+        let lbl_redo = new_label() in
+        let lbl_call_gc = new_label() in
+        let lbl_frame =
+          record_frame i.live false i.dbg ?label:label_after_call_gc
+        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 { label_after_error; })) ->
+        let lbl = bound_error_label i.dbg ?label:label_after_error 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 { label_after_error; }, n)) ->
+       let lbl = bound_error_label i.dbg ?label:label_after_error 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 (1 lsl 32 - 1)(*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 k with
+        | Cmm.Raise_withtrace ->
+          `	{emit_call "caml_raise_exn"}\n`;
+          let lbl = record_frame Reg.Set.empty true i.dbg in
+          `{emit_label lbl}:\n`
+        | Cmm.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`;
+  | 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`
+  | 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_code_label = (fun l -> `	.quad	{emit_label l}\n`);
+      efa_data_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 0000000000..a8bd2cbf74
--- /dev/null
+++ b/asmcomp/s390x/proc.ml
@@ -0,0 +1,214 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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)
+
+let loc_spacetime_node_hole = Reg.dummy  (* Spacetime unsupported *)
+
+(* 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)
+
+(* 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 { alloc = true; _ }) ->
+    all_phys_regs
+  | Iop(Iextcall { alloc = 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 0000000000..f5d710a132
--- /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 0000000000..a766d6a34f
--- /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 0000000000..9a00108d09
--- /dev/null
+++ b/asmcomp/s390x/selection.ml
@@ -0,0 +1,120 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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 _ ->
+    ( [| 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 <= 0x7FFF_FFFF && n >= (-1-0x7FFF_FFFF)
+  (* -1-.... : hack so that this can be compiled on 32-bit
+     (cf 'make check_all_arches') *)
+
+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 (-1 lsl 32 (*0x1_0000_0000*)) (-1) args
+  | (Cor, _) -> self#select_logical Ior 0 (1 lsl 32 - 1 (*0xFFFF_FFFF*)) args
+  | (Cxor, _) -> self#select_logical Ixor  0 (1 lsl 32 - 1 (*0xFFFF_FFFF*)) args
+  (* Recognize mult-add and mult-sub instructions *)
+  | (Caddf, [Cop(Cmulf, [arg1; arg2]); arg3]) ->
+      (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 0a30e75067..85b68cd264 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -145,9 +148,9 @@ val mutable trywith_nesting = 0
    that terminate a basic block. *)
 
 method oper_in_basic_block = function
-    Icall_ind -> false
+    Icall_ind _ -> false
   | Icall_imm _ -> false
-  | Itailcall_ind -> false
+  | Itailcall_ind _ -> false
   | Itailcall_imm _ -> false
   | Iextcall _ -> false
   | Istackoffset _ -> false
@@ -182,8 +185,8 @@ method is_load = function
   | _ -> false
 
 method is_checkbound = function
-    Iintop Icheckbound -> true
-  | Iintop_imm(Icheckbound, _) -> true
+    Iintop (Icheckbound _) -> true
+  | Iintop_imm(Icheckbound _, _) -> true
   | _ -> false
 
 method private instr_is_store instr =
@@ -372,7 +375,7 @@ method schedule_fundecl f =
     else begin
       let critical_outputs =
         match i.desc with
-          Lop(Icall_ind | Itailcall_ind) -> [| i.arg.(0) |]
+          Lop(Icall_ind _ | Itailcall_ind _) -> [| i.arg.(0) |]
         | Lop(Icall_imm _ | Itailcall_imm _ | Iextcall _) -> [||]
         | Lreturn -> [||]
         | _ -> i.arg in
@@ -387,7 +390,9 @@ method schedule_fundecl f =
       fun_args = f.fun_args;
       fun_body = new_body;
       fun_fast = f.fun_fast;
-      fun_dbg  = f.fun_dbg }
+      fun_dbg  = f.fun_dbg;
+      fun_spacetime_shape = f.fun_spacetime_shape;
+    }
   end else
     f
 
diff --git a/asmcomp/schedgen.mli b/asmcomp/schedgen.mli
index 911330f8ac..0fa16dacac 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 5949661d18..9383010638 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 7562c077d9..b79f8854fd 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
@@ -24,20 +27,21 @@ type environment = (Ident.t, Reg.t array) Tbl.t
 
 let oper_result_type = function
     Capply(ty, _) -> ty
-  | Cextcall(s, ty, alloc, _) -> ty
+  | 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
   | Cloadmut -> typ_addr
-  | 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
@@ -48,11 +52,11 @@ let oper_result_type = function
 
 let size_expr env exp =
   let rec size localenv = function
-      Cconst_int _ | Cconst_natint _
-    | Cconst_blockheader _ -> Arch.size_int
+      Cconst_int _ | Cconst_natint _ -> Arch.size_int
     | Cconst_symbol _ | Cconst_pointer _ | Cconst_natpointer _ ->
         Arch.size_addr
     | Cconst_float _ -> Arch.size_float
+    | Cblockheader _ -> Arch.size_int
     | Cvar id ->
         begin try
           Tbl.find id localenv
@@ -66,11 +70,11 @@ let size_expr env exp =
         end
     | Ctuple el ->
         List.fold_right (fun e sz -> size localenv e + sz) el 0
-    | Cop(op, args) ->
+    | Cop(op, _) ->
         size_machtype(oper_result_type op)
     | Clet(id, arg, body) ->
         size (Tbl.add id (size localenv arg) localenv) body
-    | Csequence(e1, e2) ->
+    | Csequence(_e1, e2) ->
         size localenv e2
     | _ ->
         fatal_error "Selection.size_expr"
@@ -114,14 +118,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
@@ -133,16 +142,25 @@ let join opt_r1 seq1 opt_r2 seq2 =
 let join_array rs =
   let some_res = ref None in
   for i = 0 to Array.length rs - 1 do
-    let (r, s) = rs.(i) in
-    if r <> None then some_res := r
+    let (r, _) = rs.(i) in
+    match r with
+    | None -> ()
+    | Some r ->
+      match !some_res with
+      | None -> some_res := Some (r, Array.map (fun r -> r.typ) r)
+      | Some (r', types) ->
+        let types =
+          Array.map2 (fun r typ -> Cmm.lub_component r.typ typ) r types
+        in
+        some_res := Some (r', types)
   done;
   match !some_res with
     None -> None
-  | Some template ->
+  | Some (template, types) ->
       let size_res = Array.length template in
       let res = Array.make size_res Reg.dummy in
       for i = 0 to size_res - 1 do
-        res.(i) <- Reg.create template.(i).typ
+        res.(i) <- Reg.create types.(i)
       done;
       for i = 0 to Array.length rs - 1 do
         let (r, s) = rs.(i) in
@@ -155,9 +173,10 @@ let join_array rs =
 (* Extract debug info contained in a C-- operation *)
 let debuginfo_op = function
   | Capply(_, dbg) -> dbg
-  | Cextcall(_, _, _, dbg) -> dbg
+  | Cextcall(_, _, _, dbg, _) -> dbg
   | Craise (_, dbg) -> dbg
   | Ccheckbound dbg -> dbg
+  | Calloc dbg -> dbg
   | _ -> Debuginfo.none
 
 (* Registers for catch constructs *)
@@ -180,19 +199,19 @@ class virtual selector_generic = object (self)
 method is_simple_expr = function
     Cconst_int _ -> true
   | Cconst_natint _ -> true
-  | Cconst_blockheader _ -> true
   | Cconst_float _ -> true
   | Cconst_symbol _ -> true
   | Cconst_pointer _ -> true
   | Cconst_natpointer _ -> true
+  | Cblockheader _ -> true
   | Cvar _ -> true
   | Ctuple el -> List.for_all self#is_simple_expr el
-  | Clet(id, arg, body) -> self#is_simple_expr arg && self#is_simple_expr body
+  | Clet(_id, arg, body) -> self#is_simple_expr arg && self#is_simple_expr body
   | Csequence(e1, e2) -> self#is_simple_expr e1 && self#is_simple_expr e2
   | Cop(op, args) ->
       begin match op with
         (* The following may have side effects *)
-      | Capply _ | Cextcall _ | Cloadmut | Calloc | Cstore _ | Craise _ -> false
+      | Capply _ | Cextcall _ | Cloadmut | Calloc _ | Cstore _ | Craise _ -> false
         (* The remaining operations are simple if their args are *)
       | _ ->
           List.for_all self#is_simple_expr args
@@ -211,7 +230,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 *)
 
@@ -223,19 +242,19 @@ method mark_tailcall = ()
 method mark_c_tailcall = ()
 
 method mark_instr = function
-  | Iop (Icall_ind | Icall_imm _ | Iextcall _) ->
+  | Iop (Icall_ind _ | Icall_imm _ | Iextcall _) ->
       self#mark_call
-  | Iop (Itailcall_ind | Itailcall_imm _) ->
+  | Iop (Itailcall_ind _ | Itailcall_imm _) ->
       self#mark_tailcall
   | Iop (Ialloc _) ->
       self#mark_call (* caml_alloc*, caml_garbage_collection *)
-  | Iop (Iintop Icheckbound | Iintop_imm(Icheckbound, _)) ->
+  | Iop (Iintop (Icheckbound _) | Iintop_imm(Icheckbound _, _)) ->
       self#mark_c_tailcall (* caml_ml_array_bound_error *)
   | Iraise raise_kind ->
     begin match raise_kind with
-      | Lambda.Raise_notrace -> ()
-      | Lambda.Raise_regular | Lambda.Raise_reraise ->
-        if !Clflags.debug then (* PR#6239 *)
+      | Cmm.Raise_notrace -> ()
+      | Cmm.Raise_withtrace ->
+          (* PR#6239 *)
         (* caml_stash_backtrace; we #mark_call rather than
            #mark_c_tailcall to get a good stack backtrace *)
           self#mark_call
@@ -246,25 +265,48 @@ method mark_instr = function
 
 (* Default instruction selection for operators *)
 
+method select_allocation words =
+  Ialloc { words; spacetime_index = 0; label_after_call_gc = None; }
+method select_allocation_args _env = [| |]
+
+method select_checkbound () =
+  Icheckbound { spacetime_index = 0; label_after_error = None; }
+method select_checkbound_extra_args () = []
+
 method select_operation op args =
   match (op, args) with
-    (Capply(ty, dbg), Cconst_symbol s :: rem) -> (Icall_imm s, rem)
-  | (Capply(ty, dbg), _) -> (Icall_ind, args)
-  | (Cextcall(s, ty, alloc, dbg), _) -> (Iextcall(s, alloc, -1), args)
+  | (Capply _, Cconst_symbol func :: rem) ->
+    let label_after = Cmm.new_label () in
+    (Icall_imm { func; label_after; }, rem)
+  | (Capply _, _) ->
+    let label_after = Cmm.new_label () in
+    (Icall_ind { label_after; }, args)
+  | (Cextcall(func, _ty, alloc, _dbg, label_after), _) ->
+    let label_after =
+      match label_after with
+      | None -> Cmm.new_label ()
+      | Some label_after -> label_after
+    in
+    Iextcall { func; alloc; label_after; stack_args = -1}, args
   | (Cload chunk, [arg]) ->
       let (addr, eloc) = self#select_addressing chunk arg in
       (Iload(chunk, addr), [eloc])
   | (Cloadmut, _) -> (Iloadmut, args)
-  | (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)
+  | (Calloc _dbg, _) -> (self#select_allocation 0), args
   | (Caddi, _) -> self#select_arith_comm Iadd args
   | (Csubi, _) -> self#select_arith Isub args
   | (Cmuli, _) -> self#select_arith_comm Imul args
@@ -278,8 +320,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)
@@ -289,7 +331,10 @@ method select_operation op args =
   | (Cdivf, _) -> (Idivf, args)
   | (Cfloatofint, _) -> (Ifloatofint, args)
   | (Cintoffloat, _) -> (Iintoffloat, args)
-  | (Ccheckbound _, _) -> self#select_arith Icheckbound args
+  | (Ccheckbound _, _) ->
+    let extra_args = self#select_checkbound_extra_args () in
+    let op = self#select_checkbound () in
+    self#select_arith op (args @ extra_args)
   | _ -> fatal_error "Selection.select_oper"
 
 method private select_arith_comm op = function
@@ -377,12 +422,15 @@ method insert_debug desc dbg arg res =
 method insert desc arg res =
   instr_seq <- instr_cons desc arg res instr_seq
 
-method extract =
+method extract_core ~end_instr =
   let rec extract res i =
     if i == dummy_instr
     then res
     else extract {i with next = res} i.next in
-  extract (end_instr()) instr_seq
+  extract end_instr instr_seq
+
+method extract =
+  self#extract_core ~end_instr:(end_instr ())
 
 (* Insert a sequence of moves from one pseudoreg set to another. *)
 
@@ -395,6 +443,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 =
@@ -416,6 +482,20 @@ method insert_op_debug op dbg rs rd =
 method insert_op op rs rd =
   self#insert_op_debug op Debuginfo.none rs rd
 
+method emit_blockheader _env n _dbg =
+  let r = self#regs_for typ_int in
+  Some(self#insert_op (Iconst_int n) [||] r)
+
+method about_to_emit_call _env _insn _arg = None
+
+(* Prior to a function call, update the Spacetime node hole pointer hard
+   register. *)
+
+method private maybe_emit_spacetime_move ~spacetime_reg =
+  Misc.Stdlib.Option.iter (fun reg ->
+      self#insert_moves reg [| Proc.loc_spacetime_node_hole |])
+    spacetime_reg
+
 (* Add the instructions for the given expression
    at the end of the self sequence *)
 
@@ -427,21 +507,20 @@ method emit_expr env exp =
   | Cconst_natint n ->
       let r = self#regs_for typ_int in
       Some(self#insert_op (Iconst_int n) [||] r)
-  | Cconst_blockheader n ->
-      let r = self#regs_for typ_int in
-      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)
+  | Cblockheader(n, dbg) ->
+      self#emit_blockheader env n dbg
   | Cvar v ->
       begin try
         Some(Tbl.find v env)
@@ -461,7 +540,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 [||]
@@ -480,7 +559,7 @@ method emit_expr env exp =
           self#insert_debug (Iraise k) dbg rd [||];
           None
       end
-  | Cop(Ccmpf comp, args) ->
+  | Cop(Ccmpf _, _) ->
       self#emit_expr env (Cifthenelse(exp, Cconst_int 1, Cconst_int 0))
   | Cop(op, args) ->
       begin match self#emit_parts_list env args with
@@ -490,39 +569,54 @@ method emit_expr env exp =
           let (new_op, new_args) = self#select_operation op simple_args in
           let dbg = debuginfo_op op in
           match new_op with
-            Icall_ind ->
+            Icall_ind _ ->
               let r1 = self#emit_tuple env new_args in
               let rarg = Array.sub r1 1 (Array.length r1 - 1) in
               let rd = self#regs_for ty in
               let (loc_arg, stack_ofs) = Proc.loc_arguments rarg in
               let loc_res = Proc.loc_results rd in
+              let spacetime_reg =
+                self#about_to_emit_call env (Iop new_op) [| r1.(0) |]
+              in
               self#insert_move_args rarg loc_arg stack_ofs;
-              self#insert_debug (Iop Icall_ind) dbg
+              self#maybe_emit_spacetime_move ~spacetime_reg;
+              self#insert_debug (Iop new_op) dbg
                           (Array.append [|r1.(0)|] loc_arg) loc_res;
               self#insert_move_results loc_res rd stack_ofs;
               Some rd
-          | Icall_imm lbl ->
+          | Icall_imm _ ->
               let r1 = self#emit_tuple env new_args in
               let rd = self#regs_for ty in
               let (loc_arg, stack_ofs) = Proc.loc_arguments r1 in
               let loc_res = Proc.loc_results rd in
+              let spacetime_reg =
+                self#about_to_emit_call env (Iop new_op) [| |]
+              in
               self#insert_move_args r1 loc_arg stack_ofs;
-              self#insert_debug (Iop(Icall_imm lbl)) dbg loc_arg loc_res;
+              self#maybe_emit_spacetime_move ~spacetime_reg;
+              self#insert_debug (Iop new_op) dbg loc_arg loc_res;
               self#insert_move_results loc_res rd stack_ofs;
               Some rd
-          | Iextcall(lbl, alloc, dummy_ofs) ->
-              assert (dummy_ofs = -1);
-              let (loc_arg, stack_ofs) =
-                self#emit_extcall_args env new_args in
+          | Iextcall r ->
+              let spacetime_reg =
+                self#about_to_emit_call env (Iop new_op) [| |]
+              in
+              let (loc_arg, stack_ofs) = self#emit_extcall_args env new_args in
+              self#maybe_emit_spacetime_move ~spacetime_reg;
               let rd = self#regs_for ty in
-              let loc_res = self#insert_op_debug (Iextcall(lbl, alloc, stack_ofs))
-                              dbg loc_arg (Proc.loc_external_results rd) in
+              let loc_res =
+                self#insert_op_debug (Iextcall {r with stack_ofs = stack_ofs}) 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
+          | Ialloc { words = _; spacetime_index; label_after_call_gc; } ->
+              let rd = self#regs_for typ_val in
               let size = size_expr env (Ctuple new_args) in
-              self#insert (Iop(Ialloc size)) [||] rd;
+              let op =
+                Ialloc { words = size; spacetime_index; label_after_call_gc; }
+              in
+              let args = self#select_allocation_args env in
+              self#insert_debug (Iop op) dbg args rd;
               self#emit_stores env new_args rd;
               Some rd
           | op ->
@@ -533,7 +627,7 @@ method emit_expr env exp =
   | Csequence(e1, e2) ->
       begin match self#emit_expr env e1 with
         None -> None
-      | Some r1 -> self#emit_expr env e2
+      | Some _ -> self#emit_expr env e2
       end
   | Cifthenelse(econd, eif, eelse) ->
       let (cond, earg) = self#select_condition econd in
@@ -554,19 +648,19 @@ method emit_expr env exp =
           let rscases = Array.map (self#emit_sequence env) ecases in
           let r = join_array rscases in
           self#insert (Iswitch(index,
-                               Array.map (fun (r, s) -> s#extract) rscases))
+                               Array.map (fun (_, s) -> s#extract) rscases))
                       rsel [||];
           r
       end
   | Cloop(ebody) ->
-      let (rarg, sbody) = self#emit_sequence env ebody in
+      let (_rarg, sbody) = self#emit_sequence env ebody in
       self#insert (Iloop(sbody#extract)) [||] [||];
       Some [||]
   | Ccatch(nfail, ids, e1, e2) ->
       let rs =
         List.map
           (fun id ->
-            let r = self#regs_for typ_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
@@ -595,7 +689,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
@@ -658,7 +752,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 ->
@@ -666,14 +760,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 =
@@ -688,7 +794,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)
@@ -721,38 +827,61 @@ method emit_tail env exp =
       | Some(simple_args, env) ->
           let (new_op, new_args) = self#select_operation op simple_args in
           match new_op with
-            Icall_ind ->
+            Icall_ind { label_after; } ->
               let r1 = self#emit_tuple env new_args in
               let rarg = Array.sub r1 1 (Array.length r1 - 1) in
               let (loc_arg, stack_ofs) = Proc.loc_arguments rarg in
               if stack_ofs = 0 then begin
+                let call = Iop (Itailcall_ind { label_after; }) in
+                let spacetime_reg =
+                  self#about_to_emit_call env call [| r1.(0) |]
+                in
                 self#insert_moves rarg loc_arg;
-                self#insert (Iop Itailcall_ind)
-                            (Array.append [|r1.(0)|] loc_arg) [||]
+                self#maybe_emit_spacetime_move ~spacetime_reg;
+                self#insert_debug call dbg
+                            (Array.append [|r1.(0)|] loc_arg) [||];
               end else begin
                 let rd = self#regs_for ty in
                 let loc_res = Proc.loc_results rd in
+                let spacetime_reg =
+                  self#about_to_emit_call env (Iop new_op) [| r1.(0) |]
+                in
                 self#insert_move_args rarg loc_arg stack_ofs;
-                self#insert_debug (Iop Icall_ind) dbg
+                self#maybe_emit_spacetime_move ~spacetime_reg;
+                self#insert_debug (Iop new_op) dbg
                             (Array.append [|r1.(0)|] loc_arg) loc_res;
                 self#insert(Iop(Istackoffset(-stack_ofs))) [||] [||];
                 self#insert Ireturn loc_res [||]
               end
-          | Icall_imm lbl ->
+          | Icall_imm { func; label_after; } ->
               let r1 = self#emit_tuple env new_args in
               let (loc_arg, stack_ofs) = Proc.loc_arguments r1 in
               if stack_ofs = 0 then begin
+                let call = Iop (Itailcall_imm { func; label_after; }) in
+                let spacetime_reg =
+                  self#about_to_emit_call env call [| |]
+                in
                 self#insert_moves r1 loc_arg;
-                self#insert (Iop(Itailcall_imm lbl)) loc_arg [||]
-              end else if lbl = !current_function_name then begin
+                self#maybe_emit_spacetime_move ~spacetime_reg;
+                self#insert_debug call dbg loc_arg [||];
+              end else if func = !current_function_name then begin
+                let call = Iop (Itailcall_imm { func; label_after; }) in
                 let loc_arg' = Proc.loc_parameters r1 in
+                let spacetime_reg =
+                  self#about_to_emit_call env call [| |]
+                in
                 self#insert_moves r1 loc_arg';
-                self#insert (Iop(Itailcall_imm lbl)) loc_arg' [||]
+                self#maybe_emit_spacetime_move ~spacetime_reg;
+                self#insert_debug call dbg loc_arg' [||];
               end else begin
                 let rd = self#regs_for ty in
                 let loc_res = Proc.loc_results rd in
+                let spacetime_reg =
+                  self#about_to_emit_call env (Iop new_op) [| |]
+                in
                 self#insert_move_args r1 loc_arg stack_ofs;
-                self#insert_debug (Iop(Icall_imm lbl)) dbg loc_arg loc_res;
+                self#maybe_emit_spacetime_move ~spacetime_reg;
+                self#insert_debug (Iop new_op) dbg loc_arg loc_res;
                 self#insert(Iop(Istackoffset(-stack_ofs))) [||] [||];
                 self#insert Ireturn loc_res [||]
               end
@@ -761,7 +890,7 @@ method emit_tail env exp =
   | Csequence(e1, e2) ->
       begin match self#emit_expr env e1 with
         None -> ()
-      | Some r1 -> self#emit_tail env e2
+      | Some _ -> self#emit_tail env e2
       end
   | Cifthenelse(econd, eif, eelse) ->
       let (cond, earg) = self#select_condition econd in
@@ -784,7 +913,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
@@ -799,7 +928,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,
@@ -820,8 +949,16 @@ method private emit_tail_sequence env exp =
   s#emit_tail env exp;
   s#extract
 
+(* Insertion of the function prologue *)
+
+method insert_prologue _f ~loc_arg ~rarg ~spacetime_node_hole:_ ~env:_ =
+  self#insert_moves loc_arg rarg;
+  None
+
 (* Sequentialization of a function definition *)
 
+method initial_env () = Tbl.empty
+
 method emit_fundecl f =
   Proc.contains_calls := false;
   current_function_name := f.Cmm.fun_name;
@@ -831,19 +968,38 @@ method emit_fundecl f =
       f.Cmm.fun_args in
   let rarg = Array.concat rargs in
   let loc_arg = Proc.loc_parameters rarg in
+  (* To make it easier to add the Spacetime instrumentation code, we
+     first emit the body and extract the resulting instruction sequence;
+     then we emit the prologue followed by any Spacetime instrumentation.  The
+     sequence resulting from extracting the latter (prologue + instrumentation)
+     together is then simply prepended to the body. *)
   let env =
     List.fold_right2
-      (fun (id, ty) r env -> Tbl.add id r env)
-      f.Cmm.fun_args rargs Tbl.empty in
-  self#insert_moves loc_arg rarg;
+      (fun (id, _ty) r env -> Tbl.add id r env)
+      f.Cmm.fun_args rargs (self#initial_env ()) in
+  let spacetime_node_hole, env =
+    if not Config.spacetime then None, env
+    else begin
+      let reg = self#regs_for typ_int in
+      let node_hole = Ident.create "spacetime_node_hole" in
+      Some (node_hole, reg), Tbl.add node_hole reg env
+    end
+  in
   self#emit_tail env f.Cmm.fun_body;
   let body = self#extract in
+  instr_seq <- dummy_instr;
+  let fun_spacetime_shape =
+    self#insert_prologue f ~loc_arg ~rarg ~spacetime_node_hole ~env
+  in
+  let body = self#extract_core ~end_instr:body in
   instr_iter (fun instr -> self#mark_instr instr.Mach.desc) body;
   { fun_name = f.Cmm.fun_name;
     fun_args = loc_arg;
     fun_body = body;
     fun_fast = f.Cmm.fun_fast;
-    fun_dbg  = f.Cmm.fun_dbg }
+    fun_dbg  = f.Cmm.fun_dbg;
+    fun_spacetime_shape;
+  }
 
 end
 
@@ -855,7 +1011,7 @@ end
 let is_tail_call nargs =
   assert (Reg.dummy.typ = Int);
   let args = Array.make (nargs + 1) Reg.dummy in
-  let (loc_arg, stack_ofs) = Proc.loc_arguments args in
+  let (_loc_arg, stack_ofs) = Proc.loc_arguments args in
   stack_ofs = 0
 
 let _ =
diff --git a/asmcomp/selectgen.mli b/asmcomp/selectgen.mli
index 0de9038215..5df80ad36b 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. *)
@@ -83,13 +86,15 @@ class virtual selector_generic : object
      above; overloading this is useful if Ispecific instructions need
      marking *)
 
-  (* The following method is the entry point and should not be overridden *)
+  (* The following method is the entry point and should not be overridden
+     (except by [Spacetime_profiling]). *)
   method emit_fundecl : Cmm.fundecl -> Mach.fundecl
 
   (* The following methods should not be overridden.  They cannot be
      declared "private" in the current implementation because they
      are not always applied to "self", but ideally they should be private. *)
   method extract : Mach.instruction
+  method extract_core : end_instr:Mach.instruction -> Mach.instruction
   method insert : Mach.instruction_desc -> Reg.t array -> Reg.t array -> unit
   method insert_debug : Mach.instruction_desc -> Debuginfo.t ->
                                         Reg.t array -> Reg.t array -> unit
@@ -97,9 +102,37 @@ 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
+
+  (* Only for the use of [Spacetime_profiling]. *)
+  method select_allocation : int -> Mach.operation
+  method select_allocation_args : (Ident.t, Reg.t array) Tbl.t -> Reg.t array
+  method select_checkbound : unit -> Mach.integer_operation
+  method select_checkbound_extra_args : unit -> Cmm.expression list
+  method emit_blockheader
+     : (Ident.t, Reg.t array) Tbl.t
+    -> nativeint
+    -> Debuginfo.t
+    -> Reg.t array option
+  method about_to_emit_call
+     : (Ident.t, Reg.t array) Tbl.t
+    -> Mach.instruction_desc
+    -> Reg.t array
+    -> Reg.t array option
+  method initial_env : unit -> (Ident.t, Reg.t array) Tbl.t
+  method insert_prologue
+     : Cmm.fundecl
+    -> loc_arg:Reg.t array
+    -> rarg:Reg.t array
+    -> spacetime_node_hole:(Ident.t * Reg.t array) option
+    -> env:(Ident.t, Reg.t array) Tbl.t
+    -> Mach.spacetime_shape option
+
+  val mutable instr_seq : Mach.instruction
 end
 
 val reset : unit -> unit
diff --git a/asmcomp/selection.mli b/asmcomp/selection.mli
index f1c9e34ce8..3c055fe033 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/spacetime_profiling.ml b/asmcomp/spacetime_profiling.ml
new file mode 100644
index 0000000000..32037c5506
--- /dev/null
+++ b/asmcomp/spacetime_profiling.ml
@@ -0,0 +1,421 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2015--2016 Jane Street Group LLC                           *)
+(*                                                                        *)
+(*   All rights reserved.  This file is distributed under the terms of    *)
+(*   the GNU Lesser General Public License version 2.1, with the          *)
+(*   special exception on linking described in the file LICENSE.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+let node_num_header_words = 2 (* [Node_num_header_words] in the runtime. *)
+let index_within_node = ref node_num_header_words
+(* The [lazy]s are to ensure that we don't create [Ident.t]s at toplevel
+   when not using Spacetime profiling.  (This could cause stamps to differ
+   between bytecode and native .cmis when no .mli is present, e.g.
+   arch.ml.) *)
+let spacetime_node = ref (lazy (Cmm.Cvar (Ident.create "dummy")))
+let spacetime_node_ident = ref (lazy (Ident.create "dummy"))
+let current_function_label = ref ""
+let direct_tail_call_point_indexes = ref []
+
+let reverse_shape = ref ([] : Mach.spacetime_shape)
+
+let something_was_instrumented () =
+  !index_within_node > node_num_header_words
+
+let next_index_within_node ~part_of_shape ~label =
+  let index = !index_within_node in
+  begin match part_of_shape with
+  | Mach.Direct_call_point _ | Mach.Indirect_call_point ->
+    incr index_within_node
+  | Mach.Allocation_point ->
+    incr index_within_node;
+    incr index_within_node;
+    incr index_within_node
+  end;
+  reverse_shape := (part_of_shape, label) :: !reverse_shape;
+  index
+
+let reset ~spacetime_node_ident:ident ~function_label =
+  index_within_node := node_num_header_words;
+  spacetime_node := lazy (Cmm.Cvar ident);
+  spacetime_node_ident := lazy ident;
+  direct_tail_call_point_indexes := [];
+  current_function_label := function_label;
+  reverse_shape := []
+
+let code_for_function_prologue ~function_name ~node_hole =
+  let node = Ident.create "node" in
+  let new_node = Ident.create "new_node" in
+  let must_allocate_node = Ident.create "must_allocate_node" in
+  let is_new_node = Ident.create "is_new_node" in
+  let no_tail_calls = List.length !direct_tail_call_point_indexes < 1 in
+  let open Cmm in
+  let initialize_direct_tail_call_points_and_return_node =
+    let new_node_encoded = Ident.create "new_node_encoded" in
+    (* The callee node pointers within direct tail call points must initially
+       point back at the start of the current node and be marked as per
+       [Encode_tail_caller_node] in the runtime. *)
+    let indexes = !direct_tail_call_point_indexes in
+    let body =
+      List.fold_left (fun init_code index ->
+          (* Cf. [Direct_callee_node] in the runtime. *)
+          let offset_in_bytes = index * Arch.size_addr in
+          Csequence (
+            Cop (Cstore (Word_int, Lambda.Assignment),
+              [Cop (Caddi, [Cvar new_node; Cconst_int offset_in_bytes]);
+               Cvar new_node_encoded]),
+            init_code))
+        (Cvar new_node)
+        indexes
+    in
+    match indexes with
+    | [] -> body
+    | _ ->
+      Clet (new_node_encoded,
+        (* Cf. [Encode_tail_caller_node] in the runtime. *)
+        Cop (Cor, [Cvar new_node; Cconst_int 1]),
+        body)
+  in
+  let pc = Ident.create "pc" in
+  Clet (node, Cop (Cload Word_int, [Cvar node_hole]),
+    Clet (must_allocate_node, Cop (Cand, [Cvar node; Cconst_int 1]),
+      Cifthenelse (Cop (Ccmpi Cne, [Cvar must_allocate_node; Cconst_int 1]),
+        Cvar node,
+        Clet (is_new_node,
+          Clet (pc, Cconst_symbol function_name,
+            Cop (Cextcall ("caml_spacetime_allocate_node",
+              [| Int |], false, Debuginfo.none, None),
+              [Cconst_int (1 (* header *) + !index_within_node);
+               Cvar pc;
+               Cvar node_hole;
+              ])),
+            Clet (new_node, Cop (Cload Word_int, [Cvar node_hole]),
+              if no_tail_calls then Cvar new_node
+              else
+                Cifthenelse (
+                  Cop (Ccmpi Ceq, [Cvar is_new_node; Cconst_int 0]),
+                  Cvar new_node,
+                  initialize_direct_tail_call_points_and_return_node))))))
+
+let code_for_blockheader ~value's_header ~node ~dbg =
+  let num_words = Nativeint.shift_right_logical value's_header 10 in
+  let existing_profinfo = Ident.create "existing_profinfo" in
+  let existing_count = Ident.create "existing_count" in
+  let profinfo = Ident.create "profinfo" in
+  let address_of_profinfo = Ident.create "address_of_profinfo" in
+  let label = Cmm.new_label () in
+  let index_within_node =
+    next_index_within_node ~part_of_shape:Mach.Allocation_point ~label
+  in
+  let offset_into_node = Arch.size_addr * index_within_node in
+  let open Cmm in
+  let generate_new_profinfo =
+    (* This will generate a static branch to a function that should usually
+       be in the cache, which hopefully gives a good code size/performance
+       balance.
+       The "Some label" is important: it provides the link between the shape
+       table, the allocation point, and the frame descriptor table---enabling
+       the latter table to be used for resolving a program counter at such
+       a point to a location.
+    *)
+    Cop (Cextcall ("caml_spacetime_generate_profinfo", [| Int |],
+        false, dbg, Some label),
+      [Cvar address_of_profinfo;
+       Cconst_int (index_within_node + 1)])
+  in
+  (* Check if we have already allocated a profinfo value for this allocation
+     point with the current backtrace.  If so, use that value; if not,
+     allocate a new one. *)
+  Clet (address_of_profinfo,
+    Cop (Caddi, [
+      Cvar node;
+      Cconst_int offset_into_node;
+    ]),
+    Clet (existing_profinfo, Cop (Cload Word_int, [Cvar address_of_profinfo]),
+      Clet (profinfo,
+        Cifthenelse (
+          Cop (Ccmpi Cne, [Cvar existing_profinfo; Cconst_int 1 (* () *)]),
+          Cvar existing_profinfo,
+          generate_new_profinfo),
+        Clet (existing_count,
+          Cop (Cload Word_int, [
+            Cop (Caddi,
+              [Cvar address_of_profinfo; Cconst_int Arch.size_addr])
+          ]),
+          Csequence (
+            Cop (Cstore (Word_int, Lambda.Assignment),
+              [Cop (Caddi,
+                [Cvar address_of_profinfo; Cconst_int Arch.size_addr]);
+                Cop (Caddi, [
+                  Cvar existing_count;
+                  (* N.B. "*2" since the count is an OCaml integer.
+                     The "1 +" is to count the value's header. *)
+                  Cconst_int (2 * (1 + Nativeint.to_int num_words));
+                ]);
+              ]),
+            (* [profinfo] looks like a black [Infix_tag] header.  Instead of
+               having to mask [profinfo] before ORing it with the desired
+               header, we can use an XOR trick, to keep code size down. *)
+            let value's_header =
+              Nativeint.logxor value's_header
+                (Nativeint.logor
+                  ((Nativeint.logor (Nativeint.of_int Obj.infix_tag)
+                    (Nativeint.shift_left 3n (* <- Caml_black *) 8)))
+                  (Nativeint.shift_left
+                    (* The following is the [Infix_offset_val], in words. *)
+                    (Nativeint.of_int (index_within_node + 1)) 10))
+            in
+            Cop (Cxor, [Cvar profinfo; Cconst_natint value's_header]))))))
+
+type callee =
+  | Direct of string
+  | Indirect of Cmm.expression
+
+let code_for_call ~node ~callee ~is_tail ~label =
+  (* We treat self recursive calls as tail calls to avoid blow-ups in the
+     graph. *)
+  let is_self_recursive_call =
+    match callee with
+    | Direct callee -> callee = !current_function_label
+    | Indirect _ -> false
+  in
+  let is_tail = is_tail || is_self_recursive_call in
+  let index_within_node =
+    match callee with
+    | Direct callee ->
+      next_index_within_node
+        ~part_of_shape:(Mach.Direct_call_point { callee; })
+        ~label
+    | Indirect _ ->
+      next_index_within_node ~part_of_shape:Mach.Indirect_call_point ~label
+  in
+  begin match callee with
+    (* If this is a direct tail call point, we need to note down its index,
+       so the correct initialization code can be emitted in the prologue. *)
+    | Direct _ when is_tail ->
+      direct_tail_call_point_indexes :=
+        index_within_node::!direct_tail_call_point_indexes
+    | Direct _ | Indirect _ -> ()
+  end;
+  let place_within_node = Ident.create "place_within_node" in
+  let open Cmm in
+  Clet (place_within_node,
+    Cop (Caddi, [node; Cconst_int (index_within_node * Arch.size_addr)]),
+    (* The following code returns the address that is to be moved into the
+       (hard) node hole pointer register immediately before the call.
+       (That move is inserted in [Selectgen].) *)
+    match callee with
+    | Direct _callee -> Cvar place_within_node
+    | Indirect callee ->
+      let caller_node =
+        if is_tail then node
+        else Cconst_int 1  (* [Val_unit] *)
+      in
+      Cop (Cextcall ("caml_spacetime_indirect_node_hole_ptr",
+          [| Int |], false, Debuginfo.none, None),
+        [callee; Cvar place_within_node; caller_node]))
+
+class virtual instruction_selection = object (self)
+  inherit Selectgen.selector_generic as super
+
+  (* [disable_instrumentation] ensures that we don't try to instrument the
+     instrumentation... *)
+  val mutable disable_instrumentation = false
+
+  method private instrument_direct_call ~env ~func ~is_tail ~label_after =
+    let instrumentation =
+      code_for_call
+        ~node:(Lazy.force !spacetime_node)
+        ~callee:(Direct func)
+        ~is_tail
+        ~label:label_after
+    in
+    match self#emit_expr env instrumentation with
+    | None -> assert false
+    | Some reg -> Some reg
+
+  method private instrument_indirect_call ~env ~callee ~is_tail
+        ~label_after =
+    (* [callee] is a pseudoregister, so we have to bind it in the environment
+       and reference the variable to which it is bound. *)
+    let callee_ident = Ident.create "callee" in
+    let env = Tbl.add callee_ident [| callee |] env in
+    let instrumentation =
+      code_for_call
+        ~node:(Lazy.force !spacetime_node)
+        ~callee:(Indirect (Cmm.Cvar callee_ident))
+        ~is_tail
+        ~label:label_after
+    in
+    match self#emit_expr env instrumentation with
+    | None -> assert false
+    | Some reg -> Some reg
+
+  method private can_instrument () =
+    Config.spacetime && not disable_instrumentation
+
+  method! about_to_emit_call env desc arg =
+    if not (self#can_instrument ()) then None
+    else
+      let module M = Mach in
+      match desc with
+      | M.Iop (M.Icall_imm { func; label_after; }) ->
+        assert (Array.length arg = 0);
+        self#instrument_direct_call ~env ~func ~is_tail:false ~label_after
+      | M.Iop (M.Icall_ind { label_after; }) ->
+        assert (Array.length arg = 1);
+        self#instrument_indirect_call ~env ~callee:arg.(0)
+          ~is_tail:false ~label_after
+      | M.Iop (M.Itailcall_imm { func; label_after; }) ->
+        assert (Array.length arg = 0);
+        self#instrument_direct_call ~env ~func ~is_tail:true ~label_after
+      | M.Iop (M.Itailcall_ind { label_after; }) ->
+        assert (Array.length arg = 1);
+        self#instrument_indirect_call ~env ~callee:arg.(0)
+          ~is_tail:true ~label_after
+      | M.Iop (M.Iextcall { func; alloc = true; label_after; }) ->
+        (* N.B. No need to instrument "noalloc" external calls. *)
+        assert (Array.length arg = 0);
+        self#instrument_direct_call ~env ~func ~is_tail:false ~label_after
+      | _ -> None
+
+  method private instrument_blockheader ~env ~value's_header ~dbg =
+    let instrumentation =
+      code_for_blockheader
+        ~node:(Lazy.force !spacetime_node_ident)
+        ~value's_header ~dbg
+    in
+    self#emit_expr env instrumentation
+
+  method private emit_prologue f ~node_hole ~env =
+    (* We don't need the prologue unless we inserted some instrumentation.
+       This corresponds to adding the prologue if the function contains one
+       or more call or allocation points. *)
+    if something_was_instrumented () then begin
+      let prologue_cmm =
+        code_for_function_prologue ~function_name:f.Cmm.fun_name ~node_hole
+      in
+      disable_instrumentation <- true;
+      let node_temp_reg =
+        match self#emit_expr env prologue_cmm with
+        | None ->
+          Misc.fatal_error "Spacetime prologue instruction \
+              selection did not yield a destination register"
+        | Some node_temp_reg -> node_temp_reg
+      in
+      disable_instrumentation <- false;
+      let node = Lazy.force !spacetime_node_ident in
+      let node_reg = Tbl.find node env in
+      self#insert_moves node_temp_reg node_reg
+    end
+
+  method! emit_blockheader env n dbg =
+    if self#can_instrument () then begin
+      disable_instrumentation <- true;
+      let result = self#instrument_blockheader ~env ~value's_header:n ~dbg in
+      disable_instrumentation <- false;
+      result
+    end else begin
+      super#emit_blockheader env n dbg
+    end
+
+  method! select_allocation words =
+    if self#can_instrument () then begin
+      (* Leave space for a direct call point.  We cannot easily insert any
+         instrumentation code, so the fields are filled in instead by
+         [caml_spacetime_caml_garbage_collection]. *)
+      let label = Cmm.new_label () in
+      let index =
+        next_index_within_node
+          ~part_of_shape:(Mach.Direct_call_point { callee = "caml_call_gc"; })
+          ~label
+      in
+      Mach.Ialloc {
+        words;
+        label_after_call_gc = Some label;
+        spacetime_index = index;
+      }
+    end else begin
+      super#select_allocation words
+    end
+
+  method! select_allocation_args env =
+    if self#can_instrument () then begin
+      let regs = Tbl.find (Lazy.force !spacetime_node_ident) env in
+      match regs with
+      | [| reg |] -> [| reg |]
+      | _ -> failwith "Expected one register only for spacetime_node_ident"
+    end else begin
+      super#select_allocation_args env
+    end
+
+  method! select_checkbound () =
+    (* This follows [select_allocation], above. *)
+    if self#can_instrument () then begin
+      let label = Cmm.new_label () in
+      let index =
+        next_index_within_node
+          ~part_of_shape:(
+            Mach.Direct_call_point { callee = "caml_ml_array_bound_error"; })
+          ~label
+      in
+      Mach.Icheckbound {
+        label_after_error = Some label;
+        spacetime_index = index;
+      }
+    end else begin
+      super#select_checkbound ()
+    end
+
+  method! select_checkbound_extra_args () =
+    if self#can_instrument () then begin
+      (* This follows [select_allocation_args], above. *)
+      [Cmm.Cvar (Lazy.force !spacetime_node_ident)]
+    end else begin
+      super#select_checkbound_extra_args ()
+    end
+
+  method! initial_env () =
+    let env = super#initial_env () in
+    if Config.spacetime then
+      Tbl.add (Lazy.force !spacetime_node_ident)
+        (self#regs_for Cmm.typ_int) env
+    else
+      env
+
+  method! emit_fundecl f =
+    if Config.spacetime then begin
+      disable_instrumentation <- false;
+      let node = Ident.create "spacetime_node" in
+      reset ~spacetime_node_ident:node ~function_label:f.Cmm.fun_name
+    end;
+    super#emit_fundecl f
+
+  method! insert_prologue f ~loc_arg ~rarg ~spacetime_node_hole ~env =
+    let fun_spacetime_shape =
+      super#insert_prologue f ~loc_arg ~rarg ~spacetime_node_hole ~env
+    in
+    (* CR-soon mshinwell: add check to make sure the node size doesn't exceed
+       the chunk size of the allocator *)
+    if not Config.spacetime then fun_spacetime_shape
+    else begin
+      let node_hole, node_hole_reg =
+        match spacetime_node_hole with
+        | None -> assert false
+        | Some (node_hole, reg) -> node_hole, reg
+      in
+      self#insert_moves [| Proc.loc_spacetime_node_hole |] node_hole_reg;
+      self#emit_prologue f ~node_hole ~env;
+      match !reverse_shape with
+      | [] -> None
+      (* N.B. We do not reverse the shape list, since the function that
+         reconstructs it (caml_spacetime_shape_table) reverses it again. *)
+      | reverse_shape -> Some reverse_shape
+    end
+end
diff --git a/asmcomp/spacetime_profiling.mli b/asmcomp/spacetime_profiling.mli
new file mode 100644
index 0000000000..16c6914808
--- /dev/null
+++ b/asmcomp/spacetime_profiling.mli
@@ -0,0 +1,17 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2015--2016 Jane Street Group LLC                           *)
+(*                                                                        *)
+(*   All rights reserved.  This file is distributed under the terms of    *)
+(*   the GNU Lesser General Public License version 2.1, with the          *)
+(*   special exception on linking described in the file LICENSE.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Insertion of instrumentation code for Spacetime profiling. *)
+
+class virtual instruction_selection : Selectgen.selector_generic
diff --git a/asmcomp/sparc/CSE.ml b/asmcomp/sparc/CSE.ml
index e48d604365..20bbb172d9 100644
--- a/asmcomp/sparc/CSE.ml
+++ b/asmcomp/sparc/CSE.ml
@@ -1,27 +1,30 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
 open Mach
 open CSEgen
 
-class cse = object (self)
+class cse = object
 
 inherit cse_generic (* as super *)
 
 method! is_cheap_operation op =
   match op with
-  | Iconst_int n | Iconst_blockheader n -> n <= 4095n && n >= -4096n
+  | Iconst_int n -> n <= 4095n && n >= -4096n
   | _ -> false
 
 end
diff --git a/asmcomp/sparc/NOTES.md b/asmcomp/sparc/NOTES.md
new file mode 100644
index 0000000000..18c3db4a99
--- /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 f5c069366b..1f7e2abdef 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 *)
 
@@ -30,6 +33,8 @@ let command_line_options =
 
 type specific_operation = unit          (* None worth mentioning *)
 
+let spacetime_node_hole_pointer_is_live_before _specific_op = false
+
 (* Addressing modes *)
 
 type addressing_mode =
@@ -60,8 +65,8 @@ let offset_addressing addr delta =
   | Iindexed n -> Iindexed(n + delta)
 
 let num_args_addressing = function
-    Ibased(s, n) -> 0
-  | Iindexed n -> 1
+    Ibased _ -> 0
+  | Iindexed _ -> 1
 
 (* Printing operations and addressing modes *)
 
@@ -74,5 +79,5 @@ let print_addressing printreg addr ppf arg =
       let idx = if n <> 0 then Printf.sprintf " + %i" n else "" in
       fprintf ppf "%a%s" printreg arg.(0) idx
 
-let print_specific_operation printreg op ppf arg =
+let print_specific_operation _printreg _op _ppf _arg =
   Misc.fatal_error "Arch_sparc.print_specific_operation"
diff --git a/asmcomp/sparc/emit.mlp b/asmcomp/sparc/emit.mlp
index 877a3d52a0..78d0098d8f 100644
--- a/asmcomp/sparc/emit.mlp
+++ b/asmcomp/sparc/emit.mlp
@@ -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/sparc/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 Sparc assembly code *)
 
@@ -54,7 +58,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"
 
@@ -95,9 +99,6 @@ let label_prefix =
 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
-
 (* Output a pseudo-register *)
 
 let emit_reg r =
@@ -160,16 +161,21 @@ type frame_descr =
 
 let frame_descriptors = ref([] : frame_descr list)
 
-let record_frame live =
-  let lbl = new_label() in
+let record_frame ?label live =
+  let lbl =
+    match label with
+    | None -> new_label()
+    | Some label -> label
+  in
   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,35 +280,44 @@ 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 _; typ = (Int | Addr | Val)}, {loc = Reg _} ->
               `	mov	{emit_reg src}, {emit_reg dst}\n`
-          | {loc = Reg rs; typ = Float}, {loc = Reg rd; typ = Float} ->
+          | {loc = Reg _; typ = Float}, {loc = Reg _; typ = Float} ->
               if !arch_version = SPARC_V9 then
                 `	fmovd	{emit_reg src}, {emit_reg dst}\n`
               else begin
                 `	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 _; typ = Float}, {loc = Reg _; 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 _; typ = (Int | Addr | Val)}, {loc = Stack _} ->
               `	st	{emit_reg src}, {emit_stack dst}\n`
-          | {loc = Reg rs; typ = Float}, {loc = Stack sd} ->
+          | {loc = Reg _; typ = Float}, {loc = Stack _} ->
               `	std	{emit_reg src}, {emit_stack dst}\n`
-          | {loc = Stack ss; typ = (Int | Addr)}, {loc = Reg rd} ->
+          | {loc = Stack _; typ = (Int | Addr | Val)}, {loc = Reg _} ->
               `	ld	{emit_stack src}, {emit_reg dst}\n`
-          | {loc = Stack ss; typ = Float}, {loc = Reg rd} ->
+          | {loc = Stack _; typ = Float}, {loc = Reg _} ->
               `	ldd	{emit_stack src}, {emit_reg dst}\n`
           | (_, _) ->
               fatal_error "Emit: Imove"
         end
-    | Lop(Iconst_int n | Iconst_blockheader n) ->
+    | Lop(Iconst_int n) ->
         if is_native_immediate n then
           `	mov	{emit_nativeint n}, {emit_reg i.res.(0)}\n`
         else begin
@@ -313,43 +328,43 @@ 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) ->
         `	sethi	%hi({emit_symbol s}), %g1\n`;
         `	or	%g1, %lo({emit_symbol s}), {emit_reg i.res.(0)}\n`
-    | Lop(Icall_ind) ->
-        `{record_frame i.live}	call	{emit_reg i.arg.(0)}\n`;
+    | Lop(Icall_ind { label_after; }) ->
+        `{record_frame i.live ~label:label_after}	call	{emit_reg i.arg.(0)}\n`;
         fill_delay_slot dslot
-    | Lop(Icall_imm s) ->
-        `{record_frame i.live}	call	{emit_symbol s}\n`;
+    | Lop(Icall_imm { func; label_after; }) ->
+        `{record_frame i.live ~label:label_after}	call	{emit_symbol func}\n`;
         fill_delay_slot dslot
-    | Lop(Itailcall_ind) ->
+    | Lop(Itailcall_ind { label_after = _; }) ->
         let n = frame_size() in
         if !contains_calls then
           `	ld	[%sp + {emit_int(n - 4 + 96)}], %o7\n`;
         `	jmp	{emit_reg i.arg.(0)}\n`;
         `	add	%sp, {emit_int n}, %sp\n` (* in delay slot *)
-    | Lop(Itailcall_imm s) ->
+    | Lop(Itailcall_imm { func; label_after = _; }) ->
         let n = frame_size() in
-        if s = !function_name then begin
+        if func = !function_name then begin
             `	b	{emit_label !tailrec_entry_point}\n`;
             fill_delay_slot dslot
         end else begin
           if !contains_calls then
             `	ld	[%sp + {emit_int(n - 4 + 96)}], %o7\n`;
-          `	sethi	%hi({emit_symbol s}), %g1\n`;
-          `	jmp	%g1 + %lo({emit_symbol s})\n`;
+          `	sethi	%hi({emit_symbol func}), %g1\n`;
+          `	jmp	%g1 + %lo({emit_symbol func})\n`;
           `	add	%sp, {emit_int n}, %sp\n` (* in delay slot *)
         end
-    | Lop(Iextcall(s, alloc)) ->
+    | Lop(Iextcall { func; alloc; label_after; }) ->
         if alloc then begin
-          `	sethi	%hi({emit_symbol s}), %g2\n`;
-          `{record_frame i.live}	call	{emit_symbol "caml_c_call"}\n`;
-          `	or	%g2, %lo({emit_symbol s}), %g2\n` (* in delay slot *)
+          `	sethi	%hi({emit_symbol func}), %g2\n`;
+          `{record_frame i.live ~label:label_after}	call	{emit_symbol "caml_c_call"}\n`;
+          `	or	%g2, %lo({emit_symbol func}), %g2\n` (* in delay slot *)
         end else begin
-          `	call	{emit_symbol s}\n`;
+          `	call	{emit_symbol func}\n`;
           fill_delay_slot dslot
         end
     | Lop(Istackoffset n) ->
@@ -393,7 +408,7 @@ let rec emit_instr i dslot =
               | _ -> "st" in
             emit_store storeinstr addr i.arg src
         end
-    | Lop(Ialloc n) ->
+    | Lop(Ialloc { words = n; label_after_call_gc; }) ->
         if !fastcode_flag then begin
           let lbl_cont = new_label() in
           if solaris then begin
@@ -406,7 +421,7 @@ let rec emit_instr i dslot =
           end;
           `	bgeu	{emit_label lbl_cont}\n`;
           `	add	%l6, 4, {emit_reg i.res.(0)}\n`; (* in delay slot *)
-          `{record_frame i.live}	call	{emit_symbol "caml_call_gc"}\n`;
+          `{record_frame i.live ?label:label_after_call_gc}	call	{emit_symbol "caml_call_gc"}\n`;
           `	mov	{emit_int n}, %g2\n`; (* in delay slot *)
           `	add	%l6, 4, {emit_reg i.res.(0)}\n`;
           `{emit_label lbl_cont}:\n`
@@ -430,7 +445,7 @@ let rec emit_instr i dslot =
           `	mov	0, {emit_reg i.res.(0)}\n`;
           `{emit_label lbl}:\n`
         end
-    | Lop(Iintop Icheckbound) ->
+    | Lop(Iintop (Icheckbound _)) ->
         `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
         if solaris then
           `	tleu	5\n`            (* 5 = ST_RANGE_CHECK *)
@@ -466,7 +481,7 @@ let rec emit_instr i dslot =
           `	mov	0, {emit_reg i.res.(0)}\n`;
           `{emit_label lbl}:\n`
         end
-    | Lop(Iintop_imm(Icheckbound, n)) ->
+    | Lop(Iintop_imm(Icheckbound _, n)) ->
         `	cmp	{emit_reg i.arg.(0)}, {emit_int n}\n`;
         if solaris then
           `	tleu	5\n`            (* 5 = ST_RANGE_CHECK *)
@@ -501,7 +516,7 @@ let rec emit_instr i dslot =
         `	st	%f30, [%sp + 96]\n`;
         `	ld	[%sp + 96], {emit_reg i.res.(0)}\n`;
         `	add	%sp, 8, %sp\n`
-    | Lop(Ispecific sop) ->
+    | Lop(Ispecific _) ->
 	assert false
     | Lreloadretaddr ->
         let n = frame_size() in
@@ -600,7 +615,7 @@ and fill_delay_slot = function
    that does not branch. *)
 
 let is_one_instr_op = function
-    Imulh | Idiv | Imod | Icomp _ | Icheckbound -> false
+    Imulh | Idiv | Imod | Icomp _ | Icheckbound _ -> false
   | _ -> true
 
 let is_one_instr i =
@@ -609,7 +624,7 @@ let is_one_instr i =
       begin match op with
         Imove | Ispill | Ireload ->
           i.arg.(0).typ <> Float && i.res.(0).typ <> Float
-      | Iconst_int n | Iconst_blockheader n -> is_native_immediate n
+      | Iconst_int n -> is_native_immediate n
       | Istackoffset _ -> true
       | Iload(_, Iindexed n) -> i.res.(0).typ <> Float && is_immediate n
       | Istore(_, Iindexed n, _) -> i.arg.(0).typ <> Float && is_immediate n
@@ -637,15 +652,16 @@ let no_interference res arg =
 let rec emit_all i =
   match i with
     {desc = Lend} -> ()
-  | {next = {desc = Lop(Icall_imm _) | Lop(Iextcall(_, false)) | Lbranch _}}
+  | {next = {desc = Lop(Icall_imm _)
+  | Lop(Iextcall { alloc = false; }) | Lbranch _}}
     when is_one_instr i ->
       emit_instr i.next (Some i);
       emit_all i.next.next
-  | {next = {desc = Lop(Itailcall_imm s)}}
-    when s = !function_name && is_one_instr i ->
+  | {next = {desc = Lop(Itailcall_imm { func; _ })}}
+    when func = !function_name && is_one_instr i ->
       emit_instr i.next (Some i);
       emit_all i.next.next
-  | {next = {desc = Lop(Icall_ind)}}
+  | {next = {desc = Lop(Icall_ind _)}}
     when is_one_instr i && no_interference i.res i.next.arg ->
       emit_instr i.next (Some i);
       emit_all i.next.next
@@ -695,8 +711,6 @@ let emit_item = function
       `	.global	{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 ->
@@ -711,8 +725,6 @@ let emit_item = function
       emit_float64_split_directive ".word" (Int64.bits_of_float f)
   | Csymbol_address s ->
       `	.word	{emit_symbol s}\n`
-  | Clabel_address lbl ->
-      `	.word	{emit_data_label lbl}\n`
   | Cstring s ->
       emit_string_directive "	.ascii	" s
   | Cskip n ->
diff --git a/asmcomp/sparc/proc.ml b/asmcomp/sparc/proc.ml
index 625f517f61..93ba635db3 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 |]
@@ -101,6 +103,8 @@ let phys_reg n =
 let stack_slot slot ty =
   Reg.at_location ty (Stack slot)
 
+let loc_spacetime_node_hole = Reg.dummy  (* Spacetime unsupported *)
+
 (* Calling conventions *)
 
 let calling_conventions first_int last_int first_float last_float make_stack
@@ -111,7 +115,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
@@ -132,48 +136,66 @@ let calling_conventions first_int last_int first_float last_float make_stack
 
 let incoming ofs = Incoming ofs
 let outgoing ofs = Outgoing ofs
-let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
+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 =
-  let (loc, ofs) = calling_conventions 6 15 100 105 incoming arg in loc
+  let (loc, _ofs) = calling_conventions 6 15 100 105 incoming arg in loc
 let loc_results res =
-  let (loc, ofs) = calling_conventions 0 5 100 105 not_supported res in loc
+  let (loc, _ofs) = calling_conventions 0 5 100 105 not_supported res in loc
 
 (* On the Sparc, all arguments to C functions, even floating-point arguments,
    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 *)
 
 (* Volatile registers: none *)
 
-let regs_are_volatile rs = false
+let regs_are_volatile _rs = false
 
 (* Registers destroyed by operations *)
 
@@ -184,8 +206,9 @@ let destroyed_at_c_call = (* %l0-%l4, %i0-%i5 preserved *)
      108; 109; 110; 111; 112; 113; 114])
 
 let destroyed_at_oper = function
-    Iop(Icall_ind | Icall_imm _ | Iextcall(_, true)) -> all_phys_regs
-  | Iop(Iextcall(_, false)) -> destroyed_at_c_call
+    Iop(Icall_ind _ | Icall_imm _ | Iextcall { alloc = true; }) ->
+    all_phys_regs
+  | Iop(Iextcall { alloc = false; }) -> destroyed_at_c_call
   | _ -> [||]
 
 let destroyed_at_raise = all_phys_regs
@@ -193,20 +216,20 @@ let destroyed_at_raise = all_phys_regs
 (* Maximal register pressure *)
 
 let safe_register_pressure = function
-    Iextcall(_, _) -> 0
+    Iextcall _ -> 0
   | _ -> 15
 
 let max_register_pressure = function
-    Iextcall(_, _) -> [| 11; 0 |]
+    Iextcall _ -> [| 11; 0 |]
   | _ -> [| 19; 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 _
+  | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _
   | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
-  | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) -> false
+  | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _) -> false
   | _ -> true
 
 (* Layout of the stack *)
diff --git a/asmcomp/sparc/reload.ml b/asmcomp/sparc/reload.ml
index caae16d7f2..356dc7f12a 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 497722bbc5..c169b47501 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
@@ -46,9 +49,9 @@ method oper_issue_cycles = function
   | Iconst_symbol _ -> 2
   | Ialloc _ -> 6
   | Iintop(Icomp _) -> 4
-  | Iintop(Icheckbound) -> 2
+  | Iintop(Icheckbound _) -> 2
   | Iintop_imm(Icomp _, _) -> 4
-  | Iintop_imm(Icheckbound, _) -> 2
+  | Iintop_imm(Icheckbound _, _) -> 2
   | Inegf -> 2
   | Iabsf -> 2
   | Ifloatofint -> 6
diff --git a/asmcomp/sparc/selection.ml b/asmcomp/sparc/selection.ml
index d938c1effe..c78a5f6560 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 *)
 
@@ -23,18 +26,21 @@ inherit Selectgen.selector_generic as super
 
 method is_immediate n = (n <= 4095) && (n >= -4096)
 
-method select_addressing chunk = function
+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)
 
+method private iextcall (func, alloc) =
+  Iextcall { func; alloc; label_after = Cmm.new_label (); }
+
 method! select_operation op args =
   match (op, args) with
   (* For SPARC V7 multiplication, division and modulus are turned into
@@ -42,11 +48,11 @@ method! select_operation op args =
      For SPARC V8 and V9, use hardware multiplication and division,
      but C library routine for modulus. *)
     (Cmuli, _) when !arch_version = SPARC_V7 ->
-      (Iextcall(".umul", false), args)
+      (self#iextcall(".umul", false), args)
   | (Cdivi, _) when !arch_version = SPARC_V7 ->
-      (Iextcall(".div", false), args)
+      (self#iextcall(".div", false), args)
   | (Cmodi, _) ->
-      (Iextcall(".rem", false), args)
+      (self#iextcall(".rem", false), args)
   | _ ->
       super#select_operation op args
 
diff --git a/asmcomp/spill.ml b/asmcomp/spill.ml
index 068f34e022..3595fa9272 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
@@ -69,7 +72,7 @@ let add_superpressure_regs op live_regs res_regs spilled =
     (fun r ->
       if Reg.Set.mem r spilled then () else begin
         match r.loc with
-          Stack s -> ()
+          Stack _ -> ()
         | _ -> let c = Proc.register_class r in
                pressure.(c) <- pressure.(c) + 1
       end)
@@ -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;
@@ -138,10 +139,10 @@ let rec reload i before =
   match i.desc with
     Iend ->
       (i, before)
-  | Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _) ->
+  | Ireturn | Iop(Itailcall_ind _) | Iop(Itailcall_imm _) ->
       (add_reloads (Reg.inter_set_array before i.arg) i,
        Reg.Set.empty)
-  | Iop(Icall_ind | Icall_imm _ | Iextcall(_, true,_)) ->
+  | Iop(Icall_ind _ | Icall_imm _ | Iextcall { alloc = true; }) ->
       (* All regs live across must be spilled *)
       let (new_next, finally) = reload i.next i.live in
       (add_reloads (Reg.inter_set_array before 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
@@ -283,7 +286,7 @@ let rec spill i finally =
   match i.desc with
     Iend ->
       (i, finally)
-  | Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _) ->
+  | Ireturn | Iop(Itailcall_ind _) | Iop(Itailcall_imm _) ->
       (i, Reg.Set.empty)
   | Iop Ireload ->
       let (new_next, after) = spill i.next finally in
@@ -295,8 +298,8 @@ let rec spill i finally =
       let before1 = Reg.diff_set_array after i.res in
       let before =
         match i.desc with
-          Iop Icall_ind | Iop(Icall_imm _) | Iop(Iextcall _)
-        | Iop(Iintop Icheckbound) | Iop(Iintop_imm(Icheckbound, _)) ->
+          Iop Icall_ind _ | Iop(Icall_imm _) | Iop(Iextcall _)
+        | Iop(Iintop (Icheckbound _)) | Iop(Iintop_imm((Icheckbound _), _)) ->
             Reg.Set.union before1 !spill_at_raise
         | _ ->
             before1 in
@@ -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,8 +407,11 @@ 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;
     fun_fast = f.fun_fast;
-    fun_dbg  = f.fun_dbg }
+    fun_dbg  = f.fun_dbg;
+    fun_spacetime_shape = f.fun_spacetime_shape;
+  }
diff --git a/asmcomp/spill.mli b/asmcomp/spill.mli
index 598a175522..cb1917e45c 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 8c553ab9ef..2bc3bc97f4 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
 
@@ -84,8 +87,8 @@ let identify_sub sub1 sub2 reg =
 let merge_substs sub1 sub2 i =
   match (sub1, sub2) with
     (None, None) -> None
-  | (Some s1, None) -> sub1
-  | (None, Some s2) -> sub2
+  | (Some _, None) -> sub1
+  | (None, Some _) -> sub2
   | (Some s1, Some s2) ->
       Reg.Set.iter (identify_sub s1 s2) (Reg.add_set_array i.live i.arg);
       sub1
@@ -122,8 +125,8 @@ let rec rename i sub =
   match i.desc with
     Iend ->
       (i, sub)
-  | Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _) ->
-      (instr_cons i.desc (subst_regs i.arg sub) [||] i.next,
+  | Ireturn | Iop(Itailcall_ind _) | Iop(Itailcall_imm _) ->
+      (instr_cons_debug i.desc (subst_regs i.arg sub) [||] i.dbg i.next,
        None)
   | Iop Ireload when i.res.(0).loc = Unknown ->
       begin match sub with
@@ -152,9 +155,9 @@ let rec rename i sub =
   | Iswitch(index, cases) ->
       let new_sub_cases = Array.map (fun c -> rename c sub) cases in
       let sub_merge =
-        merge_subst_array (Array.map (fun (n, s) -> s) new_sub_cases) i.next in
+        merge_subst_array (Array.map (fun (_n, s) -> s) new_sub_cases) i.next in
       let (new_next, sub_next) = rename i.next sub_merge in
-      (instr_cons (Iswitch(index, Array.map (fun (n, s) -> n) new_sub_cases))
+      (instr_cons (Iswitch(index, Array.map (fun (n, _s) -> n) new_sub_cases))
                   (subst_regs i.arg sub) [||] new_next,
        sub_next)
   | Iloop(body) ->
@@ -203,7 +206,7 @@ let fundecl f =
   reset ();
 
   let new_args = Array.copy f.fun_args in
-  let (new_body, sub_body) = rename f.fun_body (Some Reg.Map.empty) in
+  let (new_body, _sub_body) = rename f.fun_body (Some Reg.Map.empty) in
   repres_regs new_args;
   set_repres new_body;
   equiv_classes := Reg.Map.empty;
@@ -211,4 +214,6 @@ let fundecl f =
     fun_args = new_args;
     fun_body = new_body;
     fun_fast = f.fun_fast;
-    fun_dbg  = f.fun_dbg }
+    fun_dbg  = f.fun_dbg;
+    fun_spacetime_shape = f.fun_spacetime_shape;
+  }
diff --git a/asmcomp/split.mli b/asmcomp/split.mli
index 1924a5ad6c..ed1dea540a 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 d63e92bf03..720bd645a7 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
@@ -369,7 +368,7 @@ module Make(I:I) = struct
 (* Module entry point *)
 
     let catch arg k = match arg with
-    | Cexit (e,[]) ->  k arg
+    | Cexit (_e,[]) ->  k arg
     | _ ->
         let e =  next_raise_count () in
         Ccatch (e,[],k (Cexit (e,[])),arg)
diff --git a/asmcomp/strmatch.mli b/asmcomp/strmatch.mli
index 143dae5cb6..4371502c2c 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 0000000000..b87ac249d1
--- /dev/null
+++ b/asmcomp/un_anf.ml
@@ -0,0 +1,772 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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 (_let_kind, _value_kind, _ident, def, body) ->
+      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 (_let_kind, _value_kind, 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 (let_kind, value_kind, 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 (let_kind, value_kind,
+            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 | Constant | Moveable | Moveable_not_into_loops
+
+let both_moveable a b =
+  match a, b with
+  | Constant, Constant -> Constant
+  | Constant, Moveable
+  | Moveable, Constant
+  | Moveable, Moveable -> Moveable
+  | Moveable_not_into_loops, Constant
+  | Moveable_not_into_loops, Moveable
+  | Constant, Moveable_not_into_loops
+  | Moveable, Moveable_not_into_loops
+  | Moveable_not_into_loops, Moveable_not_into_loops -> Moveable_not_into_loops
+  | Constant, Fixed
+  | Moveable, Fixed
+  | Moveable_not_into_loops, Fixed
+  | Fixed, Constant
+  | Fixed, Moveable
+  | Fixed, Moveable_not_into_loops
+  | Fixed, Fixed -> Fixed
+
+let primitive_moveable (prim : Lambda.primitive)
+    (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 = Constant | Moveable | Moveable_not_into_loops
+
+(** Called when we are entering a loop or body of a function (which may be
+    called multiple times).  The environment is rewritten such that
+    identifiers previously moveable, but not into loops, are now fixed. *)
+let going_into_loop env =
+  Ident.Map.filter_map env ~f:(fun _var ((moveable : moveable_for_env), def) ->
+    match moveable with
+    | Constant -> Some (Constant, def)
+    | Moveable -> Some (Moveable, def)
+    | Moveable_not_into_loops -> None)
+
+(** 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
+    | Constant, def -> def, Constant
+    | Moveable, def -> def, Moveable
+    | Moveable_not_into_loops, def -> def, Moveable_not_into_loops
+    | exception Not_found ->
+      let moveable : moveable =
+        if Ident.Set.mem id ident_info.assigned then
+          Fixed
+        else
+          Moveable
+      in
+      clam, moveable
+    end
+  | Uconst _ ->
+    (* Constant closures are rewritten separately. *)
+    clam, Constant
+  | 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), both_moveable Moveable moveable
+  | Ulet (_let_kind, _value_kind, id, def, Uvar id') when Ident.same id id' ->
+    un_anf_and_moveable ident_info env def
+  | Ulet (let_kind, value_kind, 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
+    let is_assigned = Ident.Set.mem id ident_info.assigned in
+    begin match def_moveable, is_linear, is_used, is_assigned with
+    | (Constant | Moveable | Moveable_not_into_loops), _, false, _ ->
+      (* A moveable expression that is never used may be eliminated. *)
+      un_anf_and_moveable ident_info env body
+    | Constant, _, true, false
+    (* A constant expression bound to an unassigned identifier can replace any
+         occurances of the identifier. *)
+    | Moveable, true, true, false  ->
+      (* A moveable expression bound to a linear unassigned [Ident.t]
+         may replace the single occurrence of the identifier. *)
+      let def_moveable =
+        match def_moveable with
+        | Moveable -> Moveable
+        | Constant -> Constant
+        | Moveable_not_into_loops -> Moveable_not_into_loops
+        | Fixed -> assert false
+      in
+      let env = Ident.Map.add id (def_moveable, def) env in
+      un_anf_and_moveable ident_info env body
+    | Moveable_not_into_loops, true, true, false
+        (* We can't delete the [let] binding in this case because we don't
+           know whether the variable was substituted for its definition
+           (in the case of its linear use not being inside a loop) or not.
+           We could extend the code to cope with this case. *)
+    | (Constant | Moveable | Moveable_not_into_loops), _, _, true
+        (* Constant or Moveable but assigned. *)
+    | (Moveable | Moveable_not_into_loops), false, _, _
+        (* Moveable but not used linearly. *)
+    | Fixed, _, _, _ ->
+      let body, body_moveable = un_anf_and_moveable ident_info env body in
+      Ulet (let_kind, value_kind, 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 0000000000..004704da2a
--- /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 0000000000..859c21c6c6
--- /dev/null
+++ b/asmcomp/x86_ast.mli
@@ -0,0 +1,222 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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
+  | Cfi_remember_state
+  | Cfi_restore_state
+  | Cfi_def_cfa_offset of int
+  | 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 0000000000..f66771e440
--- /dev/null
+++ b/asmcomp/x86_dsl.ml
@@ -0,0 +1,202 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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 r13 = Reg64 R13
+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 cfi_remember_state () = directive Cfi_remember_state
+  let cfi_restore_state () = directive Cfi_restore_state
+  let cfi_def_cfa_offset n = directive (Cfi_def_cfa_offset n)
+  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 0000000000..080331fcee
--- /dev/null
+++ b/asmcomp/x86_dsl.mli
@@ -0,0 +1,192 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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 r13: 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 0000000000..384d6a5450
--- /dev/null
+++ b/asmcomp/x86_gas.ml
@@ -0,0 +1,314 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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"
+  | Cfi_remember_state -> bprintf b "\t.cfi_remember_state"
+  | Cfi_restore_state -> bprintf b "\t.cfi_restore_state"
+  | Cfi_def_cfa_offset n -> bprintf b "\t.cfi_def_cfa_offset %d" n
+  | 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 0000000000..3c3a4aee16
--- /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 0000000000..aec4858789
--- /dev/null
+++ b/asmcomp/x86_masm.ml
@@ -0,0 +1,264 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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
+  | Cfi_def_cfa_offset _
+  | Cfi_remember_state
+  | Cfi_restore_state
+  | 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 0000000000..9027fe67a3
--- /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 0000000000..30b77af5c6
--- /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 0000000000..388420b2d9
--- /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/.ignore b/asmrun/.ignore
deleted file mode 100644
index a7a9d33563..0000000000
--- 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 2dd7a232f1..7ea525fc11 100644
--- a/asmrun/Makefile
+++ b/asmrun/Makefile
@@ -1,43 +1,55 @@
-#########################################################################
-#                                                                       #
-#                                 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)
-CFLAGS=$(FLAGS) -ggdb $(NATIVECCCOMPOPTS)
-DFLAGS=$(FLAGS) -ggdb -DDEBUG $(NATIVECCCOMPOPTS)
-PFLAGS=$(FLAGS) -ggdb -pg -O -DPROFILING $(NATIVECCPROFOPTS)
-PICFLAGS=$(FLAGS) -O $(SHAREDCCCOMPOPTS) $(NATIVECCCOMPOPTS)
-
-COBJS=startup.o main.o fail.o roots.o globroots.o signals.o signals_asm.o \
-  misc.o major_gc.o shared_heap.o minor_gc.o memory.o alloc.o compare.o ints.o \
+      -DTARGET_$(ARCH) -DMODEL_$(MODEL) -DSYS_$(SYSTEM) $(IFLEXDIR) \
+      $(LIBUNWIND_INCLUDE_FLAGS)
+#CFLAGS=$(FLAGS) -g -O0
+CFLAGS=$(FLAGS) -g -O0 $(NATIVECCCOMPOPTS)
+DFLAGS=$(FLAGS) -g -DDEBUG $(NATIVECCCOMPOPTS)
+IFLAGS=$(FLAGS) -DCAML_INSTR
+PFLAGS=$(FLAGS) -pg -DPROFILING $(NATIVECCPROFOPTS) $(NATIVECCCOMPOPTS)
+PICFLAGS=$(FLAGS) $(SHAREDCCCOMPOPTS) $(NATIVECCCOMPOPTS)
+
+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 \
-  finalise.o custom.o $(UNIX_OR_WIN32).o backtrace.o natdynlink.o\
-  debugger.o meta.o dynlink.o addrmap.o domain.o platform.o \
-  eventlog.o params.o frame_descriptors.o fiber.o
+  compact.o finalise.o custom.o $(UNIX_OR_WIN32).o backtrace.o natdynlink.o \
+  debugger.o meta.o dynlink.o clambda_checks.o addrmap.o domain.o platform.o \
+  params.o eventlog.o frame_descriptors.o fiber.o \
+  spacetime.o spacetime_snapshot.o spacetime_offline.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)
@@ -54,6 +66,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
@@ -69,7 +86,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)
@@ -77,54 +94,49 @@ 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
+endif
 
 power.pic.o: power-$(SYSTEM).pic.o
 	cp power-$(SYSTEM).pic.o power.pic.o
 
 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
 major_gc.c: ../byterun/major_gc.c
@@ -216,6 +228,18 @@ LINKEDFILES=misc.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";\
@@ -229,15 +253,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 $@ $<
 
@@ -248,11 +263,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 dba8343c94..b008fddcbf 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,22 @@ 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) \
+  spacetime.$(O) spacetime_snapshot.$(O) spacetime_offline.$(O)
 
 LINKEDFILES=misc.c freelist.c major_gc.c minor_gc.c memory.c alloc.c array.c \
   compare.c ints.c floats.c str.c io.c extern.c intern.c hash.c sys.c \
   parsing.c gc_ctrl.c terminfo.c md5.c obj.c lexing.c printexc.c callback.c \
   weak.c compact.c meta.c finalise.c custom.c main.c globroots.c \
-  dynlink.c signals.c debugger.c
+  dynlink.c signals.c debugger.c startup_aux.c backtrace.c
 
 ifeq ($(TOOLCHAIN),mingw)
 ASMOBJS=$(ARCH).o
@@ -59,14 +64,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 011664d0a5..a04479105c 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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
@@ -247,14 +253,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); \
@@ -279,36 +286,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
 
diff --git a/asmrun/amd64nt.asm b/asmrun/amd64nt.asm
index 4883ba9772..07ac45085d 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
 
@@ -307,8 +309,6 @@ caml_raise_exn:
         pop     r14                  ; Recover previous exception handler
         ret                          ; Branch to handler
 L110:
-        mov     caml_backtrace_pos, 0
-L111:
         mov     r12, rax             ; Save exception bucket in r12
         mov     rcx, rax             ; Arg 1: exception bucket
         mov     rdx, [rsp]           ; Arg 2: PC of raise
@@ -321,15 +321,6 @@ L111:
         pop     r14                  ; Recover previous exception handler
         ret                          ; Branch to handler
 
-        PUBLIC  caml_reraise_exn
-        ALIGN   16
-caml_reraise_exn:
-        test    caml_backtrace_active, 1
-        jne     L111
-        mov     rsp, r14             ; Cut stack
-        pop     r14                  ; Recover previous exception handler
-        ret                          ; Branch to handler
-
 ; Raise an exception from C
 
         PUBLIC  caml_raise_exception
diff --git a/asmrun/arm.S b/asmrun/arm.S
index 9720665aa3..b5e3d9ae65 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.                            */
+/*   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 ecb365495f..202d739e63 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
@@ -297,6 +299,14 @@ FUNCTION(caml_call_read_barrier)
 CFI_STARTPROC
         PROFILE
         SWITCH_OCAML_TO_C(TMP)
+=======
+    /* Record return address */
+        STOREGLOBAL(x30, caml_last_return_address)
+    /* Record lowest stack address */
+        mov     TMP, sp
+        STOREGLOBAL(TMP, caml_bottom_of_stack)
+.Lcaml_call_gc:
+>>>>>>> b4.04.2
     /* Set up stack space, saving return address and frame pointer */
     /* (2 regs RA/GP, 24 allocatable int regs, 24 caller-save float regs) * 8 */
         stp     x29, x30, [sp, -400]!
@@ -919,3 +929,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 4f4aabc9ef..0000000000
--- a/asmrun/backtrace.c
+++ /dev/null
@@ -1,426 +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/fail.h"
-#include "caml/fiber.h"
-#include "caml/memory.h"
-#include "caml/misc.h"
-#include "caml/mlvalues.h"
-#include "stack.h"
-#include "frame_descriptors.h"
-
-#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)
-{
-  intnat flag = Int_val(vflag);
-
-  if (flag != Caml_state->backtrace_active) {
-    Caml_state->backtrace_active = flag;
-    Caml_state->backtrace_pos = 0;
-    if (flag) {
-      Caml_state->backtrace_last_exn = caml_create_root(Val_unit);
-    } else {
-      caml_delete_root(Caml_state->backtrace_last_exn);
-      Caml_state->backtrace_last_exn = NULL;
-    }
-  }
-  return Val_unit;
-}
-
-/* Return the status of the backtrace machinery */
-
-CAMLprim value caml_backtrace_status(value vunit)
-{
-  return Val_bool(Caml_state->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;
-
-  while (1) {
-    d = caml_find_frame_descr(*pc);
-    if (d == NULL) return NULL;
-    /* 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);
-      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. */
-      *sp = (char*)Caml_state->stack_high;
-      *pc = 0;
-      return d;
-    }
-  }
-}
-
-/* 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, uintnat trapsp_off)
-{
-  caml_domain_state* domain_state = Caml_state;
-  char* stack_high = (char*)domain_state->stack_high;
-
-  if (exn != caml_read_root(domain_state->backtrace_last_exn)) {
-    domain_state->backtrace_pos = 0;
-    caml_modify_root(domain_state->backtrace_last_exn, exn);
-  }
-  if (domain_state->backtrace_buffer == NULL) {
-    Assert(domain_state->backtrace_pos == 0);
-    domain_state->backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE * sizeof(code_t));
-    if (domain_state->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 (domain_state->backtrace_pos >= BACKTRACE_BUFFER_SIZE) return;
-    domain_state->backtrace_buffer[domain_state->backtrace_pos++] = (code_t) descr;
-
-    /* Stop when we reach the current exception handler */
-#ifndef Stack_grows_upwards
-    if (sp > stack_high - trapsp_off) return;
-#else
-    if (sp < stack_high - trapsp_off) 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. */
-
-static value get_callstack(value stack, value max_frames_value) {
-  CAMLparam2(stack, max_frames_value);
-  CAMLlocal2(saved_stack, 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_pos;
-  char *sp;
-  uintnat pc;
-
-  saved_stack = stack;
-  /* first compute the size of the trace */
-  {
-    caml_get_stack_sp_pc(stack, &sp, &pc);
-    trace_pos = 0;
-
-    while(1) {
-      frame_descr *descr = caml_next_frame_descriptor(&pc, &sp);
-      if (descr == NULL) break;
-      if (trace_pos >= max_frames) break;
-      if (descr->frame_size == 0xFFFF) {
-        stack = Stack_parent(stack);
-        if (stack == Val_unit) break;
-        caml_get_stack_sp_pc(stack, &sp, &pc);
-      } else {
-        ++trace_pos;
-      }
-    }
-  }
-
-  trace = caml_alloc((mlsize_t) trace_pos, 0);
-  stack = saved_stack;
-
-  /* then collect the trace */
-  {
-    caml_get_stack_sp_pc(stack, &sp, &pc);
-    trace_pos = 0;
-
-    while(1) {
-      frame_descr *descr = caml_next_frame_descriptor(&pc, &sp);
-      if (descr == NULL) break;
-      if (trace_pos >= max_frames) break;
-      if (descr->frame_size == 0xFFFF) {
-        stack = Stack_parent(stack);
-        if (stack == Val_unit) break;
-        caml_get_stack_sp_pc(stack, &sp, &pc);
-      } else {
-        caml_modify_field(trace, trace_pos, Val_Descrptr(descr));
-        ++trace_pos;
-      }
-    }
-  }
-
-  CAMLreturn(trace);
-}
-
-CAMLprim value caml_get_current_callstack (value max_frames_value) {
-  caml_domain_state* domain_state = Caml_state;
-  return get_callstack(domain_state->current_stack, max_frames_value);
-}
-
-CAMLprim value caml_get_continuation_callstack (value cont, value max_frames)
-{
-  CAMLparam1(cont);
-  CAMLlocal2(stack, callstack);
-  intnat bvar_stat;
-
-  bvar_stat = caml_bvar_status(cont);
-  if (bvar_stat & BVAR_EMPTY)
-    caml_invalid_argument ("continuation already taken");
-
-  caml_read_field(cont, 0, &stack);
-
-  stack = caml_reverse_fiber_stack(stack);
-  callstack = get_callstack (stack, max_frames);
-  caml_reverse_fiber_stack(stack);
-
-  CAMLreturn(callstack);
-}
-
-/* Extract location information for the given frame descriptor */
-
-struct caml_loc_info {
-  int loc_valid;
-  int loc_is_raise;
-  char * loc_filename;
-  int loc_lnum;
-  int loc_startchr;
-  int loc_endchr;
-};
-
-
-CAMLexport void extract_location_info(frame_descr * d,
-                                  /*out*/ struct caml_loc_info * li)
-{
-  uintnat infoptr;
-  uint32_t 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;
-  }
-
-  if (d->frame_size == 0xFFFF) {
-    /* Special frame marking the top of a stack chunk for an ML callback. */
-    /* XXX KC: Should the handlers be made distinct from compiler-inserted
-     * re-raise operations (above)? The backtrace ignores them currently. */
-    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);
-}
-
-/* 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)
-{
-  intnat i;
-  struct caml_loc_info li;
-
-  for (i = 0; i < Caml_state->backtrace_pos; i++) {
-    extract_location_info((frame_descr *) (Caml_state->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);
-    caml_initialize_field(p, 0, Val_bool(li.loc_is_raise));
-    caml_initialize_field(p, 1, fname);
-    caml_initialize_field(p, 2, Val_int(li.loc_lnum));
-    caml_initialize_field(p, 3, Val_int(li.loc_startchr));
-    caml_initialize_field(p, 4, Val_int(li.loc_endchr));
-  } else {
-    p = caml_alloc_small(1, 1);
-    caml_initialize_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_state->backtrace_buffer == NULL || Caml_state->backtrace_pos == 0) {
-    res = caml_alloc(0, tag);
-  }
-  else {
-    code_t saved_caml_backtrace_buffer[BACKTRACE_BUFFER_SIZE];
-    intnat saved_backtrace_pos;
-    intnat i;
-
-    saved_backtrace_pos = Caml_state->backtrace_pos;
-
-    if (saved_backtrace_pos > BACKTRACE_BUFFER_SIZE) {
-      saved_backtrace_pos = BACKTRACE_BUFFER_SIZE;
-    }
-
-    memcpy(saved_caml_backtrace_buffer, Caml_state->backtrace_buffer,
-           saved_backtrace_pos * sizeof(code_t));
-
-    res = caml_alloc(saved_backtrace_pos, tag);
-    for (i = 0; i < saved_backtrace_pos; i++) {
-      /* [Val_Descrptr] always returns an immediate. */
-      caml_initialize_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_imm(backtrace, i)));
-  }
-
-  res = caml_alloc_small(1, 0); caml_initialize_field(res, 0, arr); /* Some */
-  CAMLreturn(res);
-}
diff --git a/asmrun/backtrace_prim.c b/asmrun/backtrace_prim.c
new file mode 100644
index 0000000000..2ecf159180
--- /dev/null
+++ b/asmrun/backtrace_prim.c
@@ -0,0 +1,244 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 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.          */
+/*                                                                        */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
+/* 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 "caml/stack.h"
+
+/* 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);
+      Field(trace, trace_pos) = Val_backtrace_slot((backtrace_slot) descr);
+    }
+  }
+
+  CAMLreturn(trace);
+}
+
+
+debuginfo caml_debuginfo_extract(backtrace_slot slot)
+{
+  uintnat infoptr;
+  frame_descr * d = (frame_descr *)slot;
+
+  if ((d->frame_size & 1) == 0) {
+    return NULL;
+  }
+  /* Recover debugging info */
+  infoptr = ((uintnat) d +
+             sizeof(char *) + sizeof(short) + sizeof(short) +
+             sizeof(short) * d->num_live + sizeof(frame_descr *) - 1)
+            & -sizeof(frame_descr *);
+  return *((debuginfo*)infoptr);
+}
+
+debuginfo caml_debuginfo_next(debuginfo dbg)
+{
+  uint32_t * infoptr;
+
+  if (dbg == NULL)
+    return NULL;
+
+  infoptr = dbg;
+  infoptr += 2; /* Two packed info fields */
+  return *((debuginfo*)infoptr);
+}
+
+/* Extract location information for the given frame descriptor */
+void caml_debuginfo_location(debuginfo dbg, /*out*/ struct caml_loc_info * li)
+{
+  uint32_t info1, info2;
+
+  /* If no debugging information available, print nothing.
+     When everything is compiled with -g, this corresponds to
+     compiler-inserted re-raise operations. */
+  if (dbg == NULL) {
+    li->loc_valid = 0;
+    li->loc_is_raise = 1;
+    li->loc_is_inlined = 0;
+    return;
+  }
+  /* Recover debugging info */
+  info1 = ((uint32_t *)dbg)[0];
+  info2 = ((uint32_t *)dbg)[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 dbg
+     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) == 1;
+  li->loc_is_inlined = caml_debuginfo_next(dbg) != NULL;
+  li->loc_filename = (char *) dbg + (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 0000000000..1d25ecbc4f
--- /dev/null
+++ b/asmrun/clambda_checks.c
@@ -0,0 +1,89 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 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 %" ARCH_INT64_PRINTF_FORMAT
+      "u of NULL: %s\n", (ARCH_UINT64_TYPE) Long_val(pos), descr);
+    abort();
+  }
+  if (!Is_block(v)) {
+    fprintf(stderr,
+      "Access to field %" ARCH_INT64_PRINTF_FORMAT
+      "u 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 %" ARCH_INT64_PRINTF_FORMAT
+      "u of value %p of size %" ARCH_INT64_PRINTF_FORMAT "u is illegal: %s\n",
+      (ARCH_UINT64_TYPE) Long_val(pos), (void*) v,
+      (ARCH_UINT64_TYPE) Wosize_val(v),
+      descr);
+    abort();
+  }
+  return orig_v;
+}
diff --git a/asmrun/fail.c b/asmrun/fail.c
index 3932a1275c..24748dbf1e 100644
--- a/asmrun/fail.c
+++ b/asmrun/fail.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Raising exceptions from C. */
 
@@ -23,7 +27,7 @@
 #include "caml/mlvalues.h"
 #include "caml/printexc.h"
 #include "caml/signals.h"
-#include "stack.h"
+#include "caml/stack.h"
 #include "caml/roots.h"
 #include "caml/callback.h"
 
@@ -48,7 +52,9 @@ extern caml_generated_constant
 
 /* Exception raising */
 
-extern void caml_raise_exception (char* young_ptr, value bucket) Noreturn;
+CAMLnoreturn_start
+  extern void caml_raise_exception (value bucket)
+CAMLnoreturn_end;
 
 void caml_raise(value v)
 {
diff --git a/asmrun/i386.S b/asmrun/i386.S
index e55969ee97..0b110de165 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
@@ -332,8 +334,6 @@ FUNCTION(caml_raise_exn)
         UNDO_ALIGN_STACK(8)
         ret
 LBL(110):
-        movl    $0, G(caml_backtrace_pos)
-LBL(111):
         movl    %eax, %esi          /* Save exception bucket in esi */
         movl    G(caml_exception_pointer), %edi /* SP of handler */
         movl    0(%esp), %eax       /* PC of raise */
@@ -351,16 +351,6 @@ LBL(111):
         ret
         CFI_ENDPROC
 
-FUNCTION(caml_reraise_exn)
-        CFI_STARTPROC
-        testl   $1, G(caml_backtrace_active)
-        jne     LBL(111)
-        movl    G(caml_exception_pointer), %esp
-        popl    G(caml_exception_pointer); CFI_ADJUST(-4)
-        UNDO_ALIGN_STACK(8)
-        ret
-        CFI_ENDPROC
-
 /* Raise an exception from C */
 
 FUNCTION(caml_raise_exception)
diff --git a/asmrun/i386nt.asm b/asmrun/i386nt.asm
index 61ec34162f..b67306769f 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
 
@@ -206,8 +208,6 @@ _caml_raise_exn:
         pop     _caml_exception_pointer
         ret
 L110:
-        mov     _caml_backtrace_pos, 0
-L111:
         mov     esi, eax                ; Save exception bucket in esi
         mov     edi, _caml_exception_pointer ; SP of handler
         mov     eax, [esp]              ; PC of raise
@@ -222,16 +222,7 @@ L111:
         pop     _caml_exception_pointer
         ret
 
-        PUBLIC  _caml_reraise_exn
-        ALIGN   4
-_caml_reraise_exn:
-        test    _caml_backtrace_active, 1
-        jne     L111
-        mov     esp, _caml_exception_pointer
-        pop     _caml_exception_pointer
-        ret
-
-                                ; Raise an exception from C
+; Raise an exception from C
 
         PUBLIC  _caml_raise_exception
         ALIGN  4
diff --git a/asmrun/natdynlink.c b/asmrun/natdynlink.c
index 60bf57282c..90039eb555 100644
--- a/asmrun/natdynlink.c
+++ b/asmrun/natdynlink.c
@@ -1,20 +1,24 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 #include "caml/misc.h"
 #include "caml/mlvalues.h"
 #include "caml/memory.h"
-#include "stack.h"
+#include "caml/stack.h"
 #include "caml/callback.h"
 #include "caml/alloc.h"
 #include "caml/intext.h"
@@ -22,6 +26,14 @@
 #include "caml/fail.h"
 #include "frame_descriptors.h"
 #include "caml/globroots.h"
+#include "caml/signals.h"
+#ifdef WITH_SPACETIME
+#include "spacetime.h"
+#endif
+
+#include "caml/hooks.h"
+
+CAMLexport void (*caml_natdynlink_hook)(void* handle, char* unit) = NULL;
 
 #include 
 #include 
@@ -43,8 +55,6 @@ static void *getsym(void *handle, char *module, char *name){
   return sym;
 }
 
-extern char caml_globals_map[];
-
 CAMLprim value caml_natdynlink_getmap(value unit)
 {
   return caml_input_value_from_block(caml_globals_map, INT_MAX);
@@ -67,7 +77,7 @@ CAMLprim value caml_natdynlink_open(value filename, value global)
 
   p = caml_strdup(String_val(filename));
   caml_enter_blocking_section();
-  dlhandle = caml_dlopen(String_val(filename), 1, Int_val(global));
+  dlhandle = caml_dlopen(p, 1, Int_val(global));
   caml_leave_blocking_section();
   caml_stat_free(p);
 
@@ -103,7 +113,12 @@ CAMLprim value caml_natdynlink_run(value handle_v, value symbol) {
   sym = optsym("__frametable");
   if (NULL != sym) caml_register_frametable(sym);
 
-  sym = optsym("");
+#ifdef WITH_SPACETIME
+  sym = optsym("__spacetime_shapes");
+  if (NULL != sym) caml_spacetime_register_shapes(sym);
+#endif
+
+  sym = optsym("__gc_roots");
   if (NULL != sym) caml_register_dyn_global(sym);
 
   sym = optsym("__code_begin");
@@ -116,6 +131,8 @@ CAMLprim value caml_natdynlink_run(value handle_v, value symbol) {
     caml_ext_table_add(&caml_code_fragments_table, cf);
   }
 
+  if( caml_natdynlink_hook != NULL ) caml_natdynlink_hook(handle,unit);
+
   entrypoint = optsym("__entry");
   if (NULL != entrypoint) result = caml_callback((value)(&entrypoint), 0);
   else result = Val_unit;
diff --git a/asmrun/power-elf.S b/asmrun/power-elf.S
deleted file mode 100644
index facbfbf0e1..0000000000
--- 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 6fcb43cc2d..0000000000
--- 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 0000000000..b58391edf0
--- /dev/null
+++ b/asmrun/power.S
@@ -0,0 +1,680 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 1996 Institut National de Recherche en Informatique et     */
+/*     en Automatique.                                                    */
+/*                                                                        */
+/*   All rights reserved.  This file is distributed 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:
+        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)
+
+/* 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/s390x.S b/asmrun/s390x.S
new file mode 100644
index 0000000000..0af4199410
--- /dev/null
+++ b/asmrun/s390x.S
@@ -0,0 +1,340 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 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)
+.L101:
+    /* 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)
+    /* 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:
+        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 */
+
+/* Raise an exception from C */
+
+        .globl  caml_raise_exception
+        .type   caml_raise_exception, @function
+caml_raise_exception:
+        Loadglobal32(%r0, 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)
+    /* Pop trap frame */
+        lg      %r1, 0(%r15)
+        lg      %r13, 8(%r15)
+        agfi    %r15, 16
+    /* Branch to handler */
+        br      %r1;
+.L112:
+        lgfi      %r0, 0
+        Storeglobal32(%r0, caml_backtrace_pos)
+        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:
+        /* Save return address before decrementing SP, otherwise
+           the frame descriptor for the call site is not correct */
+        Storeglobal(%r15, caml_bottom_of_stack)
+        lay     %r15, -160(%r15)    /* Reserve stack space for C call */
+        larl    %r7, caml_array_bound_error
+        j       .L101
+        .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 2f741ce33e..279e1807ae 100644
--- a/asmrun/signals_asm.c
+++ b/asmrun/signals_asm.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Signal handling, code specific to the native-code compiler */
 
@@ -26,7 +30,8 @@
 #include "caml/signals.h"
 #include "caml/signals_machdep.h"
 #include "signals_osdep.h"
-#include "stack.h"
+#include "caml/stack.h"
+#include "spacetime.h"
 
 #ifdef HAS_STACK_OVERFLOW_DETECTION
 #include 
@@ -69,6 +74,13 @@ extern char caml_system__code_begin, caml_system__code_end;
 void caml_garbage_collection()
 {
   caml_handle_gc_interrupt();
+
+#ifdef WITH_SPACETIME
+  if (caml_young_ptr == caml_young_alloc_end) {
+    caml_spacetime_automatic_snapshot();
+  }
+#endif
+
   caml_process_pending_signals();
 }
 
@@ -257,6 +269,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 627e3b727e..3066bfebaf 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
 
@@ -135,6 +137,23 @@
  #define CONTEXT_YOUNG_PTR (context->sc_r15)
  #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr)
 
+/****************** AMD64, NetBSD */
+
+#elif defined(TARGET_amd64) && defined (SYS_netbsd)
+
+ #include 
+ #define DECLARE_SIGNAL_HANDLER(name) \
+ static void name(int sig, siginfo_t * info, ucontext_t * context)
+
+ #define SET_SIGACT(sigact,name) \
+ sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \
+ sigact.sa_flags = SA_SIGINFO
+
+ #define CONTEXT_PC (_UC_MACHINE_PC(context))
+ #define CONTEXT_EXCEPTION_POINTER (context->uc_mcontext.gregs[REG_R14])
+ #define CONTEXT_YOUNG_PTR (context->uc_mcontext.gregs[REG_R15])
+ #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr)
+
 /****************** I386, Linux */
 
 #elif defined(TARGET_i386) && defined(SYS_linux_elf)
@@ -284,9 +303,27 @@
   #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))
+#elif defined(TARGET_power) && \
+    (defined(SYS_bsd) || defined(SYS_bsd_elf) || defined(SYS_netbsd))
 
   #define DECLARE_SIGNAL_HANDLER(name) \
     static void name(int sig, int code, struct sigcontext * context)
diff --git a/asmrun/spacetime.c b/asmrun/spacetime.c
new file mode 100644
index 0000000000..effa522064
--- /dev/null
+++ b/asmrun/spacetime.c
@@ -0,0 +1,1123 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*            Mark Shinwell and Leo White, Jane Street Europe             */
+/*                                                                        */
+/*   Copyright 2013--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.          */
+/*                                                                        */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "caml/config.h"
+#ifdef HAS_UNISTD
+#include 
+#endif
+
+#include "caml/alloc.h"
+#include "caml/backtrace_prim.h"
+#include "caml/fail.h"
+#include "caml/gc.h"
+#include "caml/intext.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/osdeps.h"
+#include "caml/roots.h"
+#include "caml/signals.h"
+#include "caml/stack.h"
+#include "caml/sys.h"
+#include "spacetime.h"
+
+#ifdef WITH_SPACETIME
+
+/* We force "noinline" in certain places to be sure we know how many
+   frames there will be on the stack. */
+#define NOINLINE __attribute__((noinline))
+
+#ifdef HAS_LIBUNWIND
+#define UNW_LOCAL_ONLY
+#include "libunwind.h"
+#endif
+
+static int automatic_snapshots = 0;
+static double snapshot_interval = 0.0;
+static double next_snapshot_time = 0.0;
+static struct channel *snapshot_channel;
+static int pid_when_snapshot_channel_opened;
+
+extern value caml_spacetime_debug(value);
+
+static char* start_of_free_node_block;
+static char* end_of_free_node_block;
+
+typedef struct per_thread {
+  value* trie_node_root;
+  value* finaliser_trie_node_root;
+  struct per_thread* next;
+} per_thread;
+
+/* List of tries corresponding to threads that have been created. */
+/* CR-soon mshinwell: just include the main trie in this list. */
+static per_thread* per_threads = NULL;
+static int num_per_threads = 0;
+
+/* [caml_spacetime_shapes] is defined in the startup file. */
+extern uint64_t* caml_spacetime_shapes;
+
+uint64_t** caml_spacetime_static_shape_tables = NULL;
+shape_table* caml_spacetime_dynamic_shape_tables = NULL;
+
+static uintnat caml_spacetime_profinfo = (uintnat) 0;
+
+value caml_spacetime_trie_root = Val_unit;
+value* caml_spacetime_trie_node_ptr = &caml_spacetime_trie_root;
+
+static value caml_spacetime_finaliser_trie_root_main_thread = Val_unit;
+value* caml_spacetime_finaliser_trie_root
+  = &caml_spacetime_finaliser_trie_root_main_thread;
+
+/* CR-someday mshinwell: think about thread safety of the manipulation of
+   this list for multicore */
+allocation_point* caml_all_allocation_points = NULL;
+
+static const uintnat chunk_size = 1024 * 1024;
+
+static void reinitialise_free_node_block(void)
+{
+  size_t index;
+
+  start_of_free_node_block = (char*) malloc(chunk_size);
+  end_of_free_node_block = start_of_free_node_block + chunk_size;
+
+  for (index = 0; index < chunk_size / sizeof(value); index++) {
+    ((value*) start_of_free_node_block)[index] = Val_unit;
+  }
+}
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#if defined (_WIN32) || defined (_WIN64)
+extern value val_process_id;
+#endif
+
+static uint32_t version_number = 0;
+static uint32_t magic_number_base = 0xace00ace;
+
+static void caml_spacetime_write_magic_number_internal(struct channel* chan)
+{
+  value magic_number =
+    Val_long(((uint64_t) magic_number_base)
+             | (((uint64_t) version_number) << 32));
+
+  Lock(chan);
+  caml_output_val(chan, magic_number, Val_long(0));
+  Unlock(chan);
+}
+
+CAMLprim value caml_spacetime_write_magic_number(value v_channel)
+{
+  caml_spacetime_write_magic_number_internal(Channel(v_channel));
+  return Val_unit;
+}
+
+static char* automatic_snapshot_dir;
+
+static void open_snapshot_channel(void)
+{
+  int fd;
+  char filename[8192];
+  int pid;
+#if defined (_WIN32) || defined (_WIN64)
+  pid = Int_val(val_process_id);
+#else
+  pid = getpid();
+#endif
+  snprintf(filename, 8192, "%s/spacetime-%d", automatic_snapshot_dir, pid);
+  filename[8191] = '\0';
+  fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+  if (fd == -1) {
+    automatic_snapshots = 0;
+  }
+  else {
+    snapshot_channel = caml_open_descriptor_out(fd);
+    snapshot_channel->flags |= CHANNEL_FLAG_BLOCKING_WRITE;
+    pid_when_snapshot_channel_opened = pid;
+    caml_spacetime_write_magic_number_internal(snapshot_channel);
+  }
+}
+
+static void maybe_reopen_snapshot_channel(void)
+{
+  /* This function should be used before writing to the automatic snapshot
+     channel.  It detects whether we have forked since the channel was opened.
+     If so, we close the old channel (ignoring any errors just in case the
+     old fd has been closed, e.g. in a double-fork situation where the middle
+     process has a loop to manually close all fds and no Spacetime snapshot
+     was written during that time) and then open a new one. */
+
+  int pid;
+#if defined (_WIN32) || defined (_WIN64)
+  pid = Int_val(val_process_id);
+#else
+  pid = getpid();
+#endif
+
+  if (pid != pid_when_snapshot_channel_opened) {
+    caml_close_channel(snapshot_channel);
+    open_snapshot_channel();
+  }
+}
+
+extern void caml_spacetime_automatic_save(void);
+
+void caml_spacetime_initialize(void)
+{
+  /* Note that this is called very early (even prior to GC initialisation). */
+
+  char *ap_interval;
+
+  reinitialise_free_node_block();
+
+  caml_spacetime_static_shape_tables = &caml_spacetime_shapes;
+
+  ap_interval = getenv ("OCAML_SPACETIME_INTERVAL");
+  if (ap_interval != NULL) {
+    unsigned int interval = 0;
+    sscanf(ap_interval, "%u", &interval);
+    if (interval != 0) {
+      double time;
+      char cwd[4096];
+      char* user_specified_automatic_snapshot_dir;
+      int dir_ok = 1;
+
+      user_specified_automatic_snapshot_dir =
+        caml_secure_getenv("OCAML_SPACETIME_SNAPSHOT_DIR");
+
+      if (user_specified_automatic_snapshot_dir == NULL) {
+#ifdef HAS_GETCWD
+        if (getcwd(cwd, sizeof(cwd)) == NULL) {
+          dir_ok = 0;
+        }
+#else
+        if (getwd(cwd) == NULL) {
+          dir_ok = 0;
+        }
+#endif
+        if (dir_ok) {
+          automatic_snapshot_dir = strdup(cwd);
+        }
+      }
+      else {
+        automatic_snapshot_dir =
+          strdup(user_specified_automatic_snapshot_dir);
+      }
+
+      if (dir_ok) {
+        automatic_snapshots = 1;
+        open_snapshot_channel();
+        if (automatic_snapshots) {
+#ifdef SIGINT
+          /* Catch interrupt so that the profile can be completed.
+             We do this by marking the signal as handled without
+             specifying an actual handler. This causes the signal
+             to be handled by a call to exit. */
+          caml_set_signal_action(SIGINT, 2);
+#endif
+          snapshot_interval = interval / 1e3;
+          time = caml_sys_time_unboxed(Val_unit);
+          next_snapshot_time = time + snapshot_interval;
+          atexit(&caml_spacetime_automatic_save);
+        }
+      }
+    }
+  }
+}
+
+void caml_spacetime_register_shapes(void* dynlinked_table)
+{
+  shape_table* table;
+  table = (shape_table*) malloc(sizeof(shape_table));
+  if (table == NULL) {
+    fprintf(stderr, "Out of memory whilst registering shape table");
+    abort();
+  }
+  table->table = (uint64_t*) dynlinked_table;
+  table->next = caml_spacetime_dynamic_shape_tables;
+  caml_spacetime_dynamic_shape_tables = table;
+}
+
+CAMLprim value caml_spacetime_trie_is_initialized (value v_unit)
+{
+  return (caml_spacetime_trie_root == Val_unit) ? Val_false : Val_true;
+}
+
+CAMLprim value caml_spacetime_get_trie_root (value v_unit)
+{
+  return caml_spacetime_trie_root;
+}
+
+void caml_spacetime_register_thread(
+  value* trie_node_root, value* finaliser_trie_node_root)
+{
+  per_thread* thr;
+
+  thr = (per_thread*) malloc(sizeof(per_thread));
+  if (thr == NULL) {
+    fprintf(stderr, "Out of memory while registering thread for profiling\n");
+    abort();
+  }
+  thr->next = per_threads;
+  per_threads = thr;
+
+  thr->trie_node_root = trie_node_root;
+  thr->finaliser_trie_node_root = finaliser_trie_node_root;
+
+  /* CR-soon mshinwell: record thread ID (and for the main thread too) */
+
+  num_per_threads++;
+}
+
+static void caml_spacetime_save_event_internal (value v_time_opt,
+                                                struct channel* chan,
+                                                value v_event_name)
+{
+  value v_time;
+  double time_override = 0.0;
+  int use_time_override = 0;
+
+  if (Is_block(v_time_opt)) {
+    time_override = Double_field(Field(v_time_opt, 0), 0);
+    use_time_override = 1;
+  }
+  v_time = caml_spacetime_timestamp(time_override, use_time_override);
+
+  Lock(chan);
+  caml_output_val(chan, Val_long(2), Val_long(0));
+  caml_output_val(chan, v_event_name, Val_long(0));
+  caml_extern_allow_out_of_heap = 1;
+  caml_output_val(chan, v_time, Val_long(0));
+  caml_extern_allow_out_of_heap = 0;
+  Unlock(chan);
+
+  caml_stat_free(Hp_val(v_time));
+}
+
+CAMLprim value caml_spacetime_save_event (value v_time_opt,
+                                          value v_channel,
+                                          value v_event_name)
+{
+  struct channel* chan = Channel(v_channel);
+
+  caml_spacetime_save_event_internal(v_time_opt, chan, v_event_name);
+
+  return Val_unit;
+}
+
+
+void save_trie (struct channel *chan, double time_override,
+                int use_time_override)
+{
+  value v_time, v_frames, v_shapes;
+  /* CR-someday mshinwell: The commented-out changes here are for multicore,
+     where we think we should have one trie per domain. */
+  /* int num_marshalled = 0;
+  per_thread* thr = per_threads; */
+
+  Lock(chan);
+
+  caml_output_val(chan, Val_long(1), Val_long(0));
+
+  v_time = caml_spacetime_timestamp(time_override, use_time_override);
+  v_frames = caml_spacetime_frame_table();
+  v_shapes = caml_spacetime_shape_table();
+
+  caml_extern_allow_out_of_heap = 1;
+  caml_output_val(chan, v_time, Val_long(0));
+  caml_output_val(chan, v_frames, Val_long(0));
+  caml_output_val(chan, v_shapes, Val_long(0));
+  caml_extern_allow_out_of_heap = 0;
+
+  caml_output_val(chan, Val_long(1) /* Val_long(num_per_threads + 1) */,
+    Val_long(0));
+
+  /* Marshal both the main and finaliser tries, for all threads that have
+     been created, to an [out_channel].  This can be done by using the
+     extern.c code as usual, since the trie looks like standard OCaml values;
+     but we must allow it to traverse outside the heap. */
+
+  caml_extern_allow_out_of_heap = 1;
+  caml_output_val(chan, caml_spacetime_trie_root, Val_long(0));
+  caml_output_val(chan,
+    caml_spacetime_finaliser_trie_root_main_thread, Val_long(0));
+  /* while (thr != NULL) {
+    caml_output_val(chan, *(thr->trie_node_root), Val_long(0));
+    caml_output_val(chan, *(thr->finaliser_trie_node_root),
+      Val_long(0));
+    thr = thr->next;
+    num_marshalled++;
+  }
+  Assert(num_marshalled == num_per_threads); */
+  caml_extern_allow_out_of_heap = 0;
+
+  Unlock(chan);
+}
+
+CAMLprim value caml_spacetime_save_trie (value v_time_opt, value v_channel)
+{
+  struct channel* channel = Channel(v_channel);
+  double time_override = 0.0;
+  int use_time_override = 0;
+
+  if (Is_block(v_time_opt)) {
+    time_override = Double_field(Field(v_time_opt, 0), 0);
+    use_time_override = 1;
+  }
+
+  save_trie(channel, time_override, use_time_override);
+
+  return Val_unit;
+}
+
+c_node_type caml_spacetime_classify_c_node(c_node* node)
+{
+  return (node->pc & 2) ? CALL : ALLOCATION;
+}
+
+c_node* caml_spacetime_c_node_of_stored_pointer(value node_stored)
+{
+  Assert(node_stored == Val_unit || Is_c_node(node_stored));
+  return (node_stored == Val_unit) ? NULL : (c_node*) Hp_val(node_stored);
+}
+
+c_node* caml_spacetime_c_node_of_stored_pointer_not_null(
+      value node_stored)
+{
+  Assert(Is_c_node(node_stored));
+  return (c_node*) Hp_val(node_stored);
+}
+
+value caml_spacetime_stored_pointer_of_c_node(c_node* c_node)
+{
+  value node;
+  Assert(c_node != NULL);
+  node = Val_hp(c_node);
+  Assert(Is_c_node(node));
+  return node;
+}
+
+#ifdef HAS_LIBUNWIND
+static int pc_inside_c_node_matches(c_node* node, void* pc)
+{
+  return Decode_c_node_pc(node->pc) == pc;
+}
+#endif
+
+static value allocate_uninitialized_ocaml_node(int size_including_header)
+{
+  void* node;
+  uintnat size;
+
+  Assert(size_including_header >= 3);
+  node = caml_stat_alloc(sizeof(uintnat) * size_including_header);
+
+  size = size_including_header * sizeof(value);
+
+  node = (void*) start_of_free_node_block;
+  if (end_of_free_node_block - start_of_free_node_block < size) {
+    reinitialise_free_node_block();
+    node = (void*) start_of_free_node_block;
+    Assert(end_of_free_node_block - start_of_free_node_block >= size);
+  }
+
+  start_of_free_node_block += size;
+
+  /* We don't currently rely on [uintnat] alignment, but we do need some
+     alignment, so just be sure. */
+  Assert (((uintnat) node) % sizeof(uintnat) == 0);
+  return Val_hp(node);
+}
+
+static value find_tail_node(value node, void* callee)
+{
+  /* Search the tail chain within [node] (which corresponds to an invocation
+     of a caller of [callee]) to determine whether it contains a tail node
+     corresponding to [callee].  Returns any such node, or [Val_unit] if no
+     such node exists. */
+
+  value starting_node;
+  value pc;
+  value found = Val_unit;
+
+  starting_node = node;
+  pc = Encode_node_pc(callee);
+
+  do {
+    Assert(Is_ocaml_node(node));
+    if (Node_pc(node) == pc) {
+      found = node;
+    }
+    else {
+      node = Tail_link(node);
+    }
+  } while (found == Val_unit && starting_node != node);
+
+  return found;
+}
+
+CAMLprim value caml_spacetime_allocate_node(
+      int size_including_header, void* pc, value* node_hole)
+{
+  value node;
+  value caller_node = Val_unit;
+
+  node = *node_hole;
+  /* The node hole should either contain [Val_unit], indicating that this
+     function was not tail called and we have not been to this point in the
+     trie before; or it should contain a value encoded using
+     [Encoded_tail_caller_node] that points at the node of a caller
+     that tail called the current function.  (Such a value is necessary to
+     be able to find the start of the caller's node, and hence its tail
+     chain, so we as a tail-called callee can link ourselves in.) */
+  Assert(Is_tail_caller_node_encoded(node));
+
+  if (node != Val_unit) {
+    value tail_node;
+    /* The callee was tail called.  Find whether there already exists a node
+       for it in the tail call chain within the caller's node.  The caller's
+       node must always be an OCaml node. */
+    caller_node = Decode_tail_caller_node(node);
+    tail_node = find_tail_node(caller_node, pc);
+    if (tail_node != Val_unit) {
+      /* This tail calling sequence has happened before; just fill the hole
+         with the existing node and return. */
+      *node_hole = tail_node;
+      return 0;  /* indicates an existing node was returned */
+    }
+  }
+
+  node = allocate_uninitialized_ocaml_node(size_including_header);
+  Hd_val(node) =
+    Make_header(size_including_header - 1, OCaml_node_tag, Caml_black);
+  Assert((((uintnat) pc) % 1) == 0);
+  Node_pc(node) = Encode_node_pc(pc);
+  /* If the callee was tail called, then the tail link field will link this
+     new node into an existing tail chain.  Otherwise, it is initialized with
+     the empty tail chain, i.e. the one pointing directly at [node]. */
+  if (caller_node == Val_unit) {
+    Tail_link(node) = node;
+  }
+  else {
+    Tail_link(node) = Tail_link(caller_node);
+    Tail_link(caller_node) = node;
+  }
+
+  /* The callee node pointers for direct tail call points are
+     initialized from code emitted by the OCaml compiler.  This is done to
+     avoid having to pass this function a description of which nodes are
+     direct tail call points.  (We cannot just count them and put them at the
+     beginning of the node because we need the indexes of elements within the
+     node during instruction selection before we have found all call points.)
+
+     All other fields have already been initialised by
+     [reinitialise_free_node_block].
+  */
+
+  *node_hole = node;
+
+  return 1;  /* indicates a new node was created */
+}
+
+static c_node* allocate_c_node(void)
+{
+  c_node* node;
+  size_t index;
+
+  node = (c_node*) start_of_free_node_block;
+  if (end_of_free_node_block - start_of_free_node_block < sizeof(c_node)) {
+    reinitialise_free_node_block();
+    node = (c_node*) start_of_free_node_block;
+    Assert(end_of_free_node_block - start_of_free_node_block
+      >= sizeof(c_node));
+  }
+  start_of_free_node_block += sizeof(c_node);
+
+  Assert((sizeof(c_node) % sizeof(uintnat)) == 0);
+
+  /* CR-soon mshinwell: remove this and pad the structure properly */
+  for (index = 0; index < sizeof(c_node) / sizeof(value); index++) {
+    ((value*) node)[index] = Val_unit;
+  }
+
+  node->gc_header =
+    Make_header(sizeof(c_node)/sizeof(uintnat) - 1, C_node_tag, Caml_black);
+  node->data.callee_node = Val_unit;
+  node->next = Val_unit;
+
+  return node;
+}
+
+/* Since a given indirect call site either always yields tail calls or
+   always yields non-tail calls, the output of
+   [caml_spacetime_indirect_node_hole_ptr] is uniquely determined by its
+   first two arguments (the callee and the node hole).  We cache these
+   to increase performance of recursive functions containing an indirect
+   call (e.g. [List.map] when not inlined). */
+static void* last_indirect_node_hole_ptr_callee;
+static value* last_indirect_node_hole_ptr_node_hole;
+static value* last_indirect_node_hole_ptr_result;
+
+CAMLprim value* caml_spacetime_indirect_node_hole_ptr
+      (void* callee, value* node_hole, value caller_node)
+{
+  /* Find the address of the node hole for an indirect call to [callee].
+     If [caller_node] is not [Val_unit], it is a pointer to the caller's
+     node, and indicates that this is a tail call site. */
+
+  c_node* c_node;
+  value encoded_callee;
+
+  if (callee == last_indirect_node_hole_ptr_callee
+      && node_hole == last_indirect_node_hole_ptr_node_hole) {
+    return last_indirect_node_hole_ptr_result;
+  }
+
+  last_indirect_node_hole_ptr_callee = callee;
+  last_indirect_node_hole_ptr_node_hole = node_hole;
+
+  encoded_callee = Encode_c_node_pc_for_call(callee);
+
+  while (*node_hole != Val_unit) {
+    Assert(((uintnat) *node_hole) % sizeof(value) == 0);
+
+    c_node = caml_spacetime_c_node_of_stored_pointer_not_null(*node_hole);
+
+    Assert(c_node != NULL);
+    Assert(caml_spacetime_classify_c_node(c_node) == CALL);
+
+    if (c_node->pc == encoded_callee) {
+      last_indirect_node_hole_ptr_result = &(c_node->data.callee_node);
+      return last_indirect_node_hole_ptr_result;
+    }
+    else {
+      node_hole = &c_node->next;
+    }
+  }
+
+  c_node = allocate_c_node();
+  c_node->pc = encoded_callee;
+
+  if (caller_node != Val_unit) {
+    /* This is a tail call site.
+       Perform the initialization equivalent to that emitted by
+       [Spacetime.code_for_function_prologue] for direct tail call
+       sites. */
+    c_node->data.callee_node = Encode_tail_caller_node(caller_node);
+  }
+
+  *node_hole = caml_spacetime_stored_pointer_of_c_node(c_node);
+
+  Assert(((uintnat) *node_hole) % sizeof(value) == 0);
+  Assert(*node_hole != Val_unit);
+
+  last_indirect_node_hole_ptr_result = &(c_node->data.callee_node);
+
+  return last_indirect_node_hole_ptr_result;
+}
+
+/* Some notes on why caml_call_gc doesn't need a distinguished node.
+   (Remember that thread switches are irrelevant here because each thread
+   has its own trie.)
+
+   caml_call_gc only invokes OCaml functions in the following circumstances:
+   1. running an OCaml finaliser;
+   2. executing an OCaml signal handler.
+   Both of these are done on the finaliser trie.  Furthermore, both of
+   these invocations start via caml_callback; the code in this file for
+   handling that (caml_spacetime_c_to_ocaml) correctly copes with that by
+   attaching a single "caml_start_program" node that can cope with any
+   number of indirect OCaml calls from that point.
+
+   caml_call_gc may also invoke C functions that cause allocation.  All of
+   these (assuming libunwind support is present) will cause a chain of
+   c_node structures to be attached to the trie, starting at the node hole
+   passed to caml_call_gc from OCaml code.  These structures are extensible
+   and can thus accommodate any number of C backtraces leading from
+   caml_call_gc.
+*/
+/* CR-soon mshinwell: it might in fact be the case now that nothing called
+   from caml_call_gc will do any allocation that ends up on the trie.  We
+   can revisit this after the first release. */
+
+static NOINLINE void* find_trie_node_from_libunwind(int for_allocation,
+    uintnat wosize, struct ext_table** cached_frames)
+{
+#ifdef HAS_LIBUNWIND
+  /* Given that [caml_last_return_address] is the most recent call site in
+     OCaml code, and that we are now in C (or other) code called from that
+     site, obtain a backtrace using libunwind and graft the most recent
+     portion (everything back to but not including [caml_last_return_address])
+     onto the trie.  See the important comment below regarding the fact that
+     call site, and not callee, addresses are recorded during this process.
+
+     If [for_allocation] is non-zero, the final node recorded will be for
+     an allocation, and the returned pointer is to the allocation node.
+     Otherwise, no node is recorded for the innermost frame, and the
+     returned pointer is a pointer to the *node hole* where a node for that
+     frame should be attached.
+
+     If [for_allocation] is non-zero then [wosize] must give the size in
+     words, excluding the header, of the value being allocated.
+
+     If [cached_frames != NULL] then:
+     1. If [*cached_frames] is NULL then save the captured backtrace in a
+        newly-allocated table and store the pointer to that table in
+        [*cached_frames];
+     2. Otherwise use [*cached_frames] as the unwinding information.
+     The intention is that when the context is known (e.g. a function such
+     as [caml_make_vect] known to have been directly invoked from OCaml),
+     we can avoid expensive calls to libunwind.
+  */
+
+  unw_cursor_t cur;
+  unw_context_t ctx;
+  int ret;
+  int innermost_frame;
+  int frame;
+  static struct ext_table frames_local;
+  struct ext_table* frames;
+  static int ext_table_initialised = 0;
+  int have_frames_already = 0;
+  value* node_hole;
+  c_node* node = NULL;
+  int initial_table_size = 1000;
+  int must_initialise_node_for_allocation = 0;
+
+  if (!cached_frames) {
+    if (!ext_table_initialised) {
+      caml_ext_table_init(&frames_local, initial_table_size);
+      ext_table_initialised = 1;
+    }
+    else {
+      caml_ext_table_clear(&frames_local, 0);
+    }
+    frames = &frames_local;
+  } else {
+    if (*cached_frames) {
+      frames = *cached_frames;
+      have_frames_already = 1;
+    }
+    else {
+      frames = (struct ext_table*) malloc(sizeof(struct ext_table));
+      if (!frames) {
+        caml_fatal_error("Not enough memory for ext_table allocation");
+      }
+      caml_ext_table_init(frames, initial_table_size);
+      *cached_frames = frames;
+    }
+  }
+
+  if (!have_frames_already) {
+    /* Get the stack backtrace as far as [caml_last_return_address]. */
+
+    ret = unw_getcontext(&ctx);
+    if (ret != UNW_ESUCCESS) {
+      return NULL;
+    }
+
+    ret = unw_init_local(&cur, &ctx);
+    if (ret != UNW_ESUCCESS) {
+      return NULL;
+    }
+
+    while ((ret = unw_step(&cur)) > 0) {
+      unw_word_t ip;
+      unw_get_reg(&cur, UNW_REG_IP, &ip);
+      if (caml_last_return_address == (uintnat) ip) {
+        break;
+      }
+      else {
+        /* Inlined some of [caml_ext_table_add] for speed. */
+        if (frames->size < frames->capacity) {
+          frames->contents[frames->size++] = (void*) ip;
+        } else {
+          caml_ext_table_add(frames, (void*) ip);
+        }
+      }
+    }
+  }
+
+  /* We always need to ignore the frames for:
+      #0  find_trie_node_from_libunwind
+      #1  caml_spacetime_c_to_ocaml
+     Further, if this is not an allocation point, we should not create the
+     node for the current C function that triggered us (i.e. frame #2). */
+  innermost_frame = for_allocation ? 1 : 2;
+
+  if (frames->size - 1 < innermost_frame) {
+    /* Insufficiently many frames (maybe no frames) returned from
+       libunwind; just don't do anything. */
+    return NULL;
+  }
+
+  node_hole = caml_spacetime_trie_node_ptr;
+  /* Note that if [node_hole] is filled, then it must point to a C node,
+     since it is not possible for there to be a call point in an OCaml
+     function that sometimes calls C and sometimes calls OCaml. */
+
+  for (frame = frames->size - 1; frame >= innermost_frame; frame--) {
+    c_node_type expected_type;
+    void* pc = frames->contents[frame];
+    Assert (pc != (void*) caml_last_return_address);
+
+    if (!for_allocation) {
+      expected_type = CALL;
+    }
+    else {
+      expected_type = (frame > innermost_frame ? CALL : ALLOCATION);
+    }
+
+    if (*node_hole == Val_unit) {
+      node = allocate_c_node();
+      /* Note: for CALL nodes, the PC is the program counter at each call
+         site.  We do not store program counter addresses of the start of
+         callees, unlike for OCaml nodes.  This means that some trie nodes
+         will become conflated.  These can be split during post-processing by
+         working out which function each call site was in. */
+      node->pc = (expected_type == CALL ? Encode_c_node_pc_for_call(pc)
+        : Encode_c_node_pc_for_alloc_point(pc));
+      *node_hole = caml_spacetime_stored_pointer_of_c_node(node);
+      if (expected_type == ALLOCATION) {
+        must_initialise_node_for_allocation = 1;
+      }
+    }
+    else {
+      c_node* prev;
+      int found = 0;
+
+      node = caml_spacetime_c_node_of_stored_pointer_not_null(*node_hole);
+      Assert(node != NULL);
+      Assert(node->next == Val_unit
+        || (((uintnat) (node->next)) % sizeof(value) == 0));
+
+      prev = NULL;
+
+      while (!found && node != NULL) {
+        if (caml_spacetime_classify_c_node(node) == expected_type
+            && pc_inside_c_node_matches(node, pc)) {
+          found = 1;
+        }
+        else {
+          prev = node;
+          node = caml_spacetime_c_node_of_stored_pointer(node->next);
+        }
+      }
+      if (!found) {
+        Assert(prev != NULL);
+        node = allocate_c_node();
+        node->pc = (expected_type == CALL ? Encode_c_node_pc_for_call(pc)
+          : Encode_c_node_pc_for_alloc_point(pc));
+        if (expected_type == ALLOCATION) {
+          must_initialise_node_for_allocation = 1;
+        }
+        prev->next = caml_spacetime_stored_pointer_of_c_node(node);
+      }
+    }
+
+    Assert(node != NULL);
+
+    Assert(caml_spacetime_classify_c_node(node) == expected_type);
+    Assert(pc_inside_c_node_matches(node, pc));
+    node_hole = &node->data.callee_node;
+  }
+
+  if (must_initialise_node_for_allocation) {
+    caml_spacetime_profinfo++;
+    if (caml_spacetime_profinfo > PROFINFO_MASK) {
+      /* Profiling counter overflow. */
+      caml_spacetime_profinfo = PROFINFO_MASK;
+    }
+    node->data.allocation.profinfo =
+      Make_header_with_profinfo(
+        /* "-1" because [c_node] has the GC header as its first
+           element. */
+        offsetof(c_node, data.allocation.count)/sizeof(value) - 1,
+        Infix_tag,
+        Caml_black,
+        caml_spacetime_profinfo);
+    node->data.allocation.count = Val_long(0);
+
+    /* Add the new allocation point into the linked list of all allocation
+       points. */
+    if (caml_all_allocation_points != NULL) {
+      node->data.allocation.next =
+        (value) &caml_all_allocation_points->count;
+    } else {
+      node->data.allocation.next = Val_unit;
+    }
+    caml_all_allocation_points = &node->data.allocation;
+  }
+
+  if (for_allocation) {
+    Assert(caml_spacetime_classify_c_node(node) == ALLOCATION);
+    Assert(caml_spacetime_c_node_of_stored_pointer(node->next) != node);
+    Assert(Profinfo_hd(node->data.allocation.profinfo) > 0);
+    node->data.allocation.count =
+      Val_long(Long_val(node->data.allocation.count) + (1 + wosize));
+  }
+
+  Assert(node->next != (value) NULL);
+
+  return for_allocation ? (void*) node : (void*) node_hole;
+#else
+  return NULL;
+#endif
+}
+
+void caml_spacetime_c_to_ocaml(void* ocaml_entry_point,
+      void* identifying_pc_for_caml_start_program)
+{
+  /* Called in [caml_start_program] and [caml_callback*] when we are about
+     to cross from C into OCaml.  [ocaml_entry_point] is the branch target.
+     This situation is handled by ensuring the presence of a new OCaml node
+     for the callback veneer; the node contains a single indirect call point
+     which accumulates the [ocaml_entry_point]s.
+
+     The layout of the node is described in the "system shape table"; see
+     asmrun/amd64.S.
+  */
+
+  value node;
+
+  /* Update the trie with the current backtrace, as far back as
+     [caml_last_return_address], and leave the node hole pointer at
+     the correct place for attachment of a [caml_start_program] node. */
+
+#ifdef HAS_LIBUNWIND
+  value* node_temp;
+  node_temp = (value*) find_trie_node_from_libunwind(0, 0, NULL);
+  if (node_temp != NULL) {
+    caml_spacetime_trie_node_ptr = node_temp;
+  }
+#endif
+
+  if (*caml_spacetime_trie_node_ptr == Val_unit) {
+    uintnat size_including_header;
+
+    size_including_header =
+      1 /* GC header */ + Node_num_header_words + Indirect_num_fields;
+
+    node = allocate_uninitialized_ocaml_node(size_including_header);
+    Hd_val(node) =
+      Make_header(size_including_header - 1, OCaml_node_tag, Caml_black);
+    Assert((((uintnat) identifying_pc_for_caml_start_program) % 1) == 0);
+    Node_pc(node) = Encode_node_pc(identifying_pc_for_caml_start_program);
+    Tail_link(node) = node;
+    Indirect_pc_linked_list(node, Node_num_header_words) = Val_unit;
+    *caml_spacetime_trie_node_ptr = node;
+  }
+  else {
+    node = *caml_spacetime_trie_node_ptr;
+    /* If there is a node here already, it should never be an initialized
+       (but as yet unused) tail call point, since calls from OCaml into C
+       are never tail calls (and no C -> C call is marked as tail). */
+    Assert(!Is_tail_caller_node_encoded(node));
+  }
+
+  Assert(Is_ocaml_node(node));
+  Assert(Decode_node_pc(Node_pc(node))
+    == identifying_pc_for_caml_start_program);
+  Assert(Tail_link(node) == node);
+  Assert(Wosize_val(node) == Node_num_header_words + Indirect_num_fields);
+
+  /* Search the node to find the node hole corresponding to the indirect
+     call to the OCaml function. */
+  caml_spacetime_trie_node_ptr =
+    caml_spacetime_indirect_node_hole_ptr(
+      ocaml_entry_point,
+      &Indirect_pc_linked_list(node, Node_num_header_words),
+      Val_unit);
+  Assert(*caml_spacetime_trie_node_ptr == Val_unit
+    || Is_ocaml_node(*caml_spacetime_trie_node_ptr));
+}
+
+extern void caml_garbage_collection(void);  /* signals_asm.c */
+extern void caml_array_bound_error(void);  /* fail.c */
+
+CAMLprim uintnat caml_spacetime_generate_profinfo (void* profinfo_words,
+                                                   uintnat index_within_node)
+{
+  /* Called from code that creates a value's header inside an OCaml
+     function. */
+
+  value node;
+  uintnat profinfo;
+
+  caml_spacetime_profinfo++;
+  if (caml_spacetime_profinfo > PROFINFO_MASK) {
+    /* Profiling counter overflow. */
+    caml_spacetime_profinfo = PROFINFO_MASK;
+  }
+  profinfo = caml_spacetime_profinfo;
+
+  /* CR-someday mshinwell: we could always use the [struct allocation_point]
+     overlay instead of the macros now. */
+
+  /* [node] isn't really a node; it points into the middle of
+     one---specifically to the "profinfo" word of an allocation point.
+     It's done like this to avoid re-calculating the place in the node
+     (which already has to be done in the OCaml-generated code run before
+     this function). */
+  node = (value) profinfo_words;
+  Assert(Alloc_point_profinfo(node, 0) == Val_unit);
+
+  /* The profinfo value is stored shifted to reduce the number of
+     instructions required on the OCaml side.  It also enables us to use
+     [Infix_tag] to obtain valid value pointers into the middle of nodes,
+     which is used for the linked list of all allocation points. */
+  profinfo = Make_header_with_profinfo(
+    index_within_node, Infix_tag, Caml_black, profinfo);
+
+  Assert(!Is_block(profinfo));
+  Alloc_point_profinfo(node, 0) = profinfo;
+  /* The count is set to zero by the initialisation when the node was
+     created (see above). */
+  Assert(Alloc_point_count(node, 0) == Val_long(0));
+
+  /* Add the new allocation point into the linked list of all allocation
+     points. */
+  if (caml_all_allocation_points != NULL) {
+    Alloc_point_next_ptr(node, 0) = (value) &caml_all_allocation_points->count;
+  }
+  else {
+    Assert(Alloc_point_next_ptr(node, 0) == Val_unit);
+  }
+  caml_all_allocation_points = (allocation_point*) node;
+
+  return profinfo;
+}
+
+uintnat caml_spacetime_my_profinfo (struct ext_table** cached_frames,
+                                    uintnat wosize)
+{
+  /* Return the profinfo value that should be written into a value's header
+     during an allocation from C.  This may necessitate extending the trie
+     with information obtained from libunwind. */
+
+  c_node* node;
+  uintnat profinfo = 0;
+
+  node = find_trie_node_from_libunwind(1, wosize, cached_frames);
+  if (node != NULL) {
+    profinfo = ((uintnat) (node->data.allocation.profinfo)) >> PROFINFO_SHIFT;
+  }
+
+  return profinfo;  /* N.B. not shifted by PROFINFO_SHIFT */
+}
+
+void caml_spacetime_automatic_snapshot (void)
+{
+  if (automatic_snapshots) {
+    double start_time, end_time;
+    start_time = caml_sys_time_unboxed(Val_unit);
+    if (start_time >= next_snapshot_time) {
+      maybe_reopen_snapshot_channel();
+      caml_spacetime_save_snapshot(snapshot_channel, 0.0, 0);
+      end_time = caml_sys_time_unboxed(Val_unit);
+      next_snapshot_time = end_time + snapshot_interval;
+    }
+  }
+}
+
+CAMLprim value caml_spacetime_save_event_for_automatic_snapshots
+  (value v_event_name)
+{
+  if (automatic_snapshots) {
+    maybe_reopen_snapshot_channel();
+    caml_spacetime_save_event_internal (Val_unit, snapshot_channel,
+                                        v_event_name);
+  }
+  return Val_unit;
+}
+
+void caml_spacetime_automatic_save (void)
+{
+  /* Called from [atexit]. */
+
+  if (automatic_snapshots) {
+    automatic_snapshots = 0;
+    maybe_reopen_snapshot_channel();
+    save_trie(snapshot_channel, 0.0, 0);
+    caml_flush(snapshot_channel);
+    caml_close_channel(snapshot_channel);
+  }
+}
+
+CAMLprim value caml_spacetime_enabled (value v_unit)
+{
+  return Val_true;
+}
+
+CAMLprim value caml_register_channel_for_spacetime (value v_channel)
+{
+  struct channel* channel = Channel(v_channel);
+  channel->flags |= CHANNEL_FLAG_BLOCKING_WRITE;
+  return Val_unit;
+}
+
+#else
+
+/* Functions for when the compiler was not configured with "-spacetime". */
+
+CAMLprim value caml_spacetime_write_magic_number(value v_channel)
+{
+  return Val_unit;
+}
+
+CAMLprim value caml_spacetime_enabled (value v_unit)
+{
+  return Val_false;
+}
+
+CAMLprim value caml_spacetime_save_event (value v_time_opt,
+                                          value v_channel,
+                                          value v_event_name)
+{
+  return Val_unit;
+}
+
+CAMLprim value caml_spacetime_save_event_for_automatic_snapshots
+  (value v_event_name)
+{
+  return Val_unit;
+}
+
+CAMLprim value caml_spacetime_save_trie (value ignored)
+{
+  return Val_unit;
+}
+
+CAMLprim value caml_register_channel_for_spacetime (value v_channel)
+{
+  return Val_unit;
+}
+
+#endif
diff --git a/asmrun/spacetime.h b/asmrun/spacetime.h
new file mode 100644
index 0000000000..bb61bb3c37
--- /dev/null
+++ b/asmrun/spacetime.h
@@ -0,0 +1,191 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*            Mark Shinwell and Leo White, Jane Street Europe             */
+/*                                                                        */
+/*   Copyright 2013--2016, Jane Street Group, LLC                         */
+/*                                                                        */
+/*   All rights reserved.  This file is distributed under the terms of    */
+/*   the GNU Lesser General Public License version 2.1, with the          */
+/*   special exception on linking described in the file LICENSE.          */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef CAML_SPACETIME_H
+#define CAML_SPACETIME_H
+
+#include "caml/io.h"
+#include "caml/misc.h"
+#include "caml/stack.h"
+
+/* Runtime support for Spacetime profiling.
+ * This header file is not intended for the casual user.
+ *
+ * The implementation is split into three files:
+ *   1. spacetime.c: core management of the instrumentation;
+ *   2. spacetime_snapshot.c: the taking of heap snapshots;
+ *   3. spacetime_offline.c: functions that are also used when examining
+ *      saved profiling data.
+ */
+
+typedef enum {
+  CALL,
+  ALLOCATION
+} c_node_type;
+
+/* All pointers between nodes point at the word immediately after the
+   GC headers, and everything is traversable using the normal OCaml rules.
+
+   On entry to an OCaml function:
+   If the node hole pointer register has the bottom bit set, then the function
+   is being tail called or called from a self-recursive call site:
+   - If the node hole is empty, the callee must create a new node and link
+     it into the tail chain.  The node hole pointer will point at the tail
+     chain.
+   - Otherwise the node should be used as normal.
+   Otherwise (not a tail call):
+   - If the node hole is empty, the callee must create a new node, but the
+     tail chain is untouched.
+   - Otherwise the node should be used as normal.
+*/
+
+/* Classification of nodes (OCaml or C) with corresponding GC tags. */
+#define OCaml_node_tag 0
+#define C_node_tag 1
+#define Is_ocaml_node(node) (Is_block(node) && Tag_val(node) == OCaml_node_tag)
+#define Is_c_node(node) (Is_block(node) && Tag_val(node) == C_node_tag)
+
+/* The header words are:
+   1. The node program counter.
+   2. The tail link. */
+#define Node_num_header_words 2
+
+/* The "node program counter" at the start of an OCaml node. */
+#define Node_pc(node) (Field(node, 0))
+#define Encode_node_pc(pc) (((value) pc) | 1)
+#define Decode_node_pc(encoded_pc) ((void*) (encoded_pc & ~1))
+
+/* The circular linked list of tail-called functions within OCaml nodes. */
+#define Tail_link(node) (Field(node, 1))
+
+/* The convention for pointers from OCaml nodes to other nodes.  There are
+   two special cases:
+   1. [Val_unit] means "uninitialized", and further, that this is not a
+      tail call point.  (Tail call points are pre-initialized, as in case 2.)
+   2. If the bottom bit is set, and the value is not [Val_unit], this is a
+      tail call point. */
+#define Encode_tail_caller_node(node) ((node) | 1)
+#define Decode_tail_caller_node(node) ((node) & ~1)
+#define Is_tail_caller_node_encoded(node) (((node) & 1) == 1)
+
+/* Allocation points within OCaml nodes.
+   The "profinfo" value looks exactly like a black Infix_tag header.
+   This enables us to point just after it and return such pointer as a valid
+   OCaml value.  (Used for the list of all allocation points.  We could do
+   without this and instead just encode the list pointers as integers, but
+   this would mean that the structure was destroyed on marshalling.  This
+   might not be a great problem since it is intended that the total counts
+   be obtained via snapshots, but it seems neater and easier to use
+   Infix_tag.
+   The "count" is just an OCaml integer giving the total number of words
+   (including headers) allocated at the point.
+   The "pointer to next allocation point" points to the "count" word of the
+   next allocation point in the linked list of all allocation points.
+   There is no special encoding needed by virtue of the [Infix_tag] trick. */
+#define Alloc_point_profinfo(node, offset) (Field(node, offset))
+#define Alloc_point_count(node, offset) (Field(node, offset + 1))
+#define Alloc_point_next_ptr(node, offset) (Field(node, offset + 2))
+
+/* Direct call points (tail or non-tail) within OCaml nodes.
+   They just hold a pointer to the child node.  The call site and callee are
+   both recorded in the shape. */
+#define Direct_callee_node(node,offset) (Field(node, offset))
+#define Encode_call_point_pc(pc) (((value) pc) | 1)
+#define Decode_call_point_pc(pc) ((void*) (((value) pc) & ~((uintnat) 1)))
+
+/* Indirect call points (tail or non-tail) within OCaml nodes.
+   They hold a linked list of (PC upon entry to the callee, pointer to
+   child node) pairs.  The linked list is encoded using C nodes and should
+   be thought of as part of the OCaml node itself. */
+#define Indirect_num_fields 1
+#define Indirect_pc_linked_list(node,offset) (Field(node, offset))
+
+/* Encodings of the program counter value within a C node. */
+#define Encode_c_node_pc_for_call(pc) ((((value) pc) << 2) | 3)
+#define Encode_c_node_pc_for_alloc_point(pc) ((((value) pc) << 2) | 1)
+#define Decode_c_node_pc(pc) ((void*) (((uintnat) (pc)) >> 2))
+
+typedef struct {
+  /* The layout and encoding of this structure must match that of the
+     allocation points within OCaml nodes, so that the linked list
+     traversal across all allocation points works correctly. */
+  value profinfo;  /* encoded using [Infix_tag] (see above) */
+  value count;
+  /* [next] is [Val_unit] for the end of the list.
+     Otherwise it points at the second word of this [allocation_point]
+     structure. */
+  value next;
+} allocation_point;
+
+typedef struct {
+  /* CR-soon mshinwell: delete [gc_header], all the offset arithmetic will
+     then go away */
+  uintnat gc_header;
+  uintnat pc;           /* see above for encodings */
+  union {
+    value callee_node;  /* for CALL */
+    allocation_point allocation;  /* for ALLOCATION */
+  } data;
+  value next;           /* [Val_unit] for the end of the list */
+} c_node; /* CR-soon mshinwell: rename to dynamic_node */
+
+typedef struct shape_table {
+  uint64_t* table;
+  struct shape_table* next;
+} shape_table;
+
+extern uint64_t** caml_spacetime_static_shape_tables;
+extern shape_table* caml_spacetime_dynamic_shape_tables;
+
+typedef struct ext_table* spacetime_unwind_info_cache;
+
+extern value caml_spacetime_trie_root;
+extern value* caml_spacetime_trie_node_ptr;
+extern value* caml_spacetime_finaliser_trie_root;
+
+extern allocation_point* caml_all_allocation_points;
+
+extern void caml_spacetime_initialize(void);
+extern uintnat caml_spacetime_my_profinfo(
+  spacetime_unwind_info_cache*, uintnat);
+extern c_node_type caml_spacetime_classify_c_node(c_node* node);
+extern c_node* caml_spacetime_c_node_of_stored_pointer(value);
+extern c_node* caml_spacetime_c_node_of_stored_pointer_not_null(value);
+extern value caml_spacetime_stored_pointer_of_c_node(c_node* node);
+extern void caml_spacetime_register_thread(value*, value*);
+extern void caml_spacetime_register_shapes(void*);
+extern value caml_spacetime_frame_table(void);
+extern value caml_spacetime_shape_table(void);
+extern void caml_spacetime_save_snapshot (struct channel *chan,
+                                          double time_override,
+                                          int use_time_override);
+extern value caml_spacetime_timestamp(double time_override,
+                                      int use_time_override);
+extern void caml_spacetime_automatic_snapshot (void);
+
+/* For use in runtime functions that are executed from OCaml
+   code, to save the overhead of using libunwind every time. */
+#ifdef WITH_SPACETIME
+#define Get_my_profinfo_with_cached_backtrace(profinfo, size) \
+  do { \
+    static spacetime_unwind_info_cache spacetime_unwind_info = NULL; \
+    profinfo = caml_spacetime_my_profinfo(&spacetime_unwind_info, size); \
+  } \
+  while (0);
+#else
+#define Get_my_profinfo_with_cached_backtrace(profinfo, size) \
+  profinfo = (uintnat) 0;
+#endif
+
+#endif
diff --git a/asmrun/spacetime_offline.c b/asmrun/spacetime_offline.c
new file mode 100644
index 0000000000..221c6a6608
--- /dev/null
+++ b/asmrun/spacetime_offline.c
@@ -0,0 +1,228 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*            Mark Shinwell and Leo White, Jane Street Europe             */
+/*                                                                        */
+/*   Copyright 2013--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.          */
+/*                                                                        */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "caml/alloc.h"
+#include "caml/config.h"
+#include "caml/fail.h"
+#include "caml/gc.h"
+#include "caml/intext.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/roots.h"
+#include "caml/signals.h"
+#include "caml/stack.h"
+#include "caml/sys.h"
+#include "spacetime.h"
+
+#include "../config/s.h"
+
+#ifdef ARCH_SIXTYFOUR
+
+/* CR-someday lwhite: The following two definitions are copied from spacetime.c
+   because they are needed here, but must be inlined in spacetime.c
+   for performance. Perhaps a macro or "static inline" would be
+   more appropriate. */
+
+c_node* caml_spacetime_offline_c_node_of_stored_pointer_not_null
+          (value node_stored)
+{
+  Assert(Is_c_node(node_stored));
+  return (c_node*) Hp_val(node_stored);
+}
+
+c_node_type caml_spacetime_offline_classify_c_node(c_node* node)
+{
+  return (node->pc & 2) ? CALL : ALLOCATION;
+}
+
+CAMLprim value caml_spacetime_compare_node(
+      value node1, value node2)
+{
+  Assert(!Is_in_value_area(node1));
+  Assert(!Is_in_value_area(node2));
+
+  if (node1 == node2) {
+    return Val_long(0);
+  }
+  if (node1 < node2) {
+    return Val_long(-1);
+  }
+  return Val_long(1);
+}
+
+CAMLprim value caml_spacetime_unmarshal_trie (value v_channel)
+{
+  return caml_input_value_to_outside_heap(v_channel);
+}
+
+CAMLprim value caml_spacetime_node_num_header_words(value unit)
+{
+  unit = Val_unit;
+  return Val_long(Node_num_header_words);
+}
+
+CAMLprim value caml_spacetime_is_ocaml_node(value node)
+{
+  Assert(Is_ocaml_node(node) || Is_c_node(node));
+  return Val_bool(Is_ocaml_node(node));
+}
+
+CAMLprim value caml_spacetime_ocaml_function_identifier(value node)
+{
+  Assert(Is_ocaml_node(node));
+  return caml_copy_int64((uint64_t) Decode_node_pc(Node_pc(node)));
+}
+
+CAMLprim value caml_spacetime_ocaml_tail_chain(value node)
+{
+  Assert(Is_ocaml_node(node));
+  return Tail_link(node);
+}
+
+CAMLprim value caml_spacetime_classify_direct_call_point
+      (value node, value offset)
+{
+  uintnat field;
+  value callee_node;
+
+  Assert(Is_ocaml_node(node));
+
+  field = Long_val(offset);
+
+  callee_node = Direct_callee_node(node, field);
+  if (!Is_block(callee_node)) {
+    /* An unused call point (may be a tail call point). */
+    return Val_long(0);
+  } else if (Is_ocaml_node(callee_node)) {
+    return Val_long(1);  /* direct call point to OCaml code */
+  } else {
+    return Val_long(2);  /* direct call point to non-OCaml code */
+  }
+}
+
+CAMLprim value caml_spacetime_ocaml_allocation_point_annotation
+      (value node, value offset)
+{
+  uintnat profinfo_shifted;
+  profinfo_shifted = (uintnat) Alloc_point_profinfo(node, Long_val(offset));
+  return Val_long(Profinfo_hd(profinfo_shifted));
+}
+
+CAMLprim value caml_spacetime_ocaml_allocation_point_count
+      (value node, value offset)
+{
+  value count = Alloc_point_count(node, Long_val(offset));
+  Assert(!Is_block(count));
+  return count;
+}
+
+CAMLprim value caml_spacetime_ocaml_direct_call_point_callee_node
+      (value node, value offset)
+{
+  return Direct_callee_node(node, Long_val(offset));
+}
+
+CAMLprim value caml_spacetime_ocaml_indirect_call_point_callees
+      (value node, value offset)
+{
+  value callees = Indirect_pc_linked_list(node, Long_val(offset));
+  Assert(Is_block(callees));
+  Assert(Is_c_node(callees));
+  return callees;
+}
+
+CAMLprim value caml_spacetime_c_node_is_call(value node)
+{
+  c_node* c_node;
+  Assert(node != (value) NULL);
+  Assert(Is_c_node(node));
+  c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
+  switch (caml_spacetime_offline_classify_c_node(c_node)) {
+    case CALL: return Val_true;
+    case ALLOCATION: return Val_false;
+  }
+  Assert(0);
+  return Val_unit;  /* silence compiler warning */
+}
+
+CAMLprim value caml_spacetime_c_node_next(value node)
+{
+  c_node* c_node;
+
+  Assert(node != (value) NULL);
+  Assert(Is_c_node(node));
+  c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
+  Assert(c_node->next == Val_unit || Is_c_node(c_node->next));
+  return c_node->next;
+}
+
+CAMLprim value caml_spacetime_c_node_call_site(value node)
+{
+  c_node* c_node;
+  Assert(node != (value) NULL);
+  Assert(Is_c_node(node));
+  c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
+  return caml_copy_int64((uint64_t) Decode_c_node_pc(c_node->pc));
+}
+
+CAMLprim value caml_spacetime_c_node_callee_node(value node)
+{
+  c_node* c_node;
+  Assert(node != (value) NULL);
+  Assert(Is_c_node(node));
+  c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
+  Assert(caml_spacetime_offline_classify_c_node(c_node) == CALL);
+  /* This might be an uninitialised tail call point: for example if an OCaml
+     callee was indirectly called but the callee wasn't instrumented (e.g. a
+     leaf function that doesn't allocate). */
+  if (Is_tail_caller_node_encoded(c_node->data.callee_node)) {
+    return Val_unit;
+  }
+  return c_node->data.callee_node;
+}
+
+CAMLprim value caml_spacetime_c_node_profinfo(value node)
+{
+  c_node* c_node;
+  Assert(node != (value) NULL);
+  Assert(Is_c_node(node));
+  c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
+  Assert(caml_spacetime_offline_classify_c_node(c_node) == ALLOCATION);
+  Assert(!Is_block(c_node->data.allocation.profinfo));
+  return Val_long(Profinfo_hd(c_node->data.allocation.profinfo));
+}
+
+CAMLprim value caml_spacetime_c_node_allocation_count(value node)
+{
+  c_node* c_node;
+  Assert(node != (value) NULL);
+  Assert(Is_c_node(node));
+  c_node = caml_spacetime_offline_c_node_of_stored_pointer_not_null(node);
+  Assert(caml_spacetime_offline_classify_c_node(c_node) == ALLOCATION);
+  Assert(!Is_block(c_node->data.allocation.count));
+  return c_node->data.allocation.count;
+}
+
+#endif
diff --git a/asmrun/spacetime_snapshot.c b/asmrun/spacetime_snapshot.c
new file mode 100644
index 0000000000..9c582a83a5
--- /dev/null
+++ b/asmrun/spacetime_snapshot.c
@@ -0,0 +1,600 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*            Mark Shinwell and Leo White, Jane Street Europe             */
+/*                                                                        */
+/*   Copyright 2013--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.          */
+/*                                                                        */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "caml/alloc.h"
+#include "caml/backtrace_prim.h"
+#include "caml/config.h"
+#include "caml/custom.h"
+#include "caml/fail.h"
+#include "caml/gc.h"
+#include "caml/gc_ctrl.h"
+#include "caml/intext.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/roots.h"
+#include "caml/signals.h"
+#include "caml/stack.h"
+#include "caml/sys.h"
+#include "spacetime.h"
+
+#ifdef WITH_SPACETIME
+
+/* The following structures must match the type definitions in the
+   [Spacetime] module. */
+
+typedef struct {
+  /* (GC header here.) */
+  value minor_words;
+  value promoted_words;
+  value major_words;
+  value minor_collections;
+  value major_collections;
+  value heap_words;
+  value heap_chunks;
+  value compactions;
+  value top_heap_words;
+} gc_stats;
+
+typedef struct {
+  value profinfo;
+  value num_blocks;
+  value num_words_including_headers;
+} snapshot_entry;
+
+typedef struct {
+  /* (GC header here.) */
+  snapshot_entry entries[0];
+} snapshot_entries;
+
+typedef struct {
+  /* (GC header here.) */
+  value time;
+  value gc_stats;
+  value entries;
+  value words_scanned;
+  value words_scanned_with_profinfo;
+  value total_allocations;
+} snapshot;
+
+typedef struct {
+  uintnat num_blocks;
+  uintnat num_words_including_headers;
+} raw_snapshot_entry;
+
+static value allocate_outside_heap_with_tag(mlsize_t size_in_bytes, tag_t tag)
+{
+  /* CR-soon mshinwell: this function should live somewhere else */
+  header_t* block;
+
+  Assert(size_in_bytes % sizeof(value) == 0);
+  block = caml_stat_alloc(sizeof(header_t) + size_in_bytes);
+  *block = Make_header(size_in_bytes / sizeof(value), tag, Caml_black);
+  return (value) &block[1];
+}
+
+static value allocate_outside_heap(mlsize_t size_in_bytes)
+{
+  Assert(size_in_bytes > 0);
+  return allocate_outside_heap_with_tag(size_in_bytes, 0);
+}
+
+static value take_gc_stats(void)
+{
+  value v_stats;
+  gc_stats* stats;
+
+  v_stats = allocate_outside_heap(sizeof(gc_stats));
+  stats = (gc_stats*) v_stats;
+
+  stats->minor_words = Val_long(caml_stat_minor_words);
+  stats->promoted_words = Val_long(caml_stat_promoted_words);
+  stats->major_words =
+    Val_long(((uintnat) caml_stat_major_words)
+             + ((uintnat) caml_allocated_words));
+  stats->minor_collections = Val_long(caml_stat_minor_collections);
+  stats->major_collections = Val_long(caml_stat_major_collections);
+  stats->heap_words = Val_long(caml_stat_heap_wsz / sizeof(value));
+  stats->heap_chunks = Val_long(caml_stat_heap_chunks);
+  stats->compactions = Val_long(caml_stat_compactions);
+  stats->top_heap_words = Val_long(caml_stat_top_heap_wsz / sizeof(value));
+
+  return v_stats;
+}
+
+static value get_total_allocations(void)
+{
+  value v_total_allocations = Val_unit;
+  allocation_point* total = caml_all_allocation_points;
+
+  while (total != NULL) {
+    value v_total;
+    v_total = allocate_outside_heap_with_tag(3 * sizeof(value), 0);
+
+    /* [v_total] is of type [Raw_spacetime_lib.total_allocations]. */
+    Field(v_total, 0) = Val_long(Profinfo_hd(total->profinfo));
+    Field(v_total, 1) = total->count;
+    Field(v_total, 2) = v_total_allocations;
+    v_total_allocations = v_total;
+
+    Assert (total->next == Val_unit
+      || (Is_block(total->next) && Tag_val(total->next) == Infix_tag));
+    if (total->next == Val_unit) {
+      total = NULL;
+    }
+    else {
+      total = (allocation_point*) Hp_val(total->next);
+    }
+  }
+
+  return v_total_allocations;
+}
+
+static value take_snapshot(double time_override, int use_time_override)
+{
+  value v_snapshot;
+  snapshot* heap_snapshot;
+  value v_entries;
+  snapshot_entries* entries;
+  char* chunk;
+  value gc_stats;
+  uintnat index;
+  uintnat target_index;
+  value v_time;
+  double time;
+  uintnat profinfo;
+  uintnat num_distinct_profinfos;
+  /* Fixed size buffer to avoid needing a hash table: */
+  static raw_snapshot_entry* raw_entries = NULL;
+  uintnat words_scanned = 0;
+  uintnat words_scanned_with_profinfo = 0;
+  value v_total_allocations;
+
+  if (!use_time_override) {
+    time = caml_sys_time_unboxed(Val_unit);
+  }
+  else {
+    time = time_override;
+  }
+
+  gc_stats = take_gc_stats();
+
+  if (raw_entries == NULL) {
+    size_t size = (PROFINFO_MASK + 1) * sizeof(raw_snapshot_entry);
+    raw_entries = caml_stat_alloc(size);
+    memset(raw_entries, '\0', size);
+  } else {
+    size_t size = (PROFINFO_MASK + 1) * sizeof(raw_snapshot_entry);
+    memset(raw_entries, '\0', size);
+  }
+
+  num_distinct_profinfos = 0;
+
+  /* CR-someday mshinwell: consider reintroducing minor heap scanning,
+     properly from roots, which would then give a snapshot function
+     that doesn't do a minor GC.  Although this may not be that important
+     and potentially not worth the effort (it's quite tricky). */
+
+  /* Scan the major heap. */
+  chunk = caml_heap_start;
+  while (chunk != NULL) {
+    char* hp;
+    char* limit;
+
+    hp = chunk;
+    limit = chunk + Chunk_size (chunk);
+
+    while (hp < limit) {
+      header_t hd = Hd_hp (hp);
+      switch (Color_hd(hd)) {
+        case Caml_blue:
+          break;
+
+        default:
+          if (Wosize_hd(hd) > 0) { /* ignore atoms */
+            profinfo = Profinfo_hd(hd);
+            words_scanned += Whsize_hd(hd);
+            if (profinfo > 0 && profinfo < PROFINFO_MASK) {
+              words_scanned_with_profinfo += Whsize_hd(hd);
+              Assert (raw_entries[profinfo].num_blocks >= 0);
+              if (raw_entries[profinfo].num_blocks == 0) {
+                num_distinct_profinfos++;
+              }
+              raw_entries[profinfo].num_blocks++;
+              raw_entries[profinfo].num_words_including_headers +=
+                Whsize_hd(hd);
+            }
+          }
+          break;
+      }
+      hp += Bhsize_hd (hd);
+      Assert (hp <= limit);
+    }
+
+    chunk = Chunk_next (chunk);
+  }
+
+  if (num_distinct_profinfos > 0) {
+    v_entries = allocate_outside_heap(
+      num_distinct_profinfos*sizeof(snapshot_entry));
+    entries = (snapshot_entries*) v_entries;
+    target_index = 0;
+    for (index = 0; index <= PROFINFO_MASK; index++) {
+      Assert(raw_entries[index].num_blocks >= 0);
+      if (raw_entries[index].num_blocks > 0) {
+        Assert(target_index < num_distinct_profinfos);
+        entries->entries[target_index].profinfo = Val_long(index);
+        entries->entries[target_index].num_blocks
+          = Val_long(raw_entries[index].num_blocks);
+        entries->entries[target_index].num_words_including_headers
+          = Val_long(raw_entries[index].num_words_including_headers);
+        target_index++;
+      }
+    }
+  } else {
+    v_entries = Atom(0);
+  }
+
+  Assert(sizeof(double) == sizeof(value));
+  v_time = allocate_outside_heap_with_tag(sizeof(double), Double_tag);
+  Double_field(v_time, 0) = time;
+
+  v_snapshot = allocate_outside_heap(sizeof(snapshot));
+  heap_snapshot = (snapshot*) v_snapshot;
+
+  v_total_allocations = get_total_allocations();
+
+  heap_snapshot->time = v_time;
+  heap_snapshot->gc_stats = gc_stats;
+  heap_snapshot->entries = v_entries;
+  heap_snapshot->words_scanned
+    = Val_long(words_scanned);
+  heap_snapshot->words_scanned_with_profinfo
+    = Val_long(words_scanned_with_profinfo);
+  heap_snapshot->total_allocations = v_total_allocations;
+
+  return v_snapshot;
+}
+
+void caml_spacetime_save_snapshot (struct channel *chan, double time_override,
+                                   int use_time_override)
+{
+  value v_snapshot;
+  value v_total_allocations;
+  snapshot* heap_snapshot;
+
+  Lock(chan);
+
+  v_snapshot = take_snapshot(time_override, use_time_override);
+
+  caml_output_val(chan, Val_long(0), Val_long(0));
+
+  caml_extern_allow_out_of_heap = 1;
+  caml_output_val(chan, v_snapshot, Val_long(0));
+  caml_extern_allow_out_of_heap = 0;
+
+  Unlock(chan);
+
+  heap_snapshot = (snapshot*) v_snapshot;
+  caml_stat_free(Hp_val(heap_snapshot->time));
+  caml_stat_free(Hp_val(heap_snapshot->gc_stats));
+  if (Wosize_val(heap_snapshot->entries) > 0) {
+    caml_stat_free(Hp_val(heap_snapshot->entries));
+  }
+  v_total_allocations = heap_snapshot->total_allocations;
+  while (v_total_allocations != Val_unit) {
+    value next = Field(v_total_allocations, 2);
+    caml_stat_free(Hp_val(v_total_allocations));
+    v_total_allocations = next;
+  }
+
+  caml_stat_free(Hp_val(v_snapshot));
+}
+
+CAMLprim value caml_spacetime_take_snapshot(value v_time_opt, value v_channel)
+{
+  struct channel * channel = Channel(v_channel);
+  double time_override = 0.0;
+  int use_time_override = 0;
+
+  if (Is_block(v_time_opt)) {
+    time_override = Double_field(Field(v_time_opt, 0), 0);
+    use_time_override = 1;
+  }
+
+  caml_spacetime_save_snapshot(channel, time_override, use_time_override);
+
+  return Val_unit;
+}
+
+extern struct custom_operations caml_int64_ops;  /* ints.c */
+
+static value
+allocate_int64_outside_heap(uint64_t i)
+{
+  value v;
+
+  v = allocate_outside_heap_with_tag(2 * sizeof(value), Custom_tag);
+  Custom_ops_val(v) = &caml_int64_ops;
+  Int64_val(v) = i;
+
+  return v;
+}
+
+static value
+copy_string_outside_heap(char const *s)
+{
+  int len;
+  mlsize_t wosize, offset_index;
+  value result;
+
+  len = strlen(s);
+  wosize = (len + sizeof (value)) / sizeof (value);
+  result = allocate_outside_heap_with_tag(wosize * sizeof(value), String_tag);
+
+  Field (result, wosize - 1) = 0;
+  offset_index = Bsize_wsize (wosize) - 1;
+  Byte (result, offset_index) = offset_index - len;
+  memmove(String_val(result), s, len);
+
+  return result;
+}
+
+static value
+allocate_loc_outside_heap(struct caml_loc_info li)
+{
+  value result;
+
+  if (li.loc_valid) {
+    result = allocate_outside_heap_with_tag(5 * sizeof(value), 0);
+    Field(result, 0) = Val_bool(li.loc_is_raise);
+    Field(result, 1) = copy_string_outside_heap(li.loc_filename);
+    Field(result, 2) = Val_int(li.loc_lnum);
+    Field(result, 3) = Val_int(li.loc_startchr);
+    Field(result, 4) = Val_int(li.loc_endchr);
+  } else {
+    result = allocate_outside_heap_with_tag(sizeof(value), 1);
+    Field(result, 0) = Val_bool(li.loc_is_raise);
+  }
+
+  return result;
+}
+
+value caml_spacetime_timestamp(double time_override, int use_time_override)
+{
+  double time;
+  value v_time;
+
+  if (!use_time_override) {
+    time = caml_sys_time_unboxed(Val_unit);
+  }
+  else {
+    time = time_override;
+  }
+
+  v_time = allocate_outside_heap_with_tag(sizeof(double), Double_tag);
+  Double_field(v_time, 0) = time;
+
+  return v_time;
+}
+
+value caml_spacetime_frame_table(void)
+{
+  /* Flatten the frame table into a single associative list. */
+
+  value list = Val_long(0);  /* the empty list */
+  uintnat i;
+
+  if (!caml_debug_info_available()) {
+    return list;
+  }
+
+  if (caml_frame_descriptors == NULL) {
+    caml_init_frame_descriptors();
+  }
+
+  for (i = 0; i <= caml_frame_descriptors_mask; i++) {
+    frame_descr* descr = caml_frame_descriptors[i];
+    if (descr != NULL) {
+      value location, return_address, pair, new_list_element, location_list;
+      struct caml_loc_info li;
+      debuginfo dbg;
+      if (descr->frame_size != 0xffff) {
+        dbg = caml_debuginfo_extract(descr);
+        if (dbg != NULL) {
+          location_list = Val_unit;
+          while (dbg != NULL) {
+            value list_element;
+
+            caml_debuginfo_location(dbg, &li);
+            location = allocate_loc_outside_heap(li);
+
+            list_element =
+              allocate_outside_heap_with_tag(2 * sizeof(value), 0 /* (::) */);
+            Field(list_element, 0) = location;
+            Field(list_element, 1) = location_list;
+            location_list = list_element;
+
+            dbg = caml_debuginfo_next(dbg);
+          }
+
+          return_address = allocate_int64_outside_heap(descr->retaddr);
+          pair = allocate_outside_heap_with_tag(2 * sizeof(value), 0);
+          Field(pair, 0) = return_address;
+          Field(pair, 1) = location_list;
+
+          new_list_element =
+            allocate_outside_heap_with_tag(2 * sizeof(value), 0 /* (::) */);
+          Field(new_list_element, 0) = pair;
+          Field(new_list_element, 1) = list;
+          list = new_list_element;
+        }
+      }
+    }
+  }
+
+  return list;
+}
+
+static void add_unit_to_shape_table(uint64_t *unit_table, value *list)
+{
+  /* This function reverses the order of the lists giving the layout of each
+     node; however, spacetime_profiling.ml ensures they are emitted in
+     reverse order, so at the end of it all they're not reversed. */
+
+  uint64_t* ptr = unit_table;
+
+  while (*ptr != (uint64_t) 0) {
+    value new_list_element, pair, function_address, layout;
+
+    function_address =
+      allocate_int64_outside_heap(*ptr++);
+
+    layout = Val_long(0);  /* the empty list */
+    while (*ptr != (uint64_t) 0) {
+      int tag;
+      int stored_tag;
+      value part_of_shape;
+      value new_part_list_element;
+      value location;
+      int has_extra_argument = 0;
+
+      stored_tag = *ptr++;
+      /* CR-soon mshinwell: share with emit.mlp */
+      switch (stored_tag) {
+        case 1:  /* direct call to given location */
+          tag = 0;
+          has_extra_argument = 1;  /* the address of the callee */
+          break;
+
+        case 2:  /* indirect call to given location */
+          tag = 1;
+          break;
+
+        case 3:  /* allocation at given location */
+          tag = 2;
+          break;
+
+        default:
+          Assert(0);
+          abort();  /* silence compiler warning */
+      }
+
+      location = allocate_int64_outside_heap(*ptr++);
+
+      part_of_shape = allocate_outside_heap_with_tag(
+        sizeof(value) * (has_extra_argument ? 2 : 1), tag);
+      Field(part_of_shape, 0) = location;
+      if (has_extra_argument) {
+        Field(part_of_shape, 1) =
+          allocate_int64_outside_heap(*ptr++);
+      }
+
+      new_part_list_element =
+        allocate_outside_heap_with_tag(2 * sizeof(value), 0 /* (::) */);
+      Field(new_part_list_element, 0) = part_of_shape;
+      Field(new_part_list_element, 1) = layout;
+      layout = new_part_list_element;
+    }
+
+    pair = allocate_outside_heap_with_tag(2 * sizeof(value), 0);
+    Field(pair, 0) = function_address;
+    Field(pair, 1) = layout;
+
+    new_list_element =
+      allocate_outside_heap_with_tag(2 * sizeof(value), 0 /* (::) */);
+    Field(new_list_element, 0) = pair;
+    Field(new_list_element, 1) = *list;
+    *list = new_list_element;
+
+    ptr++;
+  }
+}
+
+value caml_spacetime_shape_table(void)
+{
+  value list;
+  uint64_t* unit_table;
+  shape_table *dynamic_table;
+  uint64_t** static_table;
+
+  /* Flatten the hierarchy of shape tables into a single associative list
+     mapping from function symbols to node layouts.  The node layouts are
+     themselves lists. */
+
+  list = Val_long(0);  /* the empty list */
+
+  /* Add static shape tables */
+  static_table = caml_spacetime_static_shape_tables;
+  while (*static_table != (uint64_t) 0) {
+    unit_table = *static_table++;
+    add_unit_to_shape_table(unit_table, &list);
+  }
+
+  /* Add dynamic shape tables */
+  dynamic_table = caml_spacetime_dynamic_shape_tables;
+
+  while (dynamic_table != NULL) {
+    unit_table = dynamic_table->table;
+    add_unit_to_shape_table(unit_table, &list);
+    dynamic_table = dynamic_table->next;
+  }
+
+  return list;
+}
+
+#else
+
+static value spacetime_disabled()
+{
+  caml_failwith("Spacetime profiling not enabled");
+  Assert(0);  /* unreachable */
+}
+
+CAMLprim value caml_spacetime_take_snapshot(value ignored)
+{
+  return Val_unit;
+}
+
+CAMLprim value caml_spacetime_marshal_frame_table ()
+{
+  return spacetime_disabled();
+}
+
+CAMLprim value caml_spacetime_frame_table ()
+{
+  return spacetime_disabled();
+}
+
+CAMLprim value caml_spacetime_marshal_shape_table ()
+{
+  return spacetime_disabled();
+}
+
+CAMLprim value caml_spacetime_shape_table ()
+{
+  return spacetime_disabled();
+}
+
+#endif
diff --git a/asmrun/sparc.S b/asmrun/sparc.S
index 7f24b4b42d..b46e71f048 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/startup.c b/asmrun/startup.c
index 7822d7801a..fc46ac421e 100644
--- a/asmrun/startup.c
+++ b/asmrun/startup.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Start-up code */
 
@@ -32,6 +36,9 @@
 #include "caml/sys.h"
 #include "caml/params.h"
 #include "caml/fiber.h"
+#ifdef WITH_SPACETIME
+#include "spacetime.h"
+#endif
 #ifdef HAS_UI
 #include "caml/ui.h"
 #endif
@@ -74,14 +81,13 @@ extern value caml_start_program (char*);
 extern void caml_init_ieee_floats (void);
 extern void caml_init_signals (void);
 
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
 
 /* PR 4887: avoid crash box of windows runtime on some system calls */
 extern void caml_install_invalid_parameter_handler();
 
 #endif
 
-
 void caml_main(char **argv)
 {
   char * exe_name;
@@ -92,8 +98,11 @@ void caml_main(char **argv)
   CAML_INIT_DOMAIN_STATE;
 
   caml_init_startup_params();
+#ifdef WITH_SPACETIME
+  caml_spacetime_initialize();
+#endif
   caml_init_ieee_floats();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
   caml_install_invalid_parameter_handler();
 #endif
   caml_init_custom_operations();
@@ -107,6 +116,7 @@ void caml_main(char **argv)
 
   init_segments();
   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 30c5866b7c..0000000000
--- 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 fedf0e3d73..ff858b7528 100755
Binary files a/boot/ocamlc and b/boot/ocamlc differ
diff --git a/boot/ocamldep b/boot/ocamldep
index afcf8b9ce0..ad1eefda62 100755
Binary files a/boot/ocamldep and b/boot/ocamldep differ
diff --git a/boot/ocamllex b/boot/ocamllex
index 3ced3a4c48..cdf5453d85 100755
Binary files a/boot/ocamllex and b/boot/ocamllex differ
diff --git a/bytecomp/.ignore b/bytecomp/.ignore
deleted file mode 100644
index d2f18a85a9..0000000000
--- a/bytecomp/.ignore
+++ /dev/null
@@ -1,2 +0,0 @@
-runtimedef.ml
-opcodes.ml
diff --git a/bytecomp/bytegen.ml b/bytecomp/bytegen.ml
index a8e5b521c3..9f6c5cf61b 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
 
@@ -133,32 +136,41 @@ type rhs_kind =
 
 let rec check_recordwith_updates id e =
   match e with
-  | Lsequence (Lprim ((Psetfield _ | Psetfloatfield _), [Lvar id2; _]), cont)
+  | Lsequence (Lprim ((Psetfield _ | Psetfloatfield _), [Lvar id2; _], _), cont)
       -> id2 = id && check_recordwith_updates id cont
   | Lvar id2 -> id2 = id
   | _ -> false
 ;;
 
 let rec size_of_lambda = function
-  | 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)
+  | Lfunction{params} as funct ->
+      RHS_function (1 + IdentSet.cardinal(free_variables funct),
+                    List.length params)
+  | Llet (Strict, _k, 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_unboxed _ -> assert false
       | 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) ->
+  | Llet(_str, _k, _id, _arg, body) -> size_of_lambda body
+  | Lletrec(_bindings, body) -> size_of_lambda body
+  | Lprim(Pmakeblock _, args, _) -> RHS_block (List.length 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 (Pduprecord (Record_float, size), args) -> RHS_floatblock size
+  | Lprim (Pmakearray (Pfloatarray, _), args, _) ->
+      RHS_floatblock (List.length args)
+  | Lprim (Pmakearray (Pgenarray, _), _, _) -> assert false
+  | Lprim (Pduprecord ((Record_regular | Record_inlined _), size), _, _) ->
+      RHS_block size
+  | Lprim (Pduprecord (Record_unboxed _, _), _, _) ->
+      assert false
+  | Lprim (Pduprecord (Record_extension, size), _, _) ->
+      RHS_block (size + 1)
+  | Lprim (Pduprecord (Record_float, size), _, _) -> RHS_floatblock size
   | Levent (lam, _) -> size_of_lambda lam
-  | Lsequence (lam, lam') -> size_of_lambda lam'
+  | Lsequence (_lam, lam') -> size_of_lambda lam'
   | _ -> RHS_nonrec
 
 (**** Merging consecutive events ****)
@@ -304,23 +316,23 @@ let comp_primitive p sz args =
     Pgetglobal id -> Kgetglobal id
   | Psetglobal id -> Ksetglobal id
   | Pintcomp cmp -> Kintcomp cmp
-  | Pmakeblock(tag, mut) -> Kmakeblock(List.length args, tag)
-  | Pfield(n, ptr, Immutable) -> Kgetfield n
-  | Pfield(n, ptr, Mutable) -> Kgetmutablefield n
-  | Psetfield(n, ptr, mut) -> Ksetfield n
+  | Pmakeblock(tag, _mut, _) -> Kmakeblock(List.length args, tag)
+  | Pfield(n, _ptr, Immutable) -> Kgetfield n
+  | Pfield(n, _ptr, Mutable) -> Kgetmutablefield 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)
-  | Pperform loc ->
+  | Pperform ->
       check_stack (sz + 4);
       Kperform
   | Pnegint -> Knegint
   | Paddint -> Kaddint
   | Psubint -> Ksubint
   | Pmulint -> Kmulint
-  | Pdivint -> Kdivint
-  | Pmodint -> Kmodint
+  | Pdivint _ -> Kdivint
+  | Pmodint _ -> Kmodint
   | Pandint -> Kandint
   | Porint -> Korint
   | Pxorint -> Kxorint
@@ -344,17 +356,19 @@ let comp_primitive p sz args =
   | Pfloatcomp Cle -> Kccall("caml_le_float", 2)
   | Pfloatcomp Cge -> Kccall("caml_ge_float", 2)
   | Pstringlength -> Kccall("caml_ml_string_length", 1)
+  | Pbyteslength -> Kccall("caml_ml_bytes_length", 1)
   | Pstringrefs -> Kccall("caml_string_get", 2)
-  | Pstringsets -> Kccall("caml_string_set", 3)
-  | Pstringrefu -> Kgetstringchar
-  | Pstringsetu -> Ksetstringchar
+  | Pbytesrefs -> Kccall("caml_bytes_get", 2)
+  | Pbytessets -> Kccall("caml_bytes_set", 3)
+  | Pstringrefu | Pbytesrefu -> Kgetstringchar
+  | Pbytessetu -> Ksetstringchar
   | Pstring_load_16(_) -> Kccall("caml_string_get16", 2)
   | Pstring_load_32(_) -> Kccall("caml_string_get32", 2)
   | Pstring_load_64(_) -> Kccall("caml_string_get64", 2)
   | Pstring_set_16(_) -> Kccall("caml_string_set16", 3)
   | Pstring_set_32(_) -> Kccall("caml_string_set32", 3)
   | Pstring_set_64(_) -> Kccall("caml_string_set64", 3)
-  | Parraylength kind -> Kvectlength
+  | Parraylength _ -> Kvectlength
   | Parrayrefs Pgenarray -> Kccall("caml_array_get", 2)
   | Parrayrefs Pfloatarray -> Kccall("caml_array_get_float", 2)
   | Parrayrefs _ -> Kccall("caml_array_get_addr", 2)
@@ -371,9 +385,12 @@ let comp_primitive p sz 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
+       | Ostype_cygwin -> "ostype_cygwin"
+       | Backend_type -> "backend_type" in
      Kccall(Printf.sprintf "caml_sys_const_%s" const_name, 1)
   | Pisint -> Kisint
   | Pisout -> Kisout
@@ -390,20 +407,20 @@ let comp_primitive p sz args =
   | Paddbint bi -> comp_bint_primitive bi "add" args
   | Psubbint bi -> comp_bint_primitive bi "sub" args
   | Pmulbint bi -> comp_bint_primitive bi "mul" args
-  | Pdivbint bi -> comp_bint_primitive bi "div" args
-  | Pmodbint bi -> comp_bint_primitive bi "mod" args
+  | Pdivbint (bi, _) -> comp_bint_primitive bi "div" args
+  | Pmodbint (bi, _) -> comp_bint_primitive bi "mod" args
   | Pandbint bi -> comp_bint_primitive bi "and" args
   | Porbint bi -> comp_bint_primitive bi "or" args
   | Pxorbint bi -> comp_bint_primitive bi "xor" args
   | Plslbint bi -> comp_bint_primitive bi "shift_left" args
   | Plsrbint bi -> comp_bint_primitive bi "shift_right_unsigned" args
   | Pasrbint bi -> comp_bint_primitive bi "shift_right" args
-  | Pbintcomp(bi, Ceq) -> Kccall("caml_equal", 2)
-  | Pbintcomp(bi, Cneq) -> Kccall("caml_notequal", 2)
-  | Pbintcomp(bi, Clt) -> Kccall("caml_lessthan", 2)
-  | Pbintcomp(bi, Cgt) -> Kccall("caml_greaterthan", 2)
-  | Pbintcomp(bi, Cle) -> Kccall("caml_lessequal", 2)
-  | Pbintcomp(bi, Cge) -> Kccall("caml_greaterequal", 2)
+  | Pbintcomp(_, Ceq) -> Kccall("caml_equal", 2)
+  | Pbintcomp(_, Cneq) -> Kccall("caml_notequal", 2)
+  | Pbintcomp(_, Clt) -> Kccall("caml_lessthan", 2)
+  | Pbintcomp(_, Cgt) -> Kccall("caml_greaterthan", 2)
+  | Pbintcomp(_, Cle) -> Kccall("caml_lessequal", 2)
+  | Pbintcomp(_, Cge) -> Kccall("caml_greaterequal", 2)
   | Pbigarrayref(_, n, _, _) -> Kccall("caml_ba_get_" ^ string_of_int n, n + 1)
   | Pbigarrayset(_, n, _, _) -> Kccall("caml_ba_set_" ^ string_of_int n, n + 2)
   | Pbigarraydim(n) -> Kccall("caml_ba_dim_" ^ string_of_int n, 1)
@@ -456,7 +473,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
@@ -496,7 +513,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{params; body} -> (* assume kind = Curried *)
       let lbl = new_label() in
       let fv = IdentSet.elements(free_variables exp) in
       let to_compile =
@@ -505,21 +522,21 @@ let rec comp_expr env exp sz cont =
       Stack.push to_compile functions_to_compile;
       comp_args env (List.map (fun n -> Lvar n) fv) sz
         (Kclosure(lbl, List.length fv) :: cont)
-  | Llet(str, id, arg, body) ->
+  | Llet(_str, _k, id, arg, body) ->
       comp_expr env arg sz
         (Kpush :: comp_expr (add_var id (sz+1) env) body (sz+1)
           (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 =
           IdentSet.elements (free_variables (Lletrec(decl, lambda_unit))) in
-        let rec_idents = List.map (fun (id, lam) -> id) decl in
+        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{params; body}) :: rem ->
               let lbl = new_label() in
               let to_compile =
                 { params = params; body = body; label = lbl; free_vars = fv;
@@ -537,57 +554,65 @@ let rec comp_expr env exp sz cont =
           List.map (fun (id, exp) -> (id, exp, size_of_lambda exp)) decl in
         let rec comp_init new_env sz = function
           | [] -> comp_nonrec new_env sz ndecl decl_size
-          | (id, exp, RHS_floatblock blocksize) :: rem ->
+          | (id, _exp, RHS_floatblock blocksize) :: rem ->
               Kconst(Const_base(Const_int blocksize)) ::
               Kccall("caml_alloc_dummy_float", 1) :: Kpush ::
               comp_init (add_var id (sz+1) new_env) (sz+1) rem
-          | (id, exp, RHS_block blocksize) :: rem ->
+          | (id, _exp, RHS_block blocksize) :: rem ->
               Kconst(Const_base(Const_int blocksize)) ::
               Kccall("caml_alloc_dummy", 1) :: Kpush ::
               comp_init (add_var id (sz+1) new_env) (sz+1) rem
-          | (id, exp, RHS_function (blocksize,arity)) :: rem ->
+          | (id, _exp, RHS_function (blocksize,arity)) :: rem ->
               Kconst(Const_base(Const_int arity)) ::
               Kpush ::
               Kconst(Const_base(Const_int blocksize)) ::
               Kccall("caml_alloc_dummy_function", 2) :: Kpush ::
               comp_init (add_var id (sz+1) new_env) (sz+1) rem
-          | (id, exp, RHS_nonrec) :: rem ->
+          | (id, _exp, RHS_nonrec) :: rem ->
               Kconst(Const_base(Const_int 0)) :: Kpush ::
               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 ->
+          | (_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)
-          | (id, exp, RHS_nonrec) :: rem ->
+          | (_id, _exp, RHS_nonrec) :: rem ->
               comp_rec new_env sz (i-1) rem
         in
         comp_init env sz decl_size
       end
-  | Lprim(Pidentity, [arg]) ->
+  | Lprim((Pidentity | Popaque | Pbytes_to_string | Pbytes_of_string), [arg], _)
+    ->
       comp_expr env arg sz cont
-  | Lprim(Pignore, [arg]) ->
+  | 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
+  | Lprim(Pdirapply, [func;arg], loc)
+  | Lprim(Prevapply, [arg;func], loc) ->
+      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]) ->
+  | Lprim(Pnot, [arg], _) ->
       let newcont =
         match cont with
           Kbranchif lbl :: cont1 -> Kbranchifnot lbl :: cont1
         | Kbranchifnot lbl :: cont1 -> Kbranchif lbl :: cont1
         | _ -> Kboolnot :: cont in
       comp_expr env arg sz newcont
-  | Lprim(Psequand, [exp1; exp2]) ->
+  | Lprim(Psequand, [exp1; exp2], _) ->
       begin match cont with
         Kbranchifnot lbl :: _ ->
           comp_expr env exp1 sz (Kbranchifnot lbl ::
@@ -601,7 +626,7 @@ let rec comp_expr env exp sz cont =
           comp_expr env exp1 sz (Kstrictbranchifnot lbl ::
             comp_expr env exp2 sz cont1)
       end
-  | Lprim(Psequor, [exp1; exp2]) ->
+  | Lprim(Psequor, [exp1; exp2], _) ->
       begin match cont with
         Kbranchif lbl :: _ ->
           comp_expr env exp1 sz (Kbranchif lbl ::
@@ -615,21 +640,21 @@ let rec comp_expr env exp sz cont =
           comp_expr env exp1 sz (Kstrictbranchif lbl ::
             comp_expr env exp2 sz cont1)
       end
-  | Lprim(Praise k, [arg]) ->
+  | Lprim(Praise k, [arg], _) ->
       comp_expr env arg sz (Kraise k :: discard_dead_code cont)
-  | Lprim(Paddint, [arg; Lconst(Const_base(Const_int n))])
+  | Lprim(Paddint, [arg; Lconst(Const_base(Const_int n))], _)
     when is_immed n ->
       comp_expr env arg sz (Koffsetint n :: cont)
-  | Lprim(Psubint, [arg; Lconst(Const_base(Const_int n))])
+  | Lprim(Psubint, [arg; Lconst(Const_base(Const_int n))], _)
     when is_immed (-n) ->
       comp_expr env arg sz (Koffsetint (-n) :: cont)
-  | Lprim (Poffsetint n, [arg])
+  | Lprim (Poffsetint n, [arg], _)
     when not (is_immed n) ->
       comp_expr env arg sz
         (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)
@@ -642,7 +667,7 @@ let rec comp_expr env exp sz cont =
                  (Kmakeblock(List.length args, 0) ::
                   Kccall("caml_make_array", 1) :: cont)
       end
-  | Lprim(Presume loc, args) ->
+  | Lprim(Presume, args, _) ->
       let nargs = List.length args - 1 in
       assert (nargs = 2);
       check_stack (sz + 3);
@@ -651,7 +676,7 @@ let rec comp_expr env exp sz cont =
           (Kresumeterm(sz + nargs) :: discard_dead_code cont)
       else
         comp_args env args sz (Kresume :: cont)
-  | Lprim(Preperform, args) ->
+  | Lprim(Preperform, args, _) ->
       let nargs = List.length args - 1 in
       assert (nargs = 1);
       check_stack (sz + 3);
@@ -660,14 +685,24 @@ let rec comp_expr env exp sz cont =
           (Kreperformterm(sz + nargs) :: discard_dead_code cont)
       else
         fatal_error "Reperform used in non-tail position"
-
+  | Lprim (Pduparray (kind, mutability),
+           [Lprim (Pmakearray (kind',_),args,_)], loc) ->
+      assert (kind = kind');
+      comp_expr env (Lprim (Pmakearray (kind, mutability), args, loc)) sz cont
+  | Lprim (Pduparray _, [arg], loc) ->
+      let prim_obj_dup =
+        Primitive.simple ~name:"caml_obj_dup" ~arity:1 ~alloc:true
+      in
+      comp_expr env (Lprim (Pccall prim_obj_dup, [arg], loc)) 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)]) ->
+  | Lprim (Pintcomp c, [arg ; (Lconst _ as k)], _) ->
       let p = Pintcomp (commute_comparison c)
       and args = [k ; arg] in
       let nargs = List.length args - 1 in
       comp_args env args sz (comp_primitive p (sz + nargs - 1) args :: cont)
-  | Lprim(p, args) ->
+  | Lprim(p, args, _) ->
       let nargs = List.length args - 1 in
       comp_args env args sz (comp_primitive p (sz + nargs - 1) args :: cont)
   | Lstaticcatch (body, (i, vars) , handler) ->
@@ -794,8 +829,8 @@ let rec comp_expr env exp sz cont =
         lbl_consts.(i) <- lbls.(act_consts.(i))
       done;
       comp_expr env arg sz (Kswitch(lbl_consts, lbl_blocks) :: !c)
-  | Lstringswitch (arg,sw,d) ->
-      comp_expr env (Matching.expand_stringswitch arg sw d) sz cont
+  | Lstringswitch (arg,sw,d,loc) ->
+      comp_expr env (Matching.expand_stringswitch loc arg sw d) sz cont
   | Lassign(id, expr) ->
       begin try
         let pos = Ident.find_same id env.ce_stack in
@@ -837,12 +872,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
@@ -900,18 +939,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 24f1d64f32..b23a1dc6bf 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 7c96dfd0e7..e89676a9e2 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 b9a4ced849..04a0316a8f 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 2f5c0ec478..714a4f4485 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
 
@@ -26,6 +29,7 @@ type error =
   | File_exists of string
   | Cannot_open_dll of string
   | Not_compatible_32
+  | Required_module_unavailable of string
 
 exception Error of error
 
@@ -50,7 +54,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,27 +86,30 @@ 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
 
-let is_required (rel, pos) =
+let is_required (rel, _pos) =
   match rel with
     Reloc_setglobal id ->
       IdentSet.mem id !missing_globals
   | _ -> false
 
-let add_required (rel, pos) =
+let add_required compunit =
+  let add_required_by_reloc (rel, _pos) =
   match rel with
     Reloc_getglobal id ->
       missing_globals := IdentSet.add id !missing_globals
   | _ -> ()
-
-let remove_required (rel, pos) =
+  in
+  let add_required_for_effects id =
+    missing_globals := IdentSet.add id !missing_globals
+  in
+  List.iter add_required_by_reloc compunit.cu_reloc;
+  List.iter add_required_for_effects compunit.cu_required_globals
+
+let remove_required (rel, _pos) =
   match rel with
     Reloc_setglobal id ->
       missing_globals := IdentSet.remove id !missing_globals
@@ -123,7 +132,8 @@ let scan_file obj_name tolink =
       seek_in ic compunit_pos;
       let compunit = (input_value ic : compilation_unit) in
       close_in ic;
-      List.iter add_required compunit.cu_reloc;
+      add_required compunit;
+      List.iter remove_required compunit.cu_reloc;
       Link_object(file_name, compunit) :: tolink
     end
     else if buffer = cma_magic_number then begin
@@ -141,8 +151,8 @@ let scan_file obj_name tolink =
             || !Clflags.link_everything
             || List.exists is_required compunit.cu_reloc
             then begin
+              add_required compunit;
               List.iter remove_required compunit.cu_reloc;
-              List.iter add_required compunit.cu_reloc;
               compunit :: reqd
             end else
               reqd)
@@ -537,6 +547,14 @@ let link ppf objfiles output_name =
     else if !Clflags.output_c_object then "stdlib.cma" :: objfiles
     else "stdlib.cma" :: (objfiles @ ["std_exit.cmo"]) in
   let tolink = List.fold_right scan_file objfiles [] in
+  let missing_modules =
+    IdentSet.filter (fun id -> not (Ident.is_predef_exn id)) !missing_globals
+  in
+  begin
+    match IdentSet.elements missing_modules with
+    | [] -> ()
+    | id :: _ -> raise (Error (Required_module_unavailable (Ident.name id)))
+  end;
   Clflags.ccobjs := !Clflags.ccobjs @ !lib_ccobjs; (* put user's libs last *)
   Clflags.all_ccopts := !lib_ccopts @ !Clflags.all_ccopts;
                                                    (* put user's opts first *)
@@ -595,7 +613,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;
@@ -652,6 +671,8 @@ let report_error ppf = function
   | Not_compatible_32 ->
       fprintf ppf "Generated bytecode executable cannot be run\
                   \ on a 32-bit platform"
+  | Required_module_unavailable s ->
+      fprintf ppf "Required module `%s' is unavailable" s
 
 let () =
   Location.register_error_of_exn
diff --git a/bytecomp/bytelink.mli b/bytecomp/bytelink.mli
index 37dad2b526..42084fe7aa 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. *)
 
@@ -30,6 +33,7 @@ type error =
   | File_exists of string
   | Cannot_open_dll of string
   | Not_compatible_32
+  | Required_module_unavailable of string
 
 exception Error of error
 
diff --git a/bytecomp/bytepackager.ml b/bytecomp/bytepackager.ml
index d8493ab322..2afe83e0be 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
@@ -183,7 +186,7 @@ let rec rename_append_bytecode_list ppf packagename oc mapping defined ofs
 let build_global_target oc target_name members mapping pos coercion =
   let components =
     List.map2
-      (fun m (id1, id2) ->
+      (fun m (_id1, id2) ->
         match m.pm_kind with
         | PM_intf -> None
         | PM_impl _ -> Some id2)
@@ -204,6 +207,24 @@ let build_global_target oc target_name members mapping pos coercion =
 let package_object_files ppf files targetfile targetname coercion =
   let members =
     map_left_right read_member_info files in
+  let required_globals =
+    List.fold_right (fun compunit required_globals -> match compunit with
+        | { pm_kind = PM_intf } ->
+            required_globals
+        | { pm_kind = PM_impl { cu_required_globals; cu_reloc } } ->
+            let remove_required (rel, _pos) required_globals =
+              match rel with
+                Reloc_setglobal id ->
+                  Ident.Set.remove id required_globals
+              | _ ->
+                  required_globals
+            in
+            let required_globals =
+              List.fold_right remove_required cu_reloc required_globals
+            in
+            List.fold_right Ident.Set.add cu_required_globals required_globals)
+      members Ident.Set.empty
+  in
   let unit_names =
     List.map (fun m -> m.pm_name) members in
   let mapping =
@@ -229,7 +250,7 @@ let package_object_files ppf files targetfile targetname coercion =
     let pos_final = pos_out oc in
     let imports =
       List.filter
-        (fun (name, crc) -> not (List.mem name unit_names))
+        (fun (name, _crc) -> not (List.mem name unit_names))
         (Bytelink.extract_crc_interfaces()) in
     let compunit =
       { cu_name = targetname;
@@ -239,6 +260,7 @@ let package_object_files ppf files targetfile targetname coercion =
         cu_imports =
           (targetname, Some (Env.crc_of_unit targetname)) :: imports;
         cu_primitives = !primitives;
+        cu_required_globals = Ident.Set.elements required_globals;
         cu_force_link = !force_link;
         cu_debug = if pos_final > pos_debug then pos_debug else 0;
         cu_debugsize = pos_final - pos_debug } in
@@ -265,8 +287,7 @@ let package_files ppf initial_env files targetfile =
     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 69e3c77acb..c856b632ce 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 759bde3b29..2beb0761b3 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 *)
 
@@ -91,7 +94,7 @@ let read_section_struct ic name =
 
 let pos_first_section ic =
   in_channel_length ic - 16 - 8 * List.length !section_table -
-  List.fold_left (fun total (name, len) -> total + len) 0 !section_table
+  List.fold_left (fun total (_name, len) -> total + len) 0 !section_table
 
 let reset () =
   section_table := [];
diff --git a/bytecomp/bytesections.mli b/bytecomp/bytesections.mli
index 12e679d73f..22e1a3bb6a 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 0c0f08f080..7fbb35a04d 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 *)
 
@@ -29,6 +32,9 @@ type compilation_unit =
     cu_reloc: (reloc_info * int) list;  (* Relocation information *)
     cu_imports:
       (string * Digest.t option) list; (* Names and CRC of intfs imported *)
+    cu_required_globals: Ident.t list; (* Compilation units whose initialization
+                                          side effects must occur before this
+                                          one. *)
     cu_primitives: string list;         (* Primitives declared inside *)
     mutable cu_force_link: bool;        (* Must be linked even if unref'ed *)
     mutable cu_debug: int;              (* Position of debugging info, or 0 *)
diff --git a/bytecomp/dll.ml b/bytecomp/dll.ml
index 21688e08ee..c64f43cf8f 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 878ffb919e..485035ea85 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 5e91a86049..955c457220 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
 
@@ -367,7 +371,7 @@ let rec emit = function
 
 (* Emission to a file *)
 
-let to_file outchan unit_name objfile code =
+let to_file outchan unit_name objfile ~required_globals code =
   init();
   output_string outchan cmo_magic_number;
   let pos_depl = pos_out outchan in
@@ -394,6 +398,7 @@ let to_file outchan unit_name objfile code =
       cu_imports = Env.imports();
       cu_primitives = List.map Primitive.byte_name
                                !Translmod.primitive_declarations;
+      cu_required_globals = Ident.Set.elements required_globals;
       cu_force_link = false;
       cu_debug = pos_debug;
       cu_debugsize = size_debug } in
@@ -415,8 +420,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 e2fdb81551..a2cf3d8b72 100644
--- a/bytecomp/emitcode.mli
+++ b/bytecomp/emitcode.mli
@@ -1,35 +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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
 open Cmo_format
 open Instruct
 
-val to_file: out_channel -> string -> string -> instruction list -> unit
+val to_file: out_channel -> string -> string ->
+  required_globals:Ident.Set.t -> instruction list -> unit
         (* Arguments:
              channel on output file
              name of compilation unit implemented
              path of cmo file being written
+             required_globals: list of compilation units that must be
+               evaluated before this one
              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 c3b542d30e..0ed2864c73 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 8f06971b36..883f33bba0 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 cadd12bf65..3e3a84012d 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,9 +20,12 @@ open Asttypes
 type compile_time_constant =
   | Big_endian
   | Word_size
+  | Int_size
+  | Max_wosize
   | Ostype_unix
   | Ostype_win32
   | Ostype_cygwin
+  | Backend_type
 
 type loc_kind =
   | Loc_FILE
@@ -28,27 +34,41 @@ type loc_kind =
   | Loc_LOC
   | Loc_POS
 
+type immediate_or_pointer =
+  | Immediate
+  | Pointer
+
+type initialization_or_assignment =
+  | Initialization
+  | Assignment
+
+type is_safe =
+  | Safe
+  | Unsafe
+
 type primitive =
-    Pidentity
+  | Pidentity
+  | Pbytes_to_string
+  | Pbytes_of_string
   | Pignore
-  | Prevapply of Location.t
-  | Pdirapply of Location.t
+  | Prevapply
+  | Pdirapply
   | Ploc of loc_kind
     (* Globals *)
   | Pgetglobal of Ident.t
   | Psetglobal of Ident.t
   (* Operations on heap blocks *)
-  | Pmakeblock of int * mutable_flag
-  | Pfield of int * bool * mutable_flag
-  | Psetfield of int * bool * mutable_flag
+  | Pmakeblock of int * mutable_flag * block_shape
+  | Pfield of int * immediate_or_pointer * mutable_flag
+  | 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
   (* Context switches *)
-  | Pperform of Location.t
-  | Presume of Location.t
+  | Pperform
+  | Presume
   | Preperform
   (* External call *)
   | Pccall of Primitive.description
@@ -57,7 +77,8 @@ type primitive =
   (* Boolean operations *)
   | Psequand | Psequor | Pnot
   (* Integer operations *)
-  | Pnegint | Paddint | Psubint | Pmulint | Pdivint | Pmodint
+  | Pnegint | Paddint | Psubint | Pmulint
+  | Pdivint of is_safe | Pmodint of is_safe
   | Pandint | Porint | Pxorint
   | Plslint | Plsrint | Pasrint
   | Pintcomp of comparison
@@ -69,9 +90,11 @@ type primitive =
   | Paddfloat | Psubfloat | Pmulfloat | Pdivfloat
   | Pfloatcomp of comparison
   (* String operations *)
-  | Pstringlength | Pstringrefu | Pstringsetu | Pstringrefs | Pstringsets
+  | Pstringlength | Pstringrefu  | Pstringrefs
+  | Pbyteslength | Pbytesrefu | Pbytessetu | Pbytesrefs | Pbytessets
   (* 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
@@ -91,8 +114,8 @@ type primitive =
   | Paddbint of boxed_integer
   | Psubbint of boxed_integer
   | Pmulbint of boxed_integer
-  | Pdivbint of boxed_integer
-  | Pmodbint of boxed_integer
+  | Pdivbint of boxed_integer * is_safe
+  | Pmodbint of boxed_integer * is_safe
   | Pandbint of boxed_integer
   | Porbint of boxed_integer
   | Pxorbint of boxed_integer
@@ -131,14 +154,22 @@ type primitive =
   | Patomic_load
   | Patomic_store
   | Patomic_cas
+  (* Inhibition of optimisation *)
+  | Popaque
 
 and comparison =
     Ceq | Cneq | Clt | Cgt | Cle | Cge
 
+and value_kind =
+    Pgenval | Pfloatval | Pboxedintval of boxed_integer | Pintval
+
+and block_shape =
+  value_kind list option
+
 and array_kind =
     Pgenarray | Paddrarray | Pintarray | Pfloatarray
 
-and boxed_integer =
+and boxed_integer = Primitive.boxed_integer =
     Pnativeint | Pint32 | Pint64
 
 and bigarray_kind =
@@ -167,6 +198,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
@@ -175,16 +217,23 @@ 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
-  | Llet of let_kind * Ident.t * lambda * lambda
+  | Lapply of lambda_apply
+  | Lfunction of lfunction
+  | Llet of let_kind * value_kind * Ident.t * lambda * lambda
   | Lletrec of (Ident.t * lambda) list * lambda
-  | Lprim of primitive * lambda list
+  | Lprim of primitive * lambda list * Location.t
   | Lswitch of lambda * lambda_switch
-  | Lstringswitch of lambda * (string * lambda) list * lambda option
+  | Lstringswitch of
+      lambda * (string * lambda) list * lambda option * Location.t
   | Lstaticraise of int * lambda list
   | Lstaticcatch of lambda * (int * Ident.t list) * lambda
   | Ltrywith of lambda * Ident.t * lambda
@@ -197,6 +246,21 @@ 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 *)
+    loc: Location.t; }
+
+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;
@@ -214,11 +278,24 @@ and lambda_event_kind =
     Lev_before
   | Lev_after of Types.type_expr
   | Lev_function
+  | Lev_pseudo
+
+type program =
+  { module_ident : Ident.t;
+    main_module_block_size : int;
+    required_globals : Ident.Set.t;
+    code : lambda }
 
 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.
@@ -242,29 +319,34 @@ 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)
-    | Llet (Alias,x,ex,e) -> (* Ignore aliases -> substitute *)
+    | 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,_k,x,ex,e) -> (* Ignore aliases -> substitute *)
         let ex = tr_rec env ex in
         tr_rec (Ident.add x ex env) e
-    | Llet (str,x,ex,e) ->
+    | Llet ((Strict | StrictOpt),_k,x,ex,Lvar v) when Ident.same v x ->
+        tr_rec env ex
+    | Llet (str,k,x,ex,e) ->
      (* Because of side effects, keep other lets with normalized names *)
         let ex = tr_rec env ex in
         let y = make_key x in
-        Llet (str,y,ex,tr_rec (Ident.add x (Lvar y) env) e)
-    | Lprim (p,es) ->
-        Lprim (p,tr_recs env es)
+        Llet (str,k,y,ex,tr_rec (Ident.add x (Lvar y) env) e)
+    | Lprim (p,es,_) ->
+        Lprim (p,tr_recs env es, Location.none)
     | Lswitch (e,sw) ->
         Lswitch (tr_rec env e,tr_sw env sw)
-    | Lstringswitch (e,sw,d) ->
+    | Lstringswitch (e,sw,d,_) ->
         Lstringswitch
           (tr_rec env e,
            List.map (fun (s,e) -> s,tr_rec env e) sw,
-           tr_opt env d)
+           tr_opt env d,
+          Location.none)
     | Lstaticraise (i,es) ->
         Lstaticraise (i,tr_recs env es)
     | Lstaticcatch (e1,xs,e2) ->
@@ -277,7 +359,7 @@ let make_key e =
         Lsequence (tr_rec env e1,tr_rec env e2)
     | Lassign (x,e) ->
         Lassign (x,tr_rec env e)
-    | Lsend (m,e1,e2,es,loc) ->
+    | Lsend (m,e1,e2,es,_loc) ->
         Lsend (m,tr_rec env e1,tr_rec env e2,tr_recs env es,Location.none)
     | Lifused (id,e) -> Lifused (id,tr_rec env e)
     | Lletrec _|Lfunction _
@@ -308,16 +390,16 @@ let make_key e =
 let name_lambda strict arg fn =
   match arg with
     Lvar id -> fn id
-  | _ -> let id = Ident.create "let" in Llet(strict, id, arg, fn id)
+  | _ -> let id = Ident.create "let" in Llet(strict, Pgenval, id, arg, fn id)
 
 let name_lambda_list args fn =
   let rec name_list names = function
     [] -> fn (List.rev names)
-  | (Lvar id as arg) :: rem ->
+  | (Lvar _ as arg) :: rem ->
       name_list (arg :: names) rem
   | arg :: rem ->
       let id = Ident.create "let" in
-      Llet(Strict, id, arg, name_list (Lvar id :: names) rem) in
+      Llet(Strict, Pgenval, id, arg, name_list (Lvar id :: names) rem) in
   name_list [] args
 
 
@@ -328,31 +410,31 @@ 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{body} ->
       f body
-  | Llet(str, id, arg, body) ->
+  | Llet(_str, _k, _id, arg, body) ->
       f arg; f body
   | Lletrec(decl, body) ->
       f body;
-      List.iter (fun (id, exp) -> f exp) decl
-  | Lprim(p, args) ->
+      List.iter (fun (_id, exp) -> f exp) decl
+  | Lprim(_p, args, _loc) ->
       List.iter f args
   | Lswitch(arg, sw) ->
       f arg;
-      List.iter (fun (key, case) -> f case) sw.sw_consts;
-      List.iter (fun (key, case) -> f case) sw.sw_blocks;
+      List.iter (fun (_key, case) -> f case) sw.sw_consts;
+      List.iter (fun (_key, case) -> f case) sw.sw_blocks;
       iter_opt f sw.sw_failaction
-  | Lstringswitch (arg,cases,default) ->
+  | Lstringswitch (arg,cases,default,_) ->
       f arg ;
       List.iter (fun (_,act) -> f act) cases ;
       iter_opt f default
   | Lstaticraise (_,args) ->
       List.iter f args
-  | Lstaticcatch(e1, (_,vars), e2) ->
+  | Lstaticcatch(e1, _, e2) ->
       f e1; f e2
-  | Ltrywith(e1, exn, e2) ->
+  | Ltrywith(e1, _, e2) ->
       f e1; f e2
   | Lifthenelse(e1, e2, e3) ->
       f e1; f e2; f e3
@@ -360,23 +442,19 @@ let iter f = function
       f e1; f e2
   | Lwhile(e1, e2) ->
       f e1; f e2
-  | Lfor(v, e1, e2, dir, e3) ->
+  | Lfor(_v, e1, e2, _dir, e3) ->
       f e1; f e2; f e3
-  | Lassign(id, e) ->
+  | Lassign(_, e) ->
       f e
-  | Lsend (k, met, obj, args, _) ->
+  | Lsend (_k, met, obj, args, _) ->
       List.iter f (met::obj::args)
-  | Levent (lam, evt) ->
+  | Levent (lam, _evt) ->
       f lam
-  | Lifused (v, e) ->
+  | Lifused (_v, e) ->
       f e
 
 
-module IdentSet =
-  Set.Make(struct
-    type t = Ident.t
-    let compare = compare
-  end)
+module IdentSet = Set.Make(Ident)
 
 let free_ids get l =
   let fv = ref IdentSet.empty in
@@ -384,19 +462,19 @@ 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{params} ->
         List.iter (fun param -> fv := IdentSet.remove param !fv) params
-    | Llet(str, id, arg, body) ->
+    | Llet(_str, _k, id, _arg, _body) ->
         fv := IdentSet.remove id !fv
-    | Lletrec(decl, body) ->
-        List.iter (fun (id, exp) -> fv := IdentSet.remove id !fv) decl
-    | Lstaticcatch(e1, (_,vars), e2) ->
+    | Lletrec(decl, _body) ->
+        List.iter (fun (id, _exp) -> fv := IdentSet.remove id !fv) decl
+    | Lstaticcatch(_e1, (_,vars), _e2) ->
         List.iter (fun id -> fv := IdentSet.remove id !fv) vars
-    | Ltrywith(e1, exn, e2) ->
+    | Ltrywith(_e1, exn, _e2) ->
         fv := IdentSet.remove exn !fv
-    | Lfor(v, e1, e2, dir, e3) ->
+    | Lfor(v, _e1, _e2, _dir, _e3) ->
         fv := IdentSet.remove v !fv
-    | Lassign(id, e) ->
+    | Lassign(id, _e) ->
         fv := IdentSet.add id !fv
     | Lvar _ | Lconst _ | Lapply _
     | Lprim _ | Lswitch _ | Lstringswitch _ | Lstaticraise _
@@ -408,7 +486,7 @@ let free_variables l =
   free_ids (function Lvar id -> [id] | _ -> []) l
 
 let free_methods l =
-  free_ids (function Lsend(Self, Lvar meth, obj, _, _) -> [meth] | _ -> []) l
+  free_ids (function Lsend(Self, Lvar meth, _, _, _) -> [meth] | _ -> []) l
 
 (* Check if an action has a "when" guard *)
 let raise_count = ref 0
@@ -427,16 +505,16 @@ let next_negative_raise_count () =
 let staticfail = Lstaticraise (0,[])
 
 let rec is_guarded = function
-  | Lifthenelse( cond, body, Lstaticraise (0,[])) -> true
-  | Llet(str, id, lam, body) -> is_guarded body
-  | Levent(lam, ev) -> is_guarded lam
+  | Lifthenelse(_cond, _body, Lstaticraise (0,[])) -> true
+  | Llet(_str, _k, _id, _lam, body) -> is_guarded body
+  | Levent(lam, _ev) -> is_guarded lam
   | _ -> false
 
 let rec patch_guarded patch = function
   | Lifthenelse (cond, body, Lstaticraise (0,[])) ->
       Lifthenelse (cond, body, patch)
-  | Llet(str, id, lam, body) ->
-      Llet (str, id, lam, patch_guarded patch body)
+  | Llet(str, k, id, lam, body) ->
+      Llet (str, k, id, lam, patch_guarded patch body)
   | Levent(lam, ev) ->
       Levent (patch_guarded patch lam, ev)
   | _ -> fatal_error "Lambda.patch_guarded"
@@ -445,10 +523,12 @@ let rec patch_guarded patch = function
 
 let rec transl_normal_path = function
     Pident id ->
-      if Ident.global id then Lprim(Pgetglobal id, []) else Lvar id
-  | Pdot(p, s, pos) ->
-      Lprim(Pfield(pos, true, Immutable), [transl_normal_path p])
-  | Papply(p1, p2) ->
+      if Ident.global id
+      then Lprim(Pgetglobal id, [], Location.none)
+      else Lvar id
+  | Pdot(p, _s, pos) ->
+      Lprim(Pfield(pos, Pointer, Immutable), [transl_normal_path p], Location.none)
+  | Papply _ ->
       fatal_error "Lambda.transl_path"
 
 (* Translation of value identifiers *)
@@ -474,20 +554,23 @@ let subst_lambda s lam =
   let rec subst = function
     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)
-  | Llet(str, id, arg, body) -> Llet(str, id, subst arg, subst body)
+  | Lconst _ as l -> l
+  | Lapply ap ->
+      Lapply{ap with ap_func = subst ap.ap_func;
+                     ap_args = List.map subst ap.ap_args}
+  | Lfunction{kind; params; body; attr; loc} ->
+      Lfunction{kind; params; body = subst body; attr; loc}
+  | Llet(str, k, id, arg, body) -> Llet(str, k, 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)
+  | Lprim(p, args, loc) -> Lprim(p, List.map subst args, loc)
   | Lswitch(arg, sw) ->
       Lswitch(subst arg,
               {sw with sw_consts = List.map subst_case sw.sw_consts;
                        sw_blocks = List.map subst_case sw.sw_blocks;
                        sw_failaction = subst_opt  sw.sw_failaction; })
-  | Lstringswitch (arg,cases,default) ->
+  | Lstringswitch (arg,cases,default,loc) ->
       Lstringswitch
-        (subst arg,List.map subst_strcase cases,subst_opt default)
+        (subst arg,List.map subst_strcase cases,subst_opt default,loc)
   | Lstaticraise (i,args) ->  Lstaticraise (i, List.map subst args)
   | Lstaticcatch(e1, io, e2) -> Lstaticcatch(subst e1, io, subst e2)
   | Ltrywith(e1, exn, e2) -> Ltrywith(subst e1, exn, subst e2)
@@ -508,13 +591,74 @@ let subst_lambda s lam =
     | Some e -> Some (subst e)
   in subst lam
 
+let rec map f lam =
+  let lam =
+    match lam with
+    | Lvar _ -> lam
+    | Lconst _ -> 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; loc; } ->
+        Lfunction { kind; params; body = map f body; attr; loc; }
+    | Llet (str, k, v, e1, e2) ->
+        Llet (str, k, 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, loc) ->
+        Lprim (p, List.map (map f) el, loc)
+    | 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, loc) ->
+        Lstringswitch (
+          map f e,
+          List.map (fun (s, e) -> (s, map f e)) sw,
+          Misc.may_map (map f) default,
+          loc)
+    | 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 *)
 
 let bind str var exp body =
   match exp with
     Lvar var' when Ident.same var var' -> body
-  | _ -> Llet(str, var, exp, body)
+  | _ -> Llet(str, Pgenval, var, exp, body)
 
 and commute_comparison = function
 | Ceq -> Ceq| Cneq -> Cneq
diff --git a/bytecomp/lambda.mli b/bytecomp/lambda.mli
index a8f3401d47..57bbaf9718 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,9 +20,12 @@ open Asttypes
 type compile_time_constant =
   | Big_endian
   | Word_size
+  | Int_size
+  | Max_wosize
   | Ostype_unix
   | Ostype_win32
   | Ostype_cygwin
+  | Backend_type
 
 type loc_kind =
   | Loc_FILE
@@ -28,27 +34,44 @@ 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 is_safe =
+  | Safe
+  | Unsafe
+
 type primitive =
-    Pidentity
+  | Pidentity
+  | Pbytes_to_string
+  | Pbytes_of_string
   | Pignore
-  | Prevapply of Location.t
-  | Pdirapply of Location.t
+  | Prevapply
+  | Pdirapply
   | Ploc of loc_kind
     (* Globals *)
   | Pgetglobal of Ident.t
   | Psetglobal of Ident.t
   (* Operations on heap blocks *)
-  | Pmakeblock of int * mutable_flag
-  | Pfield of int * bool * mutable_flag
-  | Psetfield of int * bool * mutable_flag
+  | Pmakeblock of int * mutable_flag * block_shape
+  | Pfield of int * immediate_or_pointer * mutable_flag
+  | 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
   (* Context switches *)
-  | Pperform of Location.t
-  | Presume of Location.t
+  | Pperform
+  | Presume
   | Preperform
   (* External call *)
   | Pccall of Primitive.description
@@ -57,7 +80,8 @@ type primitive =
   (* Boolean operations *)
   | Psequand | Psequor | Pnot
   (* Integer operations *)
-  | Pnegint | Paddint | Psubint | Pmulint | Pdivint | Pmodint
+  | Pnegint | Paddint | Psubint | Pmulint
+  | Pdivint of is_safe | Pmodint of is_safe
   | Pandint | Porint | Pxorint
   | Plslint | Plsrint | Pasrint
   | Pintcomp of comparison
@@ -69,9 +93,14 @@ type primitive =
   | Paddfloat | Psubfloat | Pmulfloat | Pdivfloat
   | Pfloatcomp of comparison
   (* String operations *)
-  | Pstringlength | Pstringrefu | Pstringsetu | Pstringrefs | Pstringsets
+  | Pstringlength | Pstringrefu  | Pstringrefs
+  | Pbyteslength | Pbytesrefu | Pbytessetu | Pbytesrefs | Pbytessets
   (* 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
@@ -91,8 +120,10 @@ type primitive =
   | Paddbint of boxed_integer
   | Psubbint of boxed_integer
   | Pmulbint of boxed_integer
-  | Pdivbint of boxed_integer
-  | Pmodbint of boxed_integer
+  (* XXX KC | Pdivbint of { size : boxed_integer; is_safe : is_safe }
+  | Pmodbint of { size : boxed_integer; is_safe : is_safe } *)
+  | Pdivbint of boxed_integer * is_safe
+  | Pmodbint of boxed_integer * is_safe
   | Pandbint of boxed_integer
   | Porbint of boxed_integer
   | Pxorbint of boxed_integer
@@ -131,6 +162,8 @@ type primitive =
   | Patomic_load
   | Patomic_store
   | Patomic_cas
+  (* Inhibition of optimisation *)
+  | Popaque
 
 and comparison =
     Ceq | Cneq | Clt | Cgt | Cle | Cge
@@ -138,7 +171,13 @@ and comparison =
 and array_kind =
     Pgenarray | Paddrarray | Pintarray | Pfloatarray
 
-and boxed_integer =
+and value_kind =
+    Pgenval | Pfloatval | Pboxedintval of boxed_integer | Pintval
+
+and block_shape =
+  value_kind list option
+
+and boxed_integer = Primitive.boxed_integer =
     Pnativeint | Pint32 | Pint64
 
 and bigarray_kind =
@@ -167,6 +206,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
@@ -178,24 +228,32 @@ type let_kind = Strict | Alias | StrictOpt | Variable
       in e'
     StrictOpt: e does not have side-effects, but depend on the store;
       we can discard e if x does not appear in e'
-    Variable: the variable x is assigned later in e' *)
+    Variable: the variable x is assigned later in e'
+ *)
 
 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
-  | Llet of let_kind * Ident.t * lambda * lambda
+  | Lapply of lambda_apply
+  | Lfunction of lfunction
+  | Llet of let_kind * value_kind * Ident.t * lambda * lambda
   | Lletrec of (Ident.t * lambda) list * lambda
-  | Lprim of primitive * lambda list
+  | Lprim of primitive * lambda list * Location.t
   | Lswitch of lambda * lambda_switch
 (* switch on strings, clauses are sorted by string order,
    strings are pairwise distinct *)
-  | Lstringswitch of lambda * (string * lambda) list * lambda option
+  | Lstringswitch of
+      lambda * (string * lambda) list * lambda option * Location.t
   | Lstaticraise of int * lambda list
   | Lstaticcatch of lambda * (int * Ident.t list) * lambda
   | Ltrywith of lambda * Ident.t * lambda
@@ -208,6 +266,21 @@ 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 *)
+    loc : Location.t; }
+
+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 *)
@@ -224,6 +297,25 @@ and lambda_event_kind =
     Lev_before
   | Lev_after of Types.type_expr
   | Lev_function
+  | Lev_pseudo
+
+type program =
+  { module_ident : Ident.t;
+    main_module_block_size : int;
+    required_globals : Ident.Set.t;    (* Modules whose initializer side effects
+                                          must occur before [code]. *)
+    code : lambda }
+(* Lambda code for the middle-end.
+   * In the closure case the code is a sequence of assignments to a
+     preallocated block of size [main_module_block_size] using
+     (Setfield(Getglobal(module_ident))). The size is used to preallocate
+     the block.
+   * In the flambda case the code is an expression returning a block
+     value of size [main_module_block_size]. The size is used to build
+     the module root as an initialize_symbol
+     Initialize_symbol(module_name, 0,
+       [getfield 0; ...; getfield (main_module_block_size - 1)])
+*)
 
 (* Sharing key *)
 val make_key: lambda -> lambda option
@@ -243,11 +335,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 b4389621ea..af4311fad2 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
 *)
 
@@ -70,7 +72,7 @@ let lshift {left=left ; right=right} = match right with
 | _ ->  assert false
 
 let lforget {left=left ; right=right} = match right with
-| x::xs -> {left=omega::left ; right=xs}
+| _::xs -> {left=omega::left ; right=xs}
 |  _ -> assert false
 
 let rec small_enough n = function
@@ -172,7 +174,7 @@ let ctx_matcher p =
       | Cstr_extension _ ->
           let nargs = List.length omegas in
           (fun q rem -> match q.pat_desc with
-          | Tpat_construct (_, cstr',args)
+          | Tpat_construct (_, _cstr',args)
             when List.length args = nargs ->
                 p,args @ rem
           | Tpat_any -> p,omegas @ rem
@@ -394,7 +396,7 @@ type pm_half_compiled_info =
 
 let pretty_cases cases =
   List.iter
-    (fun ((ps),l) ->
+    (fun (ps,_l) ->
       List.iter
         (fun p ->
           Parmatch.top_pretty Format.str_formatter p ;
@@ -481,7 +483,7 @@ let make_catch d k = match d with
 (* Introduce a catch, if worth it, delayed version *)
 let rec as_simple_exit = function
   | Lstaticraise (i,[]) -> Some i
-  | Llet (Alias,_,_,e) -> as_simple_exit e
+  | Llet (Alias,_k,_,_,e) -> as_simple_exit e
   | _ -> None
 
 
@@ -1076,7 +1078,7 @@ and precompile_var  args cls def k = match args with
 | []  -> assert false
 | _::((Lvar v as av,_) as arg)::rargs ->
     begin match cls with
-    | [ps,_] -> (* as splitted as it can *)
+    | [_] -> (* as splitted as it can *)
         dont_precompile_var args cls def k
     | _ ->
 (* Precompile *)
@@ -1111,7 +1113,7 @@ and dont_precompile_var args cls def k =
 
 and is_exc p = match p.pat_desc with
 | Tpat_or (p1,p2,_) -> is_exc p1 || is_exc p2
-| Tpat_alias (p,v,_) -> is_exc p
+| Tpat_alias (p,_,_) -> is_exc p
 | Tpat_construct (_,{cstr_tag=Cstr_extension _},_) -> true
 | _ -> false
 
@@ -1284,12 +1286,12 @@ let divide_constant ctx m =
 (* Matching against a constructor *)
 
 
-let make_field_args binding_kind arg first_pos last_pos argl =
+let make_field_args loc binding_kind arg first_pos last_pos argl =
   let rec make_args pos =
     if pos > last_pos
     then argl
-    else (Lprim(Pfield(pos, true, Immutable), [arg]), binding_kind)
-         :: make_args (pos + 1)
+    else (Lprim(Pfield(pos, Pointer, Immutable), [arg], loc),
+            binding_kind) :: make_args (pos + 1)
   in make_args first_pos
 
 let get_key_constr = function
@@ -1324,7 +1326,7 @@ let matcher_constr cstr = match cstr.cstr_arity with
         | None, None -> raise NoMatch
         | Some r1, None -> r1
         | None, Some r2 -> r2
-        | Some (a1::rem1), Some (a2::_) ->
+        | Some (a1::_), Some (a2::_) ->
             {a1 with
              pat_loc = Location.none ;
              pat_desc = Tpat_or (a1, a2, None)}::
@@ -1346,14 +1348,17 @@ let matcher_constr cstr = match cstr.cstr_arity with
 
 let make_constr_matching p def ctx = function
     [] -> fatal_error "Matching.make_constr_matching"
-  | ((arg, mut) :: argl) ->
+  | ((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
+            make_field_args p.pat_loc Alias arg 0 (cstr.cstr_arity - 1) argl
+        | Cstr_unboxed -> (arg, Alias) :: argl
         | Cstr_extension _ ->
-            make_field_args Alias arg 1 cstr.cstr_arity argl in
+            make_field_args p.pat_loc Alias arg 1 cstr.cstr_arity argl in
       {pm=
         {cases = []; args = newargs;
           default = make_default (matcher_constr cstr) def} ;
@@ -1384,7 +1389,7 @@ let rec matcher_variant_const lab p rem = match p.pat_desc with
 
 let make_variant_matching_constant p lab def ctx = function
     [] -> fatal_error "Matching.make_variant_matching_constant"
-  | ((arg, mut) :: argl) ->
+  | (_ :: argl) ->
       let def = make_default (matcher_variant_const lab) def
       and ctx = filter_ctx p ctx in
       {pm={ cases = []; args = argl ; default=def} ;
@@ -1400,20 +1405,16 @@ let matcher_variant_nonconst lab p rem = match p.pat_desc with
 
 let make_variant_matching_nonconst p lab def ctx = function
     [] -> fatal_error "Matching.make_variant_matching_nonconst"
-  | ((arg, mut) :: argl) ->
+  | ((arg, _mut) :: argl) ->
       let def = make_default (matcher_variant_nonconst lab) def
       and ctx = filter_ctx p ctx in
-      {pm = { cases = [];
-              args = (Lprim(Pfield(1, true, Immutable), [arg]), Alias) :: argl;
-              default = def };
+      {pm=
+        {cases = [];
+         args = (Lprim(Pfield(1, Pointer, Immutable), [arg], p.pat_loc), Alias) :: argl;
+         default = def };
        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
@@ -1433,7 +1434,7 @@ let divide_variant row ctx {cases = cl; args = al; default=def} =
               add (make_variant_matching_nonconst p lab def ctx) variants
                 (=) (Cstr_block tag) (pat :: patl, action) al
         end
-    | cl -> []
+    | _ -> []
   in
   divide cl
 
@@ -1474,10 +1475,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 (
@@ -1491,7 +1489,9 @@ let get_mod_field modname field =
       with Not_found ->
         fatal_error ("Primitive "^modname^"."^field^" not found.")
       in
-      Lprim(Pfield(p, true, Immutable), [Lprim(Pgetglobal mod_ident, [])])
+      Lprim(Pfield(p, Pointer, Immutable),
+            [Lprim(Pgetglobal mod_ident, [], Location.none)],
+            Location.none)
     with Not_found -> fatal_error ("Module "^modname^" unavailable.")
   )
 
@@ -1514,18 +1514,25 @@ let inline_lazy_force_cond arg loc =
   let varg = Lvar idarg in
   let tag = Ident.create "tag" in
   let force_fun = Lazy.force code_force_lazy_block in
-  Llet(Strict, idarg, arg,
-       Llet(Alias, tag, Lprim(Pccall prim_obj_tag, [varg]),
+  Llet(Strict, Pgenval, idarg, arg,
+       Llet(Alias, Pgenval, tag, Lprim(Pccall prim_obj_tag, [varg], loc),
             Lifthenelse(
               (* if (tag == Obj.forward_tag) then varg.(0) else ... *)
               Lprim(Pintcomp Ceq,
-                    [Lvar tag; Lconst(Const_base(Const_int Obj.forward_tag))]),
-              Lprim(Pfield(0, true, Mutable), [varg]),
+                    [Lvar tag; Lconst(Const_base(Const_int Obj.forward_tag))],
+                    loc),
+              Lprim(Pfield(0, Pointer, Mutable), [varg], loc),
               Lifthenelse(
                 (* ... 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),
+                      [Lvar tag; Lconst(Const_base(Const_int Obj.lazy_tag))],
+                      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))))
 
@@ -1533,17 +1540,22 @@ let inline_lazy_force_switch arg loc =
   let idarg = Ident.create "lzarg" in
   let varg = Lvar idarg in
   let force_fun = Lazy.force code_force_lazy_block in
-  Llet(Strict, idarg, arg,
+  Llet(Strict, Pgenval, idarg, arg,
        Lifthenelse(
-         Lprim(Pisint, [varg]), varg,
+         Lprim(Pisint, [varg], loc), varg,
          (Lswitch
             (varg,
              { sw_numconsts = 0; sw_consts = [];
                sw_numblocks = 256;  (* PR#6033 - tag ranges from 0 to 255 *)
                sw_blocks =
-                 [ (Obj.forward_tag, Lprim(Pfield(0, true, Mutable), [varg]));
+                 [ (Obj.forward_tag, Lprim(Pfield(0, Pointer, Mutable), [varg], loc));
                    (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 =
@@ -1557,7 +1569,7 @@ let inline_lazy_force arg loc =
 
 let make_lazy_matching def = function
     [] -> fatal_error "Matching.make_lazy_matching"
-  | (arg,mut) :: argl ->
+  | (arg,_mut) :: argl ->
       { cases = [];
         args =
           (inline_lazy_force arg Location.none, Strict) :: argl;
@@ -1584,13 +1596,13 @@ let matcher_tuple arity p rem = match p.pat_desc with
 | Tpat_var _          -> get_args_tuple arity omega rem
 | _                   ->  get_args_tuple arity p rem
 
-let make_tuple_matching arity def = function
+let make_tuple_matching loc arity def = function
     [] -> fatal_error "Matching.make_tuple_matching"
-  | (arg, mut) :: argl ->
+  | (arg, _mut) :: argl ->
       let rec make_args pos =
         if pos >= arity
         then argl
-        else (Lprim(Pfield(pos, true, Immutable), [arg]), Alias)
+        else (Lprim(Pfield(pos, Pointer, Immutable), [arg], loc), Alias)
              :: make_args (pos + 1) in
       {cases = []; args = make_args 0 ;
         default=make_default (matcher_tuple arity) def}
@@ -1599,7 +1611,7 @@ let make_tuple_matching arity def = function
 let divide_tuple arity p ctx pm =
   divide_line
     (filter_ctx p)
-    (make_tuple_matching arity)
+    (make_tuple_matching p.pat_loc arity)
     (get_args_tuple  arity) p ctx pm
 
 (* Matching against a record pattern *)
@@ -1622,23 +1634,27 @@ let matcher_record num_fields p rem = match p.pat_desc with
 | Tpat_var _      -> get_args_record num_fields omega rem
 | _               -> get_args_record num_fields p rem
 
-let make_record_matching env all_labels def = function
+let make_record_matching env loc all_labels def = function
     [] -> fatal_error "Matching.make_record_matching"
-  | ((arg, mut) :: argl) ->
+  | ((arg, _mut) :: argl) ->
       let rec make_args pos =
         if pos >= Array.length all_labels then argl else begin
           let lbl = all_labels.(pos) in
+          let ptr = Typeopt.maybe_pointer_type env lbl.lbl_arg in
           let access =
             match lbl.lbl_repres with
-              Record_regular ->
-                let ptr = Typeopt.maybe_pointer_type env lbl.lbl_arg in
-                  Pfield(lbl.lbl_pos, ptr, lbl.lbl_mut)
-            | Record_float -> Pfloatfield lbl.lbl_pos in
+            | Record_regular | Record_inlined _ ->
+              Lprim (Pfield (lbl.lbl_pos, ptr, lbl.lbl_mut), [arg], loc)
+            | Record_unboxed _ -> arg
+            | Record_float -> Lprim (Pfloatfield lbl.lbl_pos, [arg], loc)
+            | Record_extension ->
+              Lprim (Pfield (lbl.lbl_pos + 1, ptr, lbl.lbl_mut), [arg], loc)
+          in
           let str =
             match lbl.lbl_mut with
               Immutable -> Alias
             | Mutable -> StrictOpt in
-          (Lprim(access, [arg]), str) :: make_args(pos + 1)
+          (access, str) :: make_args(pos + 1)
         end in
       let nfields = Array.length all_labels in
       let def= make_default (matcher_record nfields) def in
@@ -1649,7 +1665,7 @@ let divide_record env all_labels p ctx pm =
   let get_args = get_args_record (Array.length all_labels) in
   divide_line
     (filter_ctx p)
-    (make_record_matching env all_labels)
+    (make_record_matching env p.pat_loc all_labels)
     get_args
     p ctx pm
 
@@ -1671,12 +1687,14 @@ let matcher_array len p rem = match p.pat_desc with
 
 let make_array_matching kind p def ctx = function
   | [] -> fatal_error "Matching.make_array_matching"
-  | ((arg, mut) :: argl) ->
+  | ((arg, _mut) :: argl) ->
       let len = get_key_array p in
       let rec make_args pos =
         if pos >= len
         then argl
-        else (Lprim(Parrayrefu kind, [arg; Lconst(Const_base(Const_int pos))]),
+        else (Lprim(Parrayrefu kind,
+                    [arg; Lconst(Const_base(Const_int pos))],
+                    p.pat_loc),
               StrictOpt) :: make_args (pos + 1) in
       let def = make_default (matcher_array len) def
       and ctx = filter_ctx p ctx in
@@ -1707,25 +1725,27 @@ 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
 | _ ->
     let id = Ident.create "switch" in
-    Llet (Strict,id,arg,k (Lvar id))
+    Llet (Strict,Pgenval,id,arg,k (Lvar id))
 
 
 (* Sequential equality tests *)
 
-let make_string_test_sequence arg sw d =
+let make_string_test_sequence loc arg sw d =
   let d,sw = match d with
   | None ->
       begin match sw with
@@ -1740,7 +1760,7 @@ let make_string_test_sequence arg sw d =
           Lifthenelse
             (Lprim
                (prim_string_notequal,
-                [arg; Lconst (Const_immstring s)]),
+                [arg; Lconst (Const_immstring s)], loc),
              k,lam))
         sw d)
 
@@ -1754,40 +1774,40 @@ let rec split k xs = match xs with
 
 let zero_lam  = Lconst (Const_base (Const_int 0))
 
-let tree_way_test arg lt eq gt =
+let tree_way_test loc arg lt eq gt =
   Lifthenelse
-    (Lprim (Pintcomp Clt,[arg;zero_lam]),lt,
-     Lifthenelse(Lprim (Pintcomp Clt,[zero_lam;arg]),gt,eq))
+    (Lprim (Pintcomp Clt,[arg;zero_lam], loc),lt,
+     Lifthenelse(Lprim (Pintcomp Clt,[zero_lam;arg], loc),gt,eq))
 
 (* Dichotomic tree *)
 
 
-let rec do_make_string_test_tree arg sw delta d =
+let rec do_make_string_test_tree loc arg sw delta d =
   let len = List.length sw in
   if len <= strings_test_threshold+delta then
-    make_string_test_sequence arg sw d
+    make_string_test_sequence loc arg sw d
   else
     let lt,(s,act),gt = split len sw in
     bind_sw
       (Lprim
          (prim_string_compare,
-          [arg; Lconst (Const_immstring s)];))
+          [arg; Lconst (Const_immstring s)], loc;))
       (fun r ->
-        tree_way_test r
-          (do_make_string_test_tree arg lt delta d)
+        tree_way_test loc r
+          (do_make_string_test_tree loc arg lt delta d)
           act
-          (do_make_string_test_tree arg gt delta d))
+          (do_make_string_test_tree loc arg gt delta d))
 
 (* Entry point *)
-let expand_stringswitch arg sw d = match d with
+let expand_stringswitch loc arg sw d = match d with
 | None ->
     bind_sw arg
-      (fun arg -> do_make_string_test_tree arg sw 0 None)
+      (fun arg -> do_make_string_test_tree loc arg sw 0 None)
 | Some e ->
     bind_sw arg
       (fun arg ->
         make_catch e
-          (fun d -> do_make_string_test_tree arg sw 1 (Some d)))
+          (fun d -> do_make_string_test_tree loc arg sw 1 (Some d)))
 
 (**********************)
 (* Generic test trees *)
@@ -1819,7 +1839,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 *)
@@ -1851,24 +1871,24 @@ let rec cut n l =
     [] -> raise (Invalid_argument "cut")
   | a::l -> let l1,l2 = cut (n-1) l in a::l1, l2
 
-let rec do_tests_fail fail tst arg = function
+let rec do_tests_fail loc fail tst arg = function
   | [] -> fail
   | (c, act)::rem ->
       Lifthenelse
-        (Lprim (tst, [arg ; Lconst (Const_base c)]),
-         do_tests_fail fail tst arg rem,
+        (Lprim (tst, [arg ; Lconst (Const_base c)], loc),
+         do_tests_fail loc fail tst arg rem,
          act)
 
-let rec do_tests_nofail tst arg = function
+let rec do_tests_nofail loc tst arg = function
   | [] -> fatal_error "Matching.do_tests_nofail"
   | [_,act] -> act
   | (c,act)::rem ->
       Lifthenelse
-        (Lprim (tst, [arg ; Lconst (Const_base c)]),
-         do_tests_nofail tst arg rem,
+        (Lprim (tst, [arg ; Lconst (Const_base c)], loc),
+         do_tests_nofail loc tst arg rem,
          act)
 
-let make_test_sequence fail tst lt_tst arg const_lambda_list =
+let make_test_sequence loc fail tst lt_tst arg const_lambda_list =
   let const_lambda_list = sort_lambda_list const_lambda_list in
   let hs,const_lambda_list,fail =
     share_actions_tree const_lambda_list fail in
@@ -1877,58 +1897,20 @@ let make_test_sequence fail tst lt_tst arg const_lambda_list =
     if List.length const_lambda_list >= 4 && lt_tst <> Pignore then
       split_sequence const_lambda_list
     else match fail with
-    | None -> do_tests_nofail tst arg const_lambda_list
-    | Some fail -> do_tests_fail fail tst arg const_lambda_list
+    | None -> do_tests_nofail loc tst arg const_lambda_list
+    | Some fail -> do_tests_fail loc fail tst arg const_lambda_list
 
   and split_sequence const_lambda_list =
     let list1, list2 =
       cut (List.length const_lambda_list / 2) const_lambda_list in
-    Lifthenelse(Lprim(lt_tst,[arg; Lconst(Const_base (fst(List.hd list2)))]),
+    Lifthenelse(Lprim(lt_tst,
+                      [arg; Lconst(Const_base (fst(List.hd list2)))],
+                      loc),
                 make_test_sequence list1, make_test_sequence list2)
   in
   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
 
@@ -1941,10 +1923,10 @@ module SArg = struct
 
   type act = Lambda.lambda
 
-  let make_prim p args = Lprim (p,args)
+  let make_prim p args = Lprim (p,args,Location.none)
   let make_offset arg n = match n with
   | 0 -> arg
-  | _ -> Lprim (Poffsetint n,[arg])
+  | _ -> Lprim (Poffsetint n,[arg],Location.none)
 
   let bind arg body =
     let newvar,newarg = match arg with
@@ -1954,8 +1936,8 @@ module SArg = struct
         newvar,Lvar newvar in
     bind Alias newvar arg (body newarg)
   let make_const i = Lconst (Const_base (Const_int i))
-  let make_isout h arg = Lprim (Pisout, [h ; arg])
-  let make_isin h arg = Lprim (Pnot,[make_isout h arg])
+  let make_isout h arg = Lprim (Pisout, [h ; arg],Location.none)
+  let make_isin h arg = Lprim (Pnot,[make_isout h arg],Location.none)
   let make_if cond ifso ifnot = Lifthenelse (cond, ifso, ifnot)
   let make_switch arg cases acts =
     let l = ref [] in
@@ -2039,8 +2021,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
@@ -2054,11 +2034,11 @@ let get_edges low high l = match l with
 let as_interval_canfail fail low high l =
   let store = StoreExp.mk_store () in
 
-  let do_store tag act =
+  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
 
@@ -2095,7 +2075,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
@@ -2112,7 +2092,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]
@@ -2125,7 +2108,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
 
@@ -2153,13 +2145,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
@@ -2167,41 +2152,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
@@ -2210,33 +2160,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
@@ -2246,20 +2169,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 ;
@@ -2281,24 +2204,40 @@ and mk_failaction_pos partial seen ctx defs  =
   | _,(pss,idef)::rem ->
       let now, later =
         List.partition
-          (fun (p,p_ctx) -> ctx_match p_ctx pss) to_test in
+          (fun (_p,p_ctx) -> ctx_match p_ctx pss) to_test in
       match now with
       | [] -> scan_def env to_test rem
       | _  -> scan_def ((List.map fst now,idef)::env) later rem in
 
+  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)
-       (complete_pats_constrs seen))
-    defs
-
+           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 combine_constant loc arg cst partial ctx def
+    (const_lambda_list, total, _pats) =
+  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 _ ->
@@ -2325,24 +2264,24 @@ let combine_constant arg cst partial ctx def
             | _ -> assert false)
             const_lambda_list in
         let hs,sw,fail = share_actions_tree sw fail in
-        hs (Lstringswitch (arg,sw,fail))
+        hs (Lstringswitch (arg,sw,fail,loc))
     | Const_float _ ->
-        make_test_sequence
+        make_test_sequence loc
           fail
           (Pfloatcomp Cneq) (Pfloatcomp Clt)
           arg const_lambda_list
     | Const_int32 _ ->
-        make_test_sequence
+        make_test_sequence loc
           fail
           (Pbintcomp(Pint32, Cneq)) (Pbintcomp(Pint32, Clt))
           arg const_lambda_list
     | Const_int64 _ ->
-        make_test_sequence
+        make_test_sequence loc
           fail
           (Pbintcomp(Pint64, Cneq)) (Pbintcomp(Pint64, Clt))
           arg const_lambda_list
     | Const_nativeint _ ->
-        make_test_sequence
+        make_test_sequence loc
           fail
           (Pbintcomp(Pnativeint, Cneq)) (Pbintcomp(Pnativeint, Clt))
           arg const_lambda_list
@@ -2358,7 +2297,8 @@ let split_cases tag_lambda_list =
         match cstr with
           Cstr_constant n -> ((n, act) :: consts, nonconsts)
         | Cstr_block n    -> (consts, (n, act) :: nonconsts)
-        | _ -> assert false in
+        | Cstr_unboxed    -> (consts, (0, act) :: nonconsts)
+        | Cstr_extension _ -> assert false in
   let const, nonconst = split_rec tag_lambda_list in
   sort_int_lambda_list const,
   sort_int_lambda_list nonconst
@@ -2375,13 +2315,12 @@ let split_extension_cases tag_lambda_list =
   split_rec tag_lambda_list
 
 
-let combine_constructor arg ex_pat cstr partial ctx def
+let combine_constructor loc 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 =
@@ -2403,17 +2342,18 @@ let combine_constructor arg ex_pat cstr partial ctx def
                 (fun (path, act) rem ->
                    Lifthenelse(Lprim(Pintcomp Ceq,
                                      [Lvar tag;
-                                      transl_path ex_pat.pat_env path]),
+                                      transl_path ex_pat.pat_env path], loc),
                                act, rem))
                 nonconsts
                 default
             in
-              Llet(Alias, tag, Lprim(Pfield(0, true, Immutable), [arg]), tests)
+              Llet(Alias, Pgenval, tag,
+                    Lprim(Pfield(0, Pointer, Immutable), [arg], loc), tests)
       in
         List.fold_right
           (fun (path, act) rem ->
              Lifthenelse(Lprim(Pintcomp Ceq,
-                               [arg; transl_path ex_pat.pat_env path]),
+                               [arg; transl_path ex_pat.pat_env path], loc),
                          act, rem))
           consts
           nonconst_lambda
@@ -2424,42 +2364,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], loc),
+                     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
 
@@ -2472,13 +2423,14 @@ let call_switcher_variant_constant fail arg int_lambda_list =
   call_switcher fail arg min_int max_int int_lambda_list
 
 
-let call_switcher_variant_constr fail arg int_lambda_list =
+let call_switcher_variant_constr loc fail arg int_lambda_list =
   let v = Ident.create "variant" in
-  Llet(Alias, v, Lprim(Pfield(0, true, Immutable), [arg]),
+  Llet(Alias, Pgenval, v, Lprim(Pfield(0, Pointer, Immutable), [arg], loc),
        call_switcher
          fail (Lvar v) min_int max_int int_lambda_list)
 
-let combine_variant row arg partial ctx def (tag_lambda_list, total1, pats) =
+let combine_variant loc row arg partial ctx def
+                    (tag_lambda_list, total1, _pats) =
   let row = Btype.row_repr row in
   let num_constr = ref 0 in
   if row.row_closed then
@@ -2491,28 +2443,27 @@ let combine_variant row arg partial ctx def (tag_lambda_list, total1, pats) =
   else
     num_constr := max_int;
   let test_int_or_block arg if_int if_block =
-    Lifthenelse(Lprim (Pisint, [arg]), if_int, if_block) in
+    Lifthenelse(Lprim (Pisint, [arg], loc), 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
   | _,_ ->
       match (consts, nonconsts) with
-      | ([n, act1], [m, act2]) when fail=None ->
+      | ([_, act1], [_, act2]) when fail=None ->
           test_int_or_block arg act1 act2
       | (_, []) -> (* One can compare integers and pointers *)
           make_test_sequence_variant_constant fail arg consts
       | ([], _) ->
-          let lam = call_switcher_variant_constr
+          let lam = call_switcher_variant_constr loc
               fail arg nonconsts in
           (* One must not dereference integers *)
           begin match fail with
@@ -2524,17 +2475,16 @@ let combine_variant row arg partial ctx def (tag_lambda_list, total1, pats) =
             call_switcher_variant_constant
               fail arg consts
           and lam_nonconst =
-            call_switcher_variant_constr
+            call_switcher_variant_constr loc
               fail arg nonconsts in
           test_int_or_block arg lam_const lam_nonconst
   in
   lambda1, jumps_union local_jumps total1
 
 
-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 combine_array loc arg kind partial ctx def
+    (len_lambda_list, total1, _pats)  =
+  let fail, local_jumps = mk_failaction_neg partial  ctx def in
   let lambda1 =
     let newvar = Ident.create "len" in
     let switch =
@@ -2542,7 +2492,7 @@ let combine_array arg kind partial ctx def
         fail (Lvar newvar)
         0 max_int len_lambda_list in
     bind
-      Alias newvar (Lprim(Parraylength kind, [arg])) switch in
+      Alias newvar (Lprim(Parraylength kind, [arg], loc)) switch in
   lambda1, jumps_union local_jumps total1
 
 (* Insertion of debugging events *)
@@ -2557,10 +2507,10 @@ let rec event_branch repr lam =
                     lev_kind = ev.lev_kind;
                     lev_repr = repr;
                     lev_env = ev.lev_env})
-  | (Llet(str, id, lam, body), _) ->
-      Llet(str, id, lam, event_branch repr body)
+  | (Llet(str, k, id, lam, body), _) ->
+      Llet(str, k, id, lam, event_branch repr body)
   | Lstaticraise _,_ -> lam
-  | (_, Some r) ->
+  | (_, Some _) ->
       Printlambda.lambda Format.str_formatter lam ;
       fatal_error
         ("Matching.event_branch: "^Format.flush_str_formatter ())
@@ -2637,8 +2587,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
@@ -2650,9 +2600,9 @@ let rec approx_present v = function
   | Lconst _ -> false
   | Lstaticraise (_,args) ->
       List.exists (fun lam -> approx_present v lam) args
-  | Lprim (_,args) ->
+  | Lprim (_,args,_) ->
       List.exists (fun lam -> approx_present v lam) args
-  | Llet (Alias, _, l1, l2) ->
+  | Llet (Alias, _k, _, l1, l2) ->
       approx_present v l1 || approx_present v l2
   | Lvar vv -> Ident.same v vv
   | _ -> true
@@ -2676,11 +2626,11 @@ let rec lower_bind v arg lam = match lam with
 | Lswitch (ls,({sw_consts=[] ; sw_blocks = [i,act]} as sw))
     when not (approx_present v ls) ->
       Lswitch (ls, {sw with sw_blocks = [i,lower_bind v arg act]})
-| Llet (Alias, vv, lv, l) ->
+| Llet (Alias, k, vv, lv, l) ->
     if approx_present v lv then
       bind Alias v arg lam
     else
-      Llet (Alias, vv, lv, lower_bind v arg l)
+      Llet (Alias, k, vv, lv, lower_bind v arg l)
 | _ ->
     bind Alias v arg lam
 
@@ -2732,10 +2682,10 @@ let rec comp_match_handlers comp_fun partial ctx arg first_match next_matchs =
 (* To find reasonable names for variables *)
 
 let rec name_pattern default = function
-    (pat :: patl, action) :: rem ->
+    (pat :: _, _) :: rem ->
       begin match pat.pat_desc with
         Tpat_var (id, _) -> id
-      | Tpat_alias(p, id, _) -> id
+      | Tpat_alias(_, id, _) -> id
       | _ -> name_pattern default rem
       end
   | _ -> Ident.create default
@@ -2759,7 +2709,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) =
@@ -2813,26 +2763,27 @@ and do_compile_matching repr partial ctx arg pmh = match pmh with
       compile_test
         (compile_match repr partial) partial
         divide_constant
-        (combine_constant arg cst partial)
+        (combine_constant pat.pat_loc arg cst partial)
         ctx pm
   | Tpat_construct (_, cstr, _) ->
       compile_test
         (compile_match repr partial) partial
-        divide_constructor (combine_constructor arg pat cstr partial)
+        divide_constructor
+        (combine_constructor pat.pat_loc arg pat cstr partial)
         ctx pm
   | Tpat_array _ ->
       let kind = Typeopt.array_pattern_kind pat in
       compile_test (compile_match repr partial) partial
-        (divide_array kind) (combine_array arg kind partial)
+        (divide_array kind) (combine_array pat.pat_loc arg kind partial)
         ctx pm
   | Tpat_lazy _ ->
       compile_no_test
         (divide_lazy (normalize_pat pat))
         ctx_combine repr partial ctx pm
-  | Tpat_variant(lab, _, row) ->
+  | Tpat_variant(_, _, row) ->
       compile_test (compile_match repr partial) partial
         (divide_variant !row)
-        (combine_variant !row arg partial)
+        (combine_variant pat.pat_loc !row arg partial)
         ctx pm
   | _ -> assert false
   end
@@ -2869,7 +2820,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 =
@@ -2925,6 +2876,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))
@@ -2947,7 +2899,7 @@ let check_total total lambda i handler_fun =
     Lstaticcatch(lambda, (i,[]), handler_fun())
   end
 
-let compile_matching loc repr handler_fun arg pat_act_list partial =
+let compile_matching repr handler_fun arg pat_act_list partial =
   let partial = check_partial pat_act_list partial in
   match partial with
   | Partial ->
@@ -2975,29 +2927,158 @@ let compile_matching loc repr handler_fun arg pat_act_list partial =
 let partial_function loc () =
   (* [Location.get_pos_info] is too expensive *)
   let (fname, line, char) = Location.get_pos_info loc.Location.loc_start in
-  Lprim(Praise Raise_regular, [Lprim(Pmakeblock(0, Immutable),
+  Lprim(Praise Raise_regular, [Lprim(Pmakeblock(0, Immutable, None),
           [transl_normal_path Predef.path_match_failure;
            Lconst(Const_block(0,
               [Const_base(Const_string (fname, None));
                Const_base(Const_int line);
-               Const_base(Const_int char)]))])])
+               Const_base(Const_int char)]))], loc)], loc)
 
 let for_function loc repr param pat_act_list partial =
-  compile_matching loc repr (partial_function loc) param pat_act_list partial
+  compile_matching repr (partial_function loc) param pat_act_list partial
 
 (* In the following three cases, exhaustiveness info is not available! *)
 let for_trywith param pat_act_list =
-  compile_matching Location.none None
-    (fun () -> Lprim(Praise Raise_reraise, [param]))
+  compile_matching None
+    (fun () -> Lprim(Praise Raise_reraise, [param], Location.none))
     param pat_act_list Partial
 
 let for_handler param raw_cont pat_act_list =
-  compile_matching Location.none None 
-    (fun () -> Lprim (Preperform, [param; raw_cont]))
+  compile_matching None
+    (fun () -> Lprim (Preperform, [param; raw_cont], Location.none))
     param pat_act_list Partial
 
+let simple_for_let loc param pat body =
+  compile_matching 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 (str, k, id, l1, l2) -> Llet (str, 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 =
-  compile_matching loc None (partial_function loc) param [pat, body] Partial
+  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 (id, _) ->
+      (* fast path, and keep track of simple bindings to unboxable numbers *)
+      let k = Typeopt.value_kind pat.pat_env pat.pat_type in
+      Llet(Strict, k, id, param, 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 *)
 
@@ -3091,12 +3172,12 @@ let do_for_multiple_match loc paraml pat_act_list partial =
         let raise_num = next_raise_count () in
         raise_num,
         { cases = List.map (fun (pat, act) -> ([pat], act)) pat_act_list;
-          args = [Lprim(Pmakeblock(0, Immutable), paraml), Strict] ;
+          args = [Lprim(Pmakeblock(0, Immutable, None), paraml, loc), Strict];
           default = [[[omega]],raise_num] }
     | _ ->
         -1,
         { cases = List.map (fun (pat, act) -> ([pat], act)) pat_act_list;
-          args = [Lprim(Pmakeblock(0, Immutable), paraml), Strict] ;
+          args = [Lprim(Pmakeblock(0, Immutable, None), paraml, loc), Strict];
           default = [] } in
 
   try
@@ -3140,13 +3221,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 b3ab0f105d..b57506f0d7 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -40,6 +43,6 @@ val flatten_pattern: int -> pattern -> pattern list
 
 (* Expand stringswitch to  string test tree *)
 val expand_stringswitch:
-    lambda -> (string * lambda) list -> lambda option -> lambda
+    Location.t -> lambda -> (string * lambda) list -> lambda option -> lambda
 
 val inline_lazy_force : lambda -> Location.t -> lambda
diff --git a/bytecomp/meta.ml b/bytecomp/meta.ml
index bad9368e0b..9debe862a6 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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"
@@ -21,3 +24,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 ac45f5207e..a360e6a2f8 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -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/printinstr.ml b/bytecomp/printinstr.ml
index 10f7afab6f..116fc74e53 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 dd4fd15b32..3cf3539d20 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 8f1dfede27..4aa298856a 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,13 +43,28 @@ 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 value_kind = function
+  | Pgenval -> ""
+  | Pintval -> "[int]"
+  | Pfloatval -> "[float]"
+  | Pboxedintval bi -> Printf.sprintf "[%s]" (boxed_integer_name bi)
+
+let field_kind = function
+  | Pgenval -> "*"
+  | Pintval -> "int"
+  | Pfloatval -> "float"
+  | Pboxedintval bi -> boxed_integer_name bi
 
 let print_boxed_integer_conversion ppf bi1 bi2 =
   fprintf ppf "%s_of_%s" (boxed_integer_name bi2) (boxed_integer_name bi1)
@@ -84,7 +102,11 @@ 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_unboxed false -> fprintf ppf "unboxed"
+  | Record_unboxed true -> fprintf ppf "inlined(unboxed)"
   | Record_float -> fprintf ppf "float"
+  | Record_extension -> fprintf ppf "ext"
 ;;
 
 let string_of_loc_kind = function
@@ -94,38 +116,64 @@ let string_of_loc_kind = function
   | Loc_POS -> "loc_POS"
   | Loc_LOC -> "loc_LOC"
 
+let block_shape ppf shape = match shape with
+  | None | Some [] -> ()
+  | Some l when List.for_all ((=) Pgenval) l -> ()
+  | Some [elt] ->
+      Format.fprintf ppf " (%s)" (field_kind elt)
+  | Some (h :: t) ->
+      Format.fprintf ppf " (%s" (field_kind h);
+      List.iter (fun elt ->
+          Format.fprintf ppf ",%s" (field_kind elt))
+        t;
+      Format.fprintf ppf ")"
+
 let primitive ppf = function
   | Pidentity -> fprintf ppf "id"
+  | Pbytes_to_string -> fprintf ppf "bytes_to_string"
+  | Pbytes_of_string -> fprintf ppf "bytes_of_string"
   | Pignore -> fprintf ppf "ignore"
-  | Prevapply _ -> fprintf ppf "revapply"
-  | Pdirapply _ -> fprintf ppf "dirapply"
+  | Prevapply -> fprintf ppf "revapply"
+  | Pdirapply -> fprintf ppf "dirapply"
   | Ploc kind -> fprintf ppf "%s" (string_of_loc_kind kind)
   | Pgetglobal id -> fprintf ppf "global %a" Ident.print id
   | Psetglobal id -> fprintf ppf "setglobal %a" Ident.print id
-  | Pmakeblock(tag, Immutable) -> fprintf ppf "makeblock %i" tag
-  | Pmakeblock(tag, Mutable) -> fprintf ppf "makemutable %i" tag
+  | Pmakeblock(tag, Immutable, shape) ->
+      fprintf ppf "makeblock %i%a" tag block_shape shape
+  | Pmakeblock(tag, Mutable, shape) ->
+      fprintf ppf "makemutable %i%a" tag block_shape shape
   | Pfield(n, ptr, mut) ->
       let instr =
         match ptr, mut with
-        | false, _ -> "field_int "
-        | true, Mutable -> "field_mut "
-        | true, Immutable -> "field_imm "
+        | Immediate, _ -> "field_int "
+        | Pointer, Mutable -> "field_mut "
+        | Pointer, Immutable -> "field_imm "
       in
       fprintf ppf "%s%i" instr n
-  | Psetfield(n, ptr, mut) ->
+  | Psetfield(n, ptr, init) ->
       let instr =
-        match ptr, mut with
-          false, _ -> "setfield_int "
-        | true, Mutable -> "setfield_mut "
-        | true, Immutable -> "setfield_imm "
+        match ptr with
+        | Pointer -> "ptr"
+        | Immediate -> "imm"
       in
-      fprintf ppf "%s%i" instr n
+      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"
-  | Pperform _ -> fprintf ppf "perform"
-  | Presume _ -> fprintf ppf "resume"
+  | Pperform -> fprintf ppf "perform"
+  | Presume -> fprintf ppf "resume"
   | Preperform -> fprintf ppf "reperform"
   | Pccall p -> fprintf ppf "%s" p.prim_name
   | Praise k -> fprintf ppf "%s" (Lambda.raise_kind k)
@@ -136,8 +184,10 @@ let primitive ppf = function
   | Paddint -> fprintf ppf "+"
   | Psubint -> fprintf ppf "-"
   | Pmulint -> fprintf ppf "*"
-  | Pdivint -> fprintf ppf "/"
-  | Pmodint -> fprintf ppf "mod"
+  | Pdivint Safe -> fprintf ppf "/"
+  | Pdivint Unsafe -> fprintf ppf "/u"
+  | Pmodint Safe -> fprintf ppf "mod"
+  | Pmodint Unsafe -> fprintf ppf "mod_unsafe"
   | Pandint -> fprintf ppf "and"
   | Porint -> fprintf ppf "or"
   | Pxorint -> fprintf ppf "xor"
@@ -168,22 +218,32 @@ let primitive ppf = function
   | Pfloatcomp(Cge) -> fprintf ppf ">=."
   | Pstringlength -> fprintf ppf "string.length"
   | Pstringrefu -> fprintf ppf "string.unsafe_get"
-  | 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"
+  | Pbyteslength -> fprintf ppf "bytes.length"
+  | Pbytesrefu -> fprintf ppf "bytes.unsafe_get"
+  | Pbytessetu -> fprintf ppf "bytes.unsafe_set"
+  | Pbytesrefs -> fprintf ppf "bytes.get"
+  | Pbytessets -> fprintf ppf "bytes.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
+       | Ostype_cygwin -> "ostype_cygwin"
+       | Backend_type -> "backend_type" in
      fprintf ppf "sys.constant_%s" const_name
   | Pisint -> fprintf ppf "isint"
   | Pisout -> fprintf ppf "isout"
@@ -195,8 +255,14 @@ let primitive ppf = function
   | Paddbint bi -> print_boxed_integer "add" ppf bi
   | Psubbint bi -> print_boxed_integer "sub" ppf bi
   | Pmulbint bi -> print_boxed_integer "mul" ppf bi
-  | Pdivbint bi -> print_boxed_integer "div" ppf bi
-  | Pmodbint bi -> print_boxed_integer "mod" ppf bi
+  | Pdivbint (bi, Safe) ->
+      print_boxed_integer "div" ppf bi
+  | Pdivbint ( bi, Unsafe ) ->
+      print_boxed_integer "div_unsafe" ppf bi
+  | Pmodbint ( bi, Safe ) ->
+      print_boxed_integer "mod" ppf bi
+  | Pmodbint ( bi, Unsafe ) ->
+      print_boxed_integer "mod_unsafe" ppf bi
   | Pandbint bi -> print_boxed_integer "and" ppf bi
   | Porbint bi -> print_boxed_integer "or" ppf bi
   | Pxorbint bi -> print_boxed_integer "xor" ppf bi
@@ -209,9 +275,9 @@ let primitive ppf = function
   | Pbintcomp(bi, Cgt) -> print_boxed_integer ">" ppf bi
   | Pbintcomp(bi, Cle) -> print_boxed_integer "<=" ppf bi
   | Pbintcomp(bi, Cge) -> print_boxed_integer ">=" ppf bi
-  | Pbigarrayref(unsafe, n, kind, layout) ->
+  | Pbigarrayref(unsafe, _n, kind, layout) ->
       print_bigarray "get" unsafe kind ppf layout
-  | Pbigarrayset(unsafe, n, kind, layout) ->
+  | Pbigarrayset(unsafe, _n, kind, layout) ->
       print_bigarray "set" unsafe kind ppf layout
   | Pbigarraydim(n) -> fprintf ppf "Bigarray.dim_%i" n
   | Pstring_load_16(unsafe) ->
@@ -256,17 +322,158 @@ let primitive ppf = function
   | Patomic_load -> fprintf ppf "atomic_load"
   | Patomic_store -> fprintf ppf "atomic_store"
   | Patomic_cas -> fprintf ppf "atomic_cas"
+  | Popaque -> fprintf ppf "opaque"
+
+let name_of_primitive = function
+  | Pidentity -> "Pidentity"
+  | Pbytes_of_string -> "Pbytes_of_string"
+  | Pbytes_to_string -> "Pbytes_to_string"
+  | 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"
+  | Pstringrefs -> "Pstringrefs"
+  | Pbyteslength -> "Pbyteslength"
+  | Pbytesrefu -> "Pbytesrefu"
+  | Pbytessetu -> "Pbytessetu"
+  | Pbytesrefs -> "Pbytesrefs"
+  | Pbytessets -> "Pbytessets"
+  | 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"
+  | Patomic_load -> "Patomic_load"
+  | Patomic_store -> "Patomic_store"
+  | Patomic_cas -> "Patomic_cas"
+  | Popaque -> "Popaque"
+  | Presume -> "Presume"
+  | Pperform -> "Pperform"
+  | Preperform -> "Preperform"
+
+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 ->
@@ -280,17 +487,20 @@ let rec lam ppf = function
                 Ident.print ppf param)
               params;
             fprintf ppf ")" in
-      fprintf ppf "@[<2>(function%a@ %a)@]" pr_params params lam body
-  | Llet(str, id, arg, body) ->
+      fprintf ppf "@[<2>(function%a@ %a%a)@]" pr_params params
+        function_attribute attr lam body
+  | Llet(str, k, id, arg, body) ->
       let kind = function
-        Alias -> "a" | Strict -> "" | StrictOpt -> "o" | Variable -> "v" in
+          Alias -> "a" | Strict -> "" | StrictOpt -> "o" | Variable -> "v"
+      in
       let rec letbody = function
-        | Llet(str, id, arg, body) ->
-            fprintf ppf "@ @[<2>%a =%s@ %a@]" Ident.print id (kind str) lam arg;
+        | Llet(str, k, id, arg, body) ->
+            fprintf ppf "@ @[<2>%a =%s%s@ %a@]"
+              Ident.print id (kind str) (value_kind k) lam arg;
             letbody body
         | expr -> expr in
-      fprintf ppf "@[<2>(let@ @[(@[<2>%a =%s@ %a@]"
-        Ident.print id (kind str) lam arg;
+      fprintf ppf "@[<2>(let@ @[(@[<2>%a =%s%s@ %a@]"
+        Ident.print id (kind str) (value_kind k) lam arg;
       let expr = letbody body in
       fprintf ppf ")@]@ %a)@]" lam expr
   | Lletrec(id_arg_list, body) ->
@@ -303,7 +513,7 @@ let rec lam ppf = function
           id_arg_list in
       fprintf ppf
         "@[<2>(letrec@ (@[%a@])@ %a)@]" bindings id_arg_list lam body
-  | Lprim(prim, largs) ->
+  | Lprim(prim, largs, _) ->
       let lams ppf largs =
         List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in
       fprintf ppf "@[<2>(%a%a)@]" primitive prim lams largs
@@ -330,7 +540,7 @@ let rec lam ppf = function
        "@[<1>(%s %a@ @[%a@])@]"
        (match sw.sw_failaction with None -> "switch*" | _ -> "switch")
        lam larg switch sw
-  | Lstringswitch(arg, cases, default) ->
+  | Lstringswitch(arg, cases, default, _) ->
       let switch ppf cases =
         let spc = ref false in
         List.iter
@@ -388,7 +598,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
@@ -408,3 +620,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 4a546b63e8..daf0d81a08 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,7 @@ 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
+val value_kind : value_kind -> string
diff --git a/bytecomp/runtimedef.mli b/bytecomp/runtimedef.mli
index c06038a463..3baabb643b 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 2c798776ea..fdf8560863 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
@@ -23,26 +26,27 @@ exception Real_reference
 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 ->
+  | Lconst _ as lam -> 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 _ as lam ->
       if IdentSet.mem id (free_variables lam)
       then raise Real_reference
       else lam
-  | Llet(str, v, e1, e2) ->
-      Llet(str, v, eliminate_ref id e1, eliminate_ref id e2)
+  | Llet(str, kind, v, e1, e2) ->
+      Llet(str, kind, v, eliminate_ref id e1, eliminate_ref id e2)
   | Lletrec(idel, e2) ->
       Lletrec(List.map (fun (v, e) -> (v, eliminate_ref id e)) idel,
               eliminate_ref id e2)
-  | Lprim(Pfield(0, _, _), [Lvar v]) when Ident.same v id ->
+  | 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]))
-  | Lprim(p, el) ->
-      Lprim(p, List.map (eliminate_ref id) el)
+  | Lprim(Poffsetref delta, [Lvar v], loc) when Ident.same v id ->
+      Lassign(id, Lprim(Poffsetint delta, [Lvar id], loc))
+  | Lprim(p, el, loc) ->
+      Lprim(p, List.map (eliminate_ref id) el, loc)
   | Lswitch(e, sw) ->
       Lswitch(eliminate_ref id e,
         {sw_numconsts = sw.sw_numconsts;
@@ -53,11 +57,11 @@ let rec eliminate_ref id = function
             List.map (fun (n, e) -> (n, eliminate_ref id e)) sw.sw_blocks;
          sw_failaction =
             Misc.may_map (eliminate_ref id) sw.sw_failaction; })
-  | Lstringswitch(e, sw, default) ->
+  | Lstringswitch(e, sw, default, loc) ->
       Lstringswitch
         (eliminate_ref id e,
          List.map (fun (s, e) -> (s, eliminate_ref id e)) sw,
-         Misc.may_map (eliminate_ref id) default)
+         Misc.may_map (eliminate_ref id) default, loc)
   | Lstaticraise (i,args) ->
       Lstaticraise (i,List.map (eliminate_ref id) args)
   | Lstaticcatch(e1, i, e2) ->
@@ -106,20 +110,20 @@ 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
-  | Llet(str, v, l1, l2) ->
+  | Lapply ap -> count ap.ap_func; List.iter count ap.ap_args
+  | Lfunction {body} -> count body
+  | Llet(_str, _kind, _v, l1, l2) ->
       count l2; count l1
   | Lletrec(bindings, body) ->
-      List.iter (fun (v, l) -> count l) bindings;
+      List.iter (fun (_v, l) -> count l) bindings;
       count body
-  | Lprim(p, ll) -> List.iter count ll
+  | Lprim(_p, ll, _) -> List.iter count ll
   | Lswitch(l, sw) ->
       count_default sw ;
       count l;
       List.iter (fun (_, l) -> count l) sw.sw_consts;
       List.iter (fun (_, l) -> count l) sw.sw_blocks
-  | Lstringswitch(l, sw, d) ->
+  | Lstringswitch(l, sw, d, _) ->
       count l;
       List.iter (fun (_, l) -> count l) sw;
       begin match  d with
@@ -146,15 +150,15 @@ let simplify_exits lam =
          l2 will be removed, so don't count its exits *)
       if count_exit i > 0 then
         count l2
-  | Ltrywith(l1, v, l2) -> count l1; count l2
+  | Ltrywith(l1, _v, l2) -> count l1; count l2
   | Lifthenelse(l1, l2, l3) -> count l1; count l2; count l3
   | Lsequence(l1, l2) -> count l1; count l2
   | Lwhile(l1, l2) -> count l1; count l2
-  | Lfor(_, l1, l2, dir, l3) -> count l1; count l2; count l3
-  | Lassign(v, l) -> count l
-  | Lsend(k, m, o, ll, _) -> List.iter count (m::o::ll)
+  | Lfor(_, l1, l2, _dir, l3) -> count l1; count l2; count l3
+  | Lassign(_v, l) -> count l
+  | Lsend(_k, m, o, ll, _) -> List.iter count (m::o::ll)
   | Levent(l, _) -> count l
-  | Lifused(v, l) -> count l
+  | Lifused(_v, l) -> count l
 
   and count_default sw = match sw.sw_failaction with
   | None -> ()
@@ -193,27 +197,40 @@ 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)
-  | Llet(kind, v, l1, l2) -> Llet(kind, v, simplif l1, simplif l2)
+  | 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; loc} ->
+     Lfunction{kind; params; body = simplif l; attr; loc}
+  | Llet(str, kind, v, l1, l2) -> Llet(str, kind, v, simplif l1, simplif l2)
   | Lletrec(bindings, body) ->
       Lletrec(List.map (fun (v, l) -> (v, simplif l)) bindings, simplif body)
-  | Lprim(p, ll) -> begin
+  | Lprim(p, ll, loc) -> begin
     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, [x; Lapply ap]
+      | Prevapply, [x; Levent (Lapply ap,_)] ->
+        Lapply {ap with ap_args = ap.ap_args @ [x]; ap_loc = loc}
+      | Prevapply, [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)
-
-      | _ -> Lprim(p, ll)
+      | Pdirapply, [Lapply ap; x]
+      | Pdirapply, [Levent (Lapply ap,_); x] ->
+        Lapply {ap with ap_args = ap.ap_args @ [x]; ap_loc = loc}
+      | Pdirapply, [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, loc)
      end
   | Lswitch(l, sw) ->
       let new_l = simplif l
@@ -224,10 +241,10 @@ let simplify_exits lam =
         (new_l,
          {sw with sw_consts = new_consts ; sw_blocks = new_blocks;
                   sw_failaction = new_fail})
-  | Lstringswitch(l,sw,d) ->
+  | Lstringswitch(l,sw,d,loc) ->
       Lstringswitch
         (simplif l,List.map (fun (s,l) -> s,simplif l) sw,
-         Misc.may_map simplif d)
+         Misc.may_map simplif d,loc)
   | Lstaticraise (i,[]) as l ->
       begin try
         let _,handler =  Hashtbl.find subst i in
@@ -245,12 +262,12 @@ let simplify_exits lam =
             (fun x y t -> Ident.add x (Lvar y) t)
             xs ys Ident.empty in
         List.fold_right2
-          (fun y l r -> Llet (Alias, y, l, r))
+          (fun y l r -> Llet (Alias, Pgenval, y, l, r))
           ys ls (Lambda.subst_lambda env handler)
       with
       | Not_found -> Lstaticraise (i,ls)
       end
-  | Lstaticcatch (l1,(i,[]),(Lstaticraise (j,[]) as l2)) ->
+  | Lstaticcatch (l1,(i,[]),(Lstaticraise (_j,[]) as l2)) ->
       Hashtbl.add subst i ([],simplif l2) ;
       simplif l1
   | Lstaticcatch (l1,(i,xs),l2) ->
@@ -285,7 +302,7 @@ let simplify_exits lam =
 *)
 
 let beta_reduce params body args =
-  List.fold_left2 (fun l param arg -> Llet(Strict, param, arg, l))
+  List.fold_left2 (fun l param arg -> Llet(Strict, Pgenval, param, arg, l))
                   body params args
 
 (* Simplification of lets *)
@@ -335,38 +352,39 @@ let simplify_lets lam =
       () in
 
   let rec count bv = function
-  | Lconst cst -> ()
+  | Lconst _ -> ()
   | 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) ->
-      count Tbl.empty l
-  | Llet(str, v, Lvar w, l2) when optimize ->
+  | Lfunction {body} ->
+      count Tbl.empty body
+  | Llet(_str, _k, v, Lvar w, l2) when optimize ->
       (* v will be replaced by w in l2, so each occurrence of v in l2
          increases w's refcount *)
       count (bind_var bv v) l2;
       use_var bv w (count_var v)
-  | Llet(str, v, l1, l2) ->
+  | Llet(str, _kind, v, l1, l2) ->
       count (bind_var bv v) l2;
       (* If v is unused, l1 will be removed, so don't count its variables *)
       if str = Strict || count_var v > 0 then count bv l1
   | Lletrec(bindings, body) ->
-      List.iter (fun (v, l) -> count bv l) bindings;
+      List.iter (fun (_v, l) -> count bv l) bindings;
       count bv body
-  | Lprim(p, ll) -> List.iter (count bv) ll
+  | Lprim(_p, ll, _) -> List.iter (count bv) ll
   | Lswitch(l, sw) ->
       count_default bv sw ;
       count bv l;
       List.iter (fun (_, l) -> count bv l) sw.sw_consts;
       List.iter (fun (_, l) -> count bv l) sw.sw_blocks
-  | Lstringswitch(l, sw, d) ->
+  | Lstringswitch(l, sw, d, _) ->
       count bv l ;
       List.iter (fun (_, l) -> count bv l) sw ;
       begin match d with
@@ -377,14 +395,14 @@ let simplify_lets lam =
           end
       | None -> ()
       end
-  | Lstaticraise (i,ls) -> List.iter (count bv) ls
-  | Lstaticcatch(l1, (i,_), l2) -> count bv l1; count bv l2
-  | Ltrywith(l1, v, l2) -> count bv l1; count bv l2
+  | Lstaticraise (_i,ls) -> List.iter (count bv) ls
+  | Lstaticcatch(l1, _, l2) -> count bv l1; count bv l2
+  | Ltrywith(l1, _v, l2) -> count bv l1; count bv l2
   | Lifthenelse(l1, l2, l3) -> count bv l1; count bv l2; count bv l3
   | Lsequence(l1, l2) -> count bv l1; count bv l2
   | Lwhile(l1, l2) -> count Tbl.empty l1; count Tbl.empty l2
-  | Lfor(_, l1, l2, dir, l3) -> count bv l1; count bv l2; count Tbl.empty l3
-  | Lassign(v, l) ->
+  | Lfor(_, l1, l2, _dir, l3) -> count bv l1; count bv l2; count Tbl.empty l3
+  | Lassign(_v, l) ->
       (* Lalias-bound variables are never assigned, so don't increase
          v's refcount *)
       count bv l
@@ -417,9 +435,9 @@ let simplify_lets lam =
 (* This (small)  optimisation is always legal, it may uncover some
    tail call later on. *)
 
-  let mklet (kind,v,e1,e2) = match e2 with
+  let mklet str kind v e1 e2  = match e2 with
   | Lvar w when optimize && Ident.same v w -> e1
-  | _ -> Llet (kind,v,e1,e2) in
+  | _ -> Llet (str, kind,v,e1,e2) in
 
 
   let rec simplif = function
@@ -429,42 +447,57 @@ let simplify_lets lam =
       with Not_found ->
         l
       end
-  | Lconst cst as l -> l
-  | Lapply(Lfunction(Curried, params, body), args, _)
+  | Lconst _ as l -> l
+  | 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)
-  | Llet(str, v, Lvar w, l2) when optimize ->
+  | 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; loc} ->
+      begin match simplif l with
+        Lfunction{kind=Curried; params=params'; body; attr; loc}
+        when kind = Curried && optimize ->
+          Lfunction{kind; params = params @ params'; body; attr; loc}
+      | body ->
+          Lfunction{kind; params; body; attr; loc}
+      end
+  | Llet(_str, _k, v, Lvar w, l2) when optimize ->
       Hashtbl.add subst v (simplif (Lvar w));
       simplif l2
-  | Llet(Strict, v, Lprim(Pmakeblock(0, Mutable), [linit]), lbody)
+  | Llet(Strict, kind, v,
+         Lprim(Pmakeblock(0, Mutable, kind_ref) as prim, [linit], loc), lbody)
     when optimize ->
       let slinit = simplif linit in
       let slbody = simplif lbody in
       begin try
-       mklet (Variable, v, slinit, eliminate_ref v slbody)
+        let kind = match kind_ref with
+          | None -> Pgenval
+          | Some [field_kind] -> field_kind
+          | Some _ -> assert false
+        in
+        mklet Variable kind v slinit (eliminate_ref v slbody)
       with Real_reference ->
-        mklet(Strict, v, Lprim(Pmakeblock(0, Mutable), [slinit]), slbody)
+        mklet Strict kind v (Lprim(prim, [slinit], loc)) slbody
       end
-  | Llet(Alias, v, l1, l2) ->
+  | Llet(Alias, kind, v, l1, l2) ->
       begin match count_var v with
         0 -> simplif l2
       | 1 when optimize -> Hashtbl.add subst v (simplif l1); simplif l2
-      | n -> Llet(Alias, v, simplif l1, simplif l2)
+      | _ -> Llet(Alias, kind, v, simplif l1, simplif l2)
       end
-  | Llet(StrictOpt, v, l1, l2) ->
+  | Llet(StrictOpt, kind, v, l1, l2) ->
       begin match count_var v with
         0 -> simplif l2
-      | n -> mklet(Alias, v, simplif l1, simplif l2)
+      | _ -> mklet Alias kind v (simplif l1) (simplif l2)
       end
-  | Llet(kind, v, l1, l2) -> mklet(kind, v, simplif l1, simplif l2)
+  | Llet(str, kind, v, l1, l2) -> mklet str kind v (simplif l1) (simplif l2)
   | Lletrec(bindings, body) ->
       Lletrec(List.map (fun (v, l) -> (v, simplif l)) bindings, simplif body)
-  | Lprim(p, ll) -> Lprim(p, List.map simplif ll)
+  | Lprim(p, ll, loc) -> Lprim(p, List.map simplif ll, loc)
   | Lswitch(l, sw) ->
       let new_l = simplif l
       and new_consts =  List.map (fun (n, e) -> (n, simplif e)) sw.sw_consts
@@ -474,10 +507,10 @@ let simplify_lets lam =
         (new_l,
          {sw with sw_consts = new_consts ; sw_blocks = new_blocks;
                   sw_failaction = new_fail})
-  | Lstringswitch (l,sw,d) ->
+  | Lstringswitch (l,sw,d,loc) ->
       Lstringswitch
         (simplif l,List.map (fun (s,l) -> s,simplif l) sw,
-         Misc.may_map simplif d)
+         Misc.may_map simplif d,loc)
   | Lstaticraise (i,ls) ->
       Lstaticraise (i, List.map simplif ls)
   | Lstaticcatch(l1, (i,args), l2) ->
@@ -504,7 +537,7 @@ let simplify_lets lam =
 (* Tail call info in annotation files *)
 
 let is_tail_native_heuristic : (int -> bool) ref =
-  ref (fun n -> true)
+  ref (fun _ -> true)
 
 let rec emit_tail_infos is_tail lambda =
   let call_kind args =
@@ -516,31 +549,37 @@ 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) ->
+  | Llet (_str, _k, _, lam, body) ->
       emit_tail_infos false lam;
       emit_tail_infos is_tail body
   | Lletrec (bindings, body) ->
       List.iter (fun (_, lam) -> emit_tail_infos false lam) bindings;
       emit_tail_infos is_tail body
-  | Lprim (Pidentity, [arg]) ->
+  | Lprim ((Pidentity | Pbytes_to_string | Pbytes_of_string), [arg], _) ->
       emit_tail_infos is_tail arg
-  | Lprim (Psequand, [arg1; arg2])
-  | Lprim (Psequor, [arg1; arg2]) ->
+  | Lprim (Psequand, [arg1; arg2], _)
+  | Lprim (Psequor, [arg1; arg2], _) ->
       emit_tail_infos false arg1;
       emit_tail_infos is_tail arg2
-  | Lprim (_, l) ->
+  | Lprim (_, l, _) ->
       list_emit_tail_infos false l
   | Lswitch (lam, sw) ->
       emit_tail_infos false lam;
       list_emit_tail_infos_fun snd is_tail sw.sw_consts;
       list_emit_tail_infos_fun snd is_tail sw.sw_blocks;
       Misc.may  (emit_tail_infos is_tail) sw.sw_failaction
-  | Lstringswitch (lam, sw, d) ->
+  | Lstringswitch (lam, sw, d, _) ->
       emit_tail_infos false lam;
       List.iter
         (fun (_,lam) ->  emit_tail_infos is_tail lam)
@@ -574,7 +613,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 +624,73 @@ 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)
+      ~id:fun_id ~kind ~params ~body ~attr ~wrapper_attr ~loc () =
+  let rec aux map = function
+    | Llet(Strict, k, id, (Lifthenelse(Lvar optparam, _, _) as def), rest) when
+        Ident.name optparam = "*opt*" && List.mem optparam params
+          && not (List.mem_assoc optparam map)
+      ->
+        let wrapper_body, inner = aux ((optparam, id) :: map) rest in
+        Llet(Strict, k, 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; loc; }
+        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 = wrapper_attr; loc}); inner]
+  with Exit ->
+    [(fun_id, Lfunction{kind; params; body; attr; loc})]
+
+module Hooks = Misc.MakeHooks(struct
+    type t = lambda
+  end)
+
 (* The entry point:
    simplification + emission of tailcall annotations, if needed. *)
 
-let simplify_lambda lam =
+let simplify_lambda sourcefile lam =
   let res = simplify_lets (simplify_exits lam) in
-  if !Clflags.annotations then emit_tail_infos true res;
+  let res = Hooks.apply_hooks { Misc.sourcefile } res in
+  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 4cc6dab977..6736ffc325 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.
@@ -17,8 +20,22 @@
 
 open Lambda
 
-val simplify_lambda: lambda -> lambda
+val simplify_lambda: string -> lambda -> lambda
+
+val split_default_wrapper
+   : ?create_wrapper_body:(lambda -> lambda)
+  -> id:Ident.t
+  -> kind:function_kind
+  -> params:Ident.t list
+  -> body:lambda
+  -> attr:function_attribute
+  -> wrapper_attr:function_attribute
+  -> loc:Location.t
+  -> unit
+  -> (Ident.t * lambda) list
 
 (* To be filled by asmcomp/selectgen.ml *)
 val is_tail_native_heuristic: (int -> bool) ref
                           (* # arguments -> can tailcall *)
+
+module Hooks : Misc.HookSig with type t = lambda
diff --git a/bytecomp/switch.ml b/bytecomp/switch.ml
index da9a48f1a9..618e5c6c02 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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"
@@ -159,6 +159,7 @@ let pcases chan cases =
 
     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 =
@@ -403,13 +390,13 @@ let rec opt_count top cases =
             if lcases < !cut then
               enum top cases
             else if lcases < !more_cut then
-              heuristic top cases
+              heuristic cases
             else
-              divide top cases in
+              divide cases in
       Hashtbl.add t key r ;
       r
 
-and divide top cases =
+and divide cases =
   let lcases = Array.length cases in
   let m = lcases/2 in
   let _,left,right = coupe cases m in
@@ -425,10 +412,10 @@ and divide top cases =
     add_test cm cml ;
   Sep m,(cm, ci)
 
-and heuristic top cases =
+and heuristic cases =
   let lcases = Array.length cases in
 
-  let sep,csep = divide false cases
+  let sep,csep = divide cases
 
   and inter,cinter =
     if !ok_inter then begin
@@ -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
@@ -614,7 +589,7 @@ and enum top cases =
 
       else begin
 
-        let w,c = opt_count false cases in
+        let w,_c = opt_count false cases in
 (*
   Printf.fprintf stderr
   "off=%d tactic=%a for %a\n"
@@ -689,13 +664,13 @@ let switch_min = ref 3
 (* Particular case 0, 1, 2 *)
 let particular_case cases i j =
   j-i = 2 &&
-  (let l1,h1,act1 = cases.(i)
-  and  l2,h2,act2 = cases.(i+1)
+  (let l1,_h1,act1 = cases.(i)
+  and  l2,_h2,_act2 = cases.(i+1)
   and  l3,h3,act3 = cases.(i+2) in
   l1+1=l2 && l2+1=l3 && l3=h3 &&
   act1 <> act3)
 
-let approx_count cases i j n_actions =
+let approx_count cases i j =
   let l = j-i+1 in
   if l < !cut then
      let _,(_,{n=ntests}) = opt_count false (Array.sub cases i l) in
@@ -705,12 +680,12 @@ let approx_count cases i j n_actions =
 
 (* Sends back a boolean that says whether is switch is worth or not *)
 
-let dense {cases=cases ; actions=actions} i j =
+let dense {cases} i j =
   if i=j then true
   else
     let l,_,_ = cases.(i)
     and _,h,_ = cases.(j) in
-    let ntests =  approx_count cases i j (Array.length actions) in
+    let ntests =  approx_count cases i j in
 (*
   (ntests+1) >= theta * (h-l+1)
 *)
@@ -726,8 +701,8 @@ let dense {cases=cases ; actions=actions} i j =
    Software Practice and Exprience Vol. 24(2) 233 (Feb 1994)
 *)
 
-let comp_clusters ({cases=cases ; actions=actions} as s) =
-  let len = Array.length cases in
+let comp_clusters s =
+  let len = Array.length s.cases in
   let min_clusters = Array.make len max_int
   and k = Array.make len 0 in
   let get_min i = if i < 0 then 0 else min_clusters.(i) in
@@ -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 53fd997485..d0eadf0c50 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 1876f0e4c1..2df00ede3b 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -329,12 +332,12 @@ let check_global_initialized patchlist =
     List.fold_left
       (fun accu rel ->
         match rel with
-          (Reloc_setglobal id, pos) -> id :: accu
+          (Reloc_setglobal id, _pos) -> id :: accu
         | _ -> accu)
       [] patchlist in
   (* Then check that all referenced, not defined globals have a value *)
   let check_reference = function
-      (Reloc_getglobal id, pos) ->
+      (Reloc_getglobal id, _pos) ->
         if not (List.mem id defined_globals)
         && Obj.is_int (get_global_value id)
         then raise (Error(Uninitialized_global(Ident.name id)))
diff --git a/bytecomp/symtable.mli b/bytecomp/symtable.mli
index ffc878bf10..2aa0eaa952 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 0000000000..fae55ccbd2
--- /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 0000000000..be855c2820
--- /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 af99363524..f207167834 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,24 +29,34 @@ 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; loc} ->
+      Lfunction {kind = Curried; params = params @ params'; body = body'; attr;
+                 loc}
   |  _ ->
-      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;
+                 loc = Location.none}
+
+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)
 
-let lfield v i = Lprim(Pfield(i, true, Mutable), [Lvar v])
+let lfield v i = Lprim(Pfield (i, Pointer, Mutable), [Lvar v], Location.none)
 
 let transl_label l = share (Const_immstring l)
 
@@ -53,18 +66,12 @@ 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
-  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 kind =
+    match Typeopt.maybe_pointer expr with
+    | Pointer -> Paddrarray
+    | Immediate -> Pintarray
+  in
+  Lprim(Parraysetu kind, [Lvar obj; Lvar id; transl_exp expr], Location.none)
 
 let transl_val tbl create name =
   mkappl (oo_prim (if create then "new_variable" else "get_variable"),
@@ -73,7 +80,7 @@ let transl_val tbl create name =
 let transl_vals tbl create strict vals rem =
   List.fold_right
     (fun (name, id) rem ->
-      Llet(strict, id, transl_val tbl create name, rem))
+      Llet(strict, Pgenval, id, transl_val tbl create name, rem))
     vals rem
 
 let meths_super tbl meths inh_meths =
@@ -88,7 +95,8 @@ let meths_super tbl meths inh_meths =
 
 let bind_super tbl (vals, meths) cl_init =
   transl_vals tbl false StrictOpt vals
-    (List.fold_right (fun (nm, id, def) rem -> Llet(StrictOpt, id, def, rem))
+    (List.fold_right (fun (_nm, id, def) rem ->
+         Llet(StrictOpt, Pgenval, id, def, rem))
        meths cl_init)
 
 let create_object cl obj init =
@@ -101,7 +109,7 @@ let create_object cl obj init =
              [obj; Lvar cl]))
   else begin
    (inh_init,
-    Llet(Strict, obj',
+    Llet(Strict, Pgenval, obj',
             mkappl (oo_prim "create_object_opt", [obj; Lvar cl]),
          Lsequence(obj_init,
                    if not has_init then Lvar obj' else
@@ -112,7 +120,7 @@ let create_object cl obj init =
 let name_pattern default p =
   match p.pat_desc with
   | Tpat_var (id, _) -> id
-  | Tpat_alias(p, id, _) -> id
+  | Tpat_alias(_, id, _) -> id
   | _ -> Ident.create default
 
 let normalize_cl_path cl path =
@@ -126,8 +134,9 @@ let rec build_object_init cl_table obj params inh_init obj_init cl =
       let env =
         match envs with None -> []
         | Some envs ->
-            [Lprim(Pfield(List.length inh_init + 1, true, Mutable),
-                   [Lvar envs])]
+            [Lprim(Pfield (List.length inh_init + 1, Pointer, Mutable),
+                   [Lvar envs],
+                   Location.none)]
       in
       ((envs, (obj_init, normalize_cl_path cl path)
         ::inh_init),
@@ -169,12 +178,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;
+                    loc = pat.pat_loc;
+                    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
+         Lfunction {kind = Curried; params; body = rem} -> build params rem
        | rem                              -> build [] rem
        end)
   | Tcl_apply (cl, oexprs) ->
@@ -188,12 +199,12 @@ let rec build_object_init cl_table obj params inh_init obj_init cl =
         build_object_init cl_table obj (vals @ params) inh_init obj_init cl
       in
       (inh_init, Translcore.transl_let rec_flag defs obj_init)
-  | Tcl_constraint (cl, _, vals, pub_meths, concr_meths) ->
+  | Tcl_constraint (cl, _, _vals, _pub_meths, _concr_meths) ->
       build_object_init cl_table obj params inh_init obj_init cl
 
 let rec build_object_init_0 cl_table params cl copy_env subst_env top ids =
   match cl.cl_desc with
-    Tcl_let (rec_flag, defs, vals, cl) ->
+    Tcl_let (_rec_flag, _defs, vals, cl) ->
       let vals = List.map (fun (id, _, e) -> id,e) vals in
       build_object_init_0 cl_table (vals@params) cl copy_env subst_env top ids
   | _ ->
@@ -202,14 +213,14 @@ let rec build_object_init_0 cl_table params cl copy_env subst_env top ids =
       let obj = if ids = [] then lambda_unit else Lvar self in
       let envs = if top then None else Some env in
       let ((_,inh_init), obj_init) =
-        build_object_init cl_table obj params (envs,[]) (copy_env env) cl in
+        build_object_init cl_table obj params (envs,[]) copy_env cl in
       let obj_init =
         if ids = [] then obj_init else lfunction [self] obj_init in
       (inh_init, lfunction [env] (subst_env env inh_init obj_init))
 
 
 let bind_method tbl lab id cl_init =
-  Llet(Strict, id, mkappl (oo_prim "get_method_label",
+  Llet(Strict, Pgenval, id, mkappl (oo_prim "get_method_label",
                            [Lvar tbl; transl_label lab]),
        cl_init)
 
@@ -224,11 +235,12 @@ let bind_methods tbl meths vals cl_init =
     if nvals = 0 then "get_method_labels", [] else
     "new_methods_variables", [transl_meth_list (List.map fst vals)]
   in
-  Llet(Strict, ids,
+  Llet(Strict, Pgenval, ids,
        mkappl (oo_prim getter,
                [Lvar tbl; transl_meth_list (List.map fst methl)] @ names),
        List.fold_right
-         (fun (lab,id) lam -> decr i; Llet(StrictOpt, id, lfield ids !i, lam))
+         (fun (_lab,id) lam -> decr i; Llet(StrictOpt, Pgenval, id,
+                                           lfield ids !i, lam))
          (methl @ vals) cl_init)
 
 let output_methods tbl methods lam =
@@ -238,7 +250,8 @@ let output_methods tbl methods lam =
       lsequence (mkappl(oo_prim "set_method", [Lvar tbl; lab; code])) lam
   | _ ->
       lsequence (mkappl(oo_prim "set_methods",
-                        [Lvar tbl; Lprim(Pmakeblock(0,Immutable), methods)]))
+                        [Lvar tbl; Lprim(Pmakeblock(0,Immutable,None),
+                                         methods, Location.none)]))
         lam
 
 let rec ignore_cstrs cl =
@@ -258,12 +271,12 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
   match cl.cl_desc with
     Tcl_ident ( path, _, _) ->
       begin match inh_init with
-        (obj_init, path')::inh_init ->
+        (obj_init, _path')::inh_init ->
           let lpath = transl_path ~loc:cl.cl_loc cl.cl_env path in
           (inh_init,
-           Llet (Strict, obj_init,
-                 mkappl(Lprim(Pfield(1, true, Mutable), [lpath]), Lvar cla ::
-                        if top then [Lprim(Pfield(3, true, Mutable), [lpath])]
+           Llet (Strict, Pgenval, obj_init,
+                 mkappl(Lprim(Pfield (1, Pointer, Mutable), [lpath], Location.none), Lvar cla ::
+                        if top then [Lprim(Pfield (3, Pointer, Mutable), [lpath], Location.none)]
                         else []),
                  bind_super cla super cl_init))
       | _ ->
@@ -297,7 +310,7 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
                   if !Clflags.native_code && List.length met_code = 1 then
                     (* Force correct naming of method for profiles *)
                     let met = Ident.create ("method_" ^ name.txt) in
-                    [Llet(Strict, met, List.hd met_code, Lvar met)]
+                    [Llet(Strict, Pgenval, met, List.hd met_code, Lvar met)]
                   else met_code
                 in
                 (inh_init, cl_init,
@@ -316,15 +329,15 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
       in
       let cl_init = output_methods cla methods cl_init in
       (inh_init, bind_methods cla str.cstr_meths values cl_init)
-  | Tcl_fun (_, pat, vals, cl, _) ->
+  | Tcl_fun (_, _pat, vals, cl, _) ->
       let (inh_init, cl_init) =
         build_class_init cla cstr super inh_init cl_init msubst top cl
       in
       let vals = List.map bind_id_as_val vals in
       (inh_init, transl_vals cla true StrictOpt vals cl_init)
-  | Tcl_apply (cl, exprs) ->
+  | Tcl_apply (cl, _exprs) ->
       build_class_init cla cstr super inh_init cl_init msubst top cl
-  | Tcl_let (rec_flag, defs, vals, cl) ->
+  | Tcl_let (_rec_flag, _defs, vals, cl) ->
       let (inh_init, cl_init) =
         build_class_init cla cstr super inh_init cl_init msubst top cl
       in
@@ -350,19 +363,21 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
           let cl_init =
             List.fold_left
               (fun init (nm, id, _) ->
-                Llet(StrictOpt, id, lfield inh (index nm concr_meths + ofs),
+                Llet(StrictOpt, Pgenval, id,
+                     lfield inh (index nm concr_meths + ofs),
                      init))
               cl_init methids in
           let cl_init =
             List.fold_left
               (fun init (nm, id) ->
-                Llet(StrictOpt, id, lfield inh (index nm vals + 1), init))
+                Llet(StrictOpt, Pgenval, id,
+                     lfield inh (index nm vals + 1), init))
               cl_init valids in
           (inh_init,
-           Llet (Strict, inh,
+           Llet (Strict, Pgenval, inh,
                  mkappl(oo_prim "inherits", narrow_args @
                         [lpath; Lconst(Const_pointer(if top then 1 else 0))]),
-                 Llet(StrictOpt, obj_init, lfield inh 0, cl_init)))
+                 Llet(StrictOpt, Pgenval, obj_init, lfield inh 0, cl_init)))
       | _ ->
           let core cl_init =
             build_class_init cla true super inh_init cl_init msubst top cl
@@ -378,7 +393,7 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
 
 let rec build_class_lets cl ids =
   match cl.cl_desc with
-    Tcl_let (rec_flag, defs, vals, cl') ->
+    Tcl_let (rec_flag, defs, _vals, cl') ->
       let env, wrap = build_class_lets cl' [] in
       (env, fun x ->
         let lam = Translcore.transl_let rec_flag defs (wrap x) in
@@ -400,6 +415,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 =
@@ -414,18 +430,20 @@ 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;
+                   loc = pat.pat_loc;
+                   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
+         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)
-  | Tcl_let (rec_flag, defs, vals, cl) ->
+  | Tcl_let (rec_flag, defs, _vals, cl) ->
       let path, obj_init = transl_class_rebind obj_init cl vf in
       (path, Translcore.transl_let rec_flag defs obj_init)
   | Tcl_structure _ -> raise Exit
@@ -441,7 +459,7 @@ let rec transl_class_rebind obj_init cl vf =
 
 let rec transl_class_rebind_0 self obj_init cl vf =
   match cl.cl_desc with
-    Tcl_let (rec_flag, defs, vals, cl) ->
+    Tcl_let (rec_flag, defs, _vals, cl) ->
       let path, obj_init = transl_class_rebind_0 self obj_init cl vf in
       (path, Translcore.transl_let rec_flag defs obj_init)
   | _ ->
@@ -452,7 +470,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));
@@ -465,19 +490,20 @@ let transl_class_rebind ids cl vf =
     and table = Ident.create "table"
     and envs = Ident.create "envs" in
     Llet(
-    Strict, new_init, lfunction [obj_init] obj_init',
+    Strict, Pgenval, new_init, lfunction [obj_init] obj_init',
     Llet(
-    Alias, cla, transl_normal_path path,
-    Lprim(Pmakeblock(0, Immutable),
+    Alias, Pgenval, cla, transl_normal_path path,
+    Lprim(Pmakeblock(0, Immutable, None),
           [mkappl(Lvar new_init, [lfield cla 0]);
            lfunction [table]
-             (Llet(Strict, env_init,
+             (Llet(Strict, Pgenval, env_init,
                    mkappl(lfield cla 1, [Lvar table]),
                    lfunction [envs]
                      (mkappl(Lvar new_init,
                              [mkappl(Lvar env_init, [Lvar envs])]))));
            lfield cla 2;
-           lfield cla 3])))
+           lfield cla 3],
+          Location.none)))
   with Exit ->
     lambda_unit
 
@@ -486,14 +512,14 @@ let transl_class_rebind ids cl vf =
 let rec module_path = function
     Lvar id ->
       let s = Ident.name id in s <> "" && s.[0] >= 'A' && s.[0] <= 'Z'
-  | Lprim(Pfield _, [p])    -> module_path p
-  | Lprim(Pgetglobal _, []) -> true
+  | Lprim(Pfield _, [p], _)    -> module_path p
+  | Lprim(Pgetglobal _, [], _) -> true
   | _                       -> false
 
 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
@@ -503,23 +529,23 @@ let rec builtin_meths self env env2 body =
   let conv = function
     (* Lvar s when List.mem s self ->  "_self", [] *)
     | p when const_path p -> "const", [p]
-    | Lprim(Parrayrefu _, [Lvar s; Lvar n]) when List.mem s self ->
+    | Lprim(Parrayrefu _, [Lvar s; Lvar n], _) when List.mem s self ->
         "var", [Lvar n]
-    | Lprim(Pfield(n, _, _), [Lvar e]) when Ident.same e env ->
+    | Lprim(Pfield(n, _, _), [Lvar e], _) when Ident.same e env ->
         "env", [Lvar env2; Lconst(Const_pointer n)]
     | Lsend(Self, met, Lvar s, [], _) when List.mem s self ->
         "meth", [met]
     | _ -> raise Not_found
   in
   match body with
-  | Llet(_, s', Lvar s, body) when List.mem s self ->
+  | Llet(_str, _k, 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 ->
@@ -533,12 +559,12 @@ 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'])
+        | Lprim(Parraysetu _, [Lvar s; Lvar n; Lvar x'], _)
           when Ident.same x x' && List.mem s self ->
             ("set_var", [Lvar n])
-        | Llet(_, s', Lvar s, body) when List.mem s self ->
+        | Llet(_str, _k, s', Lvar s, body) when List.mem s self ->
             enter (s'::self) body
         | _ -> raise Not_found
       in enter self body
@@ -583,26 +609,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 *)
@@ -641,7 +670,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
@@ -654,24 +683,27 @@ let transl_class ids cl_id pub_meths cl vflag =
         with Not_found ->
           [lfunction (self :: args)
              (if not (IdentSet.mem env (free_variables body')) then body' else
-              Llet(Alias, env,
+              Llet(Alias, Pgenval, env,
                    Lprim(Parrayrefu Paddrarray,
-                         [Lvar self; Lvar env2]), body'))]
+                         [Lvar self; Lvar env2],
+                         Location.none),
+                   body'))]
         end
       | _ -> assert false
   in
   let new_ids_init = ref [] in
   let env1 = Ident.create "env" and env1' = Ident.create "env'" in
-  let copy_env envs self =
+  let copy_env self =
     if top then lambda_unit else
     Lifused(env2, Lprim(Parraysetu Paddrarray,
-                        [Lvar self; Lvar env2; Lvar env1']))
+                        [Lvar self; Lvar env2; Lvar env1'],
+                        Location.none))
   and subst_env envs l lam =
     if top then lam else
     (* must be called only once! *)
     let lam = subst_lambda (subst env1 lam 1 new_ids_init) lam in
-    Llet(Alias, env1, (if l = [] then Lvar envs else lfield envs 0),
-    Llet(Alias, env1',
+    Llet(Alias, Pgenval, env1, (if l = [] then Lvar envs else lfield envs 0),
+    Llet(Alias, Pgenval, env1',
          (if !new_ids_init = [] then Lvar env1 else lfield env1 0),
          lam))
   in
@@ -701,10 +733,10 @@ let transl_class ids cl_id pub_meths cl vflag =
       if name' <> name then raise(Error(cl.cl_loc, Tags(name, name'))))
     tags pub_meths;
   let ltable table lam =
-    Llet(Strict, table,
+    Llet(Strict, Pgenval, table,
          mkappl (oo_prim "create_table", [transl_meth_list pub_meths]), lam)
   and ldirect obj_init =
-    Llet(Strict, obj_init, cl_init,
+    Llet(Strict, Pgenval, obj_init, cl_init,
          Lsequence(mkappl (oo_prim "init_class", [Lvar cla]),
                    mkappl (Lvar obj_init, [lambda_unit])))
   in
@@ -713,8 +745,11 @@ 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
-    Llet(Strict, class_init, cl_init, lam (free_variables cl_init))
+    let cl_init = llets (Lfunction{kind = Curried;
+                                   attr = default_function_attribute;
+                                   loc = Location.none;
+                                   params = [cla]; body = cl_init}) in
+    Llet(Strict, Pgenval, 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
       mkappl (oo_prim "make_class",[transl_meth_list pub_meths;
@@ -722,15 +757,21 @@ let transl_class ids cl_id pub_meths cl vflag =
     else
       ltable table (
       Llet(
-      Strict, env_init, mkappl (Lvar class_init, [Lvar table]),
+      Strict, Pgenval, env_init, mkappl (Lvar class_init, [Lvar table]),
       Lsequence(
       mkappl (oo_prim "init_class", [Lvar table]),
-      Lprim(Pmakeblock(0, Immutable),
+      Lprim(Pmakeblock(0, Immutable, None),
             [mkappl (Lvar env_init, [lambda_unit]);
-             Lvar class_init; Lvar env_init; lambda_unit]))))
+             Lvar class_init; Lvar env_init; lambda_unit],
+            Location.none))))
   and lbody_virt lenvs =
-    Lprim(Pmakeblock(0, Immutable),
-          [lambda_unit; Lfunction(Curried,[cla], cl_init); lambda_unit; lenvs])
+    Lprim(Pmakeblock(0, Immutable, None),
+          [lambda_unit; Lfunction{kind = Curried;
+                                  attr = default_function_attribute;
+                                  loc = Location.none;
+                                  params = [cla]; body = cl_init};
+           lambda_unit; lenvs],
+         Location.none)
   in
   (* Still easy: a class defined at toplevel *)
   if top && concrete then lclass lbody else
@@ -746,53 +787,65 @@ let transl_class ids cl_id pub_meths cl vflag =
   let lenv =
     let menv =
       if !new_ids_meths = [] then lambda_unit else
-      Lprim(Pmakeblock(0, Immutable),
-            List.map (fun id -> Lvar id) !new_ids_meths) in
+      Lprim(Pmakeblock(0, Immutable, None),
+            List.map (fun id -> Lvar id) !new_ids_meths,
+            Location.none) in
     if !new_ids_init = [] then menv else
-    Lprim(Pmakeblock(0, Immutable),
-          menv :: List.map (fun id -> Lvar id) !new_ids_init)
+    Lprim(Pmakeblock(0, Immutable, None),
+          menv :: List.map (fun id -> Lvar id) !new_ids_init,
+          Location.none)
   and linh_envs =
     List.map
-      (fun (_, p) ->
-         Lprim(Pfield(3, true, Mutable), [transl_normal_path p]))
+      (fun (_, p) -> Lprim(Pfield (3, Pointer, Mutable),
+                       [transl_normal_path p], Location.none))
       (List.rev inh_init)
   in
   let make_envs lam =
-    Llet(StrictOpt, envs,
+    Llet(StrictOpt, Pgenval, envs,
          (if linh_envs = [] then lenv else
-         Lprim(Pmakeblock(0, Immutable), lenv :: linh_envs)),
+         Lprim(Pmakeblock(0, Immutable, None),
+               lenv :: linh_envs, Location.none)),
          lam)
   and def_ids cla lam =
-    Llet(StrictOpt, env2,
+    Llet(StrictOpt, Pgenval, env2,
          mkappl (oo_prim "new_variable", [Lvar cla; transl_label ""]),
          lam)
   in
   let inh_paths =
     List.filter
-      (fun (_,path) -> List.mem (Path.head path) new_ids) inh_init in
+      (fun (_,path) -> List.mem (Path.head path) new_ids) inh_init
+  in
   let inh_keys =
-    List.map
-      (fun (_,p) ->
-         Lprim(Pfield(1, true, Mutable), [transl_normal_path p])) inh_paths in
+    List.map (fun (_,p) -> Lprim(Pfield (1, Pointer, Mutable),
+        [transl_normal_path p], Location.none))
+      inh_paths
+  in
   let lclass lam =
-    Llet(Strict, class_init,
-         Lfunction(Curried, [cla], def_ids cla cl_init), lam)
+    Llet(Strict, Pgenval, class_init,
+         Lfunction{kind = Curried; params = [cla];
+                   attr = default_function_attribute;
+                   loc = Location.none;
+                   body = def_ids cla cl_init}, lam)
   and lcache lam =
-    if inh_keys = [] then Llet(Alias, cached, Lvar tables, lam) else
-    Llet(Strict, cached,
+    if inh_keys = [] then Llet(Alias, Pgenval, cached, Lvar tables, lam) else
+    Llet(Strict, Pgenval, cached,
          mkappl (oo_prim "lookup_tables",
-                [Lvar tables; Lprim(Pmakeblock(0, Immutable), inh_keys)]),
+                [Lvar tables; Lprim(Pmakeblock(0, Immutable, None),
+                                    inh_keys, Location.none)]),
          lam)
   and lset cached i lam =
-    Lprim(Psetfield(i, true, Mutable), [Lvar cached; lam])
+    Lprim(Psetfield(i, Pointer, Assignment),
+          [Lvar cached; lam], Location.none)
   in
   let ldirect () =
     ltable cla
-      (Llet(Strict, env_init, def_ids cla cl_init,
+      (Llet(Strict, Pgenval, env_init, def_ids cla cl_init,
             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;
+                             loc = Location.none;
+                             params = [cla]; body = def_ids cla cl_init})
   in
   llets (
   lcache (
@@ -806,13 +859,14 @@ let transl_class ids cl_id pub_meths cl vflag =
                        Lvar class_init; Lvar cached]))),
   make_envs (
   if ids = [] then mkappl (lfield cached 0, [lenvs]) else
-  Lprim(Pmakeblock(0, Immutable),
-        if concrete then
+  Lprim(Pmakeblock(0, Immutable, None),
+        (if concrete then
           [mkappl (lfield cached 0, [lenvs]);
            lfield cached 1;
            lfield cached 0;
            lenvs]
-        else [lambda_unit; lfield cached 0; lambda_unit; lenvs]
+        else [lambda_unit; lfield cached 0; lambda_unit; lenvs]),
+        Location.none
        )))))
 
 (* Wrapper for class compilation *)
diff --git a/bytecomp/translclass.mli b/bytecomp/translclass.mli
index f7858da207..bbd21e93a2 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 28a979ee73..cc2ac28ab0 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,126 +29,156 @@ 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) :
+  ref((fun _cc _rootpath _modl -> assert false) :
       module_coercion -> Path.t option -> module_expr -> lambda)
 
 let transl_object =
-  ref (fun id s cl -> assert false :
+  ref (fun _id _s _cl -> assert false :
        Ident.t -> string list -> class_expr -> lambda)
 
+(* Compile an exception/extension definition *)
+
+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, !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
+  let loc = ext.ext_loc in
+  match ext.ext_kind with
+    Text_decl _ ->
+      Lprim (Pmakeblock (Obj.object_tag, Immutable, None),
+        [Lconst (Const_base (Const_string (name, None)));
+         Lprim (prim_fresh_oo_id, [Lconst (Const_base (Const_int 0))], loc)],
+        loc)
+  | Text_rebind(path, _lid) ->
+      transl_path ~loc env path
+
 (* Translation of primitives *)
 
 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),
+       Pccall(Primitive.simple ~name:"caml_bytes_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),
+       Pccall(Primitive.simple ~name:"caml_bytes_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),
+       Pccall(Primitive.simple ~name:"caml_bytes_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),
+       Pccall(Primitive.simple ~name:"caml_bytes_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),
+       Pccall(Primitive.simple ~name:"caml_bytes_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),
+       Pccall(Primitive.simple ~name:"caml_bytes_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),
+       Pccall(Primitive.simple ~name:"caml_bytes_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)
 ]
 
 let primitives_table = create_hashtable 57 [
   "%identity", Pidentity;
+  "%bytes_to_string", Pbytes_to_string;
+  "%bytes_of_string", Pbytes_of_string;
   "%ignore", Pignore;
-  "%field0", Pfield(0, true, Mutable);
-  "%field1", Pfield(1, true, Mutable);
-  "%setfield0", Psetfield(0, true, Mutable);
-  "%makeblock", Pmakeblock(0, Immutable);
-  "%makemutable", Pmakeblock(0, Mutable);
+  "%revapply", Prevapply;
+  "%apply", Pdirapply;
+  "%loc_LOC", Ploc Loc_LOC;
+  "%loc_FILE", Ploc Loc_FILE;
+  "%loc_LINE", Ploc Loc_LINE;
+  "%loc_POS", Ploc Loc_POS;
+  "%loc_MODULE", Ploc Loc_MODULE;
+  "%field0", Pfield(0, Pointer, Mutable);
+  "%field1", Pfield(1, Pointer, Mutable);
+  "%setfield0", Psetfield(0, Pointer, Assignment);
+  "%makeblock", Pmakeblock(0, Immutable, None);
+  "%makemutable", Pmakeblock(0, Mutable, None);
   "%raise", Praise Raise_regular;
   "%reraise", Praise Raise_reraise;
   "%raise_notrace", Praise Raise_notrace;
@@ -153,7 +186,10 @@ let primitives_table = create_hashtable 57 [
   "%sequor", Psequor;
   "%boolnot", Pnot;
   "%big_endian", Pctconst Big_endian;
+  "%backend_type", Pctconst Backend_type;
   "%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;
@@ -163,8 +199,8 @@ let primitives_table = create_hashtable 57 [
   "%addint", Paddint;
   "%subint", Psubint;
   "%mulint", Pmulint;
-  "%divint", Pdivint;
-  "%modint", Pmodint;
+  "%divint", Pdivint Safe;
+  "%modint", Pmodint Safe;
   "%andint", Pandint;
   "%orint", Porint;
   "%xorint", Pxorint;
@@ -195,9 +231,14 @@ let primitives_table = create_hashtable 57 [
   "%gefloat", Pfloatcomp Cge;
   "%string_length", Pstringlength;
   "%string_safe_get", Pstringrefs;
-  "%string_safe_set", Pstringsets;
+  "%string_safe_set", Pbytessets;
   "%string_unsafe_get", Pstringrefu;
-  "%string_unsafe_set", Pstringsetu;
+  "%string_unsafe_set", Pbytessetu;
+  "%bytes_length", Pbyteslength;
+  "%bytes_safe_get", Pbytesrefs;
+  "%bytes_safe_set", Pbytessets;
+  "%bytes_unsafe_get", Pbytesrefu;
+  "%bytes_unsafe_set", Pbytessetu;
   "%array_length", Parraylength Pgenarray;
   "%array_safe_get", Parrayrefs Pgenarray;
   "%array_safe_set", Parraysets Pgenarray;
@@ -214,8 +255,8 @@ let primitives_table = create_hashtable 57 [
   "%nativeint_add", Paddbint Pnativeint;
   "%nativeint_sub", Psubbint Pnativeint;
   "%nativeint_mul", Pmulbint Pnativeint;
-  "%nativeint_div", Pdivbint Pnativeint;
-  "%nativeint_mod", Pmodbint Pnativeint;
+  "%nativeint_div", Pdivbint ( Pnativeint, Safe );
+  "%nativeint_mod", Pmodbint ( Pnativeint, Safe );
   "%nativeint_and", Pandbint Pnativeint;
   "%nativeint_or",  Porbint Pnativeint;
   "%nativeint_xor", Pxorbint Pnativeint;
@@ -228,8 +269,8 @@ let primitives_table = create_hashtable 57 [
   "%int32_add", Paddbint Pint32;
   "%int32_sub", Psubbint Pint32;
   "%int32_mul", Pmulbint Pint32;
-  "%int32_div", Pdivbint Pint32;
-  "%int32_mod", Pmodbint Pint32;
+  "%int32_div", Pdivbint ( Pint32, Safe );
+  "%int32_mod", Pmodbint ( Pint32, Safe );
   "%int32_and", Pandbint Pint32;
   "%int32_or",  Porbint Pint32;
   "%int32_xor", Pxorbint Pint32;
@@ -242,8 +283,8 @@ let primitives_table = create_hashtable 57 [
   "%int64_add", Paddbint Pint64;
   "%int64_sub", Psubbint Pint64;
   "%int64_mul", Pmulbint Pint64;
-  "%int64_div", Pdivbint Pint64;
-  "%int64_mod", Pmodbint Pint64;
+  "%int64_div", Pdivbint ( Pint64, Safe );
+  "%int64_mod", Pmodbint ( Pint64, Safe );
   "%int64_and", Pandbint Pint64;
   "%int64_or",  Porbint Pint64;
   "%int64_xor", Pxorbint Pint64;
@@ -315,160 +356,181 @@ let primitives_table = create_hashtable 57 [
   "%atomic_load", Patomic_load;
   "%atomic_store", Patomic_store;
   "%atomic_cas", Patomic_cas;
+  "%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 }
-
-let find_primitive loc prim_name =
+let specialize_comparison table env ty =
+  let (gencomp, intcomp, floatcomp, stringcomp, bytescomp,
+           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_bytes     -> bytescomp
+  | () 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
+
+let find_primitive prim_name =
   match prim_name with
-      "%revapply" -> Prevapply loc
-    | "%apply" -> Pdirapply loc
+      "%revapply" -> Prevapply
+    | "%apply" -> Pdirapply
     | "%loc_LOC" -> Ploc Loc_LOC
     | "%loc_FILE" -> Ploc Loc_FILE
     | "%loc_LINE" -> Ploc Loc_LINE
     | "%loc_POS" -> Ploc Loc_POS
     | "%loc_MODULE" -> Ploc Loc_MODULE
-    | "%perform" -> Pperform loc 
-    | "%resume"-> Presume loc
+    | "%perform" -> Pperform
+    | "%resume"-> Presume
     | name -> Hashtbl.find primitives_table name
 
-let transl_prim loc prim args =
-  let prim_name = prim.prim_name in
+(* Specialize a primitive from available type information,
+   raise Not_found if primitive is unknown  *)
+let specialize_primitive 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 p.prim_name in
     (* Try strength reduction based on the type of the argument *)
-    begin match (p, args) with
-        (Psetfield(n, _, mut), [arg1; arg2]) ->
-            Psetfield(n, maybe_pointer arg2, mut)
-      | (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)
+    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),
-                      arg1 :: _) ->
-            let (k, l) = bigarray_kind_and_layout arg1 in
+       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),
-                      arg1 :: _) ->
-            let (k, l) = bigarray_kind_and_layout arg1 in
+       p1 :: _) ->
+        let (k, l) = bigarray_type_kind_and_layout env p1 in
             Pbigarrayset(unsafe, n, k, l)
+    | (Pmakeblock(tag, mut, None), fields) ->
+        let shape = List.map (Typeopt.value_kind env) fields in
+        Pmakeblock(tag, mut, Some shape)
       | _ -> 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 *)
 
-(* Eta-expand a primitive without knowing the types of its arguments *)
+let used_primitives = Hashtbl.create 7
+let add_used_primitive loc 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 =
+let transl_primitive loc p env ty path =
   let prim =
-    try
-      let (gencomp, _, _, _, _, _, _, _) =
-        Hashtbl.find comparisons_table p.prim_name in
-      gencomp
+    try specialize_primitive p env ty ~has_constant_constructor:false
     with Not_found ->
-    try
-      find_primitive loc p.prim_name
-    with Not_found ->
-      Pccall p in
+      add_used_primitive loc 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;
+                loc = loc;
+                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;
+                  loc = loc;
+                  body = Lprim(Pmakeblock(0, Immutable, None),
+                               [lam; Lvar param], loc)}
       | _ -> 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;
+                 loc = loc;
+                 body = Lprim(prim, List.map (fun id -> Lvar id) params, loc) }
+
+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 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 env path;
+    Pccall prim
+
 
 (* To check the well-formedness of r.h.s. of "let rec" definitions *)
 
 let check_recursive_lambda idlist lam =
   let rec check_top idlist = function
     | Lvar v -> not (List.mem v idlist)
-    | Llet (_, _, _, _) as lam when check_recursive_recordwith idlist lam ->
+    | Llet _ as lam when check_recursive_recordwith idlist lam ->
         true
-    | Llet(str, id, arg, body) ->
+    | Llet(_str, _k, id, arg, body) ->
         check idlist arg && check_top (add_let id arg idlist) body
     | Lletrec(bindings, body) ->
         let idlist' = add_letrec bindings idlist in
-        List.for_all (fun (id, arg) -> check idlist' arg) bindings &&
+        List.for_all (fun (_id, arg) -> check idlist' arg) bindings &&
         check_top idlist' body
-    | Lprim (Pmakearray (Pgenarray), args) -> false
+    | Lprim (Pmakearray (Pgenarray, _), _, _) -> 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
-    | Llet (_, _, _, _) as lam when check_recursive_recordwith idlist lam ->
+    | Lfunction _ -> true
+    | Llet _ as lam when check_recursive_recordwith idlist lam ->
         true
-    | Llet(str, id, arg, body) ->
+    | Llet(_str, _k, id, arg, body) ->
         check idlist arg && check (add_let id arg idlist) body
     | Lletrec(bindings, body) ->
         let idlist' = add_letrec bindings idlist in
-        List.for_all (fun (id, arg) -> check idlist' arg) bindings &&
+        List.for_all (fun (_id, arg) -> check idlist' arg) bindings &&
         check idlist' body
-    | Lprim(Pmakeblock(tag, mut), args) ->
+    | Lprim(Pmakeblock _, 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
@@ -489,13 +551,14 @@ let check_recursive_lambda idlist lam =
   (* reverse-engineering the code generated by transl_record case 2 *)
   (* If you change this, you probably need to change Bytegen.size_of_lambda. *)
   and check_recursive_recordwith idlist = function
-    | Llet (Strict, id1, Lprim (Pduprecord _, [e1]), body) ->
+    | Llet (Strict, _k, id1, Lprim (Pduprecord _, [e1], _), body) ->
        check_top idlist e1
        && check_recordwith_updates idlist id1 body
     | _ -> false
 
   and check_recordwith_updates idlist id1 = function
-    | Lsequence (Lprim ((Psetfield _ | Psetfloatfield _), [Lvar id2; e1]), cont)
+    | Lsequence (Lprim ((Psetfield _ | Psetfloatfield _), [Lvar id2; e1], _),
+                 cont)
         -> id2 = id1 && check idlist e1
            && check_recordwith_updates idlist id1 cont
     | Lvar id2 -> id2 = id1
@@ -522,10 +585,15 @@ let rec name_pattern default = function
   | {c_lhs=p; _} :: rem ->
       match p.pat_desc with
         Tpat_var (id, _) -> id
-      | Tpat_alias(p, id, _) -> id
+      | Tpat_alias(_, id, _) -> id
       | _ -> name_pattern default rem
 
 (* Push the default values under the functional abstractions *)
+(* Also push bindings of module patterns, since this sound *)
+
+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
@@ -538,14 +606,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)
+      push_defaults loc (Bind_value binds :: bindings)
+                    [{c_lhs=pat; c_cont=None; 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_cont=None;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}]
@@ -575,7 +654,7 @@ let rec push_defaults loc bindings cases partial =
 let event_before exp lam = match lam with
 | Lstaticraise (_,_) -> lam
 | _ ->
-  if !Clflags.debug
+  if !Clflags.debug && not !Clflags.native_code
   then Levent(lam, {lev_loc = exp.exp_loc;
                     lev_kind = Lev_before;
                     lev_repr = None;
@@ -583,7 +662,7 @@ let event_before exp lam = match lam with
   else lam
 
 let event_after exp lam =
-  if !Clflags.debug
+  if !Clflags.debug && not !Clflags.native_code
   then Levent(lam, {lev_loc = exp.exp_loc;
                     lev_kind = Lev_after exp.exp_type;
                     lev_repr = None;
@@ -591,7 +670,7 @@ let event_after exp lam =
   else lam
 
 let event_function exp lam =
-  if !Clflags.debug then
+  if !Clflags.debug && not !Clflags.native_code then
     let repr = Some (ref 0) in
     let (info, body) = lam repr in
     (info,
@@ -605,8 +684,9 @@ let event_function exp lam =
 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
+  | Pccall _ | Pstringrefs  | Pbytesrefs | Pbytessets | Parrayrefs _ |
+    Parraysets _ | Pbigarrayref _ | Pbigarrayset _ | Pduprecord _ | Pdirapply |
+    Prevapply -> true
   | _ -> false
 
 (* Assertions *)
@@ -615,12 +695,12 @@ let assert_failed exp =
   let (fname, line, char) =
     Location.get_pos_info exp.exp_loc.Location.loc_start in
   Lprim(Praise Raise_regular, [event_after exp
-    (Lprim(Pmakeblock(0, Immutable),
+    (Lprim(Pmakeblock(0, Immutable, None),
           [transl_normal_path Predef.path_assert_failure;
            Lconst(Const_block(0,
               [Const_base(Const_string (fname, None));
                Const_base(Const_int line);
-               Const_base(Const_int char)]))]))])
+               Const_base(Const_int char)]))], exp.exp_loc))], exp.exp_loc)
 ;;
 
 let rec cut n l =
@@ -633,6 +713,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
@@ -649,17 +730,21 @@ 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;
+                  loc = e.exp_loc;
+                  body = Lsend(kind, Lvar meth, Lvar obj, [], e.exp_loc)}
       else if p.prim_name = "%sendcache" then
         let obj = Ident.create "obj" and meth = Ident.create "meth" in
         let cache = Ident.create "cache" and pos = Ident.create "pos" in
-        Lfunction(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;
+                  loc = e.exp_loc;
+                  body = Lsend(Cached, Lvar meth, Lvar obj,
+                               [Lvar cache; Lvar pos], e.exp_loc)}
       else
-        transl_primitive e.exp_loc p
-  | Texp_ident(path, _, {val_kind = Val_anc _}) ->
+        transl_primitive e.exp_loc p e.exp_env e.exp_type (Some path)
+  | Texp_ident(_, _, {val_kind = Val_anc _}) ->
       raise(Error(e.exp_loc, Free_super_var))
   | Texp_ident(path, _, {val_kind = Val_reg | Val_self _}) ->
       transl_path ~loc:e.exp_loc e.exp_env path
@@ -675,21 +760,41 @@ 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
+      let loc = e.exp_loc in
+      Lfunction{kind; params; body; attr; loc}
+  | 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
@@ -702,7 +807,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
@@ -714,59 +820,78 @@ and transl_exp0 e =
               | _ ->
                   k
             in
-            wrap0 (Lprim(Praise k, [event_after arg1 targ]))
+            wrap0 (Lprim(Praise k, [event_after arg1 targ], e.exp_loc))
         | (Ploc kind, []) ->
           lam_of_loc kind e.exp_loc
         | (Ploc kind, [arg1]) ->
           let lam = lam_of_loc kind arg1.exp_loc in
-          Lprim(Pmakeblock(0, Immutable), lam :: argl)
+          Lprim(Pmakeblock(0, Immutable, None), lam :: argl, e.exp_loc)
         | (Ploc _, _) -> assert false
         | (_, _) ->
             begin match (prim, argl) with
             | (Plazyforce, [a]) ->
                 wrap (Matching.inline_lazy_force a e.exp_loc)
             | (Plazyforce, _) -> assert false
-            |_ -> let p = Lprim(prim, argl) in
+            |_ -> let p = Lprim(prim, argl, e.exp_loc) in
                if primitive_is_ccall prim then wrap p else wrap0 p
             end
       end
   | Texp_apply(funct, oargs) ->
-      event_after e (transl_apply (transl_exp funct) oargs e.exp_loc)
-  | Texp_match(arg, caselist, exn_caselist, [], partial) ->
-    transl_match e arg caselist exn_caselist partial
-  | Texp_match(arg, caselist, exn_caselist, eff_caselist, partial) ->
-    transl_handler e arg (Some (caselist, partial)) exn_caselist eff_caselist
-  | Texp_try(body, exn_caselist, []) ->
-      let id = name_pattern "exn" exn_caselist in
+      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_match(arg, pat_expr_list, exn_pat_expr_list, eff_pat_expr_list, partial) ->
+    transl_handler e arg (Some (pat_expr_list, partial)) exn_pat_expr_list eff_pat_expr_list
+  | Texp_try(body, exn_pat_expr_list, []) ->
+      let id = name_pattern "exn" exn_pat_expr_list in
       Ltrywith(transl_exp body, id,
-               Matching.for_trywith (Lvar id) (transl_cases_try exn_caselist))
-  | Texp_try(body, exn_caselist, eff_caselist) ->
-    transl_handler e body None exn_caselist eff_caselist
+               Matching.for_trywith (Lvar id) (transl_cases_try exn_pat_expr_list))
+  | Texp_try(body, exn_pat_expr_list, eff_pat_expr_list) ->
+    transl_handler e body None exn_pat_expr_list eff_pat_expr_list
   | Texp_tuple el ->
-      let ll = transl_list el in
+      let ll, shape = transl_list_with_shape el in
       begin try
         Lconst(Const_block(0, List.map extract_constant ll))
       with Not_constant ->
-        Lprim(Pmakeblock(0, Immutable), ll)
+        Lprim(Pmakeblock(0, Immutable, Some shape), ll, e.exp_loc)
       end
   | Texp_construct(_, cstr, args) ->
-      let ll = transl_list args in
-      begin match cstr.cstr_tag with
+      let ll, shape = transl_list_with_shape args in
+      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_unboxed ->
+          (match ll with [v] -> v | _ -> assert false)
       | Cstr_block n ->
           begin try
             Lconst(Const_block(n, List.map extract_constant ll))
           with Not_constant ->
-            Lprim(Pmakeblock(n, Immutable), ll)
+            Lprim(Pmakeblock(n, Immutable, Some shape), ll, e.exp_loc)
           end
       | Cstr_extension(path, is_const) ->
           if is_const then
             transl_path e.exp_env path
           else
-            Lprim(Pmakeblock(0, Immutable),
-                  transl_path e.exp_env path :: ll)
+            Lprim(Pmakeblock(0, Immutable, Some (Pgenval :: shape)),
+                  transl_path e.exp_env path :: ll, e.exp_loc)
       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
@@ -777,45 +902,80 @@ and transl_exp0 e =
             Lconst(Const_block(0, [Const_base(Const_int tag);
                                    extract_constant lam]))
           with Not_constant ->
-            Lprim(Pmakeblock(0, Immutable),
-                  [Lconst(Const_base(Const_int tag)); lam])
+            Lprim(Pmakeblock(0, Immutable, None),
+                  [Lconst(Const_base(Const_int tag)); lam], e.exp_loc)
       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
-  | Texp_record ([], _) ->
-      fatal_error "Translcore.transl_exp: bad Texp_record"
+  | Texp_record (fields, representation, extended_expression) ->
+      transl_record e.exp_loc e.exp_env fields representation
+        extended_expression
   | Texp_field(arg, _, lbl) ->
-      let access =
-        match lbl.lbl_repres with
-          Record_regular -> Pfield(lbl.lbl_pos, maybe_pointer e, lbl.lbl_mut)
-        | Record_float -> Pfloatfield lbl.lbl_pos in
-      Lprim(access, [transl_exp arg])
+      let targ = transl_exp arg in
+      begin match lbl.lbl_repres with
+          Record_regular | Record_inlined _ ->
+          Lprim (Pfield (lbl.lbl_pos, maybe_pointer e, lbl.lbl_mut),
+                  [targ], e.exp_loc)
+        | Record_unboxed _ -> targ
+        | Record_float -> Lprim (Pfloatfield lbl.lbl_pos, [targ], e.exp_loc)
+        | Record_extension ->
+          Lprim (Pfield (lbl.lbl_pos + 1, maybe_pointer e, lbl.lbl_mut),
+                  [targ], e.exp_loc)
+      end
   | Texp_setfield(arg, _, lbl, newval) ->
       let access =
         match lbl.lbl_repres with
-          Record_regular ->
-            Psetfield(lbl.lbl_pos, maybe_pointer newval, lbl.lbl_mut)
-        | Record_float ->
-            Psetfloatfield lbl.lbl_pos in
-      Lprim(access, [transl_exp arg; transl_exp newval])
+          Record_regular
+        | Record_inlined _ ->
+          Psetfield(lbl.lbl_pos, maybe_pointer newval, Assignment)
+        | Record_unboxed _ -> assert false
+        | 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], e.exp_loc)
   | 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 =
+        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, e.exp_loc)
+            in
+            Lprim (Pduparray (kind, Mutable), [imm_array], e.exp_loc)
+        | 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 in             (* can this really happen? *)
-        Lprim(Pccall prim_obj_dup, [master])
+                  raise Not_constant    (* can this really happen? *)
+            in
+            Lprim (Pduparray (kind, Mutable), [imm_array], e.exp_loc)
+        end
       with Not_constant ->
-        Lprim(Pmakearray kind, ll)
+        Lprim(Pmakearray (kind, Mutable), ll, e.exp_loc)
       end
   | Texp_ifthenelse(cond, ifso, Some ifnot) ->
       Lifthenelse(transl_exp cond,
@@ -845,25 +1005,41 @@ and transl_exp0 e =
       in
       event_after e lam
   | Texp_new (cl, {Location.loc=loc}, _) ->
-      Lapply(Lprim(Pfield(0, true, Mutable), [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, Pointer, Mutable),
+                            [transl_path ~loc e.exp_env cl], loc);
+             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])
+            [transl_normal_path path_self; transl_normal_path path], e.exp_loc)
   | Texp_setinstvar(path_self, path, _, expr) ->
-      transl_setinstvar (transl_normal_path path_self) path expr
+      transl_setinstvar e.exp_loc (transl_normal_path path_self) path expr
   | 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),
+      Llet(Strict, Pgenval, cpy,
+           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))
+                Lsequence(transl_setinstvar Location.none
+                            (Lvar cpy) path expr, rem))
              modifs
              (Lvar cpy))
   | Texp_letmodule(id, _, modl, body) ->
-      Llet(Strict, id, !transl_module Tcoerce_none None modl, transl_exp body)
+      Llet(Strict, Pgenval, id,
+           !transl_module Tcoerce_none None modl,
+           transl_exp body)
+  | Texp_letexception(cd, body) ->
+      Llet(Strict, Pgenval,
+           cd.ext_id, transl_extension_constructor e.exp_env None cd,
+           transl_exp body)
   | Texp_pack modl ->
       !transl_module Tcoerce_none None modl
   | Texp_assert {exp_desc=Texp_construct(_, {cstr_name="false"}, _)} ->
@@ -885,41 +1061,31 @@ and transl_exp0 e =
       | Texp_construct (_, {cstr_arity = 0}, _)
         -> transl_exp e
       | Texp_constant(Const_float _) ->
-          Lprim(Pmakeblock(Obj.forward_tag, Immutable), [transl_exp e])
-      | Texp_ident(_, _, _) -> (* according to the type *)
-          begin match e.exp_type.desc with
-          (* the following may represent a float/forward/lazy: need a
-             forward_tag *)
-          | Tvar _ | Tlink _ | Tsubst _ | Tunivar _
-          | Tpoly(_,_) | Tfield(_,_,_,_) ->
-              Lprim(Pmakeblock(Obj.forward_tag, Immutable), [transl_exp e])
-          (* the following cannot be represented as float/forward/lazy:
-             optimize *)
-          | Tarrow(_,_,_,_) | Ttuple _ | Tpackage _ | Tobject(_,_) | Tnil
-          | Tvariant _
-              -> transl_exp e
-          (* optimize predefined types (excepted float) *)
-          | Tconstr(_,_,_) ->
-              if has_base_type e Predef.path_int
-                || has_base_type e Predef.path_char
-                || has_base_type e Predef.path_string
-                || has_base_type e Predef.path_bool
-                || has_base_type e Predef.path_unit
-                || has_base_type e Predef.path_exn
-                || has_base_type e Predef.path_array
-                || has_base_type e Predef.path_list
-                || has_base_type e Predef.path_option
-                || has_base_type e Predef.path_nativeint
-                || has_base_type e Predef.path_int32
-                || has_base_type e Predef.path_int64
-              then transl_exp e
-              else
-                Lprim(Pmakeblock(Obj.forward_tag, Immutable), [transl_exp e])
-          end
+          (* We don't need to wrap with Popaque: this forward
+             block will never be shortcutted since it points to a float. *)
+          Lprim(Pmakeblock(Obj.forward_tag, Immutable, None),
+                [transl_exp e], e.exp_loc)
+      | Texp_ident _ ->
+          (* CR-someday mshinwell: Consider adding a new primitive
+             that expresses the construction of forward_tag blocks.
+             We need to use [Popaque] here to prevent unsound
+             optimisation in Flambda, but the concept of a mutable
+             block doesn't really match what is going on here.  This
+             value may subsequently turn into an immediate... *)
+          if Typeopt.lazy_val_requires_forward e.exp_env e.exp_type
+          then
+            Lprim (Popaque,
+                   [Lprim(Pmakeblock(Obj.forward_tag, Immutable, None),
+                          [transl_exp e], e.exp_loc)],
+                   e.exp_loc)
+          else transl_exp e
       (* other cases compile to a lazy block holding a function *)
       | _ ->
-          let fn = Lfunction (Curried, [Ident.create "param"], transl_exp e) in
-          Lprim(Pmakeblock(Config.lazy_tag, Mutable), [fn])
+         let fn = Lfunction {kind = Curried; params = [Ident.create "param"];
+                             attr = default_function_attribute;
+                             loc = e.exp_loc;
+                             body = transl_exp e} in
+          Lprim(Pmakeblock(Config.lazy_tag, Mutable, None), [fn], e.exp_loc)
       end
   | Texp_object (cs, meths) ->
       let cty = cs.cstr_type in
@@ -931,10 +1097,19 @@ 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
 
+and transl_list_with_shape expr_list =
+  let transl_with_shape e =
+    let shape = Typeopt.value_kind e.exp_env e.exp_type in
+    transl_exp e, shape
+  in
+  List.split (List.map transl_with_shape expr_list)
+
 and transl_guard guard rhs =
   let expr = event_before rhs (transl_exp rhs) in
     match guard with
@@ -944,7 +1119,7 @@ and transl_guard guard rhs =
 
 and transl_cont cont c_cont body =
   match cont, c_cont with
-  | Some id1, Some id2 -> Llet(Alias, id2, Lvar id1, body)
+  | Some id1, Some id2 -> Llet(Alias, Pgenval, id2, Lvar id1, body)
   | None, None
   | Some _, None -> body
   | None, Some _ -> assert false
@@ -953,6 +1128,8 @@ and transl_case ?cont {c_lhs; c_cont; c_guard; c_rhs} =
   c_lhs, transl_cont cont c_cont (transl_guard c_guard c_rhs)
 
 and transl_cases ?cont cases =
+  let cases =
+    List.filter (fun c -> c.c_rhs.exp_desc <> Texp_unreachable) cases in
   List.map (transl_case ?cont) cases
 
 and transl_case_try {c_lhs; c_guard; c_rhs} =
@@ -967,23 +1144,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 ->
@@ -997,7 +1185,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
@@ -1006,22 +1194,29 @@ 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; loc} ->
+              Lfunction{kind = Curried; params = id_arg::ids; body = lam; attr;
+                        loc}
+          | Levent(Lfunction{kind = Curried; params = ids;
+                             body = lam; attr; loc}, _) ->
+              Lfunction{kind = Curried; params = id_arg::ids; body = lam; attr;
+                        loc}
           | lam ->
-              Lfunction(Curried, [id_arg], lam)
+              Lfunction{kind = Curried; params = [id_arg]; body = lam;
+                        attr = default_function_attribute; loc = loc}
         in
         List.fold_left
-          (fun body (id, lam) -> Llet(Strict, id, lam, body))
+          (fun body (id, lam) -> Llet(Strict, Pgenval, id, lam, body))
           body !defs
     | (Some arg, optional) :: l ->
         build_apply lam ((arg, optional) :: args) l
     | [] ->
         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
@@ -1041,7 +1236,7 @@ and transl_function loc untuplify_fn repr partial cases =
             (fun {c_lhs; c_guard; c_rhs} ->
               (Matching.flatten_pattern size c_lhs, c_guard, c_rhs))
             cases in
-        let params = List.map (fun p -> Ident.create "param") pl in
+        let params = List.map (fun _ -> Ident.create "param") pl in
         ((Tupled, params),
          Matching.for_tupled_function loc params
            (transl_tupled_cases pats_expr_list) partial)
@@ -1063,8 +1258,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 =
@@ -1074,46 +1276,60 @@ 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_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])
-
-and transl_record 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
+and transl_setinstvar loc self var expr =
+  let prim =
+    match maybe_pointer expr with
+    | Pointer -> Paddrarray
+    | Immediate -> Pintarray
+  in
+  Lprim(Parraysetu prim, [self; transl_normal_path var; transl_exp expr], loc)
+
+and transl_record loc env fields repres opt_init_expr =
+  let size = Array.length fields in
+  (* Determine if there are "enough" fields (only relevant if this is a
+     functional-style record update *)
+  let no_init = match opt_init_expr with None -> true | _ -> false in
+  if no_init || size < Config.max_young_wosize
   then begin
     (* Allocate new record with given fields (and remaining fields
        taken from init_expr if any *)
-    let lv = Array.make (Array.length all_labels) staticfail in
     let init_id = Ident.create "init" in
-    begin match opt_init_expr with
-      None -> ()
-    | Some init_expr ->
-        for i = 0 to Array.length all_labels - 1 do
-          let lbl = all_labels.(i) in
-          let access =
-            match lbl.lbl_repres with
-              Record_regular ->
-                let ptr = maybe_pointer_type init_expr.exp_env lbl.lbl_arg in
-                  Pfield(i, ptr, lbl.lbl_mut)
+    let lv =
+      Array.mapi
+        (fun i (lbl, definition) ->
+           match definition with
+           | Kept typ ->
+               let field_kind = value_kind env typ in
+               let access =
+                 match repres with
+                   Record_regular | Record_inlined _ -> Pfield (i, maybe_pointer_type env typ, lbl.lbl_mut)
+                 | Record_unboxed _ -> assert false
+                 | Record_extension -> Pfield (i + 1, maybe_pointer_type env typ, lbl.lbl_mut)
             | Record_float -> Pfloatfield i in
-          lv.(i) <- Lprim(access, [Lvar init_id])
-        done
-    end;
-    List.iter
-      (fun (_, lbl, expr) -> lv.(lbl.lbl_pos) <- transl_exp expr)
-      lbl_expr_list;
-    let ll = Array.to_list lv in
+               Lprim(access, [Lvar init_id], loc), field_kind
+           | Overridden (_lid, expr) ->
+               let field_kind = value_kind expr.exp_env expr.exp_type in
+               transl_exp expr, field_kind)
+        fields
+    in
+    let ll, shape = List.split (Array.to_list lv) in
     let mut =
-      if List.exists (fun (_, lbl, expr) -> lbl.lbl_mut = Mutable) lbl_expr_list
+      if Array.exists (fun (lbl, _) -> lbl.lbl_mut = Mutable) fields
       then Mutable
       else Immutable in
     let lam =
@@ -1121,16 +1337,36 @@ 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_unboxed _ -> Lconst(match cl with [v] -> v | _ -> assert false)
         | 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_regular ->
+            Lprim(Pmakeblock(0, mut, Some shape), ll, loc)
+        | Record_inlined tag ->
+            Lprim(Pmakeblock(tag, mut, Some shape), ll, loc)
+        | Record_unboxed _ -> (match ll with [v] -> v | _ -> assert false)
+        | Record_float ->
+            Lprim(Pmakearray (Pfloatarray, mut), ll, loc)
+        | Record_extension ->
+            let path =
+              let (label, _) = fields.(0) in
+              match label.lbl_res.desc with
+              | Tconstr(p, _, _) -> p
+              | _ -> assert false
+            in
+            let slot = transl_path env path in
+            Lprim(Pmakeblock(0, mut, Some (Pgenval :: shape)), slot :: ll, loc)
+    in
     begin match opt_init_expr with
       None -> lam
-    | Some init_expr -> Llet(Strict, init_id, transl_exp init_expr, lam)
+    | Some init_expr -> Llet(Strict, Pgenval, init_id,
+                             transl_exp init_expr, lam)
     end
   end else begin
     (* Take a shallow copy of the init record, then mutate the fields
@@ -1138,25 +1374,35 @@ and transl_record all_labels repres lbl_expr_list opt_init_expr =
     (* If you change anything here, you will likely have to change
        [check_recursive_recordwith] in this file. *)
     let copy_id = Ident.create "newrecord" in
-    let update_field (_, lbl, expr) cont =
+    let update_field cont (lbl, definition) =
+      match definition with
+      | Kept _type -> cont
+      | Overridden (_lid, expr) ->
       let upd =
-        match lbl.lbl_repres with
-          Record_regular -> Psetfield(lbl.lbl_pos, maybe_pointer expr, lbl.lbl_mut)
-        | Record_float -> Psetfloatfield lbl.lbl_pos in
-      Lsequence(Lprim(upd, [Lvar copy_id; transl_exp expr]), cont) in
+            match repres with
+              Record_regular
+            | Record_inlined _ ->
+                Psetfield(lbl.lbl_pos, maybe_pointer expr, Assignment)
+            | Record_unboxed _ -> assert false
+            | 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], loc), cont)
+    in
     begin match opt_init_expr with
       None -> assert false
     | Some init_expr ->
-        Llet(Strict, copy_id,
-             Lprim(Pduprecord (repres, size), [transl_exp init_expr]),
-             List.fold_right update_field lbl_expr_list (Lvar copy_id))
+        Llet(Strict, Pgenval, copy_id,
+             Lprim(Pduprecord (repres, size), [transl_exp init_expr], loc),
+             Array.fold_left update_field (Lvar copy_id) fields)
     end
   end
 
 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
@@ -1181,40 +1427,43 @@ and transl_match e arg pat_expr_list exn_pat_expr_list partial =
       (Matching.for_function e.exp_loc None (Lvar val_id) cases partial)
 
 and prim_bvar_create =
-  Pccall { prim_name = "caml_bvar_create"; prim_arity = 1; prim_alloc = true;
-           prim_native_name = ""; prim_native_float = false }
+  Pccall (Primitive.simple ~name:"caml_bvar_create" ~arity:1 ~alloc:true)
 
 and prim_alloc_stack =
-  Pccall { prim_name = "caml_alloc_stack"; prim_arity = 3; prim_alloc = true;
-           prim_native_name = ""; prim_native_float = false }
+  Pccall (Primitive.simple ~name:"caml_alloc_stack" ~arity:3 ~alloc:true)
 
 and transl_handler e body val_caselist exn_caselist eff_caselist =
   let val_fun =
     match val_caselist with
     | None ->
         let param = Ident.create "param" in
-          Lfunction (Curried, [param], Lvar param)
+        Lfunction {kind = Curried; params = [param]; body = Lvar param;
+                   attr = default_function_attribute; loc = Location.none}
     | Some (val_caselist, partial) ->
         let val_cases = transl_cases val_caselist in
         let param = name_pattern "param" val_caselist in
-          Lfunction(Curried, [param],
-           Matching.for_function e.exp_loc None
-             (Lvar param) val_cases partial)
+        Lfunction { kind = Curried; params = [param];
+          attr = default_function_attribute; loc = Location.none;
+          body = Matching.for_function e.exp_loc None
+             (Lvar param) val_cases partial }
   in
   let exn_fun =
     let exn_cases = transl_cases exn_caselist in
     let param = name_pattern "exn" exn_caselist in
-      Lfunction(Curried, [param],
-       Matching.for_trywith (Lvar param) exn_cases)
+    Lfunction { kind = Curried; params = [param]; loc = Location.none;
+      attr = default_function_attribute;
+      body = Matching.for_trywith (Lvar param) exn_cases }
   in
   let eff_fun =
     let param = name_pattern "eff" eff_caselist in
     let raw_cont = Ident.create "cont" in
     let cont = Ident.create "k" in
     let eff_cases = transl_cases ~cont eff_caselist in
-      Lfunction(Curried, [param; raw_cont],
-        Llet(StrictOpt, cont, Lprim (prim_bvar_create, [Lvar raw_cont]),
-          Matching.for_handler (Lvar param) (Lvar raw_cont) eff_cases))
+    Lfunction { kind = Curried; params = [param; raw_cont];
+      attr = default_function_attribute; loc = Location.none;
+      body = Llet(StrictOpt, Pgenval, cont,
+          Lprim (prim_bvar_create, [Lvar raw_cont], Location.none),
+          Matching.for_handler (Lvar param) (Lvar raw_cont) eff_cases) }
   in
   let is_pure = function
     | Lconst _ -> true
@@ -1224,15 +1473,18 @@ and transl_handler e body val_caselist exn_caselist eff_caselist =
   in
   let (body_fun, arg) =
     match transl_exp body with
-    | Lapply (fn, [arg], _) when is_pure fn && is_pure arg ->
-       (fn, arg)
+    | Lapply { ap_func = fn; ap_args = [arg]; _ }
+        when is_pure fn && is_pure arg -> (fn, arg)
     | body ->
        let param = Ident.create "param" in
-       (Lfunction (Curried, [param], body), 
+       (Lfunction { kind = Curried; params = [param]; body;
+          attr = default_function_attribute; loc = Location.none },
         Lconst(Const_base(Const_int 0)))
   in
-    Lprim(Presume e.exp_loc, [Lprim(prim_alloc_stack, [val_fun; exn_fun; eff_fun]);
-                              body_fun; arg])
+  let alloc_stack =
+    Lprim(prim_alloc_stack, [val_fun; exn_fun; eff_fun], Location.none)
+  in
+  Lprim(Presume, [alloc_stack; body_fun; arg], e.exp_loc)
 
 (* Wrapper for class compilation *)
 
@@ -1263,6 +1515,8 @@ let report_error ppf = function
         "Ancestor names can only be used to select inherited methods"
   | Unknown_builtin_primitive 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 70f700fcee..fb5a506083 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,28 @@ 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 transl_extension_constructor: Env.t -> Path.t option ->
+  extension_constructor -> 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 ac65537ed2..03813f2984 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,67 +48,57 @@ 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 transl_extension_constructor env path ext =
-  let name =
-    match path with
-      None -> Ident.name ext.ext_id
-    | Some p -> 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))])])
-  | Text_rebind(path, lid) ->
-      transl_path ~loc:ext.ext_loc env path
-
 let transl_type_extension env rootpath tyext body =
   List.fold_right
     (fun ext body ->
       let lam =
         transl_extension_constructor env (field_path rootpath ext.ext_id) ext
       in
-      Llet(Strict, ext.ext_id, lam, body))
+      Llet(Strict, Pgenval, ext.ext_id, lam, body))
     tyext.tyext_constructors
     body
 
 (* Compile a coercion *)
 
-let rec apply_coercion strict restr arg =
+let rec apply_coercion loc strict restr arg =
   match restr with
     Tcoerce_none ->
       arg
   | Tcoerce_structure(pos_cc_list, id_pos_list) ->
       name_lambda strict arg (fun id ->
-        let get_field pos = Lprim(Pfield(pos, true, Immutable),[Lvar id]) in
+        let get_field pos = Lprim(Pfield (pos, Pointer, Mutable),[Lvar id], loc) in
         let lam =
-          Lprim(Pmakeblock(0, Immutable),
-                List.map (apply_coercion_field get_field) pos_cc_list)
+          Lprim(Pmakeblock(0, Immutable, None),
+                List.map (apply_coercion_field loc get_field) pos_cc_list,
+                loc)
         in
-        wrap_id_pos_list id_pos_list get_field lam)
+        wrap_id_pos_list loc id_pos_list get_field lam)
   | 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 };
+                  loc = loc;
+                  body = apply_coercion
+                           loc Strict cc_res
+                           (Lapply{ap_should_be_tailcall=false;
+                                   ap_loc=loc;
+                                   ap_func=Lvar id;
+                                   ap_args=[apply_coercion loc 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))
+        (fun _ -> apply_coercion loc Alias cc (transl_normal_path path))
 
-and apply_coercion_field get_field (pos, cc) =
-  apply_coercion Alias cc (get_field pos)
+and apply_coercion_field loc get_field (pos, cc) =
+  apply_coercion loc Alias cc (get_field pos)
 
-and wrap_id_pos_list id_pos_list get_field lam =
+and wrap_id_pos_list loc id_pos_list get_field lam =
   let fv = free_variables lam in
   (*Format.eprintf "%a@." Printlambda.lambda lam;
   IdentSet.iter (fun id -> Format.eprintf "%a " Ident.print id) fv;
@@ -114,8 +107,8 @@ and wrap_id_pos_list id_pos_list get_field lam =
     List.fold_left (fun (lam,s) (id',pos,c) ->
       if IdentSet.mem id' fv then
         let id'' = Ident.create (Ident.name id') in
-        (Llet(Alias,id'',
-              apply_coercion Alias c (get_field pos),lam),
+        (Llet(Alias, Pgenval, id'',
+              apply_coercion loc Alias c (get_field pos),lam),
          Ident.add id' (Lvar id'') s)
       else (lam,s))
       (lam, Ident.empty) id_pos_list
@@ -201,33 +194,38 @@ let init_shape modl =
         Const_block (1, [Const_pointer 0])
     | Mty_signature sg ->
         Const_block(0, [Const_block(0, init_shape_struct env sg)])
-    | Mty_functor(id, arg, res) ->
+    | Mty_functor _ ->
         raise Not_found (* can we do better? *)
   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 ->
+    | Sig_typext _ :: _ ->
         raise Not_found
     | Sig_module(id, md, _) :: rem ->
         init_shape_mod env md.md_type ::
-        init_shape_struct (Env.add_module_declaration id md env) rem
+        init_shape_struct (Env.add_module_declaration ~check:false
+                             id md env) rem
     | Sig_modtype(id, minfo) :: rem ->
         init_shape_struct (Env.add_modtype id minfo env) rem
-    | Sig_class(id, cdecl, _) :: rem ->
+    | Sig_class _ :: rem ->
         Const_pointer 2 (* camlinternalMod.Class *)
         :: init_shape_struct env rem
-    | Sig_class_type(id, ctyp, _) :: rem ->
+    | Sig_class_type _ :: rem ->
         init_shape_struct env rem
   in
   try
@@ -276,26 +274,36 @@ let eval_rec_bindings bindings cont =
   let rec bind_inits = function
     [] ->
       bind_strict bindings
-  | (id, None, rhs) :: rem ->
+  | (_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),
+  | (id, Some(loc, shape), _rhs) :: rem ->
+      Llet(Strict, Pgenval, 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
     [] ->
       patch_forwards bindings
   | (id, None, rhs) :: rem ->
-      Llet(Strict, id, rhs, bind_strict rem)
-  | (id, Some(loc, shape), rhs) :: rem ->
+      Llet(Strict, Pgenval, id, rhs, bind_strict rem)
+  | (_id, Some _, _rhs) :: rem ->
       bind_strict rem
   and patch_forwards = function
     [] ->
       cont
-  | (id, None, rhs) :: rem ->
+  | (_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),
+  | (id, Some(_loc, shape), rhs) :: rem ->
+      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
@@ -318,58 +326,93 @@ let rec bound_value_identifiers = function
     [] -> []
   | Sig_value(id, {val_kind = Val_reg}) :: rem ->
       id :: bound_value_identifiers rem
-  | Sig_typext(id, ext, _) :: rem -> id :: bound_value_identifiers rem
-  | Sig_module(id, mty, _) :: rem -> id :: bound_value_identifiers rem
-  | Sig_class(id, decl, _) :: rem -> id :: bound_value_identifiers rem
+  | Sig_typext(id, _, _) :: rem -> id :: bound_value_identifiers rem
+  | Sig_module(id, _, _) :: rem -> id :: bound_value_identifiers rem
+  | Sig_class(id, _, _) :: 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;
+  let loc = mexp.mod_loc in
   match mexp.mod_type with
-    Mty_alias _ -> apply_coercion Alias cc lambda_unit
+    Mty_alias _ -> apply_coercion loc 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)
+          apply_coercion loc Strict cc
+            (transl_path ~loc mexp.mod_env path)
   | Tmod_structure str ->
-      transl_struct [] cc rootpath str
-  | Tmod_functor( param, _, mty, body) ->
+          fst (transl_struct loc [] cc rootpath str)
+      | Tmod_functor(param, _, _, 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(Curried, [param],
-                      transl_module Tcoerce_none bodypath body)
+                  Lfunction{kind = Curried; params = [param];
+                            attr = { inline = inline_attribute;
+                                     specialise = Default_specialise;
+                                     is_a_functor = true };
+                            loc = loc;
+                            body = 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))
+                  Lfunction{kind = Curried; params = [param'];
+                            attr = { inline = inline_attribute;
+                                     specialise = Default_specialise;
+                                     is_a_functor = true };
+                            loc = loc;
+                            body = Llet(Alias, Pgenval, param,
+                                        apply_coercion loc 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(transl_module Tcoerce_none None funct,
-                [transl_module ccarg None arg], mexp.mod_loc))
-  | Tmod_constraint(arg, mty, _, ccarg) ->
+            (apply_coercion loc Strict cc)
+            (Lapply{ap_should_be_tailcall=false;
+                    ap_loc=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, _, _, ccarg) ->
       transl_module (compose_coercions cc ccarg) rootpath arg
   | Tmod_unpack(arg, _) ->
-      apply_coercion Strict cc (Translcore.transl_exp arg)
+          apply_coercion loc Strict cc (Translcore.transl_exp arg)
 
-and transl_struct fields cc rootpath str =
-  transl_structure fields cc rootpath str.str_items
+and transl_struct loc fields cc rootpath str =
+  transl_structure loc fields cc rootpath str.str_final_env str.str_items
 
-and transl_structure fields cc rootpath = function
+and transl_structure loc fields cc rootpath final_env = function
     [] ->
-      begin match cc with
+      let body, size =
+        match cc with
         Tcoerce_none ->
-          Lprim(Pmakeblock(0, Immutable),
-                List.map (fun id -> Lvar id) (List.rev fields))
+            Lprim(Pmakeblock(0, Immutable, None),
+                  List.map (fun id -> Lvar id) (List.rev fields), loc),
+              List.length fields
       | Tcoerce_structure(pos_cc_list, id_pos_list) ->
               (* Do not ignore id_pos_list ! *)
           (*Format.eprintf "%a@.@[" Includemod.print_coercion cc;
@@ -380,88 +423,141 @@ and transl_structure fields cc rootpath = function
           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
+              Lprim(Pmakeblock(0, Immutable, None),
+                  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 loc Strict cc (get_field pos))
+                    pos_cc_list, loc)
+            and id_pos_list =
+              List.filter (fun (id,_,_) -> not (IdentSet.mem id ids))
+                id_pos_list
+            in
+            wrap_id_pos_list loc id_pos_list get_field lam,
+              List.length pos_cc_list
       | _ ->
           fatal_error "Translmod.transl_structure"
-      end
+      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 && not !Clflags.native_code then
+         Levent(body,
+                {lev_loc = loc;
+                 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)
+          let body, size =
+            transl_structure loc 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
-      transl_let rec_flag pat_expr_list
-                 (transl_structure ext_fields cc rootpath rem)
+          let body, size =
+            transl_structure loc 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 rem
-  | Tstr_type decls ->
-      transl_structure fields cc rootpath rem
+          transl_structure loc fields cc rootpath final_env rem
+      | Tstr_type _ ->
+          transl_structure loc fields cc rootpath final_env 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)
+          let body, size =
+            transl_structure loc (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
-      Llet(Strict, id, transl_extension_constructor item.str_env path ext,
-           transl_structure (id :: fields) cc rootpath rem)
+      let body, size =
+        transl_structure loc (id :: fields) cc rootpath final_env rem
+      in
+      Llet(Strict, Pgenval, id,
+            transl_extension_constructor item.str_env path ext, body),
+      size
   | Tstr_effect 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)
+      let body, size =
+        transl_structure loc (id :: fields) cc rootpath final_env rem
+      in
+      Llet(Strict, Pgenval, id,
+            transl_extension_constructor item.str_env path ext, body),
+      size
   | 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)
+          let body, size =
+            transl_structure loc (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, Pgenval, 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 loc 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
-        (transl_structure ext_fields cc rootpath rem)
+              body
+          in
+          lam, size
   | 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)
+          let (ids, class_bindings) = transl_class_bindings cl_list in
+          let body, size =
+            transl_structure loc (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 rem
+                transl_structure loc newfields cc rootpath final_env rem
       | id :: ids ->
-          Llet(Alias, id, Lprim(Pfield(pos, true, Immutable), [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 =
+                  rebind_idents (pos + 1) (id :: newfields) ids
+                in
+                Llet(Alias, Pgenval, id,
+                     Lprim(Pfield (pos, Pointer, Mutable),
+                        [Lvar mid], incl.incl_loc), body),
+                size
+          in
+          let body, size = rebind_idents 0 fields ids in
+          Llet(pure_module modl, Pgenval, mid,
+               transl_module Tcoerce_none None modl, body),
+          size
   | Tstr_modtype _
   | Tstr_open _
   | Tstr_class_type _
   | Tstr_attribute _ ->
-      transl_structure fields cc rootpath rem
+          transl_structure loc fields cc rootpath final_env rem
 
 and pure_module m =
   match m.mod_desc with
@@ -473,16 +569,65 @@ 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 Ident.Set.empty in
+  let rec scan lam =
+    Lambda.iter scan lam;
+    match lam with
+      Lprim ((Pgetglobal id | Psetglobal id), _, _) ->
+        globals := Ident.Set.add id !globals
+    | _ -> ()
+  in
+  scan lam; !globals
+
+let required_globals ~flambda body =
+  let globals = scan_used_globals body in
+  let add_global id req =
+    if not flambda && Ident.Set.mem id globals then
+      req
+    else
+      Ident.Set.add id req
+  in
+  let required =
+    Hashtbl.fold
+      (fun path _ -> add_global (Path.head path)) used_primitives
+      (if flambda then globals else Ident.Set.empty)
+  in
+  let required =
+    List.fold_right add_global (Env.get_required_globals ()) required
+  in
+  Env.reset_required_globals ();
+  Hashtbl.clear used_primitives;
+  required
+
 (* 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 Location.none [] cc
+                   (global_path module_id) str)
+  in
+  { module_ident = module_id;
+    main_module_block_size = size;
+    required_globals = required_globals ~flambda:true body;
+    code = body }
 
+let transl_implementation module_name (str, cc) =
+  let implementation =
+    transl_implementation_flambda module_name (str, cc)
+  in
+  let code =
+    Lprim (Psetglobal implementation.module_ident, [implementation.code],
+           Location.none)
+  in
+  { implementation with code }
 
 (* Build the list of value identifiers defined by a toplevel structure
    (excluding primitive declarations). *)
@@ -491,11 +636,11 @@ let rec defined_idents = function
     [] -> []
   | item :: rem ->
     match item.str_desc with
-    | Tstr_eval (expr, _) -> defined_idents rem
-    | Tstr_value(rec_flag, pat_expr_list) ->
+    | Tstr_eval _ -> defined_idents rem
+    | 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_primitive _ -> defined_idents rem
+    | Tstr_type _ -> defined_idents rem
     | Tstr_typext tyext ->
       List.map (fun ext -> ext.ext_id) tyext.tyext_constructors
       @ defined_idents rem
@@ -507,8 +652,8 @@ 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
-    | Tstr_class_type cl_list -> defined_idents rem
+      List.map (fun (ci, _) -> ci.ci_id_class) cl_list @ defined_idents rem
+    | Tstr_class_type _ -> defined_idents rem
     | Tstr_include incl ->
       bound_value_identifiers incl.incl_type @ defined_idents rem
     | Tstr_attribute _ -> defined_idents rem
@@ -519,20 +664,23 @@ let rec more_idents = function
     [] -> []
   | item :: rem ->
     match item.str_desc with
-    | Tstr_eval (expr, _attrs) -> more_idents rem
-    | Tstr_value(rec_flag, pat_expr_list) -> more_idents rem
+    | Tstr_eval _ -> more_idents rem
+    | Tstr_value _ -> more_idents rem
     | Tstr_primitive _ -> more_idents rem
-    | Tstr_type decls -> more_idents rem
-    | Tstr_typext tyext -> more_idents rem
+    | Tstr_type _ -> more_idents rem
+    | Tstr_typext _ -> more_idents rem
     | Tstr_exception _ -> more_idents rem
     | Tstr_effect _ -> more_idents rem
-    | Tstr_recmodule decls -> more_idents rem
+    | Tstr_recmodule _ -> more_idents rem
     | Tstr_modtype _ -> more_idents rem
     | Tstr_open _ -> more_idents rem
-    | Tstr_class cl_list -> more_idents rem
-    | Tstr_class_type cl_list -> more_idents rem
+    | Tstr_class _ -> more_idents rem
+    | Tstr_class_type _ -> 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
@@ -541,11 +689,11 @@ and all_idents = function
     [] -> []
   | item :: rem ->
     match item.str_desc with
-    | Tstr_eval (expr, _attrs) -> all_idents rem
-    | Tstr_value(rec_flag, pat_expr_list) ->
+    | Tstr_eval _ -> all_idents rem
+    | 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 _ -> all_idents rem
     | Tstr_typext tyext ->
       List.map (fun ext -> ext.ext_id) tyext.tyext_constructors
       @ all_idents rem
@@ -556,11 +704,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
-    | Tstr_class_type cl_list -> all_idents rem
+      List.map (fun (ci, _) -> ci.ci_id_class) cl_list @ all_idents rem
+    | Tstr_class_type _ -> 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
@@ -581,7 +733,7 @@ let transl_store_subst = ref Ident.empty
 
 let nat_toplevel_name id =
   try match Ident.find_same id !transl_store_subst with
-    | Lprim(Pfield(pos, _, _), [Lprim(Pgetglobal glob, [])]) -> (glob,pos)
+    | Lprim(Pfield (pos, _, _), [Lprim(Pgetglobal glob, [], _)], _) -> (glob,pos)
     | _ -> raise Not_found
   with Not_found ->
     fatal_error("Translmod.nat_toplevel_name: " ^ Ident.unique_name id)
@@ -598,18 +750,23 @@ let transl_store_structure glob map prims str =
                 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
+            let lam =
+              transl_let rec_flag pat_expr_list (store_idents Location.none 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 ->
+  | Tstr_type _ ->
       transl_store rootpath subst rem
   | Tstr_typext(tyext) ->
-      let ids = List.map (fun ext -> ext.ext_id) tyext.tyext_constructors in
+            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)
+              transl_type_extension item.str_env rootpath tyext
+                                    (store_idents Location.none ids)
       in
         Lsequence(subst_lambda subst lam,
                   transl_store rootpath (add_idents false ids subst) rem)
@@ -617,37 +774,83 @@ let transl_store_structure glob map prims str =
       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),
+            Lsequence(Llet(Strict, Pgenval, id, subst_lambda subst lam,
+                           store_ident ext.ext_loc id),
                 transl_store rootpath (add_ident false id subst) rem)
   | Tstr_effect 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),
+      Lsequence(Llet(Strict, Pgenval, id, subst_lambda subst lam,
+                     store_ident ext.ext_loc 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,
+        | Tstr_module{mb_id=id;mb_loc=loc;
+                      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, Pgenval, id,
                    subst_lambda subst
-                   (Lprim(Pmakeblock(0, Immutable),
+                             (Lprim(Pmakeblock(0, Immutable, None),
                           List.map (fun id -> Lvar id)
-                                   (defined_idents str.str_items))),
-                   Lsequence(store_ident id,
-                             transl_store rootpath (add_ident true id subst)
+                                      (defined_idents str.str_items), loc)),
+                           Lsequence(store_ident loc 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
+        | Tstr_module{
+            mb_id=id;mb_loc=loc;
+            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 loc Strict cc (Lvar ids.(pos))
+            in
+            Lsequence(lam,
+                      Llet(Strict, Pgenval, id,
+                           subst_lambda subst
+                             (Lprim(Pmakeblock(0, Immutable, None),
+                                    List.map field map, loc)),
+                           Lsequence(store_ident loc id,
+                                     transl_store rootpath
+                                                  (add_ident true id subst)
+                                                  rem)))
+        | Tstr_module{mb_id=id; mb_expr=modl; mb_loc=loc; mb_attributes} ->
+            let lam =
+              Translattribute.add_inline_attribute
+                (transl_module Tcoerce_none (field_path rootpath id) modl)
+                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,
+            Llet(Strict, Pgenval, id, subst_lambda subst lam,
+                 Lsequence(store_ident loc id,
                   transl_store rootpath (add_ident true id subst) rem))
   | Tstr_recmodule bindings ->
       let ids = List.map (fun mb -> mb.mb_id) bindings in
@@ -657,30 +860,28 @@ let transl_store_structure glob map prims str =
             (transl_module Tcoerce_none
                            (field_path rootpath id) modl))
         bindings
-        (Lsequence(store_idents ids,
+              (Lsequence(store_idents Location.none 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 (ids, class_bindings) = transl_class_bindings 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
+              Lletrec(class_bindings, store_idents Location.none 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 loc = incl.incl_loc in
       let rec store_idents pos = function
         [] -> transl_store rootpath (add_idents true ids subst) rem
       | id :: idl ->
-          Llet(Alias, id, Lprim(Pfield(pos, true, Immutable), [Lvar mid]),
-               Lsequence(store_ident id, store_idents (pos + 1) idl)) in
-      Llet(Strict, mid,
+                  Llet(Alias, Pgenval, id, Lprim(Pfield (pos, Pointer, Mutable), [Lvar mid], loc),
+                       Lsequence(store_ident loc id,
+                                 store_idents (pos + 1) idl))
+            in
+            Llet(Strict, Pgenval, mid,
            subst_lambda subst (transl_module Tcoerce_none None modl),
            store_idents 0 ids)
   | Tstr_modtype _
@@ -689,24 +890,29 @@ let transl_store_structure glob map prims str =
   | Tstr_attribute _ ->
       transl_store rootpath subst rem
 
-  and store_ident id =
+  and store_ident loc id =
     try
       let (pos, cc) = Ident.find_same id map in
-      let init_val = apply_coercion Alias cc (Lvar id) in
-      Lprim(Psetfield(pos, true, Immutable), [Lprim(Pgetglobal glob, []); init_val])
+      let init_val = apply_coercion loc Alias cc (Lvar id) in
+      Lprim(Psetfield(pos, Pointer, Initialization),
+            [Lprim(Pgetglobal glob, [], loc); init_val],
+            loc)
     with Not_found ->
       fatal_error("Translmod.store_ident: " ^ Ident.unique_name id)
 
-  and store_idents idlist =
-    make_sequence store_ident idlist
+  and store_idents loc idlist =
+    make_sequence (store_ident loc) idlist
 
   and add_ident may_coerce id subst =
     try
       let (pos, cc) = Ident.find_same id map in
       match cc with
         Tcoerce_none ->
-          Ident.add id (Lprim(Pfield(pos, true, Immutable),
-                              [Lprim(Pgetglobal glob, [])])) subst
+          Ident.add id
+            (Lprim(Pfield (pos, Pointer, Mutable),
+                   [Lprim(Pgetglobal glob, [], Location.none)],
+                   Location.none))
+            subst
       | _ ->
           if may_coerce then subst else assert false
     with Not_found ->
@@ -716,9 +922,11 @@ 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, true, Immutable),
-                    [Lprim(Pgetglobal glob, []);
-                     transl_primitive Location.none prim]),
+    Lsequence(Lprim(Psetfield(pos, Pointer, Initialization),
+                    [Lprim(Pgetglobal glob, [], Location.none);
+                     transl_primitive Location.none
+                       prim.pc_desc prim.pc_env prim.pc_type None],
+                    Location.none),
               cont)
 
   in List.fold_right store_primitive prims
@@ -752,7 +960,7 @@ let build_ident_map restr idlist more_ids =
         let rec export_map pos map prims undef = function
         [] ->
           natural_map pos map prims undef
-          | (source_pos, Tcoerce_primitive p) :: rem ->
+          | (_source_pos, Tcoerce_primitive p) :: rem ->
             export_map (pos + 1) map ((pos, p) :: prims) undef rem
           | (source_pos, cc) :: rem ->
             let id = idarray.(source_pos) in
@@ -770,6 +978,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
@@ -787,9 +996,14 @@ 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, code) = transl_store_gen module_name (str, restr) false in
   transl_store_subst := s;
-  r
+  { Lambda.main_module_block_size = i;
+    code;
+    (* module_ident is not used by closure, but this allow to share
+       the type with the flambda version *)
+    module_ident = Ident.create_persistent module_name;
+    required_globals = required_globals ~flambda:true code }
 
 (* Compile a toplevel phrase *)
 
@@ -808,26 +1022,42 @@ let toplevel_name id =
   with Not_found -> Ident.name id
 
 let toploop_getvalue id =
-  Lapply(Lprim(Pfield(toploop_getvalue_pos, true, Immutable),
-                 [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, Pointer, Mutable),
+                       [Lprim(Pgetglobal toploop_ident, [], Location.none)],
+                       Location.none);
+         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, true, Immutable),
-                 [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, Pointer, Mutable),
+                       [Lprim(Pgetglobal toploop_ident, [], Location.none)],
+                       Location.none);
+         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 =
-  IdentSet.fold (fun id l -> Llet(Strict, id, toploop_getvalue id, l))
+let close_toplevel_term (lam, ()) =
+  IdentSet.fold (fun id l -> Llet(Strict, Pgenval, 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
@@ -837,9 +1067,13 @@ let transl_toplevel_item item =
       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_effect ext ->
@@ -860,17 +1094,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
@@ -880,9 +1106,10 @@ let transl_toplevel_item item =
           lambda_unit
       | id :: ids ->
           Lsequence(toploop_setvalue id
-                      (Lprim(Pfield(pos, true, Immutable), [Lvar mid])),
+                      (Lprim(Pfield (pos, Pointer, Mutable), [Lvar mid], Location.none)),
                     set_idents (pos + 1) ids) in
-      Llet(Strict, mid, transl_module Tcoerce_none None modl, set_idents 0 ids)
+      Llet(Strict, Pgenval, mid,
+           transl_module Tcoerce_none None modl, set_idents 0 ids)
   | Tstr_modtype _
   | Tstr_open _
   | Tstr_primitive _
@@ -892,22 +1119,42 @@ 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 *)
 
 let get_component = function
     None -> Lconst const_unit
-  | Some id -> Lprim(Pgetglobal id, [])
+  | Some id -> Lprim(Pgetglobal id, [], Location.none)
+
+let transl_package_flambda component_names 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 Location.none Strict coercion
+    (Lprim(Pmakeblock(0, Immutable, None),
+           List.map get_component component_names,
+           Location.none))
 
 let transl_package component_names target_name coercion =
   let components =
-    Lprim(Pmakeblock(0, Immutable), List.map get_component component_names) in
-  Lprim(Psetglobal target_name, [apply_coercion Strict coercion components])
+    Lprim(Pmakeblock(0, Immutable, None),
+          List.map get_component component_names, Location.none) in
+  Lprim(Psetglobal target_name,
+        [apply_coercion Location.none Strict coercion components],
+        Location.none)
   (*
   let components =
     match coercion with
@@ -934,22 +1181,27 @@ let transl_store_package component_names target_name coercion =
       (List.length component_names,
        make_sequence
          (fun pos id ->
-           Lprim(Psetfield(pos, true, Immutable),
-                 [Lprim(Pgetglobal target_name, []);
-                  get_component id]))
+           Lprim(Psetfield(pos, Pointer, Initialization),
+                 [Lprim(Pgetglobal target_name, [], Location.none);
+                  get_component id],
+                 Location.none))
          0 component_names)
-  | Tcoerce_structure (pos_cc_list, id_pos_list) ->
+  | Tcoerce_structure (pos_cc_list, _id_pos_list) ->
       let components =
-        Lprim(Pmakeblock(0, Immutable), List.map get_component component_names)
+        Lprim(Pmakeblock(0, Immutable, None),
+              List.map get_component component_names,
+              Location.none)
       in
       let blk = Ident.create "block" in
       (List.length pos_cc_list,
-       Llet (Strict, blk, apply_coercion Strict coercion components,
+       Llet (Strict, Pgenval, blk,
+             apply_coercion Location.none Strict coercion components,
              make_sequence
-               (fun pos id ->
-                 Lprim(Psetfield(pos, true, Immutable),
-                       [Lprim(Pgetglobal target_name, []);
-                        Lprim(Pfield(pos, true, Immutable), [Lvar blk])]))
+               (fun pos _id ->
+                 Lprim(Psetfield(pos, Pointer, Initialization),
+                       [Lprim(Pgetglobal target_name, [], Location.none);
+                        Lprim(Pfield (pos, Pointer, Mutable), [Lvar blk], Location.none)],
+                       Location.none))
                0 pos_cc_list))
   (*
               (* ignore id_pos_list as the ids are already bound *)
@@ -988,4 +1240,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 1d84aaabd2..f613a2f421 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 *)
@@ -16,16 +19,24 @@
 open Typedtree
 open Lambda
 
-val transl_implementation: string -> structure * module_coercion -> lambda
+val transl_implementation:
+      string -> structure * module_coercion -> Lambda.program
 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 -> Lambda.program
+
 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 -> 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 4ed1ee4080..5a2589ae5d 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
@@ -31,7 +33,7 @@ let consts : (structured_constant, Ident.t) Hashtbl.t = Hashtbl.create 17
 
 let share c =
   match c with
-    Const_block (n, l) when l <> [] ->
+    Const_block (_n, l) when l <> [] ->
       begin try
         Lvar (Hashtbl.find consts c)
       with Not_found ->
@@ -56,9 +58,9 @@ let next_cache tag =
   (tag, [!method_cache; Lconst(Const_base(Const_int n))])
 
 let rec is_path = function
-    Lvar _ | Lprim (Pgetglobal _, []) | Lconst _ -> true
-  | Lprim (Pfield _, [lam]) -> is_path lam
-  | Lprim ((Parrayrefu _ | Parrayrefs _), [lam1; lam2]) ->
+    Lvar _ | Lprim (Pgetglobal _, [], _) | Lconst _ -> true
+  | Lprim (Pfield _, [lam], _) -> is_path lam
+  | Lprim ((Parrayrefu _ | Parrayrefs _), [lam1; lam2], _) ->
       is_path lam1 && is_path lam2
   | _ -> false
 
@@ -86,42 +88,74 @@ 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))
+      (fun c id expr -> Llet(Alias, Pgenval, id, Lconst c, expr))
       consts expr
   in
-  let expr =
+  (*let expr =
     List.fold_right
-      (fun id expr -> Lsequence(Lprim(Pgetglobal id, []), expr))
+      (fun id expr -> Lsequence(Lprim(Pgetglobal id, [], Location.none), 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, Pgenval, method_cache_id,
+        Lprim (Pccall prim_makearray,
+               [int !method_count; int 0],
+               Location.none),
+        expr)
+  in
+  transl_label_init_general (fun () -> expr, size)
 
 let transl_store_label_init glob size f arg =
-  method_cache := Lprim(Pfield(size, true, Immutable), [Lprim(Pgetglobal glob, [])]);
+  assert(not Config.flambda);
+  assert(!Clflags.native_code);
+  method_cache := Lprim(Pfield (size, Pointer, Mutable), (* XXX KC: conservative *)
+                        [Lprim(Pgetglobal glob, [], Location.none)],
+                        Location.none);
   let expr = f arg in
   let (size, expr) =
     if !method_count = 0 then (size, expr) else
     (size+1,
      Lsequence(
-     Lprim(Psetfield(size, true, Immutable),
-           [Lprim(Pgetglobal glob, []);
-            Lprim (Pccall prim_makearray, [int !method_count; int 0])]),
+     Lprim(Psetfield(size, Pointer, Initialization),
+           [Lprim(Pgetglobal glob, [], Location.none);
+            Lprim (Pccall prim_makearray,
+                   [int !method_count; int 0],
+                   Location.none)],
+           Location.none),
      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 *)
 
@@ -149,9 +183,10 @@ let oo_wrap env req f x =
     let lambda =
       List.fold_left
         (fun lambda id ->
-          Llet(StrictOpt, id,
-               Lprim(Pmakeblock(0, Mutable),
-                     [lambda_unit; lambda_unit; lambda_unit]),
+          Llet(StrictOpt, Pgenval, id,
+               Lprim(Pmakeblock(0, Mutable, None),
+                     [lambda_unit; lambda_unit; lambda_unit],
+                     Location.none),
                lambda))
         lambda !classes
     in
diff --git a/bytecomp/translobj.mli b/bytecomp/translobj.mli
index a44ac683ff..d742624131 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 deb5b1be9c..996e20344d 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -17,80 +20,100 @@ open Types
 open Typedtree
 open Lambda
 
+let scrape_ty env ty =
+  let ty = Ctype.expand_head_opt env (Ctype.correct_levels ty) in
+  match ty.desc with
+  | Tconstr (p, _, _) ->
+      begin match Env.find_type p env with
+      | {type_unboxed = {unboxed = true; _}; _} ->
+        begin match Typedecl.get_unboxed_type_representation env ty with
+        | None -> ty
+        | Some ty2 -> ty2
+        end
+      | _ -> ty
+      | exception Not_found -> ty
+      end
+  | _ -> ty
+
 let scrape env ty =
-  (Ctype.repr (Ctype.expand_head_opt env (Ctype.correct_levels ty))).desc
+  (scrape_ty env 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_type env ty =
-  match scrape env ty 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 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
+  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
+type classification =
+  | Int
+  | Float
+  | Lazy
+  | Addr  (* anything except a float or a lazy *)
+  | Any
+
+let classify env ty =
+  let ty = scrape_ty env ty in
+  if maybe_pointer_type env ty = Immediate then Int
+  else match ty.desc with
   | Tvar _ | Tunivar _ ->
-      Pgenarray
-  | Tconstr(p, args, abbrev) ->
-      if Path.same p Predef.path_int || Path.same p Predef.path_char then
-        Pintarray
-      else if Path.same p Predef.path_float then
-        Pfloatarray
+      Any
+  | Tconstr (p, _args, _abbrev) ->
+      if Path.same p Predef.path_float then Float
+      else if Path.same p Predef.path_lazy_t then Lazy
       else if Path.same p Predef.path_string
+           || Path.same p Predef.path_bytes
            || Path.same p Predef.path_array
            || Path.same p Predef.path_nativeint
            || Path.same p Predef.path_int32
-           || Path.same p Predef.path_int64 then
-        Paddrarray
+           || Path.same p Predef.path_int64 then Addr
       else begin
         try
-          match Env.find_type p env with
-            {type_kind = Type_abstract} ->
-              Pgenarray
-          | {type_kind = Type_variant cstrs}
-            when List.for_all (fun c -> c.Types.cd_args = []) cstrs ->
-              Pintarray
-          | {type_kind = _} ->
-              Paddrarray
+          match (Env.find_type p env).type_kind with
+          | Type_abstract ->
+              Any
+          | Type_record _ | Type_variant _ | Type_open ->
+              Addr
         with Not_found ->
           (* This can happen due to e.g. missing -I options,
              causing some .cmi files to be unavailable.
              Maybe we should emit a warning. *)
-          Pgenarray
+          Any
       end
-  | _ ->
-      Paddrarray
+  | Tarrow _ | Ttuple _ | Tpackage _ | Tobject _ | Tnil | Tvariant _ ->
+      Addr
+  | Tlink _ | Tsubst _ | Tpoly _ | Tfield _ ->
+      assert false
 
-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 ->
-      array_element_kind env elt_ty
+      begin match classify env elt_ty with
+      | Any -> Pgenarray
+      | Float -> Pfloatarray
+      | Addr | Lazy -> Paddrarray
+      | Int -> Pintarray
+      end
+
   | _ ->
       (* 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
@@ -118,11 +141,34 @@ 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
-  | 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
+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 env elt_type kind_table Pbigarray_unknown,
+       bigarray_decode_type env layout_type layout_table
                             Pbigarray_unknown_layout)
   | _ ->
       (Pbigarray_unknown, Pbigarray_unknown_layout)
+
+let value_kind env ty =
+  match scrape env ty with
+  | Tconstr(p, _, _) when Path.same p Predef.path_int ->
+      Pintval
+  | Tconstr(p, _, _) when Path.same p Predef.path_char ->
+      Pintval
+  | Tconstr(p, _, _) when Path.same p Predef.path_float ->
+      Pfloatval
+  | Tconstr(p, _, _) when Path.same p Predef.path_int32 ->
+      Pboxedintval Pint32
+  | Tconstr(p, _, _) when Path.same p Predef.path_int64 ->
+      Pboxedintval Pint64
+  | Tconstr(p, _, _) when Path.same p Predef.path_nativeint ->
+      Pboxedintval Pnativeint
+  | _ ->
+      Pgenval
+
+
+let lazy_val_requires_forward env ty =
+  match classify env ty with
+  | Any | Float | Lazy -> true
+  | Addr | Int -> false
diff --git a/bytecomp/typeopt.mli b/bytecomp/typeopt.mli
index ecee42eed7..724504b5ca 100644
--- a/bytecomp/typeopt.mli
+++ b/bytecomp/typeopt.mli
@@ -1,21 +1,35 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 has_base_type : Typedtree.expression -> Path.t -> bool
-val maybe_pointer_type : Env.t -> Types.type_expr -> bool
-val maybe_pointer : Typedtree.expression -> bool
+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 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
+val value_kind : Env.t -> Types.type_expr -> Lambda.value_kind
+
+val lazy_val_requires_forward : Env.t -> Types.type_expr -> bool
+  (** Whether a forward block is needed for a lazy thunk on a value, i.e.
+      if the value can be represented as a float/forward/lazy *)
diff --git a/byterun/.depend b/byterun/.depend
index 09bcd545ee..cdc2850aea 100644
--- a/byterun/.depend
+++ b/byterun/.depend
@@ -1,9 +1,8 @@
 addrmap.o: addrmap.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/domain_state.h \
- caml/domain_state.tbl caml/byte_domain_state.tbl caml/major_gc.h \
- caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
- caml/addrmap.h
+ caml/domain.h caml/mlvalues.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/alloc.h caml/addrmap.h
 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/domain_state.h caml/domain_state.tbl \
@@ -16,16 +15,15 @@ array.o: array.c caml/alloc.h caml/compatibility.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/fail.h caml/memory.h caml/gc.h \
  caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/memory.h caml/alloc.h caml/misc.h caml/mlvalues.h
+ caml/memory.h caml/alloc.h caml/misc.h caml/mlvalues.h caml/signals.h \
+ spacetime.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/alloc.h caml/mlvalues.h caml/io.h \
- caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/alloc.h caml/instruct.h caml/intext.h \
- caml/io.h caml/exec.h caml/fix_code.h caml/memory.h caml/startup.h \
- caml/exec.h caml/params.h caml/fiber.h caml/roots.h caml/sys.h \
- caml/backtrace.h caml/fail.h
+ caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h caml/memory.h \
+ caml/domain.h caml/memory.h caml/alloc.h caml/startup.h caml/fiber.h \
+ caml/roots.h caml/sys.h caml/backtrace.h caml/fail.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/domain_state.h \
@@ -50,19 +48,18 @@ debugger.o: debugger.c caml/alloc.h caml/compatibility.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/config.h caml/debugger.h caml/misc.h \
  caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
- caml/domain.h caml/memory.h caml/alloc.h caml/fail.h caml/fix_code.h \
- caml/instruct.h caml/intext.h caml/io.h caml/platform.h caml/io.h \
- caml/mlvalues.h caml/fiber.h caml/roots.h caml/sys.h
+ caml/domain.h caml/memory.h caml/alloc.h caml/osdeps.h caml/fail.h \
+ caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/platform.h \
+ caml/io.h caml/mlvalues.h caml/fiber.h caml/roots.h caml/sys.h
 domain.o: domain.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/domain.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/byte_domain_state.tbl caml/domain.h caml/memory.h caml/domain.h \
  caml/alloc.h caml/domain_state.h caml/platform.h caml/custom.h \
  caml/major_gc.h caml/shared_heap.h caml/roots.h caml/memory.h \
- caml/fail.h caml/globroots.h caml/signals.h caml/startup.h caml/exec.h \
- caml/params.h caml/fiber.h caml/callback.h caml/minor_gc.h \
- caml/eventlog.h caml/gc_ctrl.h caml/osdeps.h
+ caml/fail.h caml/globroots.h caml/signals.h caml/startup.h caml/fiber.h \
+ caml/callback.h caml/minor_gc.h caml/addrmap.h caml/eventlog.h \
+ caml/gc_ctrl.h caml/osdeps.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/domain_state.h caml/domain_state.tbl \
@@ -74,15 +71,13 @@ eventlog.o: eventlog.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/eventlog.h caml/domain.h caml/mlvalues.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
- caml/alloc.h caml/startup.h caml/exec.h caml/params.h caml/domain.h \
- caml/platform.h
+ caml/memory.h caml/alloc.h caml/startup.h caml/domain.h caml/platform.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/custom.h caml/fail.h caml/gc.h \
- caml/intext.h caml/io.h caml/platform.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/byte_domain_state.tbl caml/config.h caml/custom.h caml/fail.h \
+ caml/gc.h caml/intext.h caml/io.h caml/platform.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
  caml/alloc.h caml/io.h caml/md5.h caml/memory.h caml/misc.h \
  caml/mlvalues.h caml/reverse.h caml/addrmap.h
 fail.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \
@@ -95,11 +90,11 @@ fail.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \
 fiber.o: fiber.c caml/misc.h caml/compatibility.h caml/config.h \
  caml/../../config/m.h caml/../../config/s.h caml/fiber.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/addrmap.h caml/domain.h caml/alloc.h caml/roots.h \
- caml/gc_ctrl.h caml/instruct.h caml/fail.h caml/alloc.h caml/platform.h \
- caml/fix_code.h caml/minor_gc.h caml/major_gc.h caml/shared_heap.h \
- caml/memory.h caml/params.h caml/exec.h
+ caml/byte_domain_state.tbl caml/memory.h caml/domain.h caml/alloc.h \
+ caml/roots.h caml/gc_ctrl.h caml/instruct.h caml/fail.h caml/alloc.h \
+ caml/platform.h caml/fix_code.h caml/minor_gc.h caml/addrmap.h \
+ caml/major_gc.h caml/shared_heap.h caml/memory.h caml/params.h \
+ caml/exec.h
 finalise.o: finalise.c caml/misc.h caml/compatibility.h caml/config.h \
  caml/../../config/m.h caml/../../config/s.h caml/fail.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
@@ -144,11 +139,9 @@ 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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/callback.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/byte_domain_state.tbl caml/callback.h caml/memory.h caml/domain.h \
  caml/alloc.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h \
- caml/platform.h caml/io.h caml/md5.h caml/memory.h caml/mlvalues.h \
- caml/misc.h caml/reverse.h
+ caml/md5.h caml/memory.h caml/mlvalues.h caml/misc.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/domain_state.h caml/domain_state.tbl \
@@ -158,7 +151,7 @@ interp.o: interp.c caml/alloc.h caml/compatibility.h caml/misc.h \
  caml/instrtrace.h caml/instruct.h caml/interp.h caml/major_gc.h \
  caml/memory.h caml/misc.h caml/mlvalues.h caml/prims.h caml/signals.h \
  caml/fiber.h caml/roots.h caml/domain.h caml/globroots.h caml/startup.h \
- caml/exec.h caml/params.h caml/jumptbl.h
+ caml/exec.h caml/params.h caml/params.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/domain_state.h caml/domain_state.tbl \
@@ -172,7 +165,7 @@ io.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
  caml/byte_domain_state.tbl caml/custom.h caml/fail.h caml/io.h \
  caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
  caml/addrmap.h caml/domain.h caml/alloc.h caml/memory.h caml/misc.h \
- caml/mlvalues.h caml/signals.h caml/sys.h
+ caml/mlvalues.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/domain_state.h caml/domain_state.tbl \
@@ -217,30 +210,27 @@ 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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/finalise.h caml/gc.h caml/gc_ctrl.h \
- caml/major_gc.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/minor_gc.h \
- caml/misc.h caml/mlvalues.h caml/roots.h caml/signals.h caml/weak.h \
- caml/domain.h caml/shared_heap.h caml/roots.h caml/addrmap.h \
- caml/fiber.h caml/eventlog.h
+ caml/major_gc.h caml/memory.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/minor_gc.h caml/addrmap.h caml/misc.h caml/mlvalues.h caml/roots.h \
+ caml/signals.h caml/weak.h caml/domain.h caml/shared_heap.h caml/roots.h \
+ caml/addrmap.h caml/fiber.h caml/eventlog.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/domain.h \
- caml/startup.h caml/exec.h caml/params.h
+ caml/compatibility.h caml/misc.h caml/config.h caml/memory.h \
+ caml/domain.h caml/mlvalues.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/alloc.h caml/osdeps.h caml/version.h caml/domain.h caml/startup.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
  caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h caml/memory.h \
  caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
  caml/memory.h caml/alloc.h caml/minor_gc.h caml/misc.h caml/mlvalues.h \
- caml/prims.h caml/platform.h
+ caml/prims.h caml/platform.h spacetime.h
 params.o: params.c caml/misc.h caml/compatibility.h caml/config.h \
  caml/../../config/m.h caml/../../config/s.h caml/params.h \
  caml/mlvalues.h caml/misc.h caml/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/exec.h caml/version.h caml/prims.h \
- caml/dynlink.h caml/domain.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/addrmap.h caml/domain.h caml/alloc.h
+ caml/dynlink.h caml/domain.h caml/memory.h caml/domain.h caml/alloc.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/domain_state.h caml/domain_state.tbl \
@@ -251,9 +241,8 @@ parsing.o: parsing.c caml/config.h caml/../../config/m.h \
 platform.o: platform.c caml/platform.h caml/mlvalues.h \
  caml/compatibility.h caml/config.h caml/../../config/m.h \
  caml/../../config/s.h caml/misc.h caml/domain_state.h \
- caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/alloc.h caml/fail.h
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/domain.h caml/alloc.h caml/fail.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
@@ -271,15 +260,15 @@ roots.o: roots.c caml/finalise.h caml/globroots.h caml/mlvalues.h \
  caml/domain_state.tbl caml/byte_domain_state.tbl caml/roots.h \
  caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
  caml/domain.h caml/alloc.h caml/major_gc.h caml/memory.h caml/minor_gc.h \
- caml/misc.h caml/mlvalues.h caml/roots.h caml/fiber.h caml/shared_heap.h
+ caml/misc.h caml/mlvalues.h caml/roots.h caml/shared_heap.h caml/fiber.h
 shared_heap.o: shared_heap.c caml/platform.h caml/mlvalues.h \
  caml/compatibility.h caml/config.h caml/../../config/m.h \
  caml/../../config/s.h caml/misc.h caml/domain_state.h \
- caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/alloc.h caml/mlvalues.h caml/gc.h caml/fail.h caml/memory.h \
- caml/sizeclasses.h caml/addrmap.h caml/roots.h caml/globroots.h \
- caml/roots.h caml/shared_heap.h caml/params.h caml/exec.h caml/fiber.h
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/domain.h caml/alloc.h caml/mlvalues.h caml/gc.h caml/fail.h \
+ caml/memory.h caml/sizeclasses.h caml/addrmap.h caml/roots.h \
+ caml/globroots.h caml/roots.h caml/shared_heap.h caml/params.h \
+ caml/exec.h caml/fiber.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/domain_state.h caml/domain_state.tbl \
@@ -294,6 +283,10 @@ signals_byt.o: signals_byt.c caml/config.h caml/../../config/m.h \
  caml/domain_state.tbl caml/byte_domain_state.tbl caml/major_gc.h \
  caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
  caml/osdeps.h caml/signals.h caml/signals_machdep.h
+spacetime.o: spacetime.c caml/fail.h caml/compatibility.h caml/misc.h \
+ caml/config.h caml/../../config/m.h caml/../../config/s.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/mlvalues.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/domain_state.h caml/domain_state.tbl \
@@ -326,30 +319,30 @@ terminfo.o: terminfo.c caml/config.h caml/../../config/m.h \
  caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
  caml/domain.h caml/alloc.h caml/mlvalues.h caml/memory.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/misc.h \
- caml/osdeps.h
+ caml/compatibility.h caml/fail.h caml/misc.h caml/config.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/misc.h caml/osdeps.h caml/signals.h caml/sys.h caml/io.h \
+ caml/platform.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/fail.h caml/major_gc.h caml/memory.h \
  caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/memory.h caml/alloc.h caml/mlvalues.h
-win32.o: win32.c caml/address_class.h caml/misc.h caml/compatibility.h \
+ caml/memory.h caml/alloc.h caml/mlvalues.h caml/weak.h
+win32.o: win32.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/fail.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/memory.h caml/alloc.h caml/misc.h caml/osdeps.h caml/signals.h \
- caml/sys.h
+ caml/byte_domain_state.tbl caml/address_class.h caml/fail.h caml/io.h \
+ caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
+ caml/addrmap.h caml/domain.h caml/alloc.h caml/memory.h caml/misc.h \
+ caml/osdeps.h caml/signals.h caml/sys.h caml/config.h
 addrmap.d.o: addrmap.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/domain_state.h \
- caml/domain_state.tbl caml/byte_domain_state.tbl caml/major_gc.h \
- caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
- caml/addrmap.h
+ caml/domain.h caml/mlvalues.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/alloc.h caml/addrmap.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/domain_state.h caml/domain_state.tbl \
@@ -362,16 +355,15 @@ array.d.o: array.c caml/alloc.h caml/compatibility.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/fail.h caml/memory.h caml/gc.h \
  caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/memory.h caml/alloc.h caml/misc.h caml/mlvalues.h
+ caml/memory.h caml/alloc.h caml/misc.h caml/mlvalues.h caml/signals.h \
+ spacetime.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/alloc.h caml/mlvalues.h caml/io.h \
- caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/alloc.h caml/instruct.h caml/intext.h \
- caml/io.h caml/exec.h caml/fix_code.h caml/memory.h caml/startup.h \
- caml/exec.h caml/params.h caml/fiber.h caml/roots.h caml/sys.h \
- caml/backtrace.h caml/fail.h
+ caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h caml/memory.h \
+ caml/domain.h caml/memory.h caml/alloc.h caml/startup.h caml/fiber.h \
+ caml/roots.h caml/sys.h caml/backtrace.h caml/fail.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/domain_state.h \
@@ -396,19 +388,18 @@ debugger.d.o: debugger.c caml/alloc.h caml/compatibility.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/config.h caml/debugger.h caml/misc.h \
  caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
- caml/domain.h caml/memory.h caml/alloc.h caml/fail.h caml/fix_code.h \
- caml/instruct.h caml/intext.h caml/io.h caml/platform.h caml/io.h \
- caml/mlvalues.h caml/fiber.h caml/roots.h caml/sys.h
+ caml/domain.h caml/memory.h caml/alloc.h caml/osdeps.h caml/fail.h \
+ caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/platform.h \
+ caml/io.h caml/mlvalues.h caml/fiber.h caml/roots.h caml/sys.h
 domain.d.o: domain.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/domain.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/byte_domain_state.tbl caml/domain.h caml/memory.h caml/domain.h \
  caml/alloc.h caml/domain_state.h caml/platform.h caml/custom.h \
  caml/major_gc.h caml/shared_heap.h caml/roots.h caml/memory.h \
- caml/fail.h caml/globroots.h caml/signals.h caml/startup.h caml/exec.h \
- caml/params.h caml/fiber.h caml/callback.h caml/minor_gc.h \
- caml/eventlog.h caml/gc_ctrl.h caml/osdeps.h caml/domain_state.tbl
+ caml/fail.h caml/globroots.h caml/signals.h caml/startup.h caml/fiber.h \
+ caml/callback.h caml/minor_gc.h caml/addrmap.h caml/eventlog.h \
+ caml/gc_ctrl.h caml/osdeps.h caml/domain_state.tbl
 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/domain_state.h caml/domain_state.tbl \
@@ -420,15 +411,13 @@ eventlog.d.o: eventlog.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/eventlog.h caml/domain.h caml/mlvalues.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
- caml/alloc.h caml/startup.h caml/exec.h caml/params.h caml/domain.h \
- caml/platform.h
+ caml/memory.h caml/alloc.h caml/startup.h caml/domain.h caml/platform.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/custom.h caml/fail.h caml/gc.h \
- caml/intext.h caml/io.h caml/platform.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/byte_domain_state.tbl caml/config.h caml/custom.h caml/fail.h \
+ caml/gc.h caml/intext.h caml/io.h caml/platform.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
  caml/alloc.h caml/io.h caml/md5.h caml/memory.h caml/misc.h \
  caml/mlvalues.h caml/reverse.h caml/addrmap.h
 fail.d.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \
@@ -441,11 +430,11 @@ fail.d.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \
 fiber.d.o: fiber.c caml/misc.h caml/compatibility.h caml/config.h \
  caml/../../config/m.h caml/../../config/s.h caml/fiber.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/addrmap.h caml/domain.h caml/alloc.h caml/roots.h \
- caml/gc_ctrl.h caml/instruct.h caml/fail.h caml/alloc.h caml/platform.h \
- caml/fix_code.h caml/minor_gc.h caml/major_gc.h caml/shared_heap.h \
- caml/memory.h caml/params.h caml/exec.h
+ caml/byte_domain_state.tbl caml/memory.h caml/domain.h caml/alloc.h \
+ caml/roots.h caml/gc_ctrl.h caml/instruct.h caml/fail.h caml/alloc.h \
+ caml/platform.h caml/fix_code.h caml/minor_gc.h caml/addrmap.h \
+ caml/major_gc.h caml/shared_heap.h caml/memory.h caml/params.h \
+ caml/exec.h
 finalise.d.o: finalise.c caml/misc.h caml/compatibility.h caml/config.h \
  caml/../../config/m.h caml/../../config/s.h caml/fail.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
@@ -486,22 +475,20 @@ hash.d.o: hash.c caml/mlvalues.h caml/compatibility.h caml/config.h \
  caml/custom.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
  caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
  caml/hash.h caml/fail.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/domain_state.h \
- caml/domain_state.tbl caml/byte_domain_state.tbl caml/opnames.h \
- caml/prims.h caml/fiber.h caml/mlvalues.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/alloc.h caml/roots.h caml/domain.h caml/startup.h caml/exec.h \
- caml/params.h
+ caml/../../config/s.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/instruct.h \
+ caml/misc.h caml/mlvalues.h caml/opnames.h caml/prims.h caml/fiber.h \
+ caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
+ caml/domain.h caml/alloc.h caml/roots.h caml/domain.h caml/startup.h \
+ caml/exec.h caml/params.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/callback.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/byte_domain_state.tbl caml/callback.h caml/memory.h caml/domain.h \
  caml/alloc.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h \
- caml/platform.h caml/io.h caml/md5.h caml/memory.h caml/mlvalues.h \
- caml/misc.h caml/reverse.h
+ caml/md5.h caml/memory.h caml/mlvalues.h caml/misc.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/domain_state.h caml/domain_state.tbl \
@@ -511,7 +498,7 @@ interp.d.o: interp.c caml/alloc.h caml/compatibility.h caml/misc.h \
  caml/instrtrace.h caml/instruct.h caml/interp.h caml/major_gc.h \
  caml/memory.h caml/misc.h caml/mlvalues.h caml/prims.h caml/signals.h \
  caml/fiber.h caml/roots.h caml/domain.h caml/globroots.h caml/startup.h \
- caml/exec.h caml/params.h
+ caml/exec.h caml/params.h caml/params.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/domain_state.h caml/domain_state.tbl \
@@ -525,7 +512,7 @@ io.d.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
  caml/byte_domain_state.tbl caml/custom.h caml/fail.h caml/io.h \
  caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
  caml/addrmap.h caml/domain.h caml/alloc.h caml/memory.h caml/misc.h \
- caml/mlvalues.h caml/signals.h caml/sys.h
+ caml/mlvalues.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/domain_state.h caml/domain_state.tbl \
@@ -570,30 +557,27 @@ 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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/finalise.h caml/gc.h caml/gc_ctrl.h \
- caml/major_gc.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/minor_gc.h \
- caml/misc.h caml/mlvalues.h caml/roots.h caml/signals.h caml/weak.h \
- caml/domain.h caml/shared_heap.h caml/roots.h caml/addrmap.h \
- caml/fiber.h caml/eventlog.h
+ caml/major_gc.h caml/memory.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/minor_gc.h caml/addrmap.h caml/misc.h caml/mlvalues.h caml/roots.h \
+ caml/signals.h caml/weak.h caml/domain.h caml/shared_heap.h caml/roots.h \
+ caml/addrmap.h caml/fiber.h caml/eventlog.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/domain.h \
- caml/startup.h caml/exec.h caml/params.h
+ caml/compatibility.h caml/misc.h caml/config.h caml/memory.h \
+ caml/domain.h caml/mlvalues.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/alloc.h caml/osdeps.h caml/version.h caml/domain.h caml/startup.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
  caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h caml/memory.h \
  caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
  caml/memory.h caml/alloc.h caml/minor_gc.h caml/misc.h caml/mlvalues.h \
- caml/prims.h caml/platform.h
+ caml/prims.h caml/platform.h spacetime.h
 params.d.o: params.c caml/misc.h caml/compatibility.h caml/config.h \
  caml/../../config/m.h caml/../../config/s.h caml/params.h \
  caml/mlvalues.h caml/misc.h caml/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/exec.h caml/version.h caml/prims.h \
- caml/dynlink.h caml/domain.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/addrmap.h caml/domain.h caml/alloc.h
+ caml/dynlink.h caml/domain.h caml/memory.h caml/domain.h caml/alloc.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/domain_state.h caml/domain_state.tbl \
@@ -604,9 +588,8 @@ parsing.d.o: parsing.c caml/config.h caml/../../config/m.h \
 platform.d.o: platform.c caml/platform.h caml/mlvalues.h \
  caml/compatibility.h caml/config.h caml/../../config/m.h \
  caml/../../config/s.h caml/misc.h caml/domain_state.h \
- caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/alloc.h caml/fail.h
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/domain.h caml/alloc.h caml/fail.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
@@ -624,15 +607,15 @@ roots.d.o: roots.c caml/finalise.h caml/globroots.h caml/mlvalues.h \
  caml/domain_state.tbl caml/byte_domain_state.tbl caml/roots.h \
  caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
  caml/domain.h caml/alloc.h caml/major_gc.h caml/memory.h caml/minor_gc.h \
- caml/misc.h caml/mlvalues.h caml/roots.h caml/fiber.h caml/shared_heap.h
+ caml/misc.h caml/mlvalues.h caml/roots.h caml/shared_heap.h caml/fiber.h
 shared_heap.d.o: shared_heap.c caml/platform.h caml/mlvalues.h \
  caml/compatibility.h caml/config.h caml/../../config/m.h \
  caml/../../config/s.h caml/misc.h caml/domain_state.h \
- caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/alloc.h caml/mlvalues.h caml/gc.h caml/fail.h caml/memory.h \
- caml/sizeclasses.h caml/addrmap.h caml/roots.h caml/globroots.h \
- caml/roots.h caml/shared_heap.h caml/params.h caml/exec.h caml/fiber.h
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/domain.h caml/alloc.h caml/mlvalues.h caml/gc.h caml/fail.h \
+ caml/memory.h caml/sizeclasses.h caml/addrmap.h caml/roots.h \
+ caml/globroots.h caml/roots.h caml/shared_heap.h caml/params.h \
+ caml/exec.h caml/fiber.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/domain_state.h caml/domain_state.tbl \
@@ -647,6 +630,10 @@ signals_byt.d.o: signals_byt.c caml/config.h caml/../../config/m.h \
  caml/domain_state.tbl caml/byte_domain_state.tbl caml/major_gc.h \
  caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
  caml/osdeps.h caml/signals.h caml/signals_machdep.h
+spacetime.d.o: spacetime.c caml/fail.h caml/compatibility.h caml/misc.h \
+ caml/config.h caml/../../config/m.h caml/../../config/s.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/mlvalues.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/domain_state.h caml/domain_state.tbl \
@@ -679,30 +666,370 @@ terminfo.d.o: terminfo.c caml/config.h caml/../../config/m.h \
  caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
  caml/domain.h caml/alloc.h caml/mlvalues.h caml/memory.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/misc.h \
- caml/osdeps.h
+ caml/compatibility.h caml/fail.h caml/misc.h caml/config.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/misc.h caml/osdeps.h caml/signals.h caml/sys.h caml/io.h \
+ caml/platform.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/fail.h caml/major_gc.h caml/memory.h \
  caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/memory.h caml/alloc.h caml/mlvalues.h caml/weak.h
+win32.d.o: win32.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/address_class.h caml/fail.h caml/io.h \
+ caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
+ caml/addrmap.h caml/domain.h caml/alloc.h caml/memory.h caml/misc.h \
+ caml/osdeps.h caml/signals.h caml/sys.h caml/config.h
+addrmap.i.o: addrmap.c caml/config.h caml/../../config/m.h \
+ caml/../../config/s.h caml/compatibility.h caml/memory.h caml/config.h \
+ caml/domain.h caml/mlvalues.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/alloc.h caml/addrmap.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/custom.h caml/major_gc.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/memory.h caml/alloc.h caml/mlvalues.h caml/fiber.h caml/roots.h \
+ caml/domain.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/fail.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/memory.h caml/alloc.h caml/misc.h caml/mlvalues.h caml/signals.h \
+ spacetime.h
+backtrace.i.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/alloc.h caml/mlvalues.h caml/io.h \
+ caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h caml/memory.h \
+ caml/domain.h caml/memory.h caml/alloc.h caml/startup.h caml/fiber.h \
+ caml/roots.h caml/sys.h caml/backtrace.h caml/fail.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/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.h caml/fail.h caml/memory.h caml/mlvalues.h caml/platform.h \
+ caml/interp.h caml/instruct.h caml/fix_code.h caml/fiber.h caml/roots.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
+ caml/fail.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
+ caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/custom.h caml/fail.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
  caml/memory.h caml/alloc.h caml/mlvalues.h
-win32.d.o: win32.c caml/address_class.h caml/misc.h caml/compatibility.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/config.h caml/debugger.h caml/misc.h \
+ caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
+ caml/domain.h caml/memory.h caml/alloc.h caml/osdeps.h caml/fail.h \
+ caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/platform.h \
+ caml/io.h caml/mlvalues.h caml/fiber.h caml/roots.h caml/sys.h
+domain.i.o: domain.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/domain.h caml/memory.h caml/domain.h \
+ caml/alloc.h caml/domain_state.h caml/platform.h caml/custom.h \
+ caml/major_gc.h caml/shared_heap.h caml/roots.h caml/memory.h \
+ caml/fail.h caml/globroots.h caml/signals.h caml/startup.h caml/fiber.h \
+ caml/callback.h caml/minor_gc.h caml/addrmap.h caml/eventlog.h \
+ caml/gc_ctrl.h caml/osdeps.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/config.h caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/dynlink.h caml/fail.h caml/mlvalues.h \
+ caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
+ caml/domain.h caml/memory.h caml/alloc.h caml/misc.h caml/osdeps.h \
+ caml/prims.h caml/signals.h
+eventlog.i.o: eventlog.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/eventlog.h caml/domain.h caml/mlvalues.h \
+ caml/memory.h caml/alloc.h caml/startup.h caml/domain.h caml/platform.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/config.h caml/custom.h caml/fail.h \
+ caml/gc.h caml/intext.h caml/io.h caml/platform.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.h caml/io.h caml/md5.h caml/memory.h caml/misc.h \
+ caml/mlvalues.h caml/reverse.h caml/addrmap.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/fail.h caml/io.h caml/platform.h \
+ caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
+ caml/domain.h caml/alloc.h caml/gc.h caml/memory.h caml/misc.h \
+ caml/mlvalues.h caml/printexc.h caml/signals.h caml/fiber.h caml/roots.h
+fiber.i.o: fiber.c caml/misc.h caml/compatibility.h caml/config.h \
+ caml/../../config/m.h caml/../../config/s.h caml/fiber.h caml/misc.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/memory.h caml/domain.h caml/alloc.h \
+ caml/roots.h caml/gc_ctrl.h caml/instruct.h caml/fail.h caml/alloc.h \
+ caml/platform.h caml/fix_code.h caml/minor_gc.h caml/addrmap.h \
+ caml/major_gc.h caml/shared_heap.h caml/memory.h caml/params.h \
+ caml/exec.h
+finalise.i.o: finalise.c caml/misc.h caml/compatibility.h caml/config.h \
+ caml/../../config/m.h caml/../../config/s.h caml/fail.h caml/misc.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl
+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/config.h caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/fix_code.h caml/instruct.h caml/intext.h \
+ caml/io.h caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/minor_gc.h caml/addrmap.h caml/domain.h caml/alloc.h caml/md5.h \
+ caml/memory.h caml/misc.h caml/mlvalues.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/fail.h caml/memory.h caml/gc.h \
  caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/memory.h caml/alloc.h caml/misc.h caml/osdeps.h caml/signals.h \
+ caml/memory.h caml/alloc.h caml/mlvalues.h caml/misc.h caml/reverse.h \
+ caml/fiber.h caml/roots.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/custom.h caml/finalise.h caml/gc.h \
+ caml/gc_ctrl.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
+ caml/shared_heap.h caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/minor_gc.h caml/domain.h caml/alloc.h caml/misc.h caml/mlvalues.h \
+ caml/fiber.h caml/domain.h caml/globroots.h caml/signals.h \
+ caml/startup.h caml/exec.h caml/params.h caml/eventlog.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/major_gc.h caml/minor_gc.h \
+ caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/misc.h \
+ caml/mlvalues.h caml/roots.h caml/globroots.h caml/roots.h \
+ caml/callback.h caml/platform.h caml/alloc.h caml/shared_heap.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
+ caml/custom.h caml/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/hash.h caml/fail.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/callback.h caml/memory.h caml/domain.h \
+ caml/alloc.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h \
+ caml/md5.h caml/memory.h caml/mlvalues.h caml/misc.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/backtrace.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.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/memory.h caml/misc.h caml/mlvalues.h caml/prims.h caml/signals.h \
+ caml/fiber.h caml/roots.h caml/domain.h caml/globroots.h caml/startup.h \
+ caml/exec.h caml/params.h caml/params.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/custom.h caml/fail.h caml/intext.h \
+ caml/io.h caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/minor_gc.h caml/addrmap.h caml/domain.h caml/alloc.h caml/memory.h \
+ caml/misc.h caml/mlvalues.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/config.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/custom.h caml/fail.h caml/io.h \
+ caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
+ caml/addrmap.h caml/domain.h caml/alloc.h caml/memory.h caml/misc.h \
+ caml/mlvalues.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/mlvalues.h caml/fiber.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.h caml/roots.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/misc.h \
+ caml/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
  caml/sys.h
-addrmap.pic.o: addrmap.c caml/config.h caml/../../config/m.h \
+major_gc.i.o: major_gc.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/mlvalues.h \
+ caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/memory.h caml/alloc.h caml/fail.h caml/shared_heap.h caml/roots.h \
+ caml/roots.h caml/globroots.h caml/domain.h caml/fiber.h caml/addrmap.h \
+ caml/platform.h caml/params.h caml/exec.h caml/eventlog.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
+ caml/fail.h caml/md5.h caml/io.h caml/platform.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.h caml/memory.h caml/mlvalues.h caml/io.h caml/reverse.h
+memory.i.o: memory.c caml/misc.h caml/compatibility.h caml/config.h \
+ caml/../../config/m.h caml/../../config/s.h caml/fail.h caml/misc.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/major_gc.h caml/shared_heap.h caml/roots.h caml/domain.h \
+ caml/addrmap.h caml/roots.h caml/alloc.h caml/fiber.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/config.h caml/fail.h caml/fix_code.h \
+ caml/interp.h caml/intext.h caml/io.h caml/platform.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.h caml/major_gc.h caml/memory.h caml/minor_gc.h caml/misc.h \
+ caml/mlvalues.h caml/prims.h caml/fiber.h caml/roots.h caml/params.h \
+ caml/exec.h
+minor_gc.i.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/finalise.h caml/gc.h caml/gc_ctrl.h \
+ caml/major_gc.h caml/memory.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/minor_gc.h caml/addrmap.h caml/misc.h caml/mlvalues.h caml/roots.h \
+ caml/signals.h caml/weak.h caml/domain.h caml/shared_heap.h caml/roots.h \
+ caml/addrmap.h caml/fiber.h caml/eventlog.h
+misc.i.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/domain.h caml/mlvalues.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/alloc.h caml/osdeps.h caml/version.h caml/domain.h caml/startup.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
+ caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/memory.h caml/alloc.h caml/minor_gc.h caml/misc.h caml/mlvalues.h \
+ caml/prims.h caml/platform.h spacetime.h
+params.i.o: params.c caml/misc.h caml/compatibility.h caml/config.h \
+ caml/../../config/m.h caml/../../config/s.h caml/params.h \
+ caml/mlvalues.h caml/misc.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/exec.h caml/version.h caml/prims.h \
+ caml/dynlink.h caml/domain.h caml/memory.h caml/domain.h caml/alloc.h
+parsing.i.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/mlvalues.h \
+ caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/memory.h caml/alloc.h caml/alloc.h caml/startup.h caml/exec.h \
+ caml/params.h
+platform.i.o: platform.c caml/platform.h caml/mlvalues.h \
+ caml/compatibility.h caml/config.h caml/../../config/m.h \
+ caml/../../config/s.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/domain.h caml/alloc.h caml/fail.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
+ 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/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.h caml/callback.h caml/debugger.h caml/fail.h caml/misc.h \
+ caml/mlvalues.h caml/printexc.h
+roots.i.o: roots.c caml/finalise.h caml/globroots.h caml/mlvalues.h \
+ caml/compatibility.h caml/config.h caml/../../config/m.h \
+ caml/../../config/s.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/roots.h \
+ caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
+ caml/domain.h caml/alloc.h caml/major_gc.h caml/memory.h caml/minor_gc.h \
+ caml/misc.h caml/mlvalues.h caml/roots.h caml/shared_heap.h caml/fiber.h
+shared_heap.i.o: shared_heap.c caml/platform.h caml/mlvalues.h \
+ caml/compatibility.h caml/config.h caml/../../config/m.h \
+ caml/../../config/s.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/domain.h caml/alloc.h caml/mlvalues.h caml/gc.h caml/fail.h \
+ caml/memory.h caml/sizeclasses.h caml/addrmap.h caml/roots.h \
+ caml/globroots.h caml/roots.h caml/shared_heap.h caml/params.h \
+ caml/exec.h caml/fiber.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/callback.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.h caml/config.h caml/fail.h caml/memory.h caml/misc.h \
+ caml/mlvalues.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/config.h \
  caml/gc.h caml/mlvalues.h caml/misc.h caml/domain_state.h \
  caml/domain_state.tbl caml/byte_domain_state.tbl caml/major_gc.h \
  caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
- caml/addrmap.h
+ caml/osdeps.h caml/signals.h caml/signals_machdep.h
+spacetime.i.o: spacetime.c caml/fail.h caml/compatibility.h caml/misc.h \
+ caml/config.h caml/../../config/m.h caml/../../config/s.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/mlvalues.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/config.h caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/backtrace.h caml/memory.h caml/gc.h \
+ caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.h caml/callback.h caml/custom.h caml/debugger.h \
+ caml/domain_state.h caml/dynlink.h caml/eventlog.h caml/exec.h \
+ caml/fail.h caml/fix_code.h caml/gc_ctrl.h caml/instrtrace.h \
+ caml/interp.h caml/intext.h caml/io.h caml/platform.h caml/io.h \
+ caml/memory.h caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/osdeps.h \
+ caml/params.h caml/exec.h caml/prims.h caml/printexc.h caml/reverse.h \
+ caml/signals.h caml/fiber.h caml/roots.h caml/sys.h caml/startup.h \
+ caml/params.h caml/version.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
+ caml/fail.h caml/mlvalues.h caml/misc.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/config.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/debugger.h caml/fail.h caml/instruct.h \
+ caml/mlvalues.h caml/osdeps.h caml/signals.h caml/fiber.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/alloc.h caml/roots.h caml/sys.h caml/startup.h caml/exec.h \
+ caml/params.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/config.h caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/fail.h caml/io.h caml/platform.h \
+ caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
+ caml/domain.h caml/alloc.h caml/mlvalues.h caml/memory.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/config.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/misc.h caml/osdeps.h caml/signals.h caml/sys.h caml/io.h \
+ caml/platform.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/fail.h caml/major_gc.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/memory.h caml/alloc.h caml/mlvalues.h caml/weak.h
+win32.i.o: win32.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/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/address_class.h caml/fail.h caml/io.h \
+ caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
+ caml/addrmap.h caml/domain.h caml/alloc.h caml/memory.h caml/misc.h \
+ caml/osdeps.h caml/signals.h caml/sys.h caml/config.h
+addrmap.pic.o: addrmap.c caml/config.h caml/../../config/m.h \
+ caml/../../config/s.h caml/compatibility.h caml/memory.h caml/config.h \
+ caml/domain.h caml/mlvalues.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/alloc.h caml/addrmap.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/domain_state.h caml/domain_state.tbl \
@@ -715,16 +1042,15 @@ array.pic.o: array.c caml/alloc.h caml/compatibility.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/fail.h caml/memory.h caml/gc.h \
  caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/memory.h caml/alloc.h caml/misc.h caml/mlvalues.h
+ caml/memory.h caml/alloc.h caml/misc.h caml/mlvalues.h caml/signals.h \
+ spacetime.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/alloc.h caml/mlvalues.h caml/io.h \
- caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/alloc.h caml/instruct.h caml/intext.h \
- caml/io.h caml/exec.h caml/fix_code.h caml/memory.h caml/startup.h \
- caml/exec.h caml/params.h caml/fiber.h caml/roots.h caml/sys.h \
- caml/backtrace.h caml/fail.h
+ caml/instruct.h caml/intext.h caml/exec.h caml/fix_code.h caml/memory.h \
+ caml/domain.h caml/memory.h caml/alloc.h caml/startup.h caml/fiber.h \
+ caml/roots.h caml/sys.h caml/backtrace.h caml/fail.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/domain_state.h \
@@ -749,19 +1075,18 @@ debugger.pic.o: debugger.c caml/alloc.h caml/compatibility.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/config.h caml/debugger.h caml/misc.h \
  caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
- caml/domain.h caml/memory.h caml/alloc.h caml/fail.h caml/fix_code.h \
- caml/instruct.h caml/intext.h caml/io.h caml/platform.h caml/io.h \
- caml/mlvalues.h caml/fiber.h caml/roots.h caml/sys.h
+ caml/domain.h caml/memory.h caml/alloc.h caml/osdeps.h caml/fail.h \
+ caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/platform.h \
+ caml/io.h caml/mlvalues.h caml/fiber.h caml/roots.h caml/sys.h
 domain.pic.o: domain.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/domain.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/byte_domain_state.tbl caml/domain.h caml/memory.h caml/domain.h \
  caml/alloc.h caml/domain_state.h caml/platform.h caml/custom.h \
  caml/major_gc.h caml/shared_heap.h caml/roots.h caml/memory.h \
- caml/fail.h caml/globroots.h caml/signals.h caml/startup.h caml/exec.h \
- caml/params.h caml/fiber.h caml/callback.h caml/minor_gc.h \
- caml/eventlog.h caml/gc_ctrl.h caml/osdeps.h
+ caml/fail.h caml/globroots.h caml/signals.h caml/startup.h caml/fiber.h \
+ caml/callback.h caml/minor_gc.h caml/addrmap.h caml/eventlog.h \
+ caml/gc_ctrl.h caml/osdeps.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/domain_state.h caml/domain_state.tbl \
@@ -773,15 +1098,13 @@ eventlog.pic.o: eventlog.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/eventlog.h caml/domain.h caml/mlvalues.h \
- caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
- caml/alloc.h caml/startup.h caml/exec.h caml/params.h caml/domain.h \
- caml/platform.h
+ caml/memory.h caml/alloc.h caml/startup.h caml/domain.h caml/platform.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/custom.h caml/fail.h caml/gc.h \
- caml/intext.h caml/io.h caml/platform.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/byte_domain_state.tbl caml/config.h caml/custom.h caml/fail.h \
+ caml/gc.h caml/intext.h caml/io.h caml/platform.h caml/memory.h \
+ caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
  caml/alloc.h caml/io.h caml/md5.h caml/memory.h caml/misc.h \
  caml/mlvalues.h caml/reverse.h caml/addrmap.h
 fail.pic.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \
@@ -794,11 +1117,11 @@ fail.pic.o: fail.c caml/alloc.h caml/compatibility.h caml/misc.h \
 fiber.pic.o: fiber.c caml/misc.h caml/compatibility.h caml/config.h \
  caml/../../config/m.h caml/../../config/s.h caml/fiber.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/addrmap.h caml/domain.h caml/alloc.h caml/roots.h \
- caml/gc_ctrl.h caml/instruct.h caml/fail.h caml/alloc.h caml/platform.h \
- caml/fix_code.h caml/minor_gc.h caml/major_gc.h caml/shared_heap.h \
- caml/memory.h caml/params.h caml/exec.h
+ caml/byte_domain_state.tbl caml/memory.h caml/domain.h caml/alloc.h \
+ caml/roots.h caml/gc_ctrl.h caml/instruct.h caml/fail.h caml/alloc.h \
+ caml/platform.h caml/fix_code.h caml/minor_gc.h caml/addrmap.h \
+ caml/major_gc.h caml/shared_heap.h caml/memory.h caml/params.h \
+ caml/exec.h
 finalise.pic.o: finalise.c caml/misc.h caml/compatibility.h caml/config.h \
  caml/../../config/m.h caml/../../config/s.h caml/fail.h caml/misc.h \
  caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
@@ -843,11 +1166,9 @@ 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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/callback.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
+ caml/byte_domain_state.tbl caml/callback.h caml/memory.h caml/domain.h \
  caml/alloc.h caml/custom.h caml/fail.h caml/gc.h caml/intext.h caml/io.h \
- caml/platform.h caml/io.h caml/md5.h caml/memory.h caml/mlvalues.h \
- caml/misc.h caml/reverse.h
+ caml/md5.h caml/memory.h caml/mlvalues.h caml/misc.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/domain_state.h caml/domain_state.tbl \
@@ -857,7 +1178,7 @@ interp.pic.o: interp.c caml/alloc.h caml/compatibility.h caml/misc.h \
  caml/instrtrace.h caml/instruct.h caml/interp.h caml/major_gc.h \
  caml/memory.h caml/misc.h caml/mlvalues.h caml/prims.h caml/signals.h \
  caml/fiber.h caml/roots.h caml/domain.h caml/globroots.h caml/startup.h \
- caml/exec.h caml/params.h caml/jumptbl.h
+ caml/exec.h caml/params.h caml/params.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/domain_state.h caml/domain_state.tbl \
@@ -871,7 +1192,7 @@ io.pic.o: io.c caml/config.h caml/../../config/m.h caml/../../config/s.h \
  caml/byte_domain_state.tbl caml/custom.h caml/fail.h caml/io.h \
  caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
  caml/addrmap.h caml/domain.h caml/alloc.h caml/memory.h caml/misc.h \
- caml/mlvalues.h caml/signals.h caml/sys.h
+ caml/mlvalues.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/domain_state.h caml/domain_state.tbl \
@@ -916,30 +1237,27 @@ 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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/finalise.h caml/gc.h caml/gc_ctrl.h \
- caml/major_gc.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/minor_gc.h \
- caml/misc.h caml/mlvalues.h caml/roots.h caml/signals.h caml/weak.h \
- caml/domain.h caml/shared_heap.h caml/roots.h caml/addrmap.h \
- caml/fiber.h caml/eventlog.h
+ caml/major_gc.h caml/memory.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/minor_gc.h caml/addrmap.h caml/misc.h caml/mlvalues.h caml/roots.h \
+ caml/signals.h caml/weak.h caml/domain.h caml/shared_heap.h caml/roots.h \
+ caml/addrmap.h caml/fiber.h caml/eventlog.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/domain.h \
- caml/startup.h caml/exec.h caml/params.h
+ caml/compatibility.h caml/misc.h caml/config.h caml/memory.h \
+ caml/domain.h caml/mlvalues.h caml/misc.h caml/domain_state.h \
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/alloc.h caml/osdeps.h caml/version.h caml/domain.h caml/startup.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
  caml/fail.h caml/gc.h caml/interp.h caml/major_gc.h caml/memory.h \
  caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
  caml/memory.h caml/alloc.h caml/minor_gc.h caml/misc.h caml/mlvalues.h \
- caml/prims.h caml/platform.h
+ caml/prims.h caml/platform.h spacetime.h
 params.pic.o: params.c caml/misc.h caml/compatibility.h caml/config.h \
  caml/../../config/m.h caml/../../config/s.h caml/params.h \
  caml/mlvalues.h caml/misc.h caml/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/exec.h caml/version.h caml/prims.h \
- caml/dynlink.h caml/domain.h caml/memory.h caml/gc.h caml/major_gc.h \
- caml/minor_gc.h caml/addrmap.h caml/domain.h caml/alloc.h
+ caml/dynlink.h caml/domain.h caml/memory.h caml/domain.h caml/alloc.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/domain_state.h caml/domain_state.tbl \
@@ -950,9 +1268,8 @@ parsing.pic.o: parsing.c caml/config.h caml/../../config/m.h \
 platform.pic.o: platform.c caml/platform.h caml/mlvalues.h \
  caml/compatibility.h caml/config.h caml/../../config/m.h \
  caml/../../config/s.h caml/misc.h caml/domain_state.h \
- caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/alloc.h caml/fail.h
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/domain.h caml/alloc.h caml/fail.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/domain_state.h caml/domain_state.tbl caml/byte_domain_state.tbl \
@@ -970,15 +1287,15 @@ roots.pic.o: roots.c caml/finalise.h caml/globroots.h caml/mlvalues.h \
  caml/domain_state.tbl caml/byte_domain_state.tbl caml/roots.h \
  caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
  caml/domain.h caml/alloc.h caml/major_gc.h caml/memory.h caml/minor_gc.h \
- caml/misc.h caml/mlvalues.h caml/roots.h caml/fiber.h caml/shared_heap.h
+ caml/misc.h caml/mlvalues.h caml/roots.h caml/shared_heap.h caml/fiber.h
 shared_heap.pic.o: shared_heap.c caml/platform.h caml/mlvalues.h \
  caml/compatibility.h caml/config.h caml/../../config/m.h \
  caml/../../config/s.h caml/misc.h caml/domain_state.h \
- caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/alloc.h caml/mlvalues.h caml/gc.h caml/fail.h caml/memory.h \
- caml/sizeclasses.h caml/addrmap.h caml/roots.h caml/globroots.h \
- caml/roots.h caml/shared_heap.h caml/params.h caml/exec.h caml/fiber.h
+ caml/domain_state.tbl caml/byte_domain_state.tbl caml/memory.h \
+ caml/domain.h caml/alloc.h caml/mlvalues.h caml/gc.h caml/fail.h \
+ caml/memory.h caml/sizeclasses.h caml/addrmap.h caml/roots.h \
+ caml/globroots.h caml/roots.h caml/shared_heap.h caml/params.h \
+ caml/exec.h caml/fiber.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/domain_state.h caml/domain_state.tbl \
@@ -993,6 +1310,10 @@ signals_byt.pic.o: signals_byt.c caml/config.h caml/../../config/m.h \
  caml/domain_state.tbl caml/byte_domain_state.tbl caml/major_gc.h \
  caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
  caml/osdeps.h caml/signals.h caml/signals_machdep.h
+spacetime.pic.o: spacetime.c caml/fail.h caml/compatibility.h caml/misc.h \
+ caml/config.h caml/../../config/m.h caml/../../config/s.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/mlvalues.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/domain_state.h caml/domain_state.tbl \
@@ -1025,21 +1346,22 @@ terminfo.pic.o: terminfo.c caml/config.h caml/../../config/m.h \
  caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h \
  caml/domain.h caml/alloc.h caml/mlvalues.h caml/memory.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/major_gc.h caml/minor_gc.h \
- caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h caml/misc.h \
- caml/osdeps.h
+ caml/compatibility.h caml/fail.h caml/misc.h caml/config.h \
+ caml/mlvalues.h caml/domain_state.h caml/domain_state.tbl \
+ caml/byte_domain_state.tbl caml/memory.h caml/gc.h caml/major_gc.h \
+ caml/minor_gc.h caml/addrmap.h caml/domain.h caml/memory.h caml/alloc.h \
+ caml/misc.h caml/osdeps.h caml/signals.h caml/sys.h caml/io.h \
+ caml/platform.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/domain_state.h caml/domain_state.tbl \
  caml/byte_domain_state.tbl caml/fail.h caml/major_gc.h caml/memory.h \
  caml/gc.h caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/memory.h caml/alloc.h caml/mlvalues.h
-win32.pic.o: win32.c caml/address_class.h caml/misc.h caml/compatibility.h \
+ caml/memory.h caml/alloc.h caml/mlvalues.h caml/weak.h
+win32.pic.o: win32.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/domain_state.h caml/domain_state.tbl \
- caml/byte_domain_state.tbl caml/fail.h caml/memory.h caml/gc.h \
- caml/major_gc.h caml/minor_gc.h caml/addrmap.h caml/domain.h \
- caml/memory.h caml/alloc.h caml/misc.h caml/osdeps.h caml/signals.h \
- caml/sys.h
+ caml/byte_domain_state.tbl caml/address_class.h caml/fail.h caml/io.h \
+ caml/platform.h caml/memory.h caml/gc.h caml/major_gc.h caml/minor_gc.h \
+ caml/addrmap.h caml/domain.h caml/alloc.h caml/memory.h caml/misc.h \
+ caml/osdeps.h caml/signals.h caml/sys.h caml/config.h
diff --git a/byterun/.ignore b/byterun/.ignore
deleted file mode 100644
index 7eab2b6250..0000000000
--- 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 5602387e82..5070c69546 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) -ggdb
-DFLAGS=-DCAML_NAME_SPACE -ggdb -DDEBUG $(BYTECCCOMPOPTS) $(IFLEXDIR) -Werror-implicit-function-declaration
+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 776ce45789..d061ea3d7c
--- 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
@@ -25,22 +27,15 @@ COMMONOBJS=\
   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 finalise.o custom.o \
   dynlink.o addrmap.o domain.o platform.o eventlog.o \
-  params.o
+  params.o spacetime.o
 
 PRIMS=\
   alloc.c array.c compare.c extern.c floats.c gc_ctrl.c hash.c \
   intern.c interp.c ints.c io.c lexing.c md5.c meta.c obj.c parsing.c \
   signals.c str.c sys.c terminfo.c callback.c weak.c finalise.c fiber.c \
-  dynlink.c backtrace.c domain.c memory.c params.c
+  dynlink.c backtrace.c domain.c memory.c params.c spacetime.c
 
-PUBLIC_INCLUDES=\
-  address_class.h alloc.h callback.h config.h custom.h fail.h gc.h \
-  hash.h intext.h memory.h misc.h mlvalues.h printexc.h signals.h \
-  compatibility.h version.h byte_domain_state.tbl domain_state.tbl \
-	domain_state.h
-
-
-all:: ocamlrun$(EXE) ld.conf libcamlrun.$(A) all-$(RUNTIMED)
+all:: ocamlrun$(EXE) ld.conf libcamlrun.$(A) all-$(RUNTIMED) primitives
 .PHONY: all
 
 all-noruntimed:
@@ -49,6 +44,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
@@ -60,15 +59,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
-	for i in $(PUBLIC_INCLUDES); do \
-	  sed -f ../tools/cleanup-header caml/$$i > $(INSTALL_LIBDIR)/caml/$$i; \
+	cp $(CAMLRUN)$(EXE) "$(INSTALL_BINDIR)/ocamlrun$(EXE)"
+	cp libcamlrun.$(A) "$(INSTALL_LIBDIR)/libcamlrun.$(A)"
+	cd "$(INSTALL_LIBDIR)"; $(RANLIB) libcamlrun.$(A)
+	if test -d "$(INSTALL_LIBDIR)/caml"; then : ; \
+	  else mkdir "$(INSTALL_LIBDIR)/caml"; fi
+	for i in caml/*.h; do \
+	  sed -f ../tools/cleanup-header $$i \
+	      > "$(INSTALL_LIBDIR)/$$i"; \
 	done
-	cp ld.conf $(INSTALL_LIBDIR)/ld.conf
+	cp ld.conf "$(INSTALL_LIBDIR)/ld.conf"
 .PHONY: install
 
 install:: install-$(RUNTIMED)
@@ -81,10 +81,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
@@ -111,7 +117,8 @@ maybe-update-primitives: primitives.new
 primitives: maybe-update-primitives
 
 prims.c : primitives
-	(echo '#include "caml/mlvalues.h"'; \
+	(echo '#define CAML_INTERNALS'; \
+         echo '#include "caml/mlvalues.h"'; \
 	 echo '#include "caml/prims.h"'; \
 	 sed -e 's/.*/extern value &();/' primitives; \
 	 echo 'const c_primitive caml_builtin_cprim[] = {'; \
@@ -127,7 +134,8 @@ caml/opnames.h : caml/instruct.h
 	    -e '/END_OF_INSTRUCTIONS/d' \
 	    -e 's/enum /const char * const 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 9bc342eee6..e74bdd9ca5 100644
--- a/byterun/Makefile.nt
+++ b/byterun/Makefile.nt
@@ -1,30 +1,40 @@
-#########################################################################
-#                                                                       #
-#                                 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)
+DFLAGS=$(CFLAGS) -DDEBUG
+
+ifdef BOOTSTRAPPING_FLEXLINK
+MAKE_OCAMLRUN=$(MKEXE_BOOT)
+CFLAGS:=-DBOOTSTRAPPING_FLEXLINK $(CFLAGS)
+else
+MAKE_OCAMLRUN=$(MKEXE) -o $(1) $(2)
+endif
 
 DBGO=d.$(O)
 OBJS=$(COMMONOBJS:.o=.$(O)) win32.$(O) main.$(O)
 DOBJS=$(OBJS:.$(O)=.$(DBGO)) instrtrace.$(DBGO)
 
 ocamlrun$(EXE): libcamlrun.$(A) prims.$(O)
-	$(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) \
+	$(MKEXE) -o ocamlrund$(EXE) prims.$(O) \
 	         $(call SYSLIB,ws2_32) $(EXTRALIBS) libcamlrund.$(A)
 
 libcamlrun.$(A): $(OBJS)
@@ -36,19 +46,25 @@ libcamlrund.$(A): $(DOBJS)
 %.$(O): %.c
 	$(CC) $(CFLAGS) $(BYTECCCOMPOPTS) -c $<
 
+# It is imperative that there is no space after $(NAME_OBJ_FLAG)
 %.$(DBGO): %.c
-	$(CC) $(CFLAGS) $(BYTECCDBGCOMPOPTS) -c -o $@ $<
+	$(CC) $(DFLAGS) $(BYTECCDBGCOMPOPTS) -c $(NAME_OBJ_FLAG)$@ $<
 
 .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/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):/' \
+	sed -ne '/\.pic\.o/q' \
+	    -e 's/^\(.*\)\.d\.o:/\1.$$(DBGO):/' \
+	    -e 's/^\(.*\)\.o:/\1.$$(O):/' \
+	    -e p \
 	    .depend.win32 > .depend.nt
 	rm -f .depend.win32
 
diff --git a/byterun/alloc.c b/byterun/alloc.c
index 56e6aad348..47f97155fb 100644
--- a/byterun/alloc.c
+++ b/byterun/alloc.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* 1. Allocation functions doing the same work as the macros in the
       case where [Setup_for_gc] and [Restore_after_gc] are no-ops.
@@ -163,11 +167,31 @@ CAMLexport value caml_alloc_small (mlsize_t wosize, tag_t tag)
   return caml_alloc(wosize, tag);
 }
 
+CAMLexport value caml_alloc_small_with_my_or_given_profinfo (mlsize_t wosize,
+  tag_t tag, uintnat profinfo)
+{
+  if (profinfo == 0) {
+    return caml_alloc_small(wosize, tag);
+  }
+  else {
+    value result;
+
+    Assert (wosize > 0);
+    Assert (wosize <= Max_young_wosize);
+    Assert (tag < 256);
+    Alloc_small_with_profinfo (result, wosize, tag,
+      { caml_handle_gc_interrupt(); }, profinfo);
+    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)
 {
   mlsize_t offset_index;
@@ -180,6 +204,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)
 {
@@ -218,7 +245,24 @@ CAMLexport value caml_alloc_array(value (*funct)(char const *),
   }
 }
 
-CAMLexport value caml_copy_string_array(char const * const* arr)
+/* [len] is a number of floats */
+CAMLprim value caml_alloc_float_array(mlsize_t len)
+{
+  mlsize_t wosize = len * Double_wosize;
+  value result;
+  if (wosize == 0)
+    return Atom(0);
+  else if (wosize <= Max_young_wosize){
+    Alloc_small (result, wosize, Double_array_tag, { caml_handle_gc_interrupt(); });
+  }else {
+    result = caml_alloc_shr (wosize, Double_array_tag);
+    result = caml_check_urgent_gc (result);
+  }
+  return result;
+}
+
+
+CAMLexport value caml_copy_string_array(char const * const * arr)
 {
   return caml_alloc_array(caml_copy_string, arr);
 }
@@ -236,23 +280,26 @@ CAMLexport int caml_convert_flag_list(value list, const 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);
diff --git a/byterun/array.c b/byterun/array.c
index e93497d3a5..fd0713ae80 100644
--- a/byterun/array.c
+++ b/byterun/array.c
@@ -1,25 +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 GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
+#define CAML_INTERNALS
 
+/* 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"
+#include "spacetime.h"
+
+static const mlsize_t mlsize_t_max = -1;
 
+/* returns number of elements (either fields or floats) */
 CAMLexport mlsize_t caml_array_length(value array)
 {
   if (Tag_val(array) == Double_array_tag)
@@ -133,6 +141,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;
@@ -142,7 +151,7 @@ CAMLprim value caml_make_float_vect(value len)
   else if (wosize <= Max_young_wosize){
     Alloc_small (result, wosize, Double_array_tag, { caml_handle_gc_interrupt(); });
   }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);
@@ -150,6 +159,8 @@ CAMLprim value caml_make_float_vect(value len)
   return result;
 }
 
+/* [len] is a [value] representing number of words or floats */
+/* Spacetime profiling assumes that this function is only called from OCaml. */
 CAMLprim value caml_make_vect(value len, value init)
 {
   CAMLparam2 (len, init);
@@ -177,6 +188,7 @@ CAMLprim value caml_make_vect(value len, value init)
     if (size >= Max_young_wosize &&
         Is_block(init) && Is_young(init))
       caml_minor_collection();
+    /* TODO: Spacetime */
     res = caml_alloc(size, 0);
     for (i = 0; i < size; i++) caml_initialize_field(res, i, init);
   }
@@ -247,6 +259,7 @@ static value caml_array_gather(intnat num_arrays,
   size = 0;
   isfloat = 0;
   for (i = 0; i < num_arrays; i++) {
+    if (mlsize_t_max - lengths[i] < size) caml_invalid_argument("Array.concat");
     size += lengths[i];
     if (Tag_val(arrays[i]) == Double_array_tag) isfloat = 1;
   }
@@ -256,8 +269,8 @@ static value caml_array_gather(intnat num_arrays,
   }
   else if (isfloat) {
     /* This is an array of floats.  We can use memcpy directly. */
+    if (size > Max_wosize/Double_wosize) caml_invalid_argument("Array.concat");
     wsize = size * Double_wosize;
-    if (wsize > Max_wosize) caml_invalid_argument("Array.concat");
     res = caml_alloc(wsize, Double_array_tag);
     for (i = 0, pos = 0; i < num_arrays; i++) {
       memcpy((double *)res + pos,
@@ -278,9 +291,6 @@ static value caml_array_gather(intnat num_arrays,
       pos += lengths[i];
     }
     Assert(pos == size);
-    /* Many caml_initialize_field in a row can create a lot of old-to-young
-       refs.  Give the minor GC a chance to run if it needs to. */
-    res = caml_check_urgent_gc(res);
   }
   CAMLreturn (res);
 }
@@ -319,8 +329,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_imm(l, 1), i++) {
diff --git a/byterun/backtrace.c b/byterun/backtrace.c
index 5eec0e6ba5..bc98779eae 100644
--- a/byterun/backtrace.c
+++ b/byterun/backtrace.c
@@ -11,6 +11,10 @@
 /*                                                                     */
 /***********************************************************************/
 
+/* TODO KC: Split into backtrace_prim.c */
+
+#define CAML_INTERNALS
+
 /* Stack backtrace for uncaught exceptions */
 
 #include 
@@ -415,7 +419,8 @@ 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) ||
+  li->loc_is_raise =
+    caml_is_instruction(*pc, RAISE) ||
     caml_is_instruction(*pc, RERAISE);
   if (ev == -1) {
     li->loc_valid = 0;
@@ -558,3 +563,41 @@ CAMLprim value caml_get_exception_backtrace(value unit)
   }
   CAMLreturn(res);
 }
+
+CAMLprim value caml_add_debug_info(code_t start, value size,
+                                   value events)
+{
+  return Val_unit;
+}
+
+CAMLprim value caml_remove_debug_info(code_t start)
+{
+  return Val_unit;
+}
+
+CAMLprim value caml_raw_backtrace_length(value bt)
+{
+  return Val_int(Wosize_val(bt));
+}
+
+CAMLprim value caml_raw_backtrace_slot(value bt, value index)
+{
+  /* TODO KC */
+  caml_failwith ("caml_raw_backtrace_next_slot not implemented");
+  return Val_unit;
+}
+
+CAMLprim value caml_raw_backtrace_next_slot(value slot)
+{
+  /* TODO KC */
+  caml_failwith ("caml_raw_backtrace_next_slot not implemented");
+  return Val_unit;
+}
+
+/* Convert the raw backtrace to a data structure usable from OCaml */
+CAMLprim value caml_convert_raw_backtrace(value bt)
+{
+  /* TODO KC */
+  caml_failwith ("caml_raw_backtrace_next_slot not implemented");
+  return Val_unit;
+}
diff --git a/byterun/callback.c b/byterun/callback.c
index 5fa010c8b8..04ebb7b7e6 100644
--- a/byterun/callback.c
+++ b/byterun/callback.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Callbacks from C to OCaml */
 
@@ -31,7 +35,6 @@ static __thread int callback_depth = 0;
 #include "caml/fix_code.h"
 #include "caml/fiber.h"
 
-
 static opcode_t callback_code[] = { ACC, 0, APPLY, 0, POP, 1, STOP };
 
 static void init_callback_code(void)
@@ -276,3 +279,14 @@ void caml_decr_callback_depth ()
 {
   callback_depth--;
 }
+
+CAMLexport void caml_iterate_named_values(caml_named_action f)
+{
+  int i;
+  for(i = 0; i < Named_value_size; i++){
+    struct named_value * nv;
+    for (nv = named_value_table[i]; nv != NULL; nv = nv->next) {
+      f( nv->val, nv->name );
+    }
+  }
+}
diff --git a/byterun/caml/address_class.h b/byterun/caml/address_class.h
index f7908b6dc9..4192644a6d 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.     */
-/*                                                                     */
-/***********************************************************************/
+/*     en Automatique.                                                    */
+/*                                                                        */
+/*   All rights reserved.  This file is distributed 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 586f7300e5..16da7203a0 100644
--- a/byterun/caml/alloc.h
+++ b/byterun/caml/alloc.h
@@ -42,6 +42,8 @@ CAMLextern value caml_alloc_8(tag_t, value, value, value, value,
 CAMLextern value caml_alloc_9(tag_t, value, value, value, value,
                               value, value, value, value, value);
 CAMLextern value caml_alloc_small (mlsize_t, tag_t);
+CAMLextern value caml_alloc_small_with_my_or_given_profinfo (mlsize_t wosize,
+  tag_t tag, uintnat profinfo);
 CAMLextern value caml_alloc_tuple (mlsize_t);
 CAMLextern value caml_alloc_string (mlsize_t);  /* size in bytes */
 CAMLextern value caml_copy_string (char const *);
diff --git a/byterun/caml/backtrace.h b/byterun/caml/backtrace.h
index 3b6b31ec5f..5ac00da8cf 100644
--- a/byterun/caml/backtrace.h
+++ b/byterun/caml/backtrace.h
@@ -24,5 +24,6 @@ CAMLprim value caml_get_continuation_callstack(value stack, value max_frames);
 extern void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise);
 #endif
 CAMLextern void caml_print_exception_backtrace(void);
+CAMLextern 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 0000000000..025242d001
--- /dev/null
+++ b/byterun/caml/backtrace_prim.h
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 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
+
+#ifdef CAML_INTERNALS
+
+#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;
+  int loc_is_inlined;
+};
+
+/* When compiling with -g, backtrace slots have debug info associated.
+ * When a call is inlined in native mode, debuginfos form a linked list.
+ */
+typedef void * debuginfo;
+
+/* Check availability of debug information before extracting a trace.
+ * Relevant for bytecode, always true for native code. */
+int caml_debug_info_available(void);
+
+/* Return debuginfo associated to a slot or NULL. */
+debuginfo caml_debuginfo_extract(backtrace_slot slot);
+
+/* In case of an inlined call return next debuginfo or NULL otherwise. */
+debuginfo caml_debuginfo_next(debuginfo dbg);
+
+/* Extract locations from backtrace_slot */
+void caml_debuginfo_location(debuginfo dbg, /*out*/ struct caml_loc_info * li);
+
+/* In order to prevent the GC from walking through the debug
+   information (which have no headers), we transform slots to 31/63 bits
+   ocaml integers by shifting them by 1 to the right. We do not lose
+   information as slots are aligned.
+
+   In particular, we do not need to use [caml_modify] when setting
+   an array element with such a value.
+ */
+#define Val_backtrace_slot(bslot) (Val_long(((uintnat)(bslot))>>1))
+#define Backtrace_slot_val(vslot) ((backtrace_slot)(Long_val(vslot) << 1))
+
+#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_INTERNALS */
+
+#endif /* CAML_BACKTRACE_PRIM_H */
diff --git a/byterun/caml/callback.h b/byterun/caml/callback.h
index 10498fbcdf..06f00d10ab 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
 
@@ -45,6 +47,8 @@ CAMLextern value caml_callbackN_exn (value closure, int narg, value args[]);
 #define Extract_exception(v) ((v) & ~3)
 
 CAMLextern caml_root caml_named_root (char const * name);
+typedef void (*caml_named_action) (caml_root, char *);
+CAMLextern void caml_iterate_named_values(caml_named_action f);
 
 CAMLextern void caml_main (char ** argv);
 CAMLextern void caml_startup (char ** argv);
diff --git a/byterun/caml/compact.h b/byterun/caml/compact.h
new file mode 100644
index 0000000000..4f98fb12b7
--- /dev/null
+++ b/byterun/caml/compact.h
@@ -0,0 +1,31 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 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
+
+#ifdef CAML_INTERNALS
+
+#include "config.h"
+#include "misc.h"
+#include "mlvalues.h"
+
+void caml_compact_heap (void);
+void caml_compact_heap_maybe (void);
+void invert_root (value v, value *p);
+
+#endif /* CAML_INTERNALS */
+
+#endif /* CAML_COMPACT_H */
diff --git a/byterun/caml/compatibility.h b/byterun/caml/compatibility.h
index fbec80136c..0536c28c00 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 f3adbe4eec..8930e4ec47 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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,6 +21,9 @@
 /*  */
 #include "../../config/m.h"
 #include "../../config/s.h"
+#ifdef BOOTSTRAPPING_FLEXLINK
+#undef SUPPORT_DYNAMIC_LINKING
+#endif
 /*  */
 
 #ifndef CAML_NAME_SPACE
@@ -70,6 +75,12 @@ 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
@@ -106,6 +117,7 @@ typedef uint64_t uintnat;
 #define ARCH_FLOAT_ENDIANNESS 0x01234567
 #endif
 
+
 /* We use threaded code interpretation if the compiler provides labels
    as first-class values (GCC 2.x). */
 
@@ -115,14 +127,14 @@ typedef uint64_t 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)
 
 /* Size of extra stack slop space if profiling is enabled (words) */
 #define Profile_slop 128
@@ -140,6 +152,7 @@ typedef uint64_t 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).
@@ -200,4 +213,12 @@ typedef uint64_t uintnat;
 /* Maximum number of domains */
 #define Max_domains (1 << Minor_heap_sel_bits)
 
+/* 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 b0db7bb167..d5812c4e0c 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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*/);
   value (*deserialize)(void);
   int (*compare_ext)(value v1, value v2);
 };
@@ -56,13 +58,13 @@ CAMLextern void caml_register_custom_operations(const struct custom_operations *
 /* In domain_state.tbl: intnat compare_unordered; */
 /* Used by custom comparison to report unordered NaN-like cases. */
 
-/*  */
+#ifdef CAML_INTERNALS
 extern struct custom_operations * caml_find_custom_operations(char * ident);
 extern struct custom_operations *
           caml_final_custom_operations(void (*fn)(value));
 
 extern void caml_init_custom_operations(void);
-/*  */
+#endif /* CAML_INTERNALS */
 
 #ifdef __cplusplus
 }
diff --git a/byterun/caml/debugger.h b/byterun/caml/debugger.h
index e68ef756c1..c98f35a8d1 100644
--- a/byterun/caml/debugger.h
+++ b/byterun/caml/debugger.h
@@ -1,21 +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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Interface with the debugger */
 
 #ifndef CAML_DEBUGGER_H
 #define CAML_DEBUGGER_H
 
+#ifdef CAML_INTERNALS
+
 #include "misc.h"
 #include "mlvalues.h"
 
@@ -108,4 +112,6 @@ enum debugger_reply {
   /* Program exited due to a stray exception. */
 };
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_DEBUGGER_H */
diff --git a/byterun/caml/domain.h b/byterun/caml/domain.h
index 91218a9ead..46d9a39d84 100644
--- a/byterun/caml/domain.h
+++ b/byterun/caml/domain.h
@@ -5,6 +5,7 @@
 #include "mlvalues.h"
 #include "domain_state.h"
 #include "memory.h"
+#include "major_gc.h"
 
 struct domain {
   struct dom_internal* internals;
diff --git a/byterun/caml/dynlink.h b/byterun/caml/dynlink.h
index 74cfdb663e..0eed7e7fa1 100644
--- a/byterun/caml/dynlink.h
+++ b/byterun/caml/dynlink.h
@@ -1,21 +1,25 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                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. */
 
 #ifndef CAML_DYNLINK_H
 #define CAML_DYNLINK_H
 
+#ifdef CAML_INTERNALS
+
 #include "misc.h"
 
 /* Build the table of primitives, given a search path, a list
@@ -33,4 +37,6 @@ extern struct ext_table caml_shared_libs_path;
    Used for executables generated by ocamlc -output-obj. */
 extern void caml_build_primitive_table_builtin(void);
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_DYNLINK_H */
diff --git a/byterun/caml/exec.h b/byterun/caml/exec.h
index 7e084acd41..f39747acf8 100644
--- a/byterun/caml/exec.h
+++ b/byterun/caml/exec.h
@@ -1,21 +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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* exec.h : format of executable bytecode files */
 
 #ifndef CAML_EXEC_H
 #define CAML_EXEC_H
 
+#ifdef CAML_INTERNALS
+
 /* Executable bytecode files are composed of a number of sections,
    identified by 4-character names.  A table of contents at the
    end of the file lists the section names along with their sizes,
@@ -56,5 +60,6 @@ struct exec_trailer {
 
 #define EXEC_MAGIC "Caml1999X011"
 
+#endif /* CAML_INTERNALS */
 
 #endif /* CAML_EXEC_H */
diff --git a/byterun/caml/fiber.h b/byterun/caml/fiber.h
index e3a6f6c297..f1310f20fd 100644
--- a/byterun/caml/fiber.h
+++ b/byterun/caml/fiber.h
@@ -1,6 +1,8 @@
 #ifndef CAML_FIBER_H
 #define CAML_FIBER_H
 
+#ifdef CAML_INTERNALS
+
 #include "misc.h"
 #include "mlvalues.h"
 #include "memory.h"
@@ -112,4 +114,6 @@ value caml_reverse_fiber_stack(value stack);
 void caml_get_stack_sp_pc (value stack, char** sp /* out */, uintnat* pc /* out */);
 #endif
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_FIBER_H */
diff --git a/byterun/caml/finalise.h b/byterun/caml/finalise.h
index f32b91c889..9fc67e5fa8 100644
--- a/byterun/caml/finalise.h
+++ b/byterun/caml/finalise.h
@@ -1 +1,23 @@
-/* finalise.h */
+/**************************************************************************/
+/*                                                                        */
+/*                                 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
+
+#ifdef CAML_INTERNALS
+
+#endif /* CAML_INTERNALS */
+
+#endif /* CAML_FINALISE_H */
diff --git a/byterun/caml/fix_code.h b/byterun/caml/fix_code.h
index 419ad327a5..7e5633d6d3 100644
--- a/byterun/caml/fix_code.h
+++ b/byterun/caml/fix_code.h
@@ -1,21 +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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Handling of blocks of bytecode (endianness switch, threading). */
 
 #ifndef CAML_FIX_CODE_H
 #define CAML_FIX_CODE_H
 
+#ifdef CAML_INTERNALS
 
 #include "config.h"
 #include "misc.h"
@@ -25,7 +28,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);
@@ -37,4 +40,6 @@ extern char * caml_instr_base;
 void caml_thread_code (code_t code, asize_t len);
 #endif
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_FIX_CODE_H */
diff --git a/byterun/caml/freelist.h b/byterun/caml/freelist.h
new file mode 100644
index 0000000000..54e0e822f4
--- /dev/null
+++ b/byterun/caml/freelist.h
@@ -0,0 +1,38 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 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. */
+
+#ifndef CAML_FREELIST_H
+#define CAML_FREELIST_H
+
+#ifdef CAML_INTERNALS
+
+#include "misc.h"
+#include "mlvalues.h"
+
+extern asize_t caml_fl_cur_wsz;
+
+header_t *caml_fl_allocate (mlsize_t wo_sz);
+void caml_fl_init_merge (void);
+void caml_fl_reset (void);
+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);
+
+#endif /* CAML_INTERNALS */
+
+#endif /* CAML_FREELIST_H */
diff --git a/byterun/caml/gc.h b/byterun/caml/gc.h
index 1d981e0e12..c5e9e9e868 100644
--- a/byterun/caml/gc.h
+++ b/byterun/caml/gc.h
@@ -25,6 +25,9 @@
                     + (tag_t) (tag)))                                         \
       )
 
+#define Make_header_with_profinfo(wosize, tag, color, profinfo) \
+  Make_header(wosize,tag,color)
+
 #define Whitehd_hd(hd) (((hd)  & ~(3 << 8)))
 
 #endif /* CAML_GC_H */
diff --git a/byterun/caml/globroots.h b/byterun/caml/globroots.h
index a2f66dbb58..e51f978913 100644
--- a/byterun/caml/globroots.h
+++ b/byterun/caml/globroots.h
@@ -16,6 +16,8 @@
 #ifndef CAML_GLOBROOTS_H
 #define CAML_GLOBROOTS_H
 
+#ifdef CAML_INTERNALS
+
 #include "mlvalues.h"
 #include "roots.h"
 #include "memory.h"
@@ -28,4 +30,6 @@ void caml_cleanup_deleted_roots(void);
 void caml_register_dyn_global(void *v);
 #endif
 
+#endif
+
 #endif /* CAML_GLOBROOTS_H */
diff --git a/byterun/caml/hash.h b/byterun/caml/hash.h
index 14f7af8666..ee82a4c85a 100644
--- a/byterun/caml/hash.h
+++ b/byterun/caml/hash.h
@@ -18,6 +18,10 @@
 
 #include "mlvalues.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 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);
diff --git a/byterun/caml/hooks.h b/byterun/caml/hooks.h
new file mode 100644
index 0000000000..c9814263fd
--- /dev/null
+++ b/byterun/caml/hooks.h
@@ -0,0 +1,42 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*                    Fabrice Le Fessant, INRIA de Paris                  */
+/*                                                                        */
+/*   Copyright 2016 Institut National de Recherche en Informatique et     */
+/*     en Automatique.                                                    */
+/*                                                                        */
+/*   All rights reserved.  This file is distributed under the terms of    */
+/*   the GNU Lesser General Public License version 2.1, with the          */
+/*   special exception on linking described in the file LICENSE.          */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef CAML_HOOKS_H
+#define CAML_HOOKS_H
+
+#include "misc.h"
+#include "memory.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CAML_INTERNALS
+
+#ifdef NATIVE_CODE
+
+/* executed just before calling the entry point of a dynamically
+   loaded native code module. */
+CAMLextern void (*caml_natdynlink_hook)(void* handle, char* unit);
+
+#endif /* NATIVE_CODE */
+
+#endif /* CAML_INTERNALS */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CAML_HOOKS_H */
diff --git a/byterun/caml/instrtrace.h b/byterun/caml/instrtrace.h
index 6403ebdbe2..c80171e633 100644
--- a/byterun/caml/instrtrace.h
+++ b/byterun/caml/instrtrace.h
@@ -1,21 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
 
 #ifndef _instrtrace_
 #define _instrtrace_
 
+#ifdef CAML_INTERNALS
 
 #include "mlvalues.h"
 #include "misc.h"
@@ -26,4 +29,7 @@ void caml_disasm_instr (code_t pc);
 void caml_trace_value_file (value v, code_t prog, int proglen, FILE * f);
 void caml_trace_accu_sp_file(value accu, value * sp, code_t prog, int proglen,
                              FILE * f);
+
+#endif /* CAML_INTERNALS */
+
 #endif
diff --git a/byterun/caml/instruct.h b/byterun/caml/instruct.h
index 86f9852580..b516306fd4 100644
--- a/byterun/caml/instruct.h
+++ b/byterun/caml/instruct.h
@@ -1,21 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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. */
 
 #ifndef CAML_INSTRUCT_H
 #define CAML_INSTRUCT_H
 
+#ifdef CAML_INTERNALS
+
 enum instructions {
   ACC0, ACC1, ACC2, ACC3, ACC4, ACC5, ACC6, ACC7,
   ACC, PUSH,
@@ -61,4 +65,6 @@ enum instructions {
   PERFORM, RESUME, RESUMETERM, REPERFORMTERM,
 FIRST_UNIMPLEMENTED_OP};
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_INSTRUCT_H */
diff --git a/byterun/caml/int64_emul.h b/byterun/caml/int64_emul.h
index 2554df1814..c1cddcc05d 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.  */
@@ -17,6 +19,8 @@
 #ifndef CAML_INT64_EMUL_H
 #define CAML_INT64_EMUL_H
 
+#ifdef CAML_INTERNALS
+
 #include 
 
 #ifdef ARCH_BIG_ENDIAN
@@ -284,4 +288,6 @@ static int64_t I64_bswap(int64_t x)
   return res;
 }
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_INT64_EMUL_H */
diff --git a/byterun/caml/int64_format.h b/byterun/caml/int64_format.h
index aa8f1abab5..40250ed9ef 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,6 +19,8 @@
 #ifndef CAML_INT64_FORMAT_H
 #define CAML_INT64_FORMAT_H
 
+#ifdef CAML_INTERNALS
+
 static void I64_format(char * buffer, char * fmt, int64_t x)
 {
   static char conv_lower[] = "0123456789abcdef";
@@ -102,4 +106,6 @@ static void I64_format(char * buffer, char * fmt, int64_t x)
   *p = 0;
 }
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_INT64_FORMAT_H */
diff --git a/byterun/caml/int64_native.h b/byterun/caml/int64_native.h
index b6716ada2a..7df66511cf 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,6 +20,8 @@
 #ifndef CAML_INT64_NATIVE_H
 #define CAML_INT64_NATIVE_H
 
+#ifdef CAML_INTERNALS
+
 #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)))
@@ -58,4 +62,6 @@
                       (((x) & 0x00FF000000000000ULL) >> 40) | \
                       (((x) & 0xFF00000000000000ULL) >> 56))
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_INT64_NATIVE_H */
diff --git a/byterun/caml/interp.h b/byterun/caml/interp.h
index 7c2bf0ec54..949655985a 100644
--- a/byterun/caml/interp.h
+++ b/byterun/caml/interp.h
@@ -1,25 +1,37 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                OCaml                                */
 /*                                                                     */
 /*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
 /*                                                                     */
 /*  Copyright 1996 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
 
 #ifndef CAML_INTERP_H
 #define CAML_INTERP_H
 
+#ifdef CAML_INTERNALS
+
 #include "misc.h"
 #include "mlvalues.h"
 
 /* interpret a bytecode */
 value caml_interprete (code_t prog, asize_t prog_size);
 
+/* tell the runtime that a bytecode program might be needed */
+void caml_prepare_bytecode(code_t prog, asize_t prog_size);
+
+/* tell the runtime that a bytecode program is no more needed */
+void caml_release_bytecode(code_t prog, asize_t prog_size);
+
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_INTERP_H */
diff --git a/byterun/caml/intext.h b/byterun/caml/intext.h
index 4e4e841beb..ae87b473e2 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
 
@@ -22,12 +24,30 @@
 #include "misc.h"
 #include "mlvalues.h"
 
-/*  */
+#ifdef CAML_INTERNALS
 #include "io.h"
 
 /* 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
@@ -77,7 +103,7 @@
 void caml_output_val (struct channel * chan, value v, value flags);
   /* Output [v] with flags [flags] on the channel [chan]. */
 
-/*  */
+#endif /* CAML_INTERNALS */
 
 #ifdef __cplusplus
 extern "C" {
@@ -96,10 +122,21 @@ CAMLextern intnat caml_output_value_to_block(value v, value flags,
      in bytes.  Return the number of bytes actually written in buffer.
      Raise [Failure] if buffer is too short. */
 
-/*  */
+#ifdef CAML_INTERNALS
 value caml_input_val (struct channel * chan);
   /* Read a structured value from the channel [chan]. */
-/*  */
+
+extern value caml_input_value_to_outside_heap (value channel);
+  /* As for [caml_input_value], but the value is unmarshalled into
+     malloc blocks that are not added to the heap.  Not for the
+     casual user. */
+
+extern int caml_extern_allow_out_of_heap;
+  /* Permit the marshaller to traverse structures that look like OCaml
+     values but do not live in the OCaml heap. */
+
+extern value caml_output_value(value vchan, value v, value flags);
+#endif /* CAML_INTERNALS */
 
 CAMLextern value caml_input_val_from_string (value str, intnat ofs);
   /* Read a structured value from the OCaml string [str], starting
@@ -146,7 +183,7 @@ CAMLextern void caml_deserialize_block_8(void * data, intnat len);
 CAMLextern void caml_deserialize_block_float_8(void * data, intnat len);
 CAMLextern void caml_deserialize_error(char * msg) Noreturn;
 
-/*  */
+#ifdef CAML_INTERNALS
 
 /* Auxiliary stuff for sending code pointers */
 
@@ -157,9 +194,11 @@ struct code_fragment {
   char digest_computed;
 };
 
+CAMLextern struct code_fragment * caml_extern_find_code(char *addr);
+
 struct ext_table caml_code_fragments_table;
 
-/*  */
+#endif /* CAML_INTERNALS */
 
 #ifdef __cplusplus
 }
diff --git a/byterun/caml/io.h b/byterun/caml/io.h
index 8b51eeaca9..f3a827373a 100644
--- a/byterun/caml/io.h
+++ b/byterun/caml/io.h
@@ -1,21 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
 
 #ifndef CAML_IO_H
 #define CAML_IO_H
 
+#ifdef CAML_INTERNALS
+
 #include "misc.h"
 #include "mlvalues.h"
 #include "platform.h"
@@ -46,10 +50,14 @@ 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 {
-  CHANNEL_FLAG_FROM_SOCKET = 1  /* For Windows */
+  CHANNEL_FLAG_FROM_SOCKET = 1,  /* For Windows */
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+  CHANNEL_FLAG_BLOCKING_WRITE = 2,
+#endif
 };
 
 /* For an output channel:
@@ -61,12 +69,12 @@ enum {
 /* Functions and macros that can be called from C.  Take arguments of
    type struct channel *.  No locking is performed. */
 
-#define putch(channel, ch) do{                                            \
+#define caml_putch(channel, ch) do{                                       \
   if ((channel)->curr >= (channel)->end) caml_flush_partial(channel);     \
   *((channel)->curr)++ = (ch);                                            \
 }while(0)
 
-#define getch(channel)                                                      \
+#define caml_getch(channel)                                                 \
   ((channel)->curr >= (channel)->max                                        \
    ? caml_refill(channel)                                                   \
    : (unsigned char) *((channel)->curr)++)
@@ -86,7 +94,7 @@ CAMLextern void caml_really_putblock (struct channel *, char *, intnat);
 CAMLextern unsigned char caml_refill (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);
+CAMLextern intnat caml_really_getblock (struct channel *, char *, intnat);
 
 /* Extract a struct channel * from the heap object representing it */
 
@@ -98,4 +106,6 @@ CAMLextern struct channel * caml_all_opened_channels;
 #define Val_file_offset(fofs) caml_copy_int64(fofs)
 #define File_offset_val(v) ((file_offset) Int64_val(v))
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_IO_H */
diff --git a/byterun/caml/md5.h b/byterun/caml/md5.h
index f63667d56a..e83c16cd21 100644
--- a/byterun/caml/md5.h
+++ b/byterun/caml/md5.h
@@ -1,21 +1,24 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                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 */
 
 #ifndef CAML_MD5_H
 #define CAML_MD5_H
 
+#ifdef CAML_INTERNALS
 
 #include "mlvalues.h"
 #include "io.h"
@@ -25,6 +28,8 @@ CAMLextern value caml_md5_chan (value vchan, value len);
 CAMLextern void caml_md5_block(unsigned char digest[16],
                                void * data, uintnat len);
 
+CAMLextern value caml_md5_channel(struct channel *chan, intnat toread);
+
 struct MD5Context {
         uint32_t buf[4];
         uint32_t bits[2];
@@ -37,5 +42,6 @@ CAMLextern void caml_MD5Update (struct MD5Context *context, unsigned char *buf,
 CAMLextern void caml_MD5Final (unsigned char *digest, struct MD5Context *ctx);
 CAMLextern void caml_MD5Transform (uint32_t *buf, uint32_t *in);
 
+#endif /* CAML_INTERNALS */
 
 #endif /* CAML_MD5_H */
diff --git a/byterun/caml/memory.h b/byterun/caml/memory.h
index 56e291eb49..05310e233f 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
 
@@ -20,10 +22,11 @@
 #include "compatibility.h"
 #endif
 #include "config.h"
-/*  */
+#ifdef CAML_INTERNALS
 #include "gc.h"
 #include "major_gc.h"
 #include "minor_gc.h"
+#endif /* CAML_INTERNALS */
 #include "domain.h"
 /*  */
 #include "misc.h"
@@ -37,7 +40,18 @@ extern "C" {
 #define BVAR_EMPTY      0x10000
 #define BVAR_OWNER_MASK 0x0ffff
 
-CAMLextern value caml_alloc_shr (mlsize_t, tag_t);
+CAMLextern value caml_alloc_shr (mlsize_t wosize, tag_t);
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+CAMLextern value caml_alloc_shr_with_profinfo (mlsize_t, tag_t, intnat);
+CAMLextern value caml_alloc_shr_preserving_profinfo (mlsize_t, tag_t,
+  header_t);
+#else
+#define caml_alloc_shr_with_profinfo(size, tag, profinfo) \
+  caml_alloc_shr(size, tag)
+#define caml_alloc_shr_preserving_profinfo(size, tag, header) \
+  caml_alloc_shr(size, tag)
+#endif
+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);
@@ -50,13 +64,15 @@ 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);
+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 int caml_huge_fallback_count; /* FIXME KC: Make per domain */
 
 /* void caml_shrink_heap (char *);        Only used in compact.c */
 
-/*  */
+#ifdef CAML_INTERNALS
 
 /* FIXME */
 /* There are two GC bits in the object header, with the following
@@ -67,6 +83,15 @@ int caml_add_to_heap (char *mem);
 #define Is_promoted_hd(hd)  (((hd) & (3 << 8)) == (3 << 8))
 #define Promotedhd_hd(hd)  ((hd) | (3 << 8))
 
+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
+
 #ifdef DEBUG
 #define DEBUG_clear(result, wosize) do{ \
   uintnat caml__DEBUG_i; \
@@ -84,7 +109,8 @@ int caml_add_to_heap (char *mem);
 #define Count_alloc
 #endif
 
-#define Alloc_small(result, wosize, tag, GC) do{CAMLassert ((wosize) >= 1); \
+#define Alloc_small_with_profinfo(result, wosize, tag, GC, profinfo) do{    \
+                                                CAMLassert ((wosize) >= 1); \
                                           CAMLassert ((tag_t) (tag) < 256); \
                                  CAMLassert ((wosize) <= Max_young_wosize); \
   caml_domain_state* dom_st = Caml_state;                     \
@@ -94,12 +120,19 @@ int caml_add_to_heap (char *mem);
     { GC }                                                                  \
     dom_st->young_ptr -= Bhsize_wosize (wosize);                            \
   }                                                                         \
-  Hd_hp (dom_st->young_ptr) = Make_header ((wosize), (tag), 0);             \
+  Hd_hp (dom_st->young_ptr) =                                               \
+    Make_header_with_profinfo ((wosize), (tag), 0, profinfo);               \
+  /* FIXME: Spacetime */ if (profinfo == 0);                                \
   (result) = Val_hp (dom_st->young_ptr);                                    \
   DEBUG_clear ((result), (wosize));                                         \
   Count_alloc;                                                              \
 }while(0)
 
+#define Alloc_small(result, wosize, tag, GC) \
+  Alloc_small_with_profinfo(result, wosize, tag, GC, (uintnat)0)
+
+#endif /* CAML_INTERNALS */
+
 /*  */
 struct caml__mutex_unwind;
 struct caml__roots_block {
@@ -134,7 +167,9 @@ struct caml__roots_block {
    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
@@ -168,10 +203,25 @@ struct caml__roots_block {
   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
 
@@ -185,7 +235,8 @@ struct caml__roots_block {
     (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; \
@@ -198,7 +249,8 @@ struct caml__roots_block {
     (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; \
@@ -212,7 +264,8 @@ struct caml__roots_block {
     (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; \
@@ -227,7 +280,8 @@ struct caml__roots_block {
     (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; \
@@ -243,7 +297,8 @@ struct caml__roots_block {
     (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; \
@@ -255,7 +310,8 @@ struct caml__roots_block {
     (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; \
diff --git a/byterun/caml/misc.h b/byterun/caml/misc.h
index f5c6941ea8..def9f54d62 100644
--- a/byterun/caml/misc.h
+++ b/byterun/caml/misc.h
@@ -34,14 +34,32 @@ typedef size_t asize_t;
 #define NULL 0
 #endif
 
-/*  */
+#ifdef CAML_INTERNALS
 typedef char * addr;
-/*  */
+#endif /* CAML_INTERNALS */
 
+/* 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
 
@@ -91,7 +109,7 @@ CAMLextern int caml_failed_assert (char *, char *, int);
 
 #ifndef CAML_AVOID_CONFLICTS
 #define Assert CAMLassert
-#endif  
+#endif
 
 #define CAML_STATIC_ASSERT_3(b, l) \
   typedef char static_assertion_failure_line_##l[(b) ? 1 : -1]
@@ -106,8 +124,6 @@ CAMLextern int caml_failed_assert (char *, char *, int);
 
 #define Is_power_of_2(x) (((x) & ((x) - 1)) == 0)
 
-/*  */
-
 CAMLextern void caml_fatal_error (const char *msg) Noreturn;
 CAMLextern void caml_fatal_error_arg (const char *fmt, const char *arg) Noreturn;
 CAMLextern void caml_fatal_error_arg2 (const char *fmt1, const char *arg1,
@@ -118,7 +134,103 @@ CAMLextern void caml_fatal_error_arg2 (const char *fmt1, const char *arg1,
 CAMLextern char * caml_strdup(const char * s);
 CAMLextern char * caml_strconcat(int n, ...); /* n args of const char * type */
 
-/*  */
+/* Use macros for some system calls being called from OCaml itself.
+  These calls can be either traced for security reasons, or changed to
+  virtualize the program. */
+
+
+#ifndef CAML_WITH_CPLUGINS
+
+#define CAML_SYS_EXIT(retcode) exit(retcode)
+#define CAML_SYS_OPEN(filename,flags,perm) open(filename,flags,perm)
+#define CAML_SYS_CLOSE(fd) close(fd)
+#define CAML_SYS_STAT(filename,st) stat(filename,st)
+#define CAML_SYS_UNLINK(filename) unlink(filename)
+#define CAML_SYS_RENAME(old_name,new_name) rename(old_name, new_name)
+#define CAML_SYS_CHDIR(dirname) chdir(dirname)
+#define CAML_SYS_GETENV(varname) getenv(varname)
+#define CAML_SYS_SYSTEM(command) system(command)
+#define CAML_SYS_READ_DIRECTORY(dirname,tbl) caml_read_directory(dirname,tbl)
+
+#else
+
+
+#define CAML_CPLUGINS_EXIT 0
+#define CAML_CPLUGINS_OPEN 1
+#define CAML_CPLUGINS_CLOSE 2
+#define CAML_CPLUGINS_STAT 3
+#define CAML_CPLUGINS_UNLINK 4
+#define CAML_CPLUGINS_RENAME 5
+#define CAML_CPLUGINS_CHDIR 6
+#define CAML_CPLUGINS_GETENV 7
+#define CAML_CPLUGINS_SYSTEM 8
+#define CAML_CPLUGINS_READ_DIRECTORY 9
+#define CAML_CPLUGINS_PRIMS_MAX 9
+
+#define CAML_CPLUGINS_PRIMS_BITMAP  ((1 << CAML_CPLUGINS_PRIMS_MAX)-1)
+
+extern intnat (*caml_cplugins_prim)(int,intnat,intnat,intnat);
+
+#define CAML_SYS_PRIM_1(code,prim,arg1)               \
+  (caml_cplugins_prim == NULL) ? prim(arg1) :    \
+  caml_cplugins_prim(code,(intnat) (arg1),0,0)
+#define CAML_SYS_STRING_PRIM_1(code,prim,arg1)               \
+  (caml_cplugins_prim == NULL) ? prim(arg1) :    \
+  (char*)caml_cplugins_prim(code,(intnat) (arg1),0,0)
+#define CAML_SYS_PRIM_2(code,prim,arg1,arg2)                         \
+  (caml_cplugins_prim == NULL) ? prim(arg1,arg2) :              \
+  caml_cplugins_prim(code,(intnat) (arg1), (intnat) (arg2),0)
+#define CAML_SYS_PRIM_3(code,prim,arg1,arg2,arg3)                            \
+  (caml_cplugins_prim == NULL) ? prim(arg1,arg2,arg3) :                 \
+  caml_cplugins_prim(code,(intnat) (arg1), (intnat) (arg2),(intnat) (arg3))
+
+#define CAML_SYS_EXIT(retcode) \
+  CAML_SYS_PRIM_1(CAML_CPLUGINS_EXIT,exit,retcode)
+#define CAML_SYS_OPEN(filename,flags,perm)                      \
+  CAML_SYS_PRIM_3(CAML_CPLUGINS_OPEN,open,filename,flags,perm)
+#define CAML_SYS_CLOSE(fd)                      \
+  CAML_SYS_PRIM_1(CAML_CPLUGINS_CLOSE,close,fd)
+#define CAML_SYS_STAT(filename,st)                      \
+  CAML_SYS_PRIM_2(CAML_CPLUGINS_STAT,stat,filename,st)
+#define CAML_SYS_UNLINK(filename)                       \
+  CAML_SYS_PRIM_1(CAML_CPLUGINS_UNLINK,unlink,filename)
+#define CAML_SYS_RENAME(old_name,new_name)                              \
+  CAML_SYS_PRIM_2(CAML_CPLUGINS_RENAME,rename,old_name,new_name)
+#define CAML_SYS_CHDIR(dirname)                         \
+  CAML_SYS_PRIM_1(CAML_CPLUGINS_CHDIR,chdir,dirname)
+#define CAML_SYS_GETENV(varname)                        \
+  CAML_SYS_STRING_PRIM_1(CAML_CPLUGINS_GETENV,getenv,varname)
+#define CAML_SYS_SYSTEM(command)                        \
+  CAML_SYS_PRIM_1(CAML_CPLUGINS_SYSTEM,system,command)
+#define CAML_SYS_READ_DIRECTORY(dirname,tbl)                            \
+  CAML_SYS_PRIM_2(CAML_CPLUGINS_READ_DIRECTORY,caml_read_directory,     \
+                  dirname,tbl)
+
+#define CAML_CPLUGIN_CONTEXT_API 0
+
+struct cplugin_context {
+  int api_version;
+  int prims_bitmap;
+  char *exe_name;
+  char** argv;
+  char *plugin; /* absolute filename of plugin, do a copy if you need it ! */
+  char *ocaml_version;
+/* end of CAML_CPLUGIN_CONTEXT_API version 0 */
+};
+
+extern void caml_cplugins_init(char * exe_name, char **argv);
+
+/* A plugin MUST define a symbol "caml_cplugin_init" with the prototype:
+
+void caml_cplugin_init(struct cplugin_context *ctx)
+*/
+
+/* to write plugins for CAML_SYS_READ_DIRECTORY, we will need the
+   definition of struct ext_table to be public. */
+
+#endif /* CAML_WITH_CPLUGINS */
+
+
 
 /* Data structures */
 
@@ -131,6 +243,10 @@ 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_free(struct ext_table * tbl, int free_entries);
+extern void caml_ext_table_remove(struct ext_table * tbl, void * data);
+extern void caml_ext_table_clear(struct ext_table * tbl, int free_entries);
+
+#ifdef CAML_INTERNALS
 
 /* GC flags and messages */
 
@@ -140,6 +256,17 @@ void caml_gc_log (char *, ...)
 #endif
 ;
 
+void caml_gc_message (int, char *, ...)
+#ifdef __GNUC__
+  __attribute__ ((format (printf, 2, 3)))
+#endif
+;
+
+/* Runtime warnings */
+extern uintnat caml_runtime_warnings;
+int caml_runtime_warnings_active(void);
+
+
 #ifdef DEBUG
 #ifdef ARCH_SIXTYFOUR
 #define Debug_tag(x) (0xD700D7D7D700D6D7ul \
@@ -186,7 +313,16 @@ extern int caml_snprintf(char * buf, size_t size, const char * format, ...);
 #define snprintf caml_snprintf
 #endif
 
-/*  */
+#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_INTERNALS */
 
 #ifdef __cplusplus
 }
diff --git a/byterun/caml/mlvalues.h b/byterun/caml/mlvalues.h
index d1a2d243ef..c81cc281e0 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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
@@ -80,7 +82,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)((uintnat)(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)))
@@ -104,16 +106,39 @@ For 64-bit architectures:
      +--------+-------+-----+
 bits  63    10 9     8 7   0
 
+For x86-64 with Spacetime profiling:
+  P = PROFINFO_WIDTH (as set by "configure", currently 26 bits, giving a
+    maximum block size of just under 4Gb)
+     +----------------+----------------+-------------+
+     | profiling info | wosize         | color | tag |
+     +----------------+----------------+-------------+
+bits  63        (64-P) (63-P)        10 9     8 7   0
+
 */
 
+#define PROFINFO_SHIFT (64 - PROFINFO_WIDTH)
+#define PROFINFO_MASK ((1ull << PROFINFO_WIDTH) - 1ull)
+
 #define Tag_hd(hd) ((tag_t) ((hd) & 0xFF))
+#ifdef WITH_SPACETIME
+#define Hd_no_profinfo(hd) ((hd) & ~(PROFINFO_MASK << PROFINFO_SHIFT))
+#define Wosize_hd(hd) ((mlsize_t) ((Hd_no_profinfo(hd)) >> 10))
+#else
 #define Wosize_hd(hd) ((mlsize_t) ((hd) >> 10))
+#endif /* SPACETIME */
+#ifdef ARCH_SIXTYFOUR
+/* [Profinfo_hd] is used when the compiler is not configured for Spacetime
+   (e.g. when decoding profiles). */
+#define Profinfo_hd(hd) (((mlsize_t) ((hd) >> PROFINFO_SHIFT)) & PROFINFO_MASK)
+#else
+#define Profinfo_hd(hd) ((hd) & 0)
+#endif /* ARCH_SIXTYFOUR */
 
 #define Hd_val(val) (((header_t *) (val)) [-1])        /* Also an l-value. */
 #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))
@@ -123,7 +148,11 @@ bits  63    10 9     8 7   0
 
 #define Num_tags (1 << 8)
 #ifdef ARCH_SIXTYFOUR
-#define Max_wosize (((intnat)1 << 32) - 1)
+#ifdef WITH_SPACETIME
+#define Max_wosize (((intnat)1 << (54-PROFINFO_WIDTH)) - 1)
+#else
+#define Max_wosize (((intnat)1 << 54) - 1)
+#endif
 #else
 #define Max_wosize ((1 << 22) - 1)
 #endif
@@ -150,6 +179,8 @@ bits  63    10 9     8 7   0
 #define Bhsize_hp(hp) (Bsize_wsize (Whsize_hp (hp)))
 #define Bhsize_hd(hd) (Bsize_wsize (Whsize_hd (hd)))
 
+#define Profinfo_val(val) (Profinfo_hd (Hd_val (val)))
+
 #ifdef ARCH_BIG_ENDIAN
 #define Tag_val(val) (((unsigned char *) (val)) [-1])
                                                  /* Also an l-value. */
@@ -292,7 +323,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
 #define Data_abstract_val(v) ((void*) Op_val(v))
@@ -301,6 +333,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
diff --git a/byterun/caml/osdeps.h b/byterun/caml/osdeps.h
index 3bc46d8b09..e8c08018ab 100644
--- a/byterun/caml/osdeps.h
+++ b/byterun/caml/osdeps.h
@@ -1,23 +1,43 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
 
 #ifndef CAML_OSDEPS_H
 #define CAML_OSDEPS_H
 
+#ifdef CAML_INTERNALS
+
 #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, const char * path);
@@ -74,4 +94,11 @@ extern int caml_executable_name(char * name, int name_len);
    resolution may be less. The starting point is unspecified. */
 extern int64_t caml_time_counter(void);
 
+/* Secure version of [getenv]: returns NULL if the process has special
+   privileges (setuid bit or capabilities).
+*/
+extern char *caml_secure_getenv(char const *var);
+
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_OSDEPS_H */
diff --git a/byterun/caml/prims.h b/byterun/caml/prims.h
index 861b022cd7..855925e5c7 100644
--- a/byterun/caml/prims.h
+++ b/byterun/caml/prims.h
@@ -1,21 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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. */
 
 #ifndef CAML_PRIMS_H
 #define CAML_PRIMS_H
 
+#ifdef CAML_INTERNALS
+
 typedef value (*c_primitive)();
 
 extern const c_primitive caml_builtin_cprim[];
@@ -28,4 +32,9 @@ extern struct ext_table caml_prim_name_table;
 
 #define Primitive(n) ((c_primitive)(caml_prim_table.contents[n]))
 
+extern char * caml_section_table;
+extern asize_t caml_section_table_size;
+
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_PRIMS_H */
diff --git a/byterun/caml/reverse.h b/byterun/caml/reverse.h
index 09d34a51f6..a186078e1a 100644
--- a/byterun/caml/reverse.h
+++ b/byterun/caml/reverse.h
@@ -1,21 +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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Swap byte-order in 16, 32, and 64-bit integers or floats */
 
 #ifndef CAML_REVERSE_H
 #define CAML_REVERSE_H
 
+#ifdef CAML_INTERNALS
+
 #define Reverse_16(dst,src) {                                               \
   char * _p, * _q;                                                          \
   char _a;                                                                  \
@@ -83,4 +87,6 @@
   _p[Perm_index(perm_dst, 7)] = _h;                                         \
 }
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_REVERSE_H */
diff --git a/byterun/caml/roots.h b/byterun/caml/roots.h
index ca47544103..ed1acdf55e 100644
--- a/byterun/caml/roots.h
+++ b/byterun/caml/roots.h
@@ -14,6 +14,8 @@
 #ifndef CAML_ROOTS_H
 #define CAML_ROOTS_H
 
+#ifdef CAML_INTERNALS
+
 #include "misc.h"
 #include "memory.h"
 
@@ -22,4 +24,6 @@ CAMLexport void (*caml_scan_roots_hook)(scanning_action, void*, struct domain*);
 
 void caml_do_local_roots(scanning_action, void*, struct domain*);
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_ROOTS_H */
diff --git a/byterun/caml/shared_heap.h b/byterun/caml/shared_heap.h
index 4c3ea65926..b42eba98b6 100644
--- a/byterun/caml/shared_heap.h
+++ b/byterun/caml/shared_heap.h
@@ -1,6 +1,8 @@
 #ifndef CAML_SHARED_HEAP_H
 #define CAML_SHARED_HEAP_H
 
+#ifdef CAML_INTERNALS
+
 #include "config.h"
 #include "roots.h"
 #include "domain.h"
@@ -71,4 +73,6 @@ void caml_verify_heap(struct heap_verify_state*); /* deallocates arg */
 int is_garbage (value);
 #endif
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_SHARED_HEAP_H */
diff --git a/byterun/caml/signals.h b/byterun/caml/signals.h
index 3e8e233e50..ca982fd152 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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
@@ -24,7 +26,7 @@
 extern "C" {
 #endif
 
-/*  */
+#ifdef CAML_INTERNALS
 CAMLextern intnat volatile caml_signals_are_pending;
 CAMLextern intnat volatile caml_pending_signals[];
 CAMLextern int volatile caml_something_to_do;
@@ -35,6 +37,11 @@ CAMLextern void caml_enter_blocking_section (void);
 CAMLextern void caml_leave_blocking_section (void);
 
 /*  */
+extern int volatile caml_requested_major_slice;
+extern int volatile caml_requested_minor_gc;
+
+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_record_signal(int signal_number);
@@ -42,7 +49,10 @@ void caml_process_pending_signals(void);
 int caml_set_signal_action(int signo, int action);
 
 CAMLextern void (* volatile caml_async_action_hook)(void);
-/*  */
+#endif /* CAML_INTERNALS */
+
+CAMLextern void caml_enter_blocking_section (void);
+CAMLextern void caml_leave_blocking_section (void);
 
 #ifdef __cplusplus
 }
diff --git a/byterun/caml/signals_machdep.h b/byterun/caml/signals_machdep.h
index 4987e2f6a8..ef4e5bbd42 100644
--- a/byterun/caml/signals_machdep.h
+++ b/byterun/caml/signals_machdep.h
@@ -1,22 +1,34 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                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__)
+#ifdef CAML_INTERNALS
+
+#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" \
@@ -57,4 +69,6 @@
 
 #endif
 
+#endif /* CAML_INTERNALS */
+
 #endif /* CAML_SIGNALS_MACHDEP_H */
diff --git a/asmrun/stack.h b/byterun/caml/stack.h
similarity index 81%
rename from asmrun/stack.h
rename to byterun/caml/stack.h
index f0c61e9de0..409cd57960 100644
--- a/asmrun/stack.h
+++ b/byterun/caml/stack.h
@@ -33,16 +33,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)) //FIXME KC
 #endif
 
diff --git a/byterun/caml/startup.h b/byterun/caml/startup.h
index 17e5fa5914..650caf5f26 100644
--- a/byterun/caml/startup.h
+++ b/byterun/caml/startup.h
@@ -1,19 +1,23 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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
 
+#ifdef CAML_INTERNALS
+
 #include "mlvalues.h"
 #include "exec.h"
 #include "params.h"
@@ -33,7 +37,9 @@ extern int caml_attempt_open(const char **name, struct exec_trailer *trail,
 extern void caml_read_section_descriptors(int fd, struct exec_trailer *trail);
 extern int32_t caml_seek_optional_section(int fd, struct exec_trailer *trail,
                                         char *name);
-extern int32_t 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_INTERNALS */
 
 #endif /* CAML_STARTUP_H */
diff --git a/byterun/caml/weak.h b/byterun/caml/weak.h
index 0cf4b8b2b4..c9f6958cf4 100644
--- a/byterun/caml/weak.h
+++ b/byterun/caml/weak.h
@@ -18,6 +18,10 @@
 
 #include "mlvalues.h"
 
+#define CAML_EPHE_LINK_OFFSET 0
+#define CAML_EPHE_DATA_OFFSET 1
+#define CAML_EPHE_FIRST_KEY 2
+
 extern value caml_weak_list_head;
 extern value caml_weak_none;
 
diff --git a/byterun/compare.c b/byterun/compare.c
index aa7f0b4521..3a10df3cf9 100644
--- a/byterun/compare.c
+++ b/byterun/compare.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 #include 
 #include 
@@ -19,6 +23,10 @@
 #include "caml/misc.h"
 #include "caml/mlvalues.h"
 
+#if defined(LACKS_SANE_NAN) && !defined(isnan)
+#define isnan _isnan
+#endif
+
 /* Structural comparison on trees. */
 
 struct compare_item { value * v1, * v2; mlsize_t count; };
@@ -135,7 +143,7 @@ static intnat do_compare_val(struct compare_stack* stk,
       }
       default: /*fallthrough*/;
       }
-      
+
       return LESS;                /* v1 long < v2 block */
     }
     if (Is_long(v2)) {
@@ -178,8 +186,19 @@ static intnat do_compare_val(struct compare_stack* stk,
     case Double_tag: {
       double d1 = Double_val(v1);
       double d2 = Double_val(v2);
+#ifdef LACKS_SANE_NAN
+      if (isnan(d2)) {
+        if (! total) return UNORDERED;
+        if (isnan(d1)) break;
+        return GREATER;
+      } else if (isnan(d1)) {
+        if (! total) return UNORDERED;
+        return LESS;
+      }
+#endif
       if (d1 < d2) return LESS;
       if (d1 > d2) return GREATER;
+#ifndef LACKS_SANE_NAN
       if (d1 != d2) {
         if (! total) return UNORDERED;
         /* One or both of d1 and d2 is NaN.  Order according to the
@@ -188,6 +207,7 @@ static intnat do_compare_val(struct compare_stack* stk,
         if (d2 == d2) return LESS;    /* d2 is not NaN, d1 is NaN */
         /* d1 and d2 are both NaN, thus equal: continue comparison */
       }
+#endif
       break;
     }
     case Double_array_tag: {
@@ -198,14 +218,26 @@ static intnat do_compare_val(struct compare_stack* stk,
       for (i = 0; i < sz1; i++) {
         double d1 = Double_field(v1, i);
         double d2 = Double_field(v2, i);
+#ifdef LACKS_SANE_NAN
+        if (isnan(d2)) {
+          if (! total) return UNORDERED;
+          if (isnan(d1)) break;
+          return GREATER;
+        } else if (isnan(d1)) {
+          if (! total) return UNORDERED;
+          return LESS;
+        }
+#endif
         if (d1 < d2) return LESS;
         if (d1 > d2) return GREATER;
+#ifndef LACKS_SANE_NAN
         if (d1 != d2) {
           if (! total) return UNORDERED;
           /* See comment for Double_tag case */
           if (d1 == d1) return GREATER;
           if (d2 == d2) return LESS;
         }
+#endif
       }
       break;
     }
diff --git a/byterun/custom.c b/byterun/custom.c
index 990166b0ef..c419382596 100644
--- a/byterun/custom.c
+++ b/byterun/custom.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 #include 
 
@@ -19,6 +23,7 @@
 #include "caml/memory.h"
 #include "caml/mlvalues.h"
 
+/* [size] is a number of bytes */
 CAMLexport value caml_alloc_custom(const struct custom_operations * ops,
                                    uintnat size,
                                    mlsize_t mem,
@@ -32,6 +37,13 @@ CAMLexport value caml_alloc_custom(const struct custom_operations * ops,
   if (ops->finalize == NULL && wosize <= Max_young_wosize) {
     result = caml_alloc_small(wosize, Custom_tag);
     Custom_ops_val(result) = ops;
+#if 0
+    /* XXX KC: TODO */
+    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);
+    }
+#endif
   } else {
     result = caml_alloc_shr(wosize, Custom_tag);
     Custom_ops_val(result) = ops;
diff --git a/byterun/debugger.c b/byterun/debugger.c
index 888f756053..68d8de97c9 100644
--- a/byterun/debugger.c
+++ b/byterun/debugger.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Interface with the byte-code debugger */
 
@@ -24,6 +28,7 @@
 #include "caml/debugger.h"
 #include "caml/misc.h"
 #include "caml/memory.h"
+#include "caml/osdeps.h"
 
 int caml_debugger_in_use = 0;
 uintnat caml_event_count;
@@ -169,7 +174,7 @@ void caml_debugger_init(void)
   Store_field(flags, 1, Val_emptylist);
   marshal_flags = caml_create_root(flags);
 
-  address = getenv("CAML_DEBUG_SOCKET");
+  address = caml_secure_getenv("CAML_DEBUG_SOCKET");
   if (address == NULL) return;
   dbg_addr = address;
 
@@ -219,7 +224,7 @@ void caml_debugger_init(void)
 static value getval(struct channel *chan)
 {
   value res;
-  if (caml_really_getblock(chan, (char *) &res, sizeof(res)) == 0)
+  if (caml_really_getblock(chan, (char *) &res, sizeof(res)) < sizeof(res))
     caml_raise_end_of_file(); /* Bad, but consistent with caml_getword */
   return res;
 }
@@ -268,19 +273,19 @@ void caml_debugger(enum event_kind event)
   case PROGRAM_START:           /* Nothing to report */
     goto command_loop;
   case EVENT_COUNT:
-    putch(dbg_out, REP_EVENT);
+    caml_putch(dbg_out, REP_EVENT);
     break;
   case BREAKPOINT:
-    putch(dbg_out, REP_BREAKPOINT);
+    caml_putch(dbg_out, REP_BREAKPOINT);
     break;
   case PROGRAM_EXIT:
-    putch(dbg_out, REP_EXITED);
+    caml_putch(dbg_out, REP_EXITED);
     break;
   case TRAP_BARRIER:
-    putch(dbg_out, REP_TRAP);
+    caml_putch(dbg_out, REP_TRAP);
     break;
   case UNCAUGHT_EXC:
-    putch(dbg_out, REP_UNCAUGHT_EXC);
+    caml_putch(dbg_out, REP_UNCAUGHT_EXC);
     break;
   }
   caml_putword(dbg_out, caml_event_count);
@@ -298,7 +303,7 @@ void caml_debugger(enum event_kind event)
 
   /* Read and execute the commands sent by the debugger */
   while(1) {
-    switch(getch(dbg_in)) {
+    switch(caml_getch(dbg_in)) {
     case REQ_SET_EVENT:
       pos = caml_getword(dbg_in);
       Assert (pos >= 0);
@@ -406,11 +411,11 @@ void caml_debugger(enum event_kind event)
       val = getval(dbg_in);
       i = caml_getword(dbg_in);
       if (Tag_val(val) != Double_array_tag) {
-        putch(dbg_out, 0);
+        caml_putch(dbg_out, 0);
         putval(dbg_out, Op_val(val)[i]);
       } else {
         double d = Double_field(val, i);
-        putch(dbg_out, 1);
+        caml_putch(dbg_out, 1);
         caml_really_putblock(dbg_out, (char *) &d, 8);
       }
       caml_flush(dbg_out);
diff --git a/byterun/domain.c b/byterun/domain.c
index c3890a99a6..494a597c3b 100644
--- a/byterun/domain.c
+++ b/byterun/domain.c
@@ -1,3 +1,5 @@
+#define CAML_INTERNALS
+
 #include 
 #include 
 #include 
@@ -618,7 +620,7 @@ void caml_print_stats () {
 #if defined(COLLECT_STATS) && defined(NATIVE_CODE)
   struct detailed_stats ds;
   caml_domain_state* st;
-  uint64 total;
+  uint64_t total;
   int i;
 #endif
 
diff --git a/byterun/dynlink.c b/byterun/dynlink.c
index 94700ef83f..80bdbf5185 100644
--- a/byterun/dynlink.c
+++ b/byterun/dynlink.c
@@ -1,15 +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 GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Dynamic loading of C primitives. */
 
@@ -77,8 +81,8 @@ static char * parse_ld_conf(void)
   struct stat st;
   int ldconf, nread;
 
-  stdlib = getenv("OCAMLLIB");
-  if (stdlib == NULL) stdlib = getenv("CAMLLIB");
+  stdlib = caml_secure_getenv("OCAMLLIB");
+  if (stdlib == NULL) stdlib = caml_secure_getenv("CAMLLIB");
   if (stdlib == NULL) stdlib = OCAML_STDLIB_DIR;
   ldconfname = caml_strconcat(3, stdlib, "/", LD_CONF_NAME);
   if (stat(ldconfname, &st) == -1) {
@@ -118,7 +122,7 @@ static void open_shared_lib(char * name)
   void * handle;
 
   realname = caml_search_dll_in_path(&caml_shared_libs_path, name);
-  caml_gc_log("Loading shared library %s", realname);
+  caml_gc_message(0x100, "Loading shared library %s\n", realname);
   caml_enter_blocking_section();
   handle = caml_dlopen(realname, 1, 1);
   caml_leave_blocking_section();
@@ -145,7 +149,7 @@ void caml_build_primitive_table(char * lib_path,
      - directories specified in the executable
      - directories specified in the file /ld.conf */
   tofree1 = caml_decompose_path(&caml_shared_libs_path,
-                                getenv("CAML_LD_LIBRARY_PATH"));
+                                caml_secure_getenv("CAML_LD_LIBRARY_PATH"));
   if (lib_path != NULL)
     for (p = lib_path; *p != 0; p += strlen(p) + 1)
       caml_ext_table_add(&caml_shared_libs_path, p);
@@ -206,13 +210,12 @@ CAMLprim value caml_dynlink_open_lib(value mode, value filename)
   value result;
   char * p;
 
-  caml_gc_log("Opening shared library %s", String_val(filename));
+  caml_gc_message(0x100, "Opening shared library %s\n", String_val(filename));
   p = caml_strdup(String_val(filename));
   caml_enter_blocking_section();
   handle = caml_dlopen(p, Int_val(mode), 1);
   caml_leave_blocking_section();
   caml_stat_free(p);
-
   if (handle == NULL) caml_failwith(caml_dlerror());
   result = caml_alloc_small(1, Abstract_tag);
   Handle_val(result) = handle;
diff --git a/byterun/eventlog.c b/byterun/eventlog.c
index 4112009c3c..3645a30cad 100644
--- a/byterun/eventlog.c
+++ b/byterun/eventlog.c
@@ -1,3 +1,5 @@
+#define CAML_INTERNALS
+
 #include 
 #include 
 #include 
diff --git a/byterun/extern.c b/byterun/extern.c
index 2b3b5e959b..3ceb044158 100644
--- a/byterun/extern.c
+++ b/byterun/extern.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Structured output */
 
@@ -17,6 +21,7 @@
 
 #include 
 #include "caml/alloc.h"
+#include "caml/config.h"
 #include "caml/custom.h"
 #include "caml/fail.h"
 #include "caml/gc.h"
@@ -61,10 +66,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 void free_extern_output(void);
 
 /* Free the extern stack if needed */
@@ -217,26 +234,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)
 {
   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)
 {
@@ -250,44 +288,32 @@ 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
 
 /* Marshal the given value in the output buffer */
 
+int caml_extern_allow_out_of_heap = 0;
+
 static void extern_rec(value v)
 {
   struct extern_item * sp;
@@ -297,7 +323,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)) {
@@ -333,9 +359,13 @@ 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 {
+#if !(defined(NATIVE_CODE) && defined(WITH_SPACETIME))
         writecode32(CODE_BLOCK32, hd);
+#else
+        writecode32(CODE_BLOCK32, Hd_no_profinfo(hd));
+#endif
       }
       goto next_item;
     }
@@ -351,6 +381,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);
       }
@@ -362,7 +396,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 {
@@ -370,8 +404,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;
@@ -382,7 +421,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;
@@ -401,8 +440,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;
@@ -433,12 +477,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 */
@@ -449,19 +493,24 @@ 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 !(defined(NATIVE_CODE) && defined(WITH_SPACETIME))
+        header_t hd_erased = hd;
+#else
+        header_t hd_erased = Hd_no_profinfo(hd);
+#endif
         if (sz > 0x3FFFFF && (extern_flags & COMPAT_32))
           extern_failwith("output_value: array cannot be read back on "
                           "32-bit platform");
-#endif
+        if (hd_erased < (uintnat)1 << 32)
+          writecode32(CODE_BLOCK32, Whitehd_hd (hd_erased));
+        else
+          writecode64(CODE_BLOCK64, Whitehd_hd (hd_erased));
+#else
         writecode32(CODE_BLOCK32, Whitehd_hd (hd));
+#endif
       }
       size_32 += 1 + sz;
       size_64 += 1 + sz;
@@ -495,7 +544,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 */
@@ -505,10 +556,6 @@ 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 */
@@ -520,38 +567,47 @@ static intnat extern_value(value v, value flags)
 #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. */
+    /* 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");
+      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;
@@ -573,20 +629,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);
@@ -595,50 +655,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)
@@ -651,24 +725,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_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_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)
@@ -684,7 +756,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;
 }
 
@@ -700,7 +772,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
 }
@@ -717,7 +789,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
 }
@@ -734,7 +806,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
 }
@@ -743,7 +815,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 34cbc411bf..c014f24236 100644
--- a/byterun/fail.c
+++ b/byterun/fail.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Raising exceptions from C. */
 
diff --git a/byterun/fiber.c b/byterun/fiber.c
index 8c42ca9d89..5635592966 100644
--- a/byterun/fiber.c
+++ b/byterun/fiber.c
@@ -1,3 +1,5 @@
+#define CAML_INTERNALS
+
 #include 
 #include 
 #include "caml/misc.h"
diff --git a/byterun/finalise.c b/byterun/finalise.c
index 1243901abe..624c8dccd3 100644
--- a/byterun/finalise.c
+++ b/byterun/finalise.c
@@ -11,3 +11,8 @@ CAMLprim value caml_final_release (value unit)
 {
   caml_failwith("finalisers unimplemented");
 }
+
+CAMLprim value caml_final_register_called_without_value (value f, value v)
+{
+  caml_failwith("finalisers unimplemented");
+}
diff --git a/byterun/fix_code.c b/byterun/fix_code.c
index 4f9c08ceea..498f0d7723 100644
--- a/byterun/fix_code.c
+++ b/byterun/fix_code.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Handling of blocks of bytecode (endianness switch, threading). */
 
@@ -17,6 +21,8 @@
 
 #ifdef HAS_UNISTD
 #include 
+#else
+#include 
 #endif
 
 #include "caml/debugger.h"
@@ -35,7 +41,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 +102,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);
diff --git a/byterun/floats.c b/byterun/floats.c
index d950ff802b..f9ae8a6b16 100644
--- a/byterun/floats.c
+++ b/byterun/floats.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* The interface of this file is in "caml/mlvalues.h" and "caml/alloc.h" */
 
@@ -17,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "caml/alloc.h"
@@ -29,9 +34,13 @@
 
 #ifdef _MSC_VER
 #include 
+#ifndef isnan
 #define isnan _isnan
+#endif
+#ifndef isfinite
 #define isfinite _finite
 #endif
+#endif
 
 #ifdef ARCH_ALIGN_DOUBLE
 
@@ -185,6 +194,7 @@ static int caml_float_of_hex(const char * s, double * res)
                                 /* -1 if no decimal point seen */
   int exp = 0;                  /* exponent */
   char * p;                     /* for converting the exponent */
+  double f;
 
   while (*s != 0) {
     char c = *s++;
@@ -229,10 +239,11 @@ static int caml_float_of_hex(const char * s, double * res)
     }
     }
   }
+  if (n_bits == 0) return -1;
   /* Convert mantissa to FP.  We use a signed conversion because we can
-     (m has 60 bits at most) and because it is faster 
+     (m has 60 bits at most) and because it is faster
      on several architectures. */
-  double f = (double) (int64_t) m;
+  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;
@@ -255,7 +266,7 @@ CAMLprim value caml_float_of_string(value vs)
   src = String_val(vs);
   sign = 1;
   if (*src == '-') { sign = -1; src++; }
-  else if (*src == '+') { 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");
@@ -351,6 +362,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)));
@@ -452,9 +470,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;
@@ -534,74 +554,91 @@ CAMLprim value caml_copysign_float(value f, value g)
   return caml_copy_double(caml_copysign(Double_val(f), Double_val(g)));
 }
 
-CAMLprim value caml_eq_float(value f, value g)
+#ifdef LACKS_SANE_NAN
+
+CAMLprim value caml_neq_float(value vf, value vg)
 {
-  return Val_bool(Double_val(f) == Double_val(g));
+  double f = Double_val(vf);
+  double g = Double_val(vg);
+  return Val_bool(isnan(f) || isnan(g) || f != g);
 }
 
-CAMLprim value caml_neq_float(value f, value g)
-{
-  return Val_bool(Double_val(f) != Double_val(g));
+#define DEFINE_NAN_CMP(op) (value vf, value vg) \
+{ \
+  double f = Double_val(vf); \
+  double g = Double_val(vg); \
+  return Val_bool(!isnan(f) && !isnan(g) && f op g); \
 }
 
-CAMLprim value caml_le_float(value f, value g)
+intnat caml_float_compare_unboxed(double f, double g)
 {
-  return Val_bool(Double_val(f) <= Double_val(g));
+  /* Insane => nan == everything && nan < everything && nan > everything */
+  if (isnan(f) && isnan(g)) return 0;
+  if (!isnan(g) && f < g) return -1;
+  if (f != g) return 1;
+  return 0;
 }
 
-CAMLprim value caml_lt_float(value f, value g)
+#else
+
+CAMLprim value caml_neq_float(value f, value g)
 {
-  return Val_bool(Double_val(f) < Double_val(g));
+  return Val_bool(Double_val(f) != Double_val(g));
 }
 
-CAMLprim value caml_ge_float(value f, value g)
-{
-  return Val_bool(Double_val(f) >= Double_val(g));
+#define DEFINE_NAN_CMP(op) (value f, value g) \
+{ \
+  return Val_bool(Double_val(f) op Double_val(g)); \
 }
 
-CAMLprim value caml_gt_float(value f, value g)
+intnat caml_float_compare_unboxed(double f, double g)
 {
-  return Val_bool(Double_val(f) > Double_val(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);
 }
 
+#endif
+
+CAMLprim value caml_eq_float DEFINE_NAN_CMP(==)
+CAMLprim value caml_le_float DEFINE_NAN_CMP(<=)
+CAMLprim value caml_lt_float DEFINE_NAN_CMP(<)
+CAMLprim value caml_ge_float DEFINE_NAN_CMP(>=)
+CAMLprim value caml_gt_float DEFINE_NAN_CMP(>)
+
 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:
+#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);
-  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);
+    else
+      return Val_int(FP_nan);
   }
+  return Val_int(FP_normal);
 #else
   union double_as_two_int32 u;
   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;
@@ -619,6 +656,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/gc_ctrl.c b/byterun/gc_ctrl.c
index a980d6ff9b..301c99a2ed 100644
--- a/byterun/gc_ctrl.c
+++ b/byterun/gc_ctrl.c
@@ -11,6 +11,10 @@
 /*                                                                     */
 /***********************************************************************/
 
+/* TODO: incorporate timings for instrumented runtime */
+
+#define CAML_INTERNALS
+
 #include "caml/alloc.h"
 #include "caml/custom.h"
 #include "caml/finalise.h"
@@ -300,3 +304,39 @@ void caml_init_gc ()
                    caml_allocation_policy);
 */
 }
+
+/* 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 ("caml_runtime_parameters not implemented: %d", 0);
+}
+
+/* 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 unit)
+{
+  CAMLassert (unit == Val_unit);
+  return Val_bool(caml_runtime_warnings);
+}
diff --git a/byterun/globroots.c b/byterun/globroots.c
index d510eb1a9e..03c7b50065 100644
--- a/byterun/globroots.c
+++ b/byterun/globroots.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Registration of global memory roots */
 
diff --git a/byterun/hash.c b/byterun/hash.c
index b92080d2a0..918e022317 100644
--- a/byterun/hash.c
+++ b/byterun/hash.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* The generic hashing primitive */
 
diff --git a/byterun/instrtrace.c b/byterun/instrtrace.c
index 2424115f03..fa1d880f08 100644
--- a/byterun/instrtrace.c
+++ b/byterun/instrtrace.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Trace the instructions executed */
 
@@ -19,6 +23,7 @@
 #include 
 #include 
 
+#include "caml/instrtrace.h"
 #include "caml/instruct.h"
 #include "caml/misc.h"
 #include "caml/mlvalues.h"
@@ -96,27 +101,29 @@ caml_trace_value_file (value v, code_t prog, int proglen, FILE * f)
   fprintf (f, "%#lx", v);
   if (!v)
     return;
-  if (prog && (v & 1) && ((value)(Pc_val(v))) % sizeof (int) == 0
-           && Pc_val(v) >= prog
-           && Pc_val(v) < (code_t) ((char *) prog + proglen))
-    fprintf (f, "=code@%ld", Pc_val(v) - prog);
+  if (prog && v % sizeof (int) == 0
+           && (code_t) v >= prog
+           && (code_t) v < (code_t) ((char *) prog + proglen))
+    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 (caml_on_current_stack((value*)v))
-    fprintf (f, "=stack_%ld", (intnat*)Caml_state->stack_high - (intnat*)v);
+  else if ((void*)v >= (void*)caml_stack_low
+           && (void*)v < (void*)caml_stack_high)
+    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);
@@ -166,10 +173,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_state->stack_high - sp);
-  for (p = sp, i = 0; i < 12 + (1 << caml_params->trace_flag) && p < Caml_state->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_state->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 1d3c2da1df..9de16b4a6b 100644
--- a/byterun/intern.c
+++ b/byterun/intern.c
@@ -1,15 +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_INTERNALS
 
 /* Structured input, compact format */
 
@@ -19,6 +23,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"
@@ -30,55 +35,92 @@
 #include "caml/misc.h"
 #include "caml/reverse.h"
 
+/* XXX KC: Should this be made local? */
 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. */
+/* XXX KC: Should this be made local? */
+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 char * intern_resolve_code_pointer(unsigned char digest[16],
                                           asize_t offset);
-static void intern_bad_code_pointer(unsigned char digest[16]) Noreturn;
-
-#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])
+
+CAMLnoreturn_start
+static void intern_bad_code_pointer(unsigned char digest[16])
+CAMLnoreturn_end;
+
+static inline unsigned char read8u(void)
+{ return *intern_src++; }
+
+static inline signed char read8s(void)
+{ return *intern_src++; }
+
+static inline uint16_t read16u(void)
+{
+  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 intnat read64s(void)
+static uintnat read64u(void)
 {
-  intnat res;
-  int i;
-  res = 0;
-  for (i = 0; i < 8; i++) res = (res << 8) + intern_src[i];
+  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_src = src;
+  intern_input = input;
+}
 
 struct intern_stack;
 static void intern_cleanup(struct intern_stack*);
@@ -86,7 +128,7 @@ static void intern_cleanup(struct intern_stack*);
 static void readfloat(double * dest, unsigned int code)
 {
   if (sizeof(double) != 8) {
-    intern_cleanup(0); /* !! LEAK */
+    intern_cleanup(0); // Leak!!
     caml_invalid_argument("input_value: non-standard floats");
   }
   readblock((char *) dest, 8);
@@ -106,11 +148,12 @@ 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;
   if (sizeof(double) != 8) {
-    intern_cleanup(0); /* !! LEAK */
+    intern_cleanup(0); // Leak!!
     caml_invalid_argument("input_value: non-standard floats");
   }
   readblock((char *) dest, len * 8);
@@ -140,14 +183,12 @@ static void readfloats(double * dest, mlsize_t len, unsigned int code)
 #endif
 }
 
-
 enum {
   OReadItems, /* read arg items and store them in dest[0], dest[1], ... */
   OFreshOID,  /* generate a fresh OID and store it in *dest */
   OShift      /* offset *dest by arg */
 };
 
-
 #define STACK_NFIELDS 4
 #define STACK_VAL(s, i)   (s)[i][0] /* the value being read */
 #define STACK_FIELD(s, i) (s)[i][1] /* the next field to be read */
@@ -269,11 +310,6 @@ static int stack_curr_field(struct intern_stack* s) {
   return Int_val(STACK_FIELD(s->curr_vals, s->sp - 1));
 }
 
-static intnat stack_curr_arg(struct intern_stack* s) {
-  Assert(!stack_is_empty(s));
-  return Long_val(STACK_ARG(s->curr_vals, s->sp - 1));
-}
-
 static void stack_advance_field(struct intern_stack* s) {
   Assert(!stack_is_empty(s));
   int field = Int_val(STACK_FIELD(s->curr_vals, s->sp - 1));
@@ -290,16 +326,15 @@ static void stack_push_items(struct intern_stack* s, value dest, int n) {
   }
 }
 
-
 static void intern_cleanup(struct intern_stack* s)
 {
+  if (intern_input != NULL) {
+    caml_stat_free (intern_input);
+    intern_input = NULL;
+  }
   if (s) stack_free(s);
-  /* !!
-  if (intern_input_malloced) caml_stat_free(intern_input);
-  */
 }
 
-
 static value intern_rec(mlsize_t whsize, mlsize_t num_objects)
 {
   int first = 1;
@@ -415,7 +450,7 @@ static value intern_rec(mlsize_t whsize, mlsize_t num_objects)
             break;
           case CODE_INT64:
 #ifdef ARCH_SIXTYFOUR
-            v = Val_long(read64s());
+            v = Val_long((intnat) (read64u()));
             break;
 #else
             intern_cleanup(&S);
@@ -443,7 +478,7 @@ static value intern_rec(mlsize_t whsize, mlsize_t num_objects)
             goto read_block;
           case CODE_BLOCK64:
 #ifdef ARCH_SIXTYFOUR
-            header = (header_t) read64s();
+            header = (header_t) read64u();
             tag = Tag_hd(header);
             size = Wosize_hd(header);
             goto read_block;
@@ -538,47 +573,107 @@ static value intern_rec(mlsize_t whsize, mlsize_t num_objects)
   CAMLreturn(result);
 }
 
-value caml_input_val(struct channel *chan)
-{
+/* Parsing the header */
+
+struct marshal_header {
   uint32_t magic;
-  mlsize_t block_len, num_objects, whsize;
+  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 */
+
+static value caml_input_val_core(struct channel *chan)
+{
+  intnat r;
+  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 */
+  r = caml_really_getblock(chan, header, 20);
+  if (r == 0)
+    caml_raise_end_of_file();
+  else if (r < 20)
+    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) < 32 - 20)
+      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) < h.data_len) {
     caml_stat_free(block);
     caml_failwith("input_value: truncated object");
   }
-  intern_input = (unsigned char *) block;
-  intern_input_malloced = 1;
-  intern_src = intern_input;
+  /* Initialize global state */
+  intern_init(block, block);
   /* Fill it in */
-  res = intern_rec(whsize, num_objects);
+  res = intern_rec(h.whsize, h.num_objects);
   /* Free everything */
-  /* !!
-  caml_stat_free(intern_input);
-  */
-  res = caml_check_urgent_gc(res);
-  return res;
+  intern_cleanup(0); // Leak!!
+  return caml_check_urgent_gc(res);
+}
+
+value caml_input_val(struct channel* chan)
+{
+  return caml_input_val_core(chan);
 }
 
 CAMLprim value caml_input_value(value vchan)
@@ -593,75 +688,65 @@ CAMLprim value caml_input_value(value vchan)
   CAMLreturn (res);
 }
 
-static value input_val_from_block(void)
+/* Reading from memory-resident blocks */
+
+CAMLprim value caml_input_value_to_outside_heap(value vchan)
 {
-  mlsize_t num_objects, whsize;
-  value obj;
+  /* XXX KC: outside_heap is ignored */
+  return caml_input_value(vchan);
+}
 
-  num_objects = read32u();
-#ifdef ARCH_SIXTYFOUR
-  intern_src += 4;  /* skip size_32 */
-  whsize = read32u();
-#else
-  whsize = read32u();
-  intern_src += 4;  /* skip size_64 */
-#endif
+static value input_val_from_block(struct marshal_header * h)
+{
+  value obj;
   /* Fill it in */
-  obj = intern_rec(whsize, num_objects);
+  obj = intern_rec(h->whsize, h->num_objects);
   /* Free internal data structures */
+  intern_cleanup(0); //Leak!!
   return caml_check_urgent_gc(obj);
 }
 
 CAMLexport value caml_input_value_from_malloc(char * data, intnat ofs)
 {
-  uint32_t 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 */
-  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(const char * data, intnat len)
 {
-  uint32_t 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((void*)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);
 }
 
 CAMLexport value caml_input_val_from_string(value str, intnat ofs)
 {
   CAMLparam1 (str);
   CAMLlocal1 (obj);
-
-  intern_input = caml_stat_alloc(caml_string_length(str));
-  intern_input_malloced = 1;
-  memcpy(intern_input, &Byte(str, ofs), caml_string_length(str) - ofs);
-  intern_src = intern_input + 2*4;
-  obj = input_val_from_block();
-  caml_stat_free(intern_input);
-
-  CAMLreturn (obj);
+  struct marshal_header h;
+
+  /* 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");
+  intern_src = &Byte_u(str, ofs + h.header_len); /* If a GC occurred */
+  /* Fill it in */
+  obj = intern_rec(h.whsize, h.num_objects);
+  /* Free everything */
+  intern_cleanup(0); // Leak!!
+  CAMLreturn (caml_check_urgent_gc(obj));
 }
 
 CAMLprim value caml_input_value_from_string(value str, value ofs)
@@ -669,20 +754,40 @@ CAMLprim value caml_input_value_from_string(value str, value ofs)
   return caml_input_val_from_string(str, Long_val(ofs));
 }
 
+/* [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_t magic;
-  mlsize_t block_len;
+  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 */
@@ -783,7 +888,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;
 }
 
@@ -795,7 +900,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
 }
@@ -808,7 +913,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
 }
@@ -821,7 +926,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
 }
@@ -829,7 +934,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;
@@ -846,6 +951,6 @@ CAMLexport void caml_deserialize_block_float_8(void * data, intnat len)
 
 CAMLexport void caml_deserialize_error(char * msg)
 {
-  intern_cleanup(0); /* !! LEAK */
+  intern_cleanup(0); // Leak!!
   caml_failwith(msg);
 }
diff --git a/byterun/interp.c b/byterun/interp.c
index c84459804e..632c455d5b 100644
--- a/byterun/interp.c
+++ b/byterun/interp.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* The bytecode interpreter */
 #include 
@@ -32,6 +36,7 @@
 #include "caml/domain.h"
 #include "caml/globroots.h"
 #include "caml/startup.h"
+#include "caml/params.h"
 
 /* Registers for the abstract machine:
         pc         the code pointer
@@ -1331,9 +1336,13 @@ value caml_interprete(code_t prog, asize_t prog_size)
       Stack_parent(self) = performer;
 
       domain_state->extern_sp = sp;
+#ifdef DEBUG
       value old_stack = caml_switch_stack(parent);
-      sp = domain_state->extern_sp;
       Assert(old_stack == self);
+#else
+      caml_switch_stack(parent);
+#endif
+      sp = domain_state->extern_sp;
 
       domain_state->trap_sp_off = Long_val(sp[0]);
       extra_args = Long_val(sp[1]);
diff --git a/byterun/ints.c b/byterun/ints.c
index cd8e2c0236..4720893ba4 100644
--- a/byterun/ints.c
+++ b/byterun/ints.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 #include 
 #include 
@@ -23,22 +27,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 +64,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 +132,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
@@ -182,11 +195,11 @@ 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 value int32_deserialize()
@@ -283,18 +296,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_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_t i1 = Int32_val(v1);
-  int32_t 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)
@@ -307,21 +328,31 @@ 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));
 }
 
-CAMLprim value caml_int32_bits_of_float(value vd)
+int32_t caml_int32_bits_of_float_unboxed(double d)
 {
   union { float d; int32_t i; } u;
-  u.d = Double_val(vd);
-  return caml_copy_int32(u.i);
+  u.d = d;
+  return u.i;
 }
 
-CAMLprim value caml_int32_float_of_bits(value vi)
+double caml_int32_float_of_bits_unboxed(int32_t i)
 {
   union { float d; int32_t i; } u;
-  u.i = Int32_val(vi);
-  return caml_copy_double(u.d);
+  u.i = i;
+  return u.d;
+}
+
+CAMLprim value caml_int32_bits_of_float(value vd)
+{
+  return caml_copy_int32(caml_int32_bits_of_float_unboxed(Double_val(vd)));
+}
+
+CAMLprim value caml_int32_float_of_bits(value vi)
+{
+  return caml_copy_double(caml_int32_float_of_bits_unboxed(Int32_val(vi)));
 }
 
 /* 64-bit integers */
@@ -352,11 +383,11 @@ static intnat int64_hash(value v)
   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 value int64_deserialize()
@@ -420,7 +451,9 @@ CAMLprim value caml_int64_mod(value v1, value 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_t)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);
 }
 
@@ -463,14 +496,14 @@ CAMLprim value caml_int64_bswap(value v)
 {
   int64_t x = Int64_val(v);
   return caml_copy_int64
-    (((x & 0x00000000000000FFULL) << 56) |
-     ((x & 0x000000000000FF00ULL) << 40) |
-     ((x & 0x0000000000FF0000ULL) << 24) |
-     ((x & 0x00000000FF000000ULL) << 8) |
-     ((x & 0x000000FF00000000ULL) >> 8) |
-     ((x & 0x0000FF0000000000ULL) >> 24) |
-     ((x & 0x00FF000000000000ULL) >> 40) |
-     ((x & 0xFF00000000000000ULL) >> 56));
+    (((x & INT64_LITERAL(0x00000000000000FFU)) << 56) |
+     ((x & INT64_LITERAL(0x000000000000FF00U)) << 40) |
+     ((x & INT64_LITERAL(0x0000000000FF0000U)) << 24) |
+     ((x & INT64_LITERAL(0x00000000FF000000U)) << 8) |
+     ((x & INT64_LITERAL(0x000000FF00000000U)) >> 8) |
+     ((x & INT64_LITERAL(0x0000FF0000000000U)) >> 24) |
+     ((x & INT64_LITERAL(0x00FF000000000000U)) >> 40) |
+     ((x & INT64_LITERAL(0xFF00000000000000U)) >> 56));
 }
 
 CAMLprim value caml_int64_of_int(value v)
@@ -479,9 +512,15 @@ CAMLprim value caml_int64_of_int(value 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_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))); }
 
@@ -497,11 +536,14 @@ CAMLprim value caml_int64_of_nativeint(value 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_t i1 = Int64_val(v1);
-  int64_t 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)
@@ -516,12 +558,12 @@ CAMLprim value caml_int64_of_string(value s)
 {
   char * p;
   uint64_t 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 = ((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;
@@ -529,44 +571,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_t) 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_t)1 << 63) caml_failwith("int_of_string");
+      if (res >= (uint64_t)1 << 63) caml_failwith(INT64_ERRMSG);
     } else {
-      if (res >  (uint64_t)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_t i; int32_t h[2]; } u;
-  u.d = Double_val(vd);
+  u.d = d;
 #if defined(__arm__) && !defined(__ARM_EABI__)
   { 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_t i; int32_t h[2]; } u;
-  u.i = Int64_val(vi);
+  u.i = i;
 #if defined(__arm__) && !defined(__ARM_EABI__)
   { 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 */
@@ -590,8 +642,8 @@ 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
@@ -606,8 +658,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 value nativeint_deserialize()
@@ -725,9 +777,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))); }
 
@@ -737,12 +795,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)
@@ -755,5 +816,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 97cb53090c..315e22e386 100644
--- a/byterun/io.c
+++ b/byterun/io.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Buffered input/output. */
 
@@ -17,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "caml/config.h"
 #ifdef HAS_UNISTD
@@ -32,6 +37,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"
 
@@ -68,6 +74,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;
@@ -98,10 +105,11 @@ static void unlink_channel(struct channel *channel)
 
 CAMLexport void caml_close_channel(struct channel *channel)
 {
-  close(channel->fd);
+  CAML_SYS_CLOSE(channel->fd);
   if (channel->refcount > 0) return;
   caml_plat_mutex_free(&channel->mutex);
   unlink_channel(channel);
+  caml_stat_free(channel->name);
   caml_stat_free(channel);
 }
 
@@ -138,39 +146,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.
@@ -181,8 +156,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);
@@ -204,10 +181,10 @@ 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");
-  putch(channel, w >> 24);
-  putch(channel, w >> 16);
-  putch(channel, w >> 8);
-  putch(channel, w);
+  caml_putch(channel, w >> 24);
+  caml_putch(channel, w >> 16);
+  caml_putch(channel, w >> 8);
+  caml_putch(channel, w);
 }
 
 CAMLexport int caml_putblock(struct channel *channel, char *p, intnat len)
@@ -226,7 +203,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;
@@ -268,27 +246,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;
@@ -305,7 +271,7 @@ CAMLexport uint32_t caml_getword(struct channel *channel)
     caml_failwith("input_binary_int: not a binary channel");
   res = 0;
   for(i = 0; i < 4; i++) {
-    res = (res << 8) + getch(channel);
+    res = (res << 8) + caml_getch(channel);
   }
   return res;
 }
@@ -325,7 +291,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;
@@ -336,16 +302,18 @@ CAMLexport int caml_getblock(struct channel *channel, char *p, intnat len)
   }
 }
 
-CAMLexport int caml_really_getblock(struct channel *chan, char *p, intnat n)
+/* Returns the number of bytes read. */
+CAMLexport intnat caml_really_getblock(struct channel *chan, char *p, intnat n)
 {
+  intnat k = n;
   int r;
-  while (n > 0) {
-    r = caml_getblock(chan, p, n);
+  while (k > 0) {
+    r = caml_getblock(chan, p, k);
     if (r == 0) break;
     p += r;
-    n -= r;
+    k -= r;
   }
-  return (n == 0);
+  return n - k;
 }
 
 CAMLexport void caml_seek_in(struct channel *channel, file_offset dest)
@@ -395,7 +363,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
@@ -413,13 +382,44 @@ 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;
   caml_plat_mutex_free(&chan->mutex);
+  /* TODO KC: See commented out section */
+#if 0
+  if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_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 {
+#endif
   unlink_channel(chan);
+    caml_stat_free(chan->name);
   caml_stat_free(chan);
 }
 
@@ -465,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)
@@ -519,7 +530,7 @@ CAMLprim value caml_ml_close_channel(value vchannel)
 
   if (do_syscall) {
     caml_enter_blocking_section();
-    result = close(fd);
+    result = CAML_SYS_CLOSE(fd);
     caml_leave_blocking_section();
   }
 
@@ -552,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
@@ -596,7 +616,7 @@ CAMLprim value caml_ml_output_char(value vchannel, value ch)
   struct channel * channel = Channel(vchannel);
 
   With_mutex(&channel->mutex) {
-    putch(channel, Long_val(ch));
+    caml_putch(channel, Long_val(ch));
   }
   CAMLreturn (Val_unit);
 }
@@ -625,7 +645,7 @@ CAMLprim value caml_ml_output_partial(value vchannel, value buff, value start,
   CAMLreturn (Val_int(res));
 }
 
-CAMLprim value caml_ml_output(value vchannel, value buff, value start,
+CAMLprim value caml_ml_output_bytes(value vchannel, value buff, value start,
                               value length)
 {
   CAMLparam4 (vchannel, buff, start, length);
@@ -643,6 +663,12 @@ CAMLprim value caml_ml_output(value vchannel, value buff, value start,
   CAMLreturn (Val_unit);
 }
 
+CAMLprim value caml_ml_output(value vchannel, value buff, value start,
+                              value length)
+{
+  return caml_ml_output_bytes (vchannel, buff, start, length);
+}
+
 CAMLprim value caml_ml_seek_out(value vchannel, value pos)
 {
   CAMLparam2 (vchannel, pos);
@@ -684,7 +710,7 @@ CAMLprim value caml_ml_input_char(value vchannel)
   unsigned char c;
 
   With_mutex(&channel->mutex) {
-    c = getch(channel);
+    c = caml_getch(channel);
   }
   CAMLreturn (Val_long(c));
 }
@@ -714,7 +740,7 @@ CAMLprim value caml_ml_input(value vchannel, value buff, value vstart,
 
   With_mutex(&channel->mutex) {
     /* 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;
@@ -727,7 +753,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 80f8a39031..898e5f7d08 100644
--- a/byterun/lexing.c
+++ b/byterun/lexing.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* The table-driven automaton for lexers generated by camllex. */
 
diff --git a/byterun/main.c b/byterun/main.c
index b801717bcf..a1f5e9c421 100644
--- a/byterun/main.c
+++ b/byterun/main.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Main entry point (can be overridden by a user-provided main()
    function that calls caml_main() later). */
@@ -26,22 +30,6 @@ CAMLextern void caml_expand_command_line (int *, char ***);
 
 int main(int argc, char **argv)
 {
-#ifdef DEBUG
-  caml_gc_log ("### OCaml runtime: debug mode ###");
-#if 0
-  {
-    int i;
-    char *ocp;
-    char *cp;
-
-    ocp = getenv ("OCAMLRUNPARAM");
-    caml_gc_log ("### OCAMLRUNPARAM=%s", ocp == NULL ? "" : ocp);
-    cp = getenv ("CAMLRUNPARAM");
-    caml_gc_log ("### CAMLRUNPARAM=%s", cp == NULL ? "" : cp);
-    caml_gc_log ("### working dir: %s", 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 bd62c1f588..f10a4ab98b 100644
--- a/byterun/major_gc.c
+++ b/byterun/major_gc.c
@@ -1,3 +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 Lesser General Public License version 2.1, with the          */
+/*   special exception on linking described in the file LICENSE.          */
+/*                                                                        */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
 #include 
 
 #include "caml/config.h"
diff --git a/byterun/md5.c b/byterun/md5.c
index a63bd772ff..5cabc2cce0 100644
--- a/byterun/md5.c
+++ b/byterun/md5.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 #include 
 #include "caml/alloc.h"
@@ -33,18 +37,16 @@ CAMLprim value caml_md5_string(value str, value ofs, value len)
   return res;
 }
 
-CAMLprim value caml_md5_chan(value vchan, value len)
+CAMLexport value caml_md5_channel(struct channel *chan, intnat toread)
 {
-  CAMLparam2 (vchan, len);
-  struct channel * chan = Channel(vchan);
+  CAMLparam0();
   struct MD5Context ctx;
   value res;
-  intnat toread, read;
+  intnat read;
   char buffer[4096];
 
   With_mutex(&chan->mutex) {
     caml_MD5Init(&ctx);
-    toread = Long_val(len);
     if (toread < 0){
       while (1){
         read = caml_getblock (chan, buffer, sizeof(buffer));
@@ -66,6 +68,12 @@ CAMLprim value caml_md5_chan(value vchan, value len)
   CAMLreturn (res);
 }
 
+CAMLprim value caml_md5_chan(value vchan, value len)
+{
+   CAMLparam2 (vchan, len);
+   CAMLreturn (caml_md5_channel(Channel(vchan), Long_val(len)));
+}
+
 CAMLexport void caml_md5_block(unsigned char digest[16],
                                void * data, uintnat len)
 {
diff --git a/byterun/memory.c b/byterun/memory.c
index 3498f4cd56..76f67892b9 100644
--- a/byterun/memory.c
+++ b/byterun/memory.c
@@ -1,3 +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 Lesser General Public License version 2.1, with the          */
+/*   special exception on linking described in the file LICENSE.          */
+/*                                                                        */
+/**************************************************************************/
+
+#define CAML_INTERNALS
+
 #include 
 #include 
 #include 
diff --git a/byterun/meta.c b/byterun/meta.c
index 82e87940b4..bfad87c5a2 100644
--- a/byterun/meta.c
+++ b/byterun/meta.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Primitives for the toplevel */
 
@@ -45,6 +49,13 @@ 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));
+
+  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
@@ -54,6 +65,33 @@ CAMLprim value caml_reify_bytecode(value prog, value len)
   return caml_alloc_1(Closure_tag, Val_bytecode(prog));
 }
 
+/* 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);
+  }
+
+  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));
@@ -168,4 +206,20 @@ 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;
+value * caml_extern_sp;
+value * caml_trapsp;
+int caml_callback_depth;
+int volatile caml_something_to_do;
+void (* volatile caml_async_action_hook)(void);
+struct longjmp_buffer * caml_external_raise;
+
 #endif
diff --git a/byterun/minor_gc.c b/byterun/minor_gc.c
index 7dc77138aa..c3c78e74e3 100644
--- a/byterun/minor_gc.c
+++ b/byterun/minor_gc.c
@@ -11,6 +11,8 @@
 /*                                                                     */
 /***********************************************************************/
 
+#define CAML_INTERNALS
+
 #include 
 #include "caml/config.h"
 #include "caml/fail.h"
@@ -133,7 +135,8 @@ static void oldify_one (void* st_v, value v, value *p)
 
  tail_call:
   if (!Is_block(v)
-      || !(young_ptr <= Hp_val(v) && Hp_val(v) < young_end)) {
+      || !(young_ptr <= (char*)Hp_val(v)
+           && (char*)Hp_val(v) < young_end)) {
     /* not a minor block */
     *p = v;
     return;
@@ -278,15 +281,15 @@ static void oldify_mopup (struct oldify_state* st)
 
       f = Op_val (new_v)[0];
       Assert (!Is_debug_tag(f));
-      if (Is_block (f) && young_ptr <= Hp_val(v)
-          && Hp_val(v) < young_end) {
+      if (Is_block (f) && young_ptr <= (char*)Hp_val(v)
+          && (char*)Hp_val(v) < young_end) {
         oldify_one (st, f, Op_val (new_v));
       }
       for (i = 1; i < Wosize_val (new_v); i++){
         f = Op_val (v)[i];
         Assert (!Is_debug_tag(f));
-        if (Is_block (f) && young_ptr <= Hp_val(v)
-            && Hp_val(v) < young_end) {
+        if (Is_block (f) && young_ptr <= (char*)Hp_val(v)
+            && (char*)Hp_val(v) < young_end) {
           oldify_one (st, f, Op_val (new_v) + i);
         } else {
           Op_val (new_v)[i] = f;
@@ -310,7 +313,7 @@ void forward_pointer (void* state, value v, value *p) {
   char* young_ptr = domain_state->young_ptr;
   char* young_end = domain_state->young_end;
 
-  if (Is_block (v) && young_ptr <= Hp_val(v) && Hp_val(v) < young_end) {
+  if (Is_block (v) && young_ptr <= (char*)Hp_val(v) && (char*)Hp_val(v) < young_end) {
     hd = Hd_val(v);
     if (hd == 0) {
       // caml_gc_log ("forward_pointer: p=%p old=%p new=%p", p, (value*)v, (value*)Op_val(v)[0]);
@@ -551,8 +554,8 @@ void caml_empty_minor_heap_domain (struct domain* domain)
     for (r = remembered_set->major_ref.base; r < remembered_set->major_ref.ptr; r++) {
       value v = **r;
       if (Is_block (v) &&
-          (char*)young_ptr <= Hp_val(v) &&
-          Hp_val(v) < (char*)young_end) {
+          young_ptr <= (value)Hp_val(v) &&
+          (value)Hp_val(v) < young_end) {
         Assert (Hp_val (v) >= domain_state->young_ptr);
         value vnew;
         header_t hd = Hd_val(v);
diff --git a/byterun/misc.c b/byterun/misc.c
index 2e7f083248..062518e7bb 100644
--- a/byterun/misc.c
+++ b/byterun/misc.c
@@ -1,27 +1,38 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 "caml/config.h"
 #include "caml/misc.h"
 #include "caml/memory.h"
+#include "caml/osdeps.h"
+#include "caml/version.h"
 #include "caml/domain.h"
 #include "caml/startup.h"
+#include "caml/params.h"
+
+caml_timing_hook caml_major_slice_begin_hook = NULL;
+caml_timing_hook caml_major_slice_end_hook = NULL;
+caml_timing_hook caml_minor_gc_begin_hook = NULL;
+caml_timing_hook caml_minor_gc_end_hook = NULL;
+caml_timing_hook caml_finalise_begin_hook = NULL;
+caml_timing_hook caml_finalise_end_hook = NULL;
 
 #if defined(DEBUG) || defined(NATIVE_CODE)
 
@@ -49,8 +60,15 @@ int caml_failed_assert (char * expr, char * file, int line)
            Caml_state ? Caml_state->id : -1, file, line, expr);
   print_trace ();
   fflush (stderr);
-  abort();
-  return 1; /* not reached */
+  exit (100);
+}
+
+void caml_set_fields (value v, unsigned long start, unsigned long filler)
+{
+  mlsize_t i;
+  for (i = start; i < Wosize_val (v); i++){
+    Field (v, i) = (value) filler;
+  }
 }
 
 #endif /* DEBUG */
@@ -71,6 +89,18 @@ void caml_gc_log (char *msg, ...)
   va_end (args);
 }
 
+void caml_gc_message (int level, char *msg, ...)
+{
+  if ((caml_params->verb_gc & level) != 0){
+    va_list ap;
+    va_start(ap, msg);
+    vfprintf (stderr, msg, ap);
+    va_end(ap);
+    fflush (stderr);
+  }
+}
+
+
 CAMLexport void caml_fatal_error (const char *msg)
 {
   fprintf (stderr, "%s", msg);
@@ -91,7 +121,35 @@ CAMLexport void caml_fatal_error_arg2 (const char *fmt1, const 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;
+  uintnat aligned_mem;
+                                                  Assert (modulo < Page_size);
+  raw_mem = (char *) malloc (size + Page_size);
+  if (raw_mem == NULL) return NULL;
+  *block = raw_mem;
+  raw_mem += modulo;                /* Address to be aligned */
+  aligned_mem = (((uintnat) raw_mem / Page_size + 1) * Page_size);
+#ifdef DEBUG
+  {
+    uintnat *p;
+    uintnat *p0 = (void *) *block,
+            *p1 = (void *) (aligned_mem - modulo),
+            *p2 = (void *) (aligned_mem - modulo + size),
+            *p3 = (void *) ((char *) *block + size + Page_size);
 
+    for (p = p0; p < p1; p++) *p = Debug_filler_align;
+    for (p = p1; p < p2; p++) *p = Debug_uninit_align;
+    for (p = p2; p < p3; p++) *p = Debug_filler_align;
+  }
+#endif
+  return (char *) (aligned_mem - modulo);
+}
+
+/* If you change the caml_ext_table* functions, also update
+   asmrun/spacetime.c:find_trie_node_from_libunwind. */
 
 void caml_ext_table_init(struct ext_table * tbl, int init_capa)
 {
@@ -114,11 +172,31 @@ int caml_ext_table_add(struct ext_table * tbl, void * data)
   return res;
 }
 
-void caml_ext_table_free(struct ext_table * tbl, int free_entries)
+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_clear(struct ext_table * tbl, int free_entries)
 {
   int i;
-  if (free_entries)
+  if (free_entries) {
     for (i = 0; i < tbl->size; i++) caml_stat_free(tbl->contents[i]);
+  }
+  tbl->size = 0;
+}
+
+void caml_ext_table_free(struct ext_table * tbl, int free_entries)
+{
+  caml_ext_table_clear(tbl, free_entries);
   caml_stat_free(tbl->contents);
 }
 
@@ -157,3 +235,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 = caml_secure_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 8e50b702f9..9512ced30f 100644
--- a/byterun/obj.c
+++ b/byterun/obj.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Operations on objects */
 
@@ -27,6 +31,9 @@
 #include "caml/platform.h"
 
 /* all uses of this are bugs */
+#include "spacetime.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));
@@ -42,6 +49,7 @@ CAMLprim value caml_static_resize(value blk, value new_size)
   return (value) caml_stat_resize((char *) blk, (asize_t) Long_val(new_size));
 }
 
+/* unused since GPR#427 */
 CAMLprim value caml_obj_is_block(value arg)
 {
   return Val_bool(Is_block(arg));
@@ -64,11 +72,13 @@ 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)
 {
   return caml_alloc(Long_val(size), Long_val(tag));
 }
 
+/* Spacetime profiling assumes that this function is only called from OCaml. */
 CAMLprim value caml_obj_dup(value arg)
 {
   CAMLparam1 (arg);
@@ -82,6 +92,14 @@ CAMLprim value caml_obj_dup(value arg)
   if (tg >= No_scan_tag) {
     res = caml_alloc(sz, tg);
     memcpy(Bp_val(res), Bp_val(arg), sz * sizeof(value));
+  } else if (sz <= Max_young_wosize) {
+    uintnat profinfo;
+    Get_my_profinfo_with_cached_backtrace(profinfo, sz);
+    res = caml_alloc_small_with_my_or_given_profinfo(sz, tg, profinfo);
+    for (i = 0; i < sz; i++) {
+      caml_read_field(arg, i, &x);
+      caml_initialize_field(res, i, x);
+    }
   } else {
     res = caml_alloc(sz, tg);
     for (i = 0; i < sz; i++) {
@@ -172,15 +190,143 @@ CAMLprim value caml_get_public_method (value obj, value tag)
 
 static atomic_uintnat oo_next_id;
 
-CAMLprim value caml_set_oo_id (value obj) {
+CAMLprim value caml_fresh_oo_id (value v) {
   if (Caml_state->oo_next_id_local % Id_chunk == 0) {
     Caml_state->oo_next_id_local =
       atomic_fetch_add(&oo_next_id, Id_chunk);
   }
-  Op_val(obj)[1] = Val_long(Caml_state->oo_next_id_local++);
+  v = Val_long(Caml_state->oo_next_id_local++);
+  return v;
+}
+
+CAMLprim value caml_set_oo_id (value obj) {
+  value v = Val_unit;
+  Op_val(obj)[1] = caml_fresh_oo_id(v);
   return obj;
 }
 
 CAMLprim value caml_int_as_pointer (value n) {
   return n - 1;
 }
+
+/* Compute how many words in the heap are occupied by blocks accessible
+   from a given value */
+
+#define ENTRIES_PER_QUEUE_CHUNK 4096
+struct queue_chunk {
+  struct queue_chunk *next;
+  value entries[ENTRIES_PER_QUEUE_CHUNK];
+};
+
+
+CAMLprim value caml_obj_reachable_words(value v)
+{
+  return Val_int(0);
+#if 0
+  static struct queue_chunk first_chunk;
+  struct queue_chunk *read_chunk, *write_chunk;
+  int write_pos, read_pos, i;
+
+  intnat size = 0;
+  header_t hd;
+  mlsize_t sz;
+
+  if (Is_long(v) || !Is_in_heap_or_young(v)) return Val_int(0);
+  if (Tag_hd(Hd_val(v)) == Infix_tag) v -= Infix_offset_hd(Hd_val(v));
+  hd = Hd_val(v);
+  sz = Wosize_hd(hd);
+
+  read_chunk = write_chunk = &first_chunk;
+  read_pos = 0;
+  write_pos = 1;
+  write_chunk->entries[0] = v | Colornum_hd(hd);
+  Hd_val(v) = Bluehd_hd(hd);
+
+  /* We maintain a queue of "interesting" blocks that have been seen.
+     An interesting block is a block in the heap which does not
+     represent an infix pointer. Infix pointers are normalized to the
+     beginning of their block.  Blocks in the static data area are excluded.
+
+     The function maintains a queue of block pointers.  Concretely,
+     the queue is stored as a linked list of chunks, each chunk
+     holding a number of pointers to interesting blocks.  Initially,
+     it contains only the "root" value.  The first chunk of the queue
+     is allocated statically.  More chunks can be allocated as needed
+     and released before this function exits.
+
+     When a block is inserted in the queue, it is marked as blue.
+     This mark is used to avoid a second visit of the same block.
+     The real color is stored in the last 2 bits of the pointer in the
+     queue.  (Same technique as in extern.c.)
+
+     Note: we make the assumption that there is no pointer
+     from the static data area to the heap.
+  */
+
+  /* First pass: mark accessible blocks and compute their total size */
+  while (read_pos != write_pos || read_chunk != write_chunk) {
+    /* Pop the next element from the queue */
+    if (read_pos == ENTRIES_PER_QUEUE_CHUNK) {
+      read_pos = 0;
+      read_chunk = read_chunk->next;
+    }
+    v = read_chunk->entries[read_pos++] & ~3;
+
+    hd = Hd_val(v);
+    sz = Wosize_hd(hd);
+
+    size += Whsize_wosize(sz);
+
+    if (Tag_hd(hd) < No_scan_tag) {
+      /* Push the interesting fields on the queue */
+      for (i = 0; i < sz; i++) {
+        value v2 = Field(v, i);
+        if (Is_block(v2) && Is_in_heap_or_young(v2)) {
+          if (Tag_hd(Hd_val(v2)) == Infix_tag){
+            v2 -= Infix_offset_hd(Hd_val(v2));
+          }
+          hd = Hd_val(v2);
+          if (Color_hd(hd) != Caml_blue) {
+            if (write_pos == ENTRIES_PER_QUEUE_CHUNK) {
+              struct queue_chunk *new_chunk =
+                malloc(sizeof(struct queue_chunk));
+              if (new_chunk == NULL) {
+                size = (-1);
+                goto release;
+              }
+              write_chunk->next = new_chunk;
+              write_pos = 0;
+              write_chunk = new_chunk;
+            }
+            write_chunk->entries[write_pos++] = v2 | Colornum_hd(hd);
+            Hd_val(v2) = Bluehd_hd(hd);
+          }
+        }
+      }
+    }
+  }
+
+  /* Second pass: restore colors and free extra queue chunks */
+ release:
+  read_pos = 0;
+  read_chunk = &first_chunk;
+  while (read_pos != write_pos || read_chunk != write_chunk) {
+    color_t colornum;
+    if (read_pos == ENTRIES_PER_QUEUE_CHUNK) {
+      struct queue_chunk *prev = read_chunk;
+      read_pos = 0;
+      read_chunk = read_chunk->next;
+      if (prev != &first_chunk) free(prev);
+    }
+    v = read_chunk->entries[read_pos++];
+    colornum = v & 3;
+    v &= ~3;
+    Hd_val(v) = Coloredhd_hd(Hd_val(v), colornum);
+  }
+  if (read_chunk != &first_chunk) free(read_chunk);
+
+  if (size < 0)
+    caml_raise_out_of_memory();
+  return Val_int(size);
+#endif /* 0 */
+}
diff --git a/byterun/params.c b/byterun/params.c
index 3e34905a1a..0b5a0425b8 100644
--- a/byterun/params.c
+++ b/byterun/params.c
@@ -1,8 +1,11 @@
+#define CAML_INTERNALS
+
 #include 
 #include 
 #include "caml/misc.h"
 #include "caml/params.h"
 #include "caml/version.h"
+#include "caml/osdeps.h"
 #include "caml/prims.h"
 #include "caml/dynlink.h"
 #include "caml/domain.h"
@@ -70,9 +73,9 @@ void caml_init_startup_params(void)
 
   init_startup_params();
 
-  opt = getenv ("OCAMLRUNPARAM");
+  opt = caml_secure_getenv ("OCAMLRUNPARAM");
 
-  if (opt == NULL) opt = getenv ("CAMLRUNPARAM");
+  if (opt == NULL) opt = caml_secure_getenv ("CAMLRUNPARAM");
 
   if (opt != NULL){
     while (*opt != '\0'){
@@ -84,11 +87,9 @@ void caml_init_startup_params(void)
       case 'o': scanmult (opt, ¶ms.percent_free_init); break;
       case 'O': scanmult (opt, ¶ms.max_percent_free_init); break;
       case 'p': params.parser_trace = 1; break;
-      /* case 'R': see stdlib/hashtbl.mli */
+      case 'R': break; /* case 'R': see stdlib/hashtbl.mli */
       case 's': scanmult (opt, ¶ms.minor_heap_init); break;
-#ifdef DEBUG
       case 't': params.trace_flag = 1; break;
-#endif
       case 'v': scanmult (opt, ¶ms.verb_gc); break;
       case 'V': params.verify_heap = 1; break;
       case 'f': scanmult (opt, ¶ms.fiber_wsz_init); break;
diff --git a/byterun/parsing.c b/byterun/parsing.c
index 10516ed299..7e28995954 100644
--- a/byterun/parsing.c
+++ b/byterun/parsing.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* The PDA automaton for parsers generated by camlyacc */
 
diff --git a/byterun/platform.c b/byterun/platform.c
index d597ea7726..2ba47c3282 100644
--- a/byterun/platform.c
+++ b/byterun/platform.c
@@ -1,3 +1,5 @@
+#define CAML_INTERNALS
+
 #define _GNU_SOURCE /* for PTHREAD_MUTEX_ERRORCHECK_NP */
 #include 
 #include 
diff --git a/byterun/printexc.c b/byterun/printexc.c
index b075410418..a33fbe4868 100644
--- a/byterun/printexc.c
+++ b/byterun/printexc.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Print an uncaught exception and abort */
 
@@ -155,5 +159,6 @@ void caml_fatal_uncaught_exception(value exn)
   else
     default_fatal_uncaught_exception(exn);
   /* Terminate the process */
-  exit(2);
+  CAML_SYS_EXIT(2);
+  exit(2); /* Second exit needed for the Noreturn flag */
 }
diff --git a/byterun/roots.c b/byterun/roots.c
index ab5a850911..979399498b 100644
--- a/byterun/roots.c
+++ b/byterun/roots.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* To walk the memory roots for garbage collection */
 
@@ -21,7 +25,6 @@
 #include "caml/misc.h"
 #include "caml/mlvalues.h"
 #include "caml/roots.h"
-#include "caml/fiber.h"
 #include "caml/major_gc.h"
 #include "caml/shared_heap.h"
 #include "caml/fiber.h"
diff --git a/byterun/shared_heap.c b/byterun/shared_heap.c
index b7495257f1..0b0ff5fce8 100644
--- a/byterun/shared_heap.c
+++ b/byterun/shared_heap.c
@@ -1,3 +1,5 @@
+#define CAML_INTERNALS
+
 #include 
 #include 
 #include "caml/platform.h"
diff --git a/byterun/signals.c b/byterun/signals.c
index 175866de96..76c66c70c4 100644
--- a/byterun/signals.c
+++ b/byterun/signals.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Signal handling, code common to the bytecode and native systems */
 
@@ -27,6 +31,10 @@
 #include "caml/signals_machdep.h"
 #include "caml/sys.h"
 
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+#include "../asmrun/spacetime.h"
+#endif
+
 #ifndef NSIG
 #define NSIG 64
 #endif
@@ -83,6 +91,9 @@ static void caml_execute_signal(int signal_number)
 {
   CAMLparam0 ();
   CAMLlocal2 (res, handler);
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+  void* saved_spacetime_trie_node_ptr;
+#endif
 #ifdef POSIX_SIGNALS
   sigset_t sigs;
   /* Block the signal before executing the handler, and record in sigs
@@ -91,10 +102,36 @@ static void caml_execute_signal(int signal_number)
   sigaddset(&sigs, signal_number);
   sigprocmask(SIG_BLOCK, &sigs, &sigs);
 #endif
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+  /* We record the signal handler's execution separately, in the same
+     trie used for finalisers. */
+  saved_spacetime_trie_node_ptr
+    = caml_spacetime_trie_node_ptr;
+  caml_spacetime_trie_node_ptr
+    = caml_spacetime_finaliser_trie_root;
+#endif
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+  /* Handled action may have no associated handler, which we interpret
+     as meaning the signal should be handled by a call to exit.  This is
+     is used to allow spacetime profiles to be completed on interrupt */
+  if (caml_signal_handlers == 0) {
+    res = caml_sys_exit(Val_int(2));
+  } else {
+    caml_read_field(caml_read_root(caml_signal_handlers), signal_number, &handler);
+    if (!Is_block(handler)) {
+      res = caml_sys_exit(Val_int(2));
+    } else {
+#else
   caml_read_field(caml_read_root(caml_signal_handlers), signal_number, &handler);
+#endif
   res = caml_callback_exn(
            handler,
            Val_int(caml_rev_convert_signal_number(signal_number)));
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+    }
+  }
+  caml_spacetime_trie_node_ptr = saved_spacetime_trie_node_ptr;
+#endif
 #ifdef POSIX_SIGNALS
   /* Restore the original signal mask */
   sigprocmask(SIG_SETMASK, &sigs, NULL);
@@ -103,6 +140,36 @@ static void caml_execute_signal(int signal_number)
   CAMLreturn0;
 }
 
+/* Arrange for a garbage collection to be performed as soon as possible */
+
+int volatile caml_requested_major_slice = 0;
+int volatile caml_requested_minor_gc = 0;
+
+void caml_request_major_slice (void)
+{
+  caml_requested_major_slice = 1;
+#ifndef NATIVE_CODE
+  caml_something_to_do = 1;
+#else
+  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
+     from [caml_young_limit]. */
+#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
@@ -168,11 +235,33 @@ static void caml_execute_signal(int signal_number)
 #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 7da3a9bcd7..5fdc7e230c 100644
--- a/byterun/signals_byt.c
+++ b/byterun/signals_byt.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Signal handling, code specific to the bytecode interpreter */
 
@@ -31,6 +35,22 @@ extern sighandler caml_win32_signal(int sig, sighandler action);
 #define signal(sig,act) caml_win32_signal(sig,act)
 #endif
 
+CAMLexport int volatile caml_something_to_do = 0;
+CAMLexport void (* volatile caml_async_action_hook)(void) = NULL;
+
+void caml_process_event(void)
+{
+  void (*async_action)(void);
+
+  caml_check_urgent_gc (Val_unit);
+  caml_process_pending_signals();
+  async_action = caml_async_action_hook;
+  if (async_action != NULL) {
+    caml_async_action_hook = NULL;
+    (*async_action)();
+  }
+}
+
 static void handle_signal(int signal_number)
 {
   int saved_errno;
diff --git a/byterun/spacetime.c b/byterun/spacetime.c
new file mode 100644
index 0000000000..fd8b4fd247
--- /dev/null
+++ b/byterun/spacetime.c
@@ -0,0 +1,40 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*            Mark Shinwell and Leo White, Jane Street Europe             */
+/*                                                                        */
+/*   Copyright 2013--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 
+#include "caml/fail.h"
+#include "caml/mlvalues.h"
+
+int ensure_spacetime_dot_o_is_included = 42;
+
+CAMLprim value caml_spacetime_only_works_for_native_code(value foo, ...)
+{
+  caml_failwith("Spacetime profiling only works for native code");
+  assert(0);  /* unreachable */
+}
+
+uintnat caml_spacetime_my_profinfo (void)
+{
+  return 0;
+}
+
+CAMLprim value caml_spacetime_enabled (value v_unit)
+{
+  return Val_false;  /* running in bytecode */
+}
+
+CAMLprim value caml_register_channel_for_spacetime (value v_channel)
+{
+  return Val_unit;
+}
diff --git a/byterun/spacetime.h b/byterun/spacetime.h
new file mode 100644
index 0000000000..ffb006bf18
--- /dev/null
+++ b/byterun/spacetime.h
@@ -0,0 +1,21 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*            Mark Shinwell and Leo White, Jane Street Europe             */
+/*                                                                        */
+/*   Copyright 2016, Jane Street Group, LLC                               */
+/*                                                                        */
+/*   All rights reserved.  This file is distributed under the terms of    */
+/*   the GNU Lesser General Public License version 2.1, with the          */
+/*   special exception on linking described in the file LICENSE.          */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef CAML_SPACETIME_H
+#define CAML_SPACETIME_H
+
+#define Get_my_profinfo_with_cached_backtrace(profinfo, size) \
+  profinfo = (uintnat) 0;
+
+#endif
diff --git a/byterun/startup.c b/byterun/startup.c
index 0c51bff423..27cd5b3928 100644
--- a/byterun/startup.c
+++ b/byterun/startup.c
@@ -1,15 +1,19 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Start-up code */
 
@@ -138,7 +142,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_t 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;
@@ -213,13 +218,15 @@ extern void caml_init_ieee_floats (void);
 extern void caml_signal_thread(void * lpParam);
 #endif
 
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
 
 /* PR 4887: avoid crash box of windows runtime on some system calls */
 extern void caml_install_invalid_parameter_handler();
 
 #endif
 
+extern int ensure_spacetime_dot_o_is_included;
+
 /* Main entry point when loading code from a file */
 
 CAMLexport void caml_main(char **argv)
@@ -235,10 +242,12 @@ CAMLexport void caml_main(char **argv)
   CAML_INIT_DOMAIN_STATE;
 
   caml_init_startup_params();
+  ensure_spacetime_dot_o_is_included++;
+
   /* Machine-dependent initialization of the floating-point hardware
      so that it behaves as much as possible as specified in IEEE */
   caml_init_ieee_floats();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
   caml_install_invalid_parameter_handler();
 #endif
   caml_init_custom_operations();
@@ -290,6 +299,9 @@ 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);
+  /* XXX KC: Fix me.
+  caml_init_debug_info();
+  */
   /* Build the table of primitives */
   shared_lib_path = read_section(fd, &trail, "DLPT");
   shared_libs = read_section(fd, &trail, "DLLS");
@@ -308,7 +320,7 @@ CAMLexport void caml_main(char **argv)
   caml_stat_free(trail.section);
 #ifdef _WIN32
   /* Start a thread to handle signals */
-  if (getenv("CAMLSIGPIPE"))
+  if (caml_secure_getenv("CAMLSIGPIPE"))
     _beginthread(caml_signal_thread, 4096, NULL);
 #endif
   /* Execute the program */
@@ -342,7 +354,7 @@ CAMLexport void caml_startup_code(
 
   caml_init_startup_params();
   caml_init_ieee_floats();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
   caml_install_invalid_parameter_handler();
 #endif
   caml_init_custom_operations();
@@ -362,6 +374,9 @@ CAMLexport void caml_startup_code(
   caml_start_code = code;
   caml_code_size = code_size;
   caml_init_code_fragments();
+  /* XXX: Fix me.
+  caml_init_debug_info();
+  */
   if (caml_debugger_in_use) {
     int len, i;
     len = code_size / sizeof(opcode_t);
diff --git a/byterun/str.c b/byterun/str.c
index 6994ce59b7..3c2a76304a 100644
--- a/byterun/str.c
+++ b/byterun/str.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Operations on strings */
 
@@ -22,6 +26,7 @@
 #include "caml/mlvalues.h"
 #include "caml/misc.h"
 
+/* returns a number of bytes (chars) */
 CAMLexport mlsize_t caml_string_length(value s)
 {
   mlsize_t temp;
@@ -30,6 +35,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;
@@ -38,6 +44,20 @@ CAMLprim value caml_ml_string_length(value s)
   return Val_long(temp - Byte (s, temp));
 }
 
+CAMLprim value caml_ml_bytes_length(value s)
+{
+  return caml_ml_string_length(s);
+}
+
+CAMLexport int caml_string_is_c_safe (value s)
+{
+  return strlen(String_val(s)) == caml_string_length(s);
+}
+
+/**
+ * [caml_create_string] is deprecated,
+ * use [caml_create_bytes] instead
+ */
 CAMLprim value caml_create_string(value len)
 {
   mlsize_t size = Long_val(len);
@@ -47,6 +67,18 @@ CAMLprim value caml_create_string(value len)
   return caml_alloc_string(size);
 }
 
+/* [len] is a value that represents a number of bytes (chars) */
+CAMLprim value caml_create_bytes(value len)
+{
+  mlsize_t size = Long_val(len);
+  if (size > Bsize_wsize (Max_wosize) - 1){
+    caml_invalid_argument("Bytes.create");
+  }
+  return caml_alloc_string(size);
+}
+
+
+
 CAMLprim value caml_string_get(value str, value index)
 {
   intnat idx = Long_val(index);
@@ -54,7 +86,12 @@ CAMLprim value caml_string_get(value str, value index)
   return Val_int(Byte_u(str, idx));
 }
 
-CAMLprim value caml_string_set(value str, value index, value newval)
+CAMLprim value caml_bytes_get(value str, value index)
+{
+  return caml_string_get(str, index);
+}
+
+CAMLprim value caml_bytes_set(value str, value index, value newval)
 {
   intnat idx = Long_val(index);
   if (idx < 0 || idx >= caml_string_length(str)) caml_array_bound_error();
@@ -62,6 +99,16 @@ CAMLprim value caml_string_set(value str, value index, value newval)
   return Val_unit;
 }
 
+/**
+ * [caml_string_set] is deprecated,
+ * use [caml_bytes_set] instead
+ */
+CAMLprim value caml_string_set(value str, value index, value newval)
+{
+  return caml_bytes_set(str,index,newval);
+}
+
+
 CAMLprim value caml_string_get16(value str, value index)
 {
   intnat res;
@@ -219,11 +266,21 @@ CAMLprim value caml_string_equal(value s1, value s2)
   return Val_true;
 }
 
+CAMLprim value caml_bytes_equal(value s1, value s2)
+{
+  return caml_string_equal(s1,s2);
+}
+
 CAMLprim value caml_string_notequal(value s1, value s2)
 {
   return Val_not(caml_string_equal(s1, s2));
 }
 
+CAMLprim value caml_bytes_notequal(value s1, value s2)
+{
+  return caml_string_notequal(s1,s2);
+}
+
 CAMLprim value caml_string_compare(value s1, value s2)
 {
   mlsize_t len1, len2;
@@ -240,42 +297,83 @@ CAMLprim value caml_string_compare(value s1, value s2)
   return Val_int(0);
 }
 
+CAMLprim value caml_bytes_compare(value s1, value s2)
+{
+  return caml_string_compare(s1,s2);
+}
+
 CAMLprim value caml_string_lessthan(value s1, value s2)
 {
   return caml_string_compare(s1, s2) < Val_int(0) ? Val_true : Val_false;
 }
 
+CAMLprim value caml_bytes_lessthan(value s1, value s2)
+{
+  return caml_string_lessthan(s1,s2);
+}
+
+
 CAMLprim value caml_string_lessequal(value s1, value s2)
 {
   return caml_string_compare(s1, s2) <= Val_int(0) ? Val_true : Val_false;
 }
 
+CAMLprim value caml_bytes_lessequal(value s1, value s2)
+{
+  return caml_string_lessequal(s1,s2);
+}
+
+
 CAMLprim value caml_string_greaterthan(value s1, value s2)
 {
   return caml_string_compare(s1, s2) > Val_int(0) ? Val_true : Val_false;
 }
 
+CAMLprim value caml_bytes_greaterthan(value s1, value s2)
+{
+  return caml_string_greaterthan(s1,s2);
+}
+
 CAMLprim value caml_string_greaterequal(value s1, value s2)
 {
   return caml_string_compare(s1, s2) >= Val_int(0) ? Val_true : Val_false;
 }
 
-CAMLprim value caml_blit_string(value s1, value ofs1, value s2, value ofs2,
+CAMLprim value caml_bytes_greaterequal(value s1, value s2)
+{
+  return caml_string_greaterequal(s1,s2);
+}
+
+CAMLprim value caml_blit_bytes(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;
 }
 
-CAMLprim value caml_fill_string(value s, value offset, value len, value init)
+CAMLprim value caml_blit_string(value s1, value ofs1, value s2, value ofs2,
+                                value n)
+{
+  return caml_blit_bytes (s1, ofs1, s2, ofs2, n);
+}
+
+CAMLprim value caml_fill_bytes(value s, value offset, value len, value init)
 {
   memset(&Byte(s, Long_val(offset)), Int_val(init), Long_val(len));
   return Val_unit;
 }
 
+/**
+ * [caml_fill_string] is deprecated, use [caml_fill_bytes] instead
+ */
+CAMLprim value caml_fill_string(value s, value offset, value len, value init)
+{
+  return caml_fill_bytes (s, offset, len, init);
+}
+
 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)));
 }
 
@@ -286,7 +384,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 ab96380edb..a530043269 100644
--- a/byterun/sys.c
+++ b/byterun/sys.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Basic system calls */
 
@@ -22,7 +26,9 @@
 #include 
 #include 
 #include 
-#if !_WIN32
+#ifdef _WIN32
+#include  /* for isatty */
+#else
 #include 
 #endif
 #include "caml/config.h"
@@ -43,12 +49,14 @@
 #include "caml/debugger.h"
 #include "caml/fail.h"
 #include "caml/instruct.h"
+#include "caml/io.h"
 #include "caml/mlvalues.h"
 #include "caml/osdeps.h"
 #include "caml/signals.h"
 #include "caml/fiber.h"
 #include "caml/sys.h"
 #include "caml/startup.h"
+#include "caml/version.h"
 
 static char * error_message(void)
 {
@@ -92,12 +100,45 @@ CAMLexport void caml_sys_io_error(value arg)
   }
 }
 
-CAMLprim value caml_sys_exit(value retcode)
+/* 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_v)
+{
+  caml_domain_state* domain_state = Caml_state;
+  int retcode = Int_val(retcode_v);
+
+
+  /* XXX KC: Only prints stats for this domain */
+  if ((caml_params->verb_gc & 0x400) != 0) {
+    /* cf caml_gc_counters */
+    double minwords = domain_state->stat_minor_words
+      + (double) (domain_state->young_end - domain_state->young_ptr);
+    double prowords = domain_state->stat_promoted_words;
+    double majwords = domain_state->stat_major_words + (double) domain_state->allocated_words;
+    double allocated_words = minwords + majwords - prowords;
+    intnat mincoll = domain_state->stat_minor_collections;
+    intnat majcoll = domain_state->stat_major_collections;
+    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: %ld\n", mincoll);
+    caml_gc_message(0x400, "major_collections: %ld\n", majcoll);
+  }
+
 #ifndef NATIVE_CODE
   caml_debugger(PROGRAM_EXIT);
 #endif
-  exit(Int_val(retcode));
+  CAML_INSTR_ATEXIT ();
+  CAML_SYS_EXIT(retcode);
   return Val_unit;
 }
 
@@ -126,12 +167,13 @@ 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);
   /* open on a named FIFO can block (PR#1533) */
   caml_enter_blocking_section();
-  fd = open(p, flags, perm);
+  fd = CAML_SYS_OPEN(p, flags, perm);
   /* fcntl on a fd can block (PR#5069)*/
 #if defined(F_SETFD) && defined(FD_CLOEXEC)
   if (fd != -1)
@@ -143,10 +185,11 @@ CAMLprim value caml_sys_open(value path, value vflags, value vperm)
   CAMLreturn(Val_long(fd));
 }
 
-CAMLprim value caml_sys_close(value fd)
+CAMLprim value caml_sys_close(value fd_v)
 {
+  int fd = Int_val(fd_v);
   caml_enter_blocking_section();
-  close(Int_val(fd));
+  CAML_SYS_CLOSE(fd);
   caml_leave_blocking_section();
   return Val_unit;
 }
@@ -161,12 +204,13 @@ 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
   ret = _stati64(p, &st);
 #else
-  ret = stat(p, &st);
+  ret = CAML_SYS_STAT(p, &st);
 #endif
   caml_leave_blocking_section();
   caml_stat_free(p);
@@ -185,12 +229,13 @@ 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
   ret = _stati64(p, &st);
 #else
-  ret = stat(p, &st);
+  ret = CAML_SYS_STAT(p, &st);
 #endif
   caml_leave_blocking_section();
   caml_stat_free(p);
@@ -208,9 +253,10 @@ 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);
+  ret = CAML_SYS_UNLINK(p);
   caml_leave_blocking_section();
   caml_stat_free(p);
   if (ret != 0) caml_sys_error(name);
@@ -222,10 +268,12 @@ 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();
-  ret = rename(p_old, p_new);
+  ret = CAML_SYS_RENAME(p_old, p_new);
   caml_leave_blocking_section();
   caml_stat_free(p_new);
   caml_stat_free(p_old);
@@ -239,9 +287,10 @@ 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);
+  ret = CAML_SYS_CHDIR(p);
   caml_leave_blocking_section();
   caml_stat_free(p);
   if (ret != 0) caml_sys_error(dirname);
@@ -259,11 +308,22 @@ CAMLprim value caml_sys_getcwd(value unit)
   return caml_copy_string(buff);
 }
 
+CAMLprim value caml_sys_unsafe_getenv(value var)
+{
+  char * res;
+
+  if (! caml_string_is_c_safe(var)) caml_raise_not_found();
+  res = CAML_SYS_GETENV(String_val(var));
+  if (res == 0) caml_raise_not_found();
+  return caml_copy_string(res);
+}
+
 CAMLprim value caml_sys_getenv(value var)
 {
   char * res;
 
-  res = getenv(String_val(var));
+  if (! caml_string_is_c_safe(var)) caml_raise_not_found();
+  res = caml_secure_getenv(String_val(var));
   if (res == 0) caml_raise_not_found();
   return caml_copy_string(res);
 }
@@ -280,6 +340,18 @@ CAMLprim value caml_sys_get_argv(value unit)
   CAMLreturn(res);
 }
 
+void caml_sys_init(char * exe_name, char **argv)
+{
+  caml_failwith ("caml_sys_init: not implemented");
+#if 0
+#ifdef CAML_WITH_CPLUGINS
+  caml_cplugins_init(exe_name, argv);
+#endif
+  caml_exe_name = exe_name;
+  caml_main_argv = argv;
+#endif
+}
+
 #ifdef _WIN32
 #define WIFEXITED(status) 1
 #define WEXITSTATUS(status) (status)
@@ -297,9 +369,13 @@ 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);
+  status = CAML_SYS_SYSTEM(buf);
   caml_leave_blocking_section ();
   caml_stat_free(buf);
   if (status == -1) caml_sys_error(command);
@@ -310,14 +386,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
@@ -329,14 +405,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
@@ -393,26 +474,43 @@ 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_const_backend_type(value unit)
+{
+  return Val_int(1); /* Bytecode backed */
+}
 CAMLprim value caml_sys_get_config(value unit)
 {
   CAMLparam0 ();   /* unit is unused */
@@ -438,10 +536,11 @@ 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();
-  ret = caml_read_directory(p, &tbl);
+  ret = CAML_SYS_READ_DIRECTORY(p, &tbl);
   caml_leave_blocking_section();
   caml_stat_free(p);
   if (ret == -1){
@@ -453,3 +552,91 @@ 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;
+}
+
+/* Load dynamic plugins indicated in the CAML_CPLUGINS environment
+   variable. These plugins can be used to set currently existing
+   hooks, such as GC hooks and system calls tracing (see misc.h).
+ */
+
+#ifdef CAML_WITH_CPLUGINS
+
+value (*caml_cplugins_prim)(int,value,value,value) = NULL;
+
+#define DLL_EXECUTABLE 1
+#define DLL_NOT_GLOBAL 0
+
+static struct cplugin_context cplugin_context;
+
+void caml_load_plugin(char *plugin)
+{
+  void* dll_handle = NULL;
+
+  dll_handle = caml_dlopen(plugin, DLL_EXECUTABLE, DLL_NOT_GLOBAL);
+  if( dll_handle != NULL ){
+   void (* dll_init)(struct cplugin_context*) =
+     caml_dlsym(dll_handle, "caml_cplugin_init");
+   if( dll_init != NULL ){
+     cplugin_context.plugin=plugin;
+     dll_init(&cplugin_context);
+   } else {
+     caml_dlclose(dll_handle);
+   }
+  } else {
+   fprintf(stderr, "Cannot load C plugin %s\nReason: %s\n",
+          plugin, caml_dlerror());
+  }
+}
+
+void caml_cplugins_load(char *env_variable)
+{
+  char *plugins = caml_secure_getenv(env_variable);
+  if(plugins != NULL){
+    char* curs = plugins;
+    while(*curs != 0){
+        if(*curs == ','){
+          if(curs > plugins){
+            *curs = 0;
+            caml_load_plugin(plugins);
+          }
+          plugins = curs+1;
+        }
+        curs++;
+    }
+    if(curs > plugins) caml_load_plugin(plugins);
+  }
+}
+
+void caml_cplugins_init(char * exe_name, char **argv)
+{
+  cplugin_context.api_version = CAML_CPLUGIN_CONTEXT_API;
+  cplugin_context.prims_bitmap = CAML_CPLUGINS_PRIMS_BITMAP;
+  cplugin_context.exe_name = exe_name;
+  cplugin_context.argv = argv;
+  cplugin_context.ocaml_version = OCAML_VERSION_STRING;
+  caml_cplugins_load("CAML_CPLUGINS");
+#ifdef NATIVE_CODE
+  caml_cplugins_load("CAML_NATIVE_CPLUGINS");
+#else
+  caml_cplugins_load("CAML_BYTE_CPLUGINS");
+#endif
+}
+
+#endif /* CAML_WITH_CPLUGINS */
diff --git a/byterun/terminfo.c b/byterun/terminfo.c
index 6f010d49cc..63fd020f4a 100644
--- a/byterun/terminfo.c
+++ b/byterun/terminfo.c
@@ -1,15 +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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Read and output terminal commands */
 
@@ -76,7 +80,7 @@ CAMLprim value caml_terminfo_setup (value vchan)
 
 static int terminfo_putc (int c)
 {
-  putch (chan, c);
+  caml_putch (chan, c);
   return c;
 }
 
diff --git a/byterun/unix.c b/byterun/unix.c
index fa3193cc24..8efa50839f 100644
--- a/byterun/unix.c
+++ b/byterun/unix.c
@@ -1,20 +1,25 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Unix-specific stuff */
 
 #define _GNU_SOURCE
            /* Helps finding RTLD_DEFAULT in glibc */
+           /* also secure_getenv */
 
 #include 
 #include 
@@ -24,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "caml/config.h"
 #ifdef SUPPORT_DYNAMIC_LINKING
 #ifdef __CYGWIN__
@@ -40,14 +46,71 @@
 #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"
+#include "caml/io.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:
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+  if (flags & CHANNEL_FLAG_BLOCKING_WRITE) {
+    retcode = write(fd, buf, n);
+  } else {
+#endif
+  caml_enter_blocking_section();
+  retcode = write(fd, buf, n);
+  caml_leave_blocking_section();
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+  }
+#endif
+  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, const char * path)
 {
   char * p, * q;
@@ -274,7 +337,7 @@ char * caml_dlerror(void)
    the directory named [dirname].  No entries are added for [.] and [..].
    Return 0 on success, -1 on error; set errno in the case of error. */
 
-int caml_read_directory(char * dirname, struct ext_table * contents)
+CAMLexport int caml_read_directory(char * dirname, struct ext_table * contents)
 {
   DIR * d;
 #ifdef HAS_DIRENT
@@ -341,3 +404,20 @@ int64_t caml_time_counter(void)
 # error "No timesource available"
 #endif
 }
+
+char *caml_secure_getenv (char const *var)
+{
+#ifdef HAS_SECURE_GETENV
+  return secure_getenv (var);
+#elif defined(HAS_ISSETUGID)
+  if (!issetugid ())
+    return CAML_SYS_GETENV (var);
+  else
+    return NULL;
+#else
+  if (geteuid () == getuid () && getegid () == getgid ())
+    return CAML_SYS_GETENV (var);
+  else
+    return NULL;
+#endif
+}
diff --git a/byterun/weak.c b/byterun/weak.c
index ec1ec05290..4b1184171a 100644
--- a/byterun/weak.c
+++ b/byterun/weak.c
@@ -1,17 +1,21 @@
-/***********************************************************************/
+/**************************************************************************/
 /*                                                                     */
 /*                                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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
+#define CAML_INTERNALS
+
+/* Operations on weak arrays and ephemerons (named ephe here)*/
 
 #include 
 
@@ -20,54 +24,216 @@
 #include "caml/major_gc.h"
 #include "caml/memory.h"
 #include "caml/mlvalues.h"
-
-
-/* Stub implementation of "weak" pointers */
-
-value caml_array_blit(value, value, value, value, value); /* array.c */
+#include "caml/weak.h"
 
 #define None_val (Val_int(0))
+#define Some_tag 0
 
-CAMLprim value caml_weak_create (value len)
+/* [len] is a value that represents a number of words (fields) */
+CAMLprim value caml_ephe_create (value len)
 {
-  value res = caml_alloc(len, 0);
-  int i;
-  for (i = 0; i < len; i++) 
+  mlsize_t size, i;
+  value res;
+
+  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, 0);
+  for (i = 1; i < size; i++)
     caml_initialize_field(res, i, None_val);
   return res;
 }
 
-CAMLprim value caml_weak_set (value ar, value n, value el)
+CAMLprim value caml_weak_create (value len)
+{
+  return caml_ephe_create(len);
+}
+
+CAMLprim value caml_ephe_set_key (value ar, value n, value el)
+{
+  CAMLparam3(ar,n,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");
+  }
+  caml_modify_field (ar, offset, el);
+  CAMLreturn(Val_unit);
+}
+
+CAMLprim value caml_ephe_unset_key (value ar, value n)
 {
-  CAMLparam3(ar, n, el);
-  int idx = Int_val(n);
-  if (idx < 0 || idx >= Wosize_val(ar)) caml_array_bound_error();
-  caml_modify_field(ar, idx, el);
-  CAMLreturn (Val_unit);
+  CAMLparam2(ar,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");
+  }
+  caml_modify_field (ar, offset, None_val);
+  CAMLreturn(Val_unit);
 }
 
-CAMLprim value caml_weak_get (value ar, value n)
+value caml_ephe_set_key_option (value ar, value n, value el)
+{
+  CAMLparam3(ar,n,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");
+  }
+  if (el != None_val && Is_block (el)){
+                                              Assert (Wosize_val (el) == 1);
+    caml_modify_field (ar, offset, Field (el, 0));
+  }else{
+    caml_modify_field (ar, offset, None_val);
+  }
+  CAMLreturn(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)
+{
+  CAMLparam2(ar,el);
+                                                   Assert (Is_in_heap (ar));
+  caml_modify_field (ar, 1, el);
+  CAMLreturn(Val_unit);
+}
+
+CAMLprim value caml_ephe_unset_data (value ar)
+{
+  CAMLparam1(ar);
+                                                   Assert (Is_in_heap (ar));
+  caml_modify_field (ar, CAML_EPHE_DATA_OFFSET, None_val);
+  CAMLreturn(Val_unit);
+}
+
+CAMLprim value caml_ephe_get_key (value ar, value n)
 {
   CAMLparam2(ar, n);
-  CAMLlocal1(x);
-  int idx = Int_val(n);
-  if (idx < 0 || idx >= Wosize_val(ar)) caml_array_bound_error();
-  caml_read_field(ar, idx, &x);
-  CAMLreturn (x);
+  mlsize_t offset = Long_val (n) + 2;
+  CAMLlocal2 (res, elt);
+                                                   Assert (Is_in_heap (ar));
+  if (offset < 2 || offset >= Wosize_val (ar)){
+    caml_invalid_argument ("Weak.get_key");
+  }
+  caml_read_field(ar, offset, &elt);
+  if (elt == None_val){
+    res = None_val;
+  }else{
+    res = caml_alloc_small (1, Some_tag);
+    caml_initialize_field(res, 0, elt);
+  }
+  CAMLreturn (res);
 }
 
-CAMLprim value caml_weak_get_copy (value ar, value n)
+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));
+  caml_read_field (ar, offset, &elt);
+  if (elt == None_val){
+    res = None_val;
+  }else{
+    res = caml_alloc_small (1, Some_tag);
+    caml_initialize_field(res, 0, elt);
+  }
+  CAMLreturn (res);
+}
+
+CAMLprim value caml_ephe_get_key_copy (value ar, value n)
+{
+  caml_failwith("caml_ephe_get_key_copy: not implemented");
+}
+
+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)
+{
+  caml_failwith("caml_ephe_get_data_copy: not implemented");
+}
+
+CAMLprim value caml_ephe_check_key (value ar, value n)
 {
-  caml_failwith("weak_get_copy unsupported");
+  CAMLparam2(ar,n);
+  CAMLlocal1(v);
+  mlsize_t offset = Long_val (n) + 2;
+                                                   Assert (Is_in_heap (ar));
+  if (offset < 2 || offset >= Wosize_val (ar)){
+    caml_invalid_argument ("Weak.check");
+  }
+  caml_read_field (ar, offset, &v);
+  CAMLreturn(Val_bool (v != None_val));
 }
 
 CAMLprim value caml_weak_check (value ar, value n)
 {
-  caml_failwith("weak_check unsupported");
+  return caml_ephe_check_key(ar,n);
 }
 
-CAMLprim value caml_weak_blit (value ars, value ofs,
+CAMLprim value caml_ephe_check_data (value ar)
+{
+  CAMLparam1(ar);
+  CAMLlocal1(v);
+
+  caml_read_field(ar, CAML_EPHE_DATA_OFFSET, &v);
+  CAMLreturn(Val_bool (v != None_val));
+}
+
+CAMLprim value caml_ephe_blit_key (value ars, value ofs,
                                value ard, value ofd, value len)
 {
-  return caml_array_blit(ars, ofs, ard, ofd, len);
+  CAMLparam2(ars, ard);
+  CAMLlocal1(v);
+  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));
+                                                   Assert (Is_in_heap (ard));
+  if (offset_s < 1 || offset_s + length > Wosize_val (ars)){
+    caml_invalid_argument ("Weak.blit");
+  }
+  if (offset_d < 1 || offset_d + length > Wosize_val (ard)){
+    caml_invalid_argument ("Weak.blit");
+  }
+  if (offset_d < offset_s){
+    for (i = 0; i < length; i++){
+      caml_read_field(ars, offset_s + i, &v);
+      caml_modify_field (ard, offset_d + i, v);
+    }
+  }else{
+    for (i = length - 1; i >= 0; i--){
+      caml_read_field(ars, offset_s + i, &v);
+      caml_modify_field (ard, offset_d + i, v);
+    }
+  }
+  CAMLreturn(Val_unit);
+}
+
+CAMLprim value caml_ephe_blit_data (value ars, value ard)
+{
+#if 0
+  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));
+#endif
+  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 ceb92137e0..1f5f343ad2 100644
--- a/byterun/win32.c
+++ b/byterun/win32.c
@@ -1,19 +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 Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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_INTERNALS
 
 /* Win32-specific stuff */
 
-#include 
+#define WIN32_LEAN_AND_MEAN
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -25,21 +32,102 @@
 #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
 
-char * caml_decompose_path(struct ext_table * tbl, const char * path)
+/* Very old Microsoft headers don't include intptr_t */
+#if defined(_MSC_VER) && !defined(_UINTPTR_T_DEFINED)
+typedef unsigned int uintptr_t;
+#define _UINTPTR_T_DEFINED
+#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) {
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+  if (flags & CHANNEL_FLAG_BLOCKING_WRITE) {
+    retcode = write(fd, buf, n);
+  } else {
+#endif
+    caml_enter_blocking_section();
+    retcode = write(fd, buf, n);
+    caml_leave_blocking_section();
+#if defined(NATIVE_CODE) && defined(WITH_SPACETIME)
+  }
+#endif
+    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;
   int n;
@@ -123,6 +211,8 @@ char * caml_search_dll_in_path(struct ext_table * path, const char * name)
   return res;
 }
 
+#ifdef SUPPORT_DYNAMIC_LINKING
+
 void * caml_dlopen(char * libname, int for_execution, int global)
 {
   void *handle;
@@ -156,6 +246,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);
@@ -320,7 +438,8 @@ 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(caml_secure_getenv("CAMLSIGPIPE"), &endptr, 16);
   while (1) {
     DWORD numread;
     BOOL ret;
@@ -478,7 +597,7 @@ int caml_win32_random_seed (intnat data[16])
 }
 
 
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
 
 static void invalid_parameter_handler(const wchar_t* expression,
    const wchar_t* function,
@@ -511,6 +630,27 @@ int caml_executable_name(char * name, int name_len)
 
 /* snprintf emulation */
 
+#ifdef LACKS_VSCPRINTF
+/* No _vscprintf until Visual Studio .NET 2002 and sadly no version number
+   in the CRT headers until Visual Studio 2005 so forced to predicate this
+   on the compiler version instead */
+int _vscprintf(const char * format, va_list args)
+{
+  int n;
+  int sz = 5;
+  char* buf = (char*)malloc(sz);
+  n = _vsnprintf(buf, sz, format, args);
+  while (n < 0 || n > sz) {
+    sz += 512;
+    buf = (char*)realloc(buf, sz);
+    n = _vsnprintf(buf, sz, format, args);
+  }
+  free(buf);
+  return n;
+}
+#endif
+
+#if defined(_WIN32) && !defined(_UCRT)
 int caml_snprintf(char * buf, size_t size, const char * format, ...)
 {
   int len;
@@ -535,3 +675,10 @@ int caml_snprintf(char * buf, size_t size, const char * format, ...)
   va_end(args);
   return len;
 }
+#endif
+
+char *caml_secure_getenv (char const *var)
+{
+  /* Win32 doesn't have a notion of setuid bit, so getenv is safe. */
+  return CAML_SYS_GETENV (var);
+}
diff --git a/compilerlibs/.gitignore b/compilerlibs/.gitignore
index 72e8ffc0db..c1eda49d00 100644
--- a/compilerlibs/.gitignore
+++ b/compilerlibs/.gitignore
@@ -1 +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 259ce3f6e3..0000000000
--- 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 b9142c6608..1cd797eb26 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
 
@@ -31,9 +33,9 @@ MANEXT=1
 ### Do #! scripts work on your system?
 ### Beware: on some systems (e.g. SunOS 4), this will work only if
 ### the string "#!$(BINDIR)/ocamlrun" is less than 32 characters long.
-### In doubt, set SHARPBANGSCRIPTS to false.
-SHARPBANGSCRIPTS=true
-#SHARPBANGSCRIPTS=false
+### In doubt, set HASHBANGSCRIPTS to false.
+HASHBANGSCRIPTS=true
+#HASHBANGSCRIPTS=false
 
 ########## Configuration for the bytecode compiler
 
@@ -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 5b4658f71b..f2d0411687 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
 
@@ -62,7 +61,7 @@ EXT_OBJ=.$(O)
 EXT_LIB=.$(A)
 EXT_ASM=.$(S)
 MANEXT=1
-SHARPBANGSCRIPTS=false
+HASHBANGSCRIPTS=false
 PTHREAD_LINK=
 X11_INCLUDES=
 X11_LINK=
@@ -86,6 +85,12 @@ RUNTIMED=noruntimed
 ASM_CFI_SUPPORTED=false
 UNIXLIB=win32unix
 GRAPHLIB=win32graph
+FLAMBDA=false
+WITH_SPACETIME=false
+LIBUNWIND_AVAILABLE=false
+LIBUNWIND_LINK_FLAGS=
+PROFINFO_WIDTH=26
+SAFE_STRING=false
 
 ########## Configuration for the bytecode compiler
 
@@ -95,6 +100,12 @@ BYTECC=$(TOOLPREF)gcc
 ### Additional compile-time options for $(BYTECC).  (For static linking.)
 BYTECCCOMPOPTS=-O -mms-bitfields -Wall -Wno-unused
 
+### Additional compile-time options for $(BYTECC).  (For debug version.)
+BYTECCDBGCOMPOPTS=-g
+
+### Flag to use to rename object files.  (for debug version.)
+NAME_OBJ_FLAG=-o
+
 ### Additional link-time options for $(BYTECC).  (For static linking.)
 BYTECCLINKOPTS=
 
@@ -109,16 +120,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 +201,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 19a9b94376..14c575b3c3 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
 
@@ -62,7 +61,7 @@ EXT_OBJ=.$(O)
 EXT_LIB=.$(A)
 EXT_ASM=.$(S)
 MANEXT=1
-SHARPBANGSCRIPTS=false
+HASHBANGSCRIPTS=false
 PTHREAD_LINK=
 X11_INCLUDES=
 X11_LINK=
@@ -86,6 +85,12 @@ RUNTIMED=noruntimed
 ASM_CFI_SUPPORTED=false
 UNIXLIB=win32unix
 GRAPHLIB=win32graph
+FLAMBDA=false
+WITH_SPACETIME=false
+LIBUNWIND_AVAILABLE=false
+LIBUNWIND_LINK_FLAGS=
+PROFINFO_WIDTH=26
+SAFE_STRING=false
 
 ########## Configuration for the bytecode compiler
 
@@ -95,6 +100,12 @@ BYTECC=$(TOOLPREF)gcc
 ### Additional compile-time options for $(BYTECC).  (For static linking.)
 BYTECCCOMPOPTS=-O -mms-bitfields -Wall -Wno-unused
 
+### Additional compile-time options for $(BYTECC).  (For debug version.)
+BYTECCDBGCOMPOPTS=-g
+
+### Flag to use to rename object files.  (for debug version.)
+NAME_OBJ_FLAG=-o
+
 ### Additional link-time options for $(BYTECC).  (For static linking.)
 BYTECCLINKOPTS=
 
@@ -109,16 +120,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 +201,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 e014510230..5ffd6c0ecf 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
 
@@ -54,7 +56,7 @@ EXT_OBJ=.$(O)
 EXT_LIB=.$(A)
 EXT_ASM=.$(S)
 MANEXT=1
-SHARPBANGSCRIPTS=false
+HASHBANGSCRIPTS=false
 PTHREAD_LINK=
 X11_INCLUDES=
 X11_LINK=
@@ -77,6 +79,12 @@ RUNTIMED=noruntimed
 ASM_CFI_SUPPORTED=false
 UNIXLIB=win32unix
 GRAPHLIB=win32graph
+FLAMBDA=false
+WITH_SPACETIME=false
+LIBUNWIND_AVAILABLE=false
+LIBUNWIND_LINK_FLAGS=
+PROFINFO_WIDTH=26
+SAFE_STRING=false
 
 ########## Configuration for the bytecode compiler
 
@@ -84,13 +92,19 @@ 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=-Zi
+
+### Flag to use to rename object files.  (for debug version.)
+NAME_OBJ_FLAG=-Fo
 
 ### Additional link-time options for $(BYTECC).  (For static linking.)
 BYTECCLINKOPTS=
 
 ### Additional compile-time options for $(BYTECC).  (For building a DLL.)
-DLLCCCOMPOPTS=-Ox -MD
+DLLCCCOMPOPTS=-O2 -Gy- -MD
 
 ### Libraries needed
 BYTECCLIBS=advapi32.lib ws2_32.lib
@@ -100,16 +114,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 +172,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 +183,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 +205,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 783ce95340..720b2e1403 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
 
@@ -54,7 +56,7 @@ EXT_OBJ=.$(O)
 EXT_LIB=.$(A)
 EXT_ASM=.$(S)
 MANEXT=1
-SHARPBANGSCRIPTS=false
+HASHBANGSCRIPTS=false
 PTHREAD_LINK=
 X11_INCLUDES=
 X11_LINK=
@@ -76,6 +78,12 @@ RUNTIMED=noruntimed
 ASM_CFI_SUPPORTED=false
 UNIXLIB=win32unix
 GRAPHLIB=win32graph
+FLAMBDA=false
+WITH_SPACETIME=false
+LIBUNWIND_AVAILABLE=false
+LIBUNWIND_LINK_FLAGS=
+PROFINFO_WIDTH=26
+SAFE_STRING=false
 
 ########## Configuration for the bytecode compiler
 
@@ -83,16 +91,19 @@ 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
+BYTECCDBGCOMPOPTS=-Zi
+
+### Flag to use to rename object files.  (for debug version.)
+NAME_OBJ_FLAG=-Fo
 
 ### Additional link-time options for $(BYTECC).  (For static linking.)
 BYTECCLINKOPTS=
 
 ### Additional compile-time options for $(BYTECC).  (For building a DLL.)
-DLLCCCOMPOPTS=-Ox -MD
+DLLCCCOMPOPTS=-O2 -Gy- -MD
 
 ### Libraries needed
 #EXTRALIBS=bufferoverflowu.lib  # for the old PSDK compiler only
@@ -104,16 +115,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 +174,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 +185,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 +207,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 cb1ca8a9f0..0000000000
--- 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 579db9c63e..c5f5f3f0d0 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 01d46252ae..65d8240079 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 3e2bb983a0..b8f52572de 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 34f29c4869..0000000000
--- 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 0000000000..7277a7ad66
--- /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 e86fb198ec..69097103cf 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 e85e4b3fc1..0000000000
--- 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 c7548ae4ad..e7f044b9ea 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 91312f7161..bd2bbe0401 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 2cfbe73712..0000000000
--- 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 e3f73f52aa..a538ed038a 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 f09d65a80b..a932d11fb2 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 da52d89b4a..aefd85fcbe 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 53d578660b..8b6c690396 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"
@@ -22,6 +24,7 @@ while : ; do
   case "$1" in
     -i) echo "#include <$2>" >> hasgot.c; shift;;
     -t) echo "$2 $var;" >> hasgot.c; var="x$var"; shift;;
+    -Xl) libs="$libs $2"; shift;;
     -l*|-L*|-F*) libs="$libs $1";;
     -framework) libs="$libs $1 $2"; shift;;
     -*) opts="$opts $1";;
@@ -30,9 +33,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 0e9cef9b0d..6ec6b90470 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/sharpbang b/config/auto-aux/hashbang
similarity index 100%
rename from config/auto-aux/sharpbang
rename to config/auto-aux/hashbang
diff --git a/config/auto-aux/sharpbang2 b/config/auto-aux/hashbang2
similarity index 100%
rename from config/auto-aux/sharpbang2
rename to config/auto-aux/hashbang2
diff --git a/config/auto-aux/ia32sse2.c b/config/auto-aux/ia32sse2.c
index 47bafb60d6..d0391eaf3e 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 0086e92a44..af968039c5 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 c1439869f0..5914d1c267 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 
@@ -26,9 +28,9 @@ typedef long long int64_t;
 #error "No 64-bit integer type available"
 #endif
 
-int64_t foo;
+volatile int64_t foo;
 
-void access_int64(int64_t *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_t *) n);
-    access_int64((int64_t *) (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 e18f9e28f9..0000000000
--- 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 0000000000..9bd43ba15a
--- /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 fc92e67b9c..8a15a30d61 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 c8d7c435a4..2950f8014e 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 a9c355e518..0000000000
--- 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 9d18d2ac4f..0000000000
--- 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 e229ac921b..0f5d9e8c89 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 4be3c1d7a6..8a9e365889 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 3c341feae2..0000000000
--- 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 ed84e98036..90b893f745 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 daa9615d12..ffa9fb7de1 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 cc846a31b3..bd0da5ddff 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 3e3181bd81..0000000000
--- 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 06b9b27c82..b6d5217c60 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 934a00a9b7..845061d7f4 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 a80b0ac5e7..9676d2638f 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,17 @@
 #endif
 #define ARCH_INT64_PRINTF_FORMAT "I64"
 
+#if defined(_MSC_VER) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
 #undef NONSTANDARD_DIV_MOD
+
+#define PROFINFO_WIDTH 26
+
+/* Microsoft introduced the LL integer literal suffix in Visual C++ .NET 2003 */
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#define INT64_LITERAL(s) s ## i64
+#else
+#define INT64_LITERAL(s) s ## LL
+#endif
diff --git a/config/m-templ.h b/config/m-templ.h
index a5497b56b5..74ce64e193 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 ccf1bf4c57..96ed067d35 100644
--- a/config/s-nt.h
+++ b/config/s-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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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 */
 
@@ -31,3 +33,8 @@
 #define HAS_BROKEN_PRINTF
 #define HAS_IPV6
 #define HAS_NICE
+#define SUPPORT_DYNAMIC_LINKING
+#if defined(_MSC_VER) && _MSC_VER < 1300
+#define LACKS_SANE_NAN
+#define LACKS_VSCPRINTF
+#endif
diff --git a/config/s-templ.h b/config/s-templ.h
index 383b401557..2542d41cca 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.     */
+/*     en Automatique.                                                    */
 /*                                                                     */
-/***********************************************************************/
+/*   All rights reserved.  This file is distributed 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. */
 
@@ -128,6 +130,9 @@
 /* Define HAS_SYS_SELECT_H if /usr/include/sys/select.h exists
    and should be included before using select(). */
 
+#define HAS_NANOSLEEP
+/* Define HAS_NANOSLEEP if you have nanosleep(). */
+
 #define HAS_SYMLINK
 
 /* Define HAS_SYMLINK if you have symlink() and readlink() and lstat(). */
diff --git a/configure b/configure
index 4e48d9ecb2..1bdbb9310d 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
@@ -31,23 +36,33 @@ mathlib='-lm'
 dllib=''
 x11_include_dir=''
 x11_lib_dir=''
+libunwind_include_dir=''
+libunwind_lib_dir=''
+libunwind_available=false
+disable_libunwind=false
 graph_wanted=yes
 pthread_wanted=yes
 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
+with_spacetime=false
 no_naked_pointers=false
+native_compiler=true
 TOOLPREF=""
 with_cfi=true
 stats=false
+flambda=false
+safe_string=false
+max_testsuite_dir_retries=0
+with_cplugins=true
+with_fpic=false
 
 # Try to turn internationalization off, can cause config.guess to malfunction!
 unset LANG
@@ -108,6 +123,16 @@ while : ; do
             manext=1;;
         esac
         shift;;
+    -libunwinddir|--libunwinddir)
+        libunwind_include_dir=$2/include;
+        libunwind_lib_dir=$2/lib;
+        shift;;
+    -libunwindlib|--libunwindlib)
+        libunwind_lib_dir=$2; shift;;
+    -libunwindinclude|--libunwindinclude)
+        libunwind_include_dir=$2; shift;;
+    -disable-libunwind|--disable-libunwind)
+        disable_libunwind=true;;
     -host*|--host*)
         host_type=$2; shift;;
     -target*|--target*)
@@ -143,20 +168,34 @@ 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;;
+    -spacetime|--spacetime)
+        with_spacetime=true;;
     -no-cfi|--no-cfi)
         with_cfi=false;;
 		-enable-stats|--enable-stats)
 			  stats=true;;
+    -no-native-compiler|--no-native-compiler)
+        native_compiler=false;;
+    -flambda|--flambda)
+        flambda=true;;
+    -no-cplugins|--no-cplugins)
+        with_cplugins=false;;
+    -fPIC|--fPIC)
+        with_fpic=true;;
+    -safe-string|--safe-string)
+        safe_string=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 '=')."
@@ -201,6 +240,7 @@ touch s.h m.h Makefile
 # Write options to Makefile
 
 echo "# generated by ./configure $configure_options" >> Makefile
+echo "CONFIGURE_ARGS=$configure_options" >> Makefile
 
 # Where to install
 
@@ -268,50 +308,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)
-
-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.
+# Determine the C compiler family (GCC, Clang, etc)
 
-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
@@ -329,17 +332,53 @@ SO="so"
 TOOLCHAIN="cc"
 cpp="$cc -E -P"
 
+# 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
@@ -348,15 +387,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
@@ -370,34 +406,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
@@ -413,8 +441,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
@@ -437,48 +464,39 @@ 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."
      fi;;
 esac
 
-# Check C preprocessor (particularly, whether it supports -P)
-
-cpp_output="`$cpp cpp.c | tr -d '[[:space:]]'`"
-
-if test x"$cpp_output" != x"ok"; then
-    err "C preprocessor not working: got '$cpp_output', expected 'ok'"
-fi
-
 # For cross-compilation, we need a host-based ocamlrun and ocamlyacc,
 # and the user must specify the target BINDIR
 if $cross_compiler; then
@@ -491,8 +509,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
@@ -503,7 +521,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
@@ -576,6 +595,7 @@ echo "#define SIZEOF_LONG $2" >> m.h
 echo "#define SIZEOF_PTR $3" >> m.h
 echo "#define SIZEOF_SHORT $4" >> m.h
 echo "#define SIZEOF_LONGLONG $5" >> m.h
+echo "#define INT64_LITERAL(s) s ## LL" >> m.h
 
 # Determine endianness
 
@@ -585,13 +605,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
 
@@ -624,7 +645,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."
@@ -665,7 +687,7 @@ esac
 shared_libraries_supported=false
 dl_needs_underscore=false
 sharedcccompopts=''
-mksharedlib=''
+mksharedlib='shared-libs-not-available'
 byteccrpath=''
 mksharedlibrpath=''
 natdynlinkopts=""
@@ -680,7 +702,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*|*-*-dragonfly*|*-*-gnu*|*-*-haiku*)
       sharedcccompopts="-fPIC"
       mksharedlib="$bytecc -shared"
       bytecclinkopts="$bytecclinkopts -Wl,-E"
@@ -708,7 +731,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
@@ -736,12 +759,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;;
@@ -781,10 +806,12 @@ 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;;
     x86_64-*-kfreebsd*)           natdynlink=true;;
+    x86_64-*-dragonfly*)          natdynlink=true;;
     i[3456]86-*-freebsd*)         natdynlink=true;;
     x86_64-*-freebsd*)            natdynlink=true;;
     i[3456]86-*-openbsd*)         natdynlink=true;;
@@ -795,6 +822,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
@@ -835,18 +863,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;;
@@ -854,6 +885,7 @@ case "$target" in
   zaurus*-*-openbsd*)           arch=arm; system=bsd;;
   x86_64-*-linux*)              arch=amd64; system=linux;;
   x86_64-*-gnu*)                arch=amd64; system=gnu;;
+  x86_64-*-dragonfly*)          arch=amd64; system=dragonfly;;
   x86_64-*-freebsd*)            arch=amd64; system=freebsd;;
   x86_64-*-netbsd*)             arch=amd64; system=netbsd;;
   x86_64-*-openbsd*)            arch=amd64; system=openbsd;;
@@ -865,14 +897,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
+
+case "$native_compiler" in
+    true) ;;
+    false)
+      arch=none; model=default; system=unknown; natdynlink=false;;
+esac
 
 if test -z "$ccoption"; then
   nativecc="$bytecc"
@@ -880,23 +917,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'
@@ -912,11 +947,16 @@ case "$arch,$system" in
   amd64,solaris)  as="${TOOLPREF}as --64"
                   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";;
@@ -924,6 +964,8 @@ case "$arch,$system" in
                   esac;;
   arm,freebsd)    as="${TOOLPREF}cc -c"
                   aspp="${TOOLPREF}cc -c";;
+  *,dragonfly)    as="${TOOLPREF}as"
+                  aspp="${TOOLPREF}cc -c";;
   *,freebsd)      as="${TOOLPREF}as"
                   aspp="${TOOLPREF}cc -c";;
   amd64,*|arm,*|arm64,*|i386,*|power,bsd*|sparc,*)
@@ -949,6 +991,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';;
@@ -984,27 +1027,27 @@ fi
 
 # Do #! scripts work?
 
-if (SHELL=/bin/sh; export SHELL; (./sharpbang || ./sharpbang2) >/dev/null); then
+if (SHELL=/bin/sh; export SHELL; (./hashbang || ./hashbang2) >/dev/null); then
   inf "#! appears to work in shell scripts."
   case "$target" in
     *-*-sunos*|*-*-unicos*)
       wrn "We won't use it, though, because under SunOS and Unicos it breaks " \
           "on pathnames longer than 30 characters"
-      echo "SHARPBANGSCRIPTS=false" >> Makefile;;
+      echo "HASHBANGSCRIPTS=false" >> Makefile;;
     *-*-cygwin*)
       wrn "We won't use it, though, because of conflicts with .exe extension " \
           "under Cygwin"
-      echo "SHARPBANGSCRIPTS=false" >> Makefile;;
+      echo "HASHBANGSCRIPTS=false" >> Makefile;;
     *-*-mingw*)
       inf "We won't use it, though, because it's on the target platform " \
           "it would be used and windows doesn't support it."
-      echo "SHARPBANGSCRIPTS=false" >> Makefile;;
+      echo "HASHBANGSCRIPTS=false" >> Makefile;;
     *)
-      echo "SHARPBANGSCRIPTS=true" >> Makefile;;
+      echo "HASHBANGSCRIPTS=true" >> Makefile;;
   esac
 else
   inf "No support for #! in shell scripts"
-  echo "SHARPBANGSCRIPTS=false" >> Makefile
+  echo "HASHBANGSCRIPTS=false" >> Makefile
 fi
 
 # Use 64-bit file offset if possible
@@ -1049,6 +1092,16 @@ if sh ./hasgot times; then
   echo "#define HAS_TIMES" >> s.h
 fi
 
+if sh ./hasgot2 -D_GNU_SOURCE -i stdlib.h secure_getenv; then
+  inf "secure_getenv() found."
+  echo "#define HAS_SECURE_GETENV" >> s.h
+fi
+
+if sh ./hasgot -i unistd.h issetugid; then
+  inf "issetugid() found."
+  echo "#define HAS_ISSETUGID" >> s.h
+fi
+
 # For the terminfo module
 
 if test "$with_curses" = "yes"; then
@@ -1062,6 +1115,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
@@ -1075,6 +1146,17 @@ echo "GRAPHLIB=$graphlib" >> Makefile
 
 otherlibraries="$unixlib str num dynlink bigarray"
 
+# Spacetime profiling is only available for native code on 64-bit targets.
+
+case "$native_compiler" in
+    true)
+      if $arch64; then
+        otherlibraries="$otherlibraries raw_spacetime_lib"
+      fi
+      ;;
+    *) ;;
+esac
+
 # For the Unix library
 
 has_sockets=no
@@ -1211,6 +1293,11 @@ if sh ./hasgot select && \
   has_select=yes
 fi
 
+if sh ./hasgot nanosleep ; then
+  inf "nanosleep() found."
+  echo "#define HAS_NANOSLEEP" >> s.h
+fi
+
 if sh ./hasgot symlink readlink lstat;  then
   inf "symlink() found."
   echo "#define HAS_SYMLINK" >> s.h
@@ -1335,7 +1422,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."
@@ -1344,7 +1433,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)."
@@ -1353,7 +1445,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)."
@@ -1418,6 +1513,8 @@ if true; then
   case "$target" in
     *-*-solaris*)  pthread_link="-lpthread -lposix4"
                    pthread_caml_link="-cclib -lpthread -cclib -lposix4";;
+    *-*-dragon*)   pthread_link="-pthread"
+                   pthread_caml_link="-cclib -pthread";;
     *-*-freebsd*)  pthread_link="-pthread"
                    pthread_caml_link="-cclib -pthread";;
     *-*-openbsd*)  pthread_link="-pthread"
@@ -1434,7 +1531,7 @@ if true; then
     bytecccompopts="$bytecccompopts -D_REENTRANT"
     nativecccompopts="$nativecccompopts -D_REENTRANT"
     case "$target" in
-      *-*-freebsd*)
+      *-*-freebsd*|*-*-dragonfly*)
           bytecccompopts="$bytecccompopts -D_THREAD_SAFE"
           nativecccompopts="$nativecccompopts -D_THREAD_SAFE";;
       *-*-openbsd*)
@@ -1604,6 +1701,7 @@ if test "$x11_include" = "not found"; then
       else
         x11_libs="-L$dir"
         case "$target" in
+          *-*-freebsd*|*-*-dragonfly*) x11_link="-L$dir -lX11";;
           *-kfreebsd*-gnu) x11_link="-L$dir -lX11";;
           *-*-*bsd*) x11_link="-R$dir -L$dir -lX11";;
           *) x11_link="-L$dir -lX11";;
@@ -1651,9 +1749,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
@@ -1682,27 +1792,135 @@ 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"
+# 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
+
+# Spacetime profiling, including libunwind detection
+
+# The number of bits used for profiling information is configurable here.
+# The more bits used for profiling, the smaller will be Max_wosize.
+# Note that PROFINFO_WIDTH must still be defined even if not configuring
+# for Spacetime (see comment in byterun/caml/mlvalues.h on [Profinfo_hd]).
+profinfo_width=26
+echo "#define PROFINFO_WIDTH $profinfo_width" >> m.h
+if $with_spacetime; then
+  case "$arch,$system" in
+    amd64,*)
+      spacetime_supported=true
+      ;;
+    *)
+      spacetime_supported=false
+      ;;
+  esac
+  libunwind_warning=false
+  if $spacetime_supported; then
+    echo "Spacetime profiling will be available."
+    echo "#define WITH_SPACETIME" >> m.h
+    if $disable_libunwind; then
+      has_libunwind=no
+      libunwind_available=false
+      echo "libunwind support for Spacetime profiling was explicitly disabled."
+    else
+      # On Mac OS X, we always use the system libunwind.
+      if test "$libunwind_lib_dir" != ""; then
+        case "$arch,$system" in
+          amd64,macosx)
+            inf "[WARNING] -libunwind* options are ignored on Mac OS X"
+            libunwind_warning=true
+            libunwind_lib="-framework System"
+            libunwind_lib_temp="$libunwind_lib"
+            # We need unwinding information at runtime, but since we use
+            # -no_compact_unwind, we also need -keep_dwarf_unwind otherwise
+            # the OS X linker will chuck away the DWARF-like (.eh_frame)
+            # information.  (Older versions of OS X don't provide this.)
+            mkexe="$mkexe -Wl,-keep_dwarf_unwind"
+            mksharedlib="$mksharedlib -Wl,-keep_dwarf_unwind"
+            ;;
+          *)
+            libunwind_lib="-L$libunwind_lib_dir -lunwind -lunwind-x86_64"
+            libunwind_lib_temp="-Xl $libunwind_lib"
+            ;;
+        esac
+      else
+        case "$arch,$system" in
+          amd64,macosx)
+            libunwind_lib="-framework System"
+            libunwind_lib_temp="$libunwind_lib"
+            mkexe="$mkexe -Wl,-keep_dwarf_unwind"
+            mksharedlib="$mksharedlib -Wl,-keep_dwarf_unwind"
+            ;;
+          *)
+            libunwind_lib="-lunwind -lunwind-x86_64"
+            libunwind_lib_temp="$libunwind_lib"
+            ;;
+esac
+      fi
+      if test "$libunwind_include_dir" != ""; then
+        case "$arch,$system" in
+          amd64,macosx)
+            if ! $libunwind_warning; then
+              inf "[WARNING] -libunwind* options are ignored on Mac OS X"
+            fi
+            libunwind_include=""
+            ;;
+          *)
+            libunwind_include="-I$libunwind_include_dir"
+            ;;
+        esac
+      else
+        libunwind_include=""
+      fi
+      if sh ./hasgot -i libunwind.h $libunwind_lib_temp $libunwind_include; \
+      then
+        echo "#define HAS_LIBUNWIND" >> s.h
+        has_libunwind=yes
+        libunwind_available=true
+        echo "libunwind support for Spacetime profiling will be available."
+      else
+        has_libunwind=no
+        libunwind_available=false
+        echo "libunwind support for Spacetime profiling will not be available."
+      fi
+    fi
+  else
+    echo "Spacetime profiling is not available on 32-bit platforms."
+    with_spacetime=false
+    libunwind_available=false
+    has_libunwind=no
+  fi
+fi
 
-# Final twiddling of compiler options to work around known bugs
+if ! $shared_libraries_supported; then
+  with_cplugins=false
+fi
 
-nativeccprofopts="$nativecccompopts"
-case "$buggycc" in
-  gcc.2.96)
-    bytecccompopts="$bytecccompopts -fomit-frame-pointer"
-    nativecccompopts="$nativecccompopts -fomit-frame-pointer";;
-esac
+if $with_fpic; then
+  bytecccompopts="$bytecccompopts $sharedcccompopts"
+  nativecccompopts="$nativecccompopts $sharedcccompopts"
+  aspp="$aspp $sharedcccompopts"
+fi
+
+
+if $with_cplugins; then
+  echo "#define CAML_WITH_CPLUGINS" >> m.h
+fi
+
+if $with_fpic; then
+  echo "#define CAML_WITH_FPIC" >> m.h
+fi
 
 # Finish generated files
 
@@ -1711,7 +1929,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 "CPP=$cpp" >> Makefile
 echo "EXE=$exe" >> Makefile
@@ -1725,7 +1944,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
@@ -1772,22 +1993,26 @@ 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 "WITH_SPACETIME=$with_spacetime" >> Makefile
+echo "LIBUNWIND_AVAILABLE=$libunwind_available" >> Makefile
+echo "LIBUNWIND_INCLUDE_FLAGS=$libunwind_include" >> Makefile
+echo "LIBUNWIND_LINK_FLAGS=$libunwind_lib" >> Makefile
+echo "PROFINFO_WIDTH=$profinfo_width" >> Makefile
+echo "WITH_CPLUGINS=$with_cplugins" >> Makefile
+echo "WITH_FPIC=$with_fpic" >> Makefile
 echo "TARGET=$target" >> Makefile
 echo "HOST=$host" >> Makefile
 if [ "$ostype" = Cygwin ]; then
   echo "DIFF=diff -q --strip-trailing-cr" >>Makefile
 fi
-case "$target" in
-    *-apple-darwin*)
-      echo "BYTECAMLRUN=\$(ROOTDIR)/byterun/libcamlrun.a" >> Makefile;;
-    *)
-      echo "BYTECAMLRUN=" >> Makefile;;
-esac
+echo "FLAMBDA=$flambda" >> Makefile
+echo "SAFE_STRING=$safe_string" >> Makefile
+echo "MAX_TESTSUITE_DIR_RETRIES=$max_testsuite_dir_retries" >> Makefile
 
 
 rm -f tst hasgot.c
@@ -1807,11 +2032,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
@@ -1848,12 +2075,54 @@ else
   else
   inf "        naked pointers forbidden.. no"
   fi
+  if $with_spacetime; then
+    inf "        spacetime profiling....... yes"
+    inf "          ... with libunwind...... $has_libunwind"
+  else
+    inf "        spacetime profiling....... no"
+  fi
+  case "$arch,$system" in
+    amd64,macosx)
+      ;;
+    amd64,*)
+      if test "$has_libunwind" = "yes"; then
+        if test "$libunwind_include_dir" != ""; then
+          inf "        libunwind include dir..... $libunwind_include_dir"
+        fi
+        if test "$libunwind_lib_dir" != ""; then
+          inf "        libunwind library dir..... $libunwind_lib_dir"
+        fi
+      fi
+      ;;
+    *)
+      ;;
+  esac
+  if $with_cplugins; then
+  inf "        C plugins................. yes"
+  else
+  inf "        C plugins................. no"
+  fi
+  if $with_fpic; then
+  inf "        compile with -fPIC........ yes"
+  else
+  inf "        compile with -fPIC........ no"
+  fi
   inf "        native dynlink ........... $natdynlink"
   if test "$profiling" = "prof"; then
   inf "        profiling with gprof ..... supported"
   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
+  if test "$safe_string" = "true"; then
+  inf "        safe strings ............. yes"
+  else
+  inf "        safe strings ............. no"
+  fi
 fi
 
 if test "$with_debugger" = "ocamldebugger"; then
@@ -1866,6 +2135,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/.depend b/debugger/.depend
index b62541619a..ed8ab4bf5a 100644
--- a/debugger/.depend
+++ b/debugger/.depend
@@ -1,46 +1,11 @@
-breakpoints.cmi : primitives.cmi ../bytecomp/instruct.cmi
-checkpoints.cmi : primitives.cmi debugcom.cmi
-command_line.cmi :
-debugcom.cmi : primitives.cmi
-debugger_config.cmi :
-dynlink.cmi :
-eval.cmi : ../typing/types.cmi ../typing/path.cmi parser_aux.cmi \
-    ../parsing/longident.cmi ../bytecomp/instruct.cmi ../typing/ident.cmi \
-    ../typing/env.cmi debugcom.cmi
-events.cmi : ../bytecomp/instruct.cmi
-exec.cmi :
-frames.cmi : primitives.cmi ../bytecomp/instruct.cmi
-history.cmi :
-input_handling.cmi : primitives.cmi
-int64ops.cmi :
-lexer.cmi : parser.cmi
-loadprinter.cmi : ../parsing/longident.cmi dynlink.cmi
-parameters.cmi :
-parser.cmi : parser_aux.cmi ../parsing/longident.cmi
-parser_aux.cmi : primitives.cmi ../parsing/longident.cmi
-pattern_matching.cmi : ../typing/typedtree.cmi parser_aux.cmi debugcom.cmi
-pos.cmi : ../bytecomp/instruct.cmi
-primitives.cmi : $(UNIXDIR)/unix.cmi
-printval.cmi : ../typing/types.cmi ../typing/path.cmi parser_aux.cmi \
-    ../typing/env.cmi debugcom.cmi
-program_loading.cmi : primitives.cmi
-program_management.cmi :
-question.cmi :
-show_information.cmi : ../bytecomp/instruct.cmi
-show_source.cmi : ../bytecomp/instruct.cmi
-source.cmi :
-symbols.cmi : ../bytecomp/instruct.cmi
-time_travel.cmi : primitives.cmi
-trap_barrier.cmi :
-unix_tools.cmi : $(UNIXDIR)/unix.cmi
-breakpoints.cmo : symbols.cmi primitives.cmi pos.cmi \
-    ../bytecomp/instruct.cmi exec.cmi debugcom.cmi checkpoints.cmi \
-    breakpoints.cmi
-breakpoints.cmx : symbols.cmx primitives.cmx pos.cmx \
-    ../bytecomp/instruct.cmx exec.cmx debugcom.cmx checkpoints.cmx \
-    breakpoints.cmi
+breakpoints.cmo : symbols.cmi pos.cmi ../bytecomp/instruct.cmi exec.cmi \
+    debugcom.cmi checkpoints.cmi breakpoints.cmi
+breakpoints.cmx : symbols.cmx pos.cmx ../bytecomp/instruct.cmx exec.cmx \
+    debugcom.cmx checkpoints.cmx breakpoints.cmi
+breakpoints.cmi : ../bytecomp/instruct.cmi
 checkpoints.cmo : primitives.cmi int64ops.cmi debugcom.cmi checkpoints.cmi
 checkpoints.cmx : primitives.cmx int64ops.cmx debugcom.cmx checkpoints.cmi
+checkpoints.cmi : primitives.cmi debugcom.cmi
 command_line.cmo : unix_tools.cmi $(UNIXDIR)/unix.cmi \
     ../typing/types.cmi time_travel.cmi symbols.cmi source.cmi \
     show_source.cmi show_information.cmi question.cmi program_management.cmi \
@@ -61,20 +26,15 @@ command_line.cmx : unix_tools.cmx $(UNIXDIR)/unix.cmx \
     events.cmx eval.cmx ../typing/envaux.cmx ../typing/env.cmx \
     debugger_config.cmx debugcom.cmx ../typing/ctype.cmx ../utils/config.cmx \
     checkpoints.cmx breakpoints.cmx command_line.cmi
+command_line.cmi :
 debugcom.cmo : primitives.cmi ../utils/misc.cmi int64ops.cmi \
     input_handling.cmi debugcom.cmi
 debugcom.cmx : primitives.cmx ../utils/misc.cmx int64ops.cmx \
     input_handling.cmx debugcom.cmi
+debugcom.cmi : primitives.cmi
 debugger_config.cmo : int64ops.cmi debugger_config.cmi
 debugger_config.cmx : int64ops.cmx debugger_config.cmi
-dynlink.cmo : ../bytecomp/symtable.cmi ../bytecomp/opcodes.cmo \
-    ../utils/misc.cmi ../bytecomp/meta.cmi ../bytecomp/dll.cmi \
-    ../utils/consistbl.cmi ../utils/config.cmi ../bytecomp/cmo_format.cmi \
-    ../typing/cmi_format.cmi dynlink.cmi
-dynlink.cmx : ../bytecomp/symtable.cmx ../bytecomp/opcodes.cmx \
-    ../utils/misc.cmx ../bytecomp/meta.cmx ../bytecomp/dll.cmx \
-    ../utils/consistbl.cmx ../utils/config.cmx ../bytecomp/cmo_format.cmi \
-    ../typing/cmi_format.cmx dynlink.cmi
+debugger_config.cmi :
 eval.cmo : ../typing/types.cmi ../bytecomp/symtable.cmi ../typing/subst.cmi \
     printval.cmi ../typing/printtyp.cmi ../typing/predef.cmi \
     ../typing/path.cmi parser_aux.cmi ../utils/misc.cmi \
@@ -87,34 +47,47 @@ eval.cmx : ../typing/types.cmx ../bytecomp/symtable.cmx ../typing/subst.cmx \
     ../parsing/longident.cmx ../bytecomp/instruct.cmx ../typing/ident.cmx \
     frames.cmx ../typing/env.cmx debugcom.cmx ../typing/ctype.cmx \
     ../typing/btype.cmx eval.cmi
+eval.cmi : ../typing/types.cmi ../typing/path.cmi parser_aux.cmi \
+    ../parsing/longident.cmi ../bytecomp/instruct.cmi ../typing/ident.cmi \
+    ../typing/env.cmi debugcom.cmi
 events.cmo : ../parsing/location.cmi ../bytecomp/instruct.cmi events.cmi
 events.cmx : ../parsing/location.cmx ../bytecomp/instruct.cmx events.cmi
+events.cmi : ../bytecomp/instruct.cmi
 exec.cmo : exec.cmi
 exec.cmx : exec.cmi
+exec.cmi :
 frames.cmo : symbols.cmi ../utils/misc.cmi ../bytecomp/instruct.cmi \
     events.cmi debugcom.cmi frames.cmi
 frames.cmx : symbols.cmx ../utils/misc.cmx ../bytecomp/instruct.cmx \
     events.cmx debugcom.cmx frames.cmi
+frames.cmi : ../bytecomp/instruct.cmi
 history.cmo : primitives.cmi int64ops.cmi debugger_config.cmi \
     checkpoints.cmi history.cmi
 history.cmx : primitives.cmx int64ops.cmx debugger_config.cmx \
     checkpoints.cmx history.cmi
+history.cmi :
 input_handling.cmo : $(UNIXDIR)/unix.cmi primitives.cmi \
     input_handling.cmi
 input_handling.cmx : $(UNIXDIR)/unix.cmx primitives.cmx \
     input_handling.cmi
+input_handling.cmi : primitives.cmi
 int64ops.cmo : int64ops.cmi
 int64ops.cmx : int64ops.cmi
+int64ops.cmi :
 lexer.cmo : parser.cmi lexer.cmi
 lexer.cmx : parser.cmx lexer.cmi
+lexer.cmi : parser.cmi
 loadprinter.cmo : ../typing/types.cmi ../bytecomp/symtable.cmi printval.cmi \
     ../typing/printtyp.cmi ../typing/path.cmi ../utils/misc.cmi \
     ../parsing/longident.cmi ../typing/ident.cmi ../typing/env.cmi \
-    dynlink.cmi ../typing/ctype.cmi ../utils/config.cmi loadprinter.cmi
+    ../typing/ctype.cmi ../utils/config.cmi ../driver/compdynlink.cmi \
+    loadprinter.cmi
 loadprinter.cmx : ../typing/types.cmx ../bytecomp/symtable.cmx printval.cmx \
     ../typing/printtyp.cmx ../typing/path.cmx ../utils/misc.cmx \
     ../parsing/longident.cmx ../typing/ident.cmx ../typing/env.cmx \
-    dynlink.cmx ../typing/ctype.cmx ../utils/config.cmx loadprinter.cmi
+    ../typing/ctype.cmx ../utils/config.cmx ../driver/compdynlink.cmi \
+    loadprinter.cmi
+loadprinter.cmi : ../parsing/longident.cmi ../driver/compdynlink.cmi
 main.cmo : unix_tools.cmi $(UNIXDIR)/unix.cmi time_travel.cmi \
     show_information.cmi question.cmi program_management.cmi primitives.cmi \
     parameters.cmi ../utils/misc.cmi input_handling.cmi frames.cmi exec.cmi \
@@ -131,22 +104,26 @@ parameters.cmo : primitives.cmi ../typing/envaux.cmi debugger_config.cmi \
     ../utils/config.cmi parameters.cmi
 parameters.cmx : primitives.cmx ../typing/envaux.cmx debugger_config.cmx \
     ../utils/config.cmx parameters.cmi
+parameters.cmi :
 parser.cmo : parser_aux.cmi ../parsing/longident.cmi int64ops.cmi \
     input_handling.cmi parser.cmi
 parser.cmx : parser_aux.cmi ../parsing/longident.cmx int64ops.cmx \
     input_handling.cmx parser.cmi
+parser.cmi : parser_aux.cmi ../parsing/longident.cmi
+parser_aux.cmi : ../parsing/longident.cmi
 pattern_matching.cmo : ../typing/typedtree.cmi parser_aux.cmi \
     ../utils/misc.cmi debugger_config.cmi debugcom.cmi ../typing/ctype.cmi \
     pattern_matching.cmi
 pattern_matching.cmx : ../typing/typedtree.cmx parser_aux.cmi \
     ../utils/misc.cmx debugger_config.cmx debugcom.cmx ../typing/ctype.cmx \
     pattern_matching.cmi
-pos.cmo : source.cmi primitives.cmi ../parsing/location.cmi \
-    ../bytecomp/instruct.cmi pos.cmi
-pos.cmx : source.cmx primitives.cmx ../parsing/location.cmx \
-    ../bytecomp/instruct.cmx pos.cmi
+pattern_matching.cmi : ../typing/typedtree.cmi parser_aux.cmi debugcom.cmi
+pos.cmo : ../parsing/location.cmi ../bytecomp/instruct.cmi pos.cmi
+pos.cmx : ../parsing/location.cmx ../bytecomp/instruct.cmx pos.cmi
+pos.cmi : ../bytecomp/instruct.cmi
 primitives.cmo : $(UNIXDIR)/unix.cmi primitives.cmi
 primitives.cmx : $(UNIXDIR)/unix.cmx primitives.cmi
+primitives.cmi : $(UNIXDIR)/unix.cmi
 printval.cmo : ../typing/types.cmi ../bytecomp/symtable.cmi \
     ../typing/printtyp.cmi ../typing/path.cmi parser_aux.cmi \
     ../typing/outcometree.cmi ../typing/oprint.cmi \
@@ -155,12 +132,15 @@ printval.cmx : ../typing/types.cmx ../bytecomp/symtable.cmx \
     ../typing/printtyp.cmx ../typing/path.cmx parser_aux.cmi \
     ../typing/outcometree.cmi ../typing/oprint.cmx \
     ../toplevel/genprintval.cmx debugcom.cmx printval.cmi
+printval.cmi : ../typing/types.cmi ../typing/path.cmi parser_aux.cmi \
+    ../typing/env.cmi debugcom.cmi
 program_loading.cmo : unix_tools.cmi $(UNIXDIR)/unix.cmi \
     primitives.cmi parameters.cmi input_handling.cmi debugger_config.cmi \
     program_loading.cmi
 program_loading.cmx : unix_tools.cmx $(UNIXDIR)/unix.cmx \
     primitives.cmx parameters.cmx input_handling.cmx debugger_config.cmx \
     program_loading.cmi
+program_loading.cmi : primitives.cmi
 program_management.cmo : unix_tools.cmi $(UNIXDIR)/unix.cmi \
     time_travel.cmi symbols.cmi question.cmi program_loading.cmi \
     primitives.cmi parameters.cmi int64ops.cmi input_handling.cmi history.cmi \
@@ -171,8 +151,10 @@ program_management.cmx : unix_tools.cmx $(UNIXDIR)/unix.cmx \
     primitives.cmx parameters.cmx int64ops.cmx input_handling.cmx history.cmx \
     ../typing/envaux.cmx debugger_config.cmx ../utils/config.cmx \
     breakpoints.cmx program_management.cmi
+program_management.cmi :
 question.cmo : primitives.cmi lexer.cmi input_handling.cmi question.cmi
 question.cmx : primitives.cmx lexer.cmx input_handling.cmx question.cmi
+question.cmi :
 show_information.cmo : symbols.cmi source.cmi show_source.cmi printval.cmi \
     parameters.cmi ../utils/misc.cmi ../bytecomp/instruct.cmi frames.cmi \
     events.cmi debugcom.cmi checkpoints.cmi breakpoints.cmi \
@@ -181,22 +163,26 @@ show_information.cmx : symbols.cmx source.cmx show_source.cmx printval.cmx \
     parameters.cmx ../utils/misc.cmx ../bytecomp/instruct.cmx frames.cmx \
     events.cmx debugcom.cmx checkpoints.cmx breakpoints.cmx \
     show_information.cmi
+show_information.cmi : ../bytecomp/instruct.cmi
 show_source.cmo : source.cmi primitives.cmi parameters.cmi \
     ../parsing/location.cmi ../bytecomp/instruct.cmi events.cmi \
     debugger_config.cmi show_source.cmi
 show_source.cmx : source.cmx primitives.cmx parameters.cmx \
     ../parsing/location.cmx ../bytecomp/instruct.cmx events.cmx \
     debugger_config.cmx show_source.cmi
+show_source.cmi : ../bytecomp/instruct.cmi
 source.cmo : primitives.cmi ../utils/misc.cmi debugger_config.cmi \
     ../utils/config.cmi source.cmi
 source.cmx : primitives.cmx ../utils/misc.cmx debugger_config.cmx \
     ../utils/config.cmx source.cmi
+source.cmi :
 symbols.cmo : ../bytecomp/symtable.cmi program_loading.cmi \
     ../bytecomp/instruct.cmi events.cmi debugger_config.cmi debugcom.cmi \
     checkpoints.cmi ../bytecomp/bytesections.cmi symbols.cmi
 symbols.cmx : ../bytecomp/symtable.cmx program_loading.cmx \
     ../bytecomp/instruct.cmx events.cmx debugger_config.cmx debugcom.cmx \
     checkpoints.cmx ../bytecomp/bytesections.cmx symbols.cmi
+symbols.cmi : ../bytecomp/instruct.cmi
 time_travel.cmo : trap_barrier.cmi symbols.cmi question.cmi \
     program_loading.cmi primitives.cmi ../utils/misc.cmi int64ops.cmi \
     ../bytecomp/instruct.cmi input_handling.cmi exec.cmi events.cmi \
@@ -207,9 +193,10 @@ time_travel.cmx : trap_barrier.cmx symbols.cmx question.cmx \
     ../bytecomp/instruct.cmx input_handling.cmx exec.cmx events.cmx \
     debugger_config.cmx debugcom.cmx checkpoints.cmx breakpoints.cmx \
     time_travel.cmi
+time_travel.cmi : primitives.cmi
 trap_barrier.cmo : exec.cmi debugcom.cmi checkpoints.cmi trap_barrier.cmi
 trap_barrier.cmx : exec.cmx debugcom.cmx checkpoints.cmx trap_barrier.cmi
-unix_tools.cmo : $(UNIXDIR)/unix.cmi primitives.cmi ../utils/misc.cmi \
-    unix_tools.cmi
-unix_tools.cmx : $(UNIXDIR)/unix.cmx primitives.cmx ../utils/misc.cmx \
-    unix_tools.cmi
+trap_barrier.cmi :
+unix_tools.cmo : $(UNIXDIR)/unix.cmi ../utils/misc.cmi unix_tools.cmi
+unix_tools.cmx : $(UNIXDIR)/unix.cmx ../utils/misc.cmx unix_tools.cmi
+unix_tools.cmi : $(UNIXDIR)/unix.cmi
diff --git a/debugger/.ignore b/debugger/.ignore
deleted file mode 100644
index 45eec7cceb..0000000000
--- 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 75f4aa8ebd..d0ac2565cc 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 4182c7c77b..86a6d00d39 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 f3859c63d2..aed8aa12b5 100644
--- a/debugger/Makefile.shared
+++ b/debugger/Makefile.shared
@@ -1,21 +1,25 @@
-#########################################################################
-#                                                                       #
-#                                 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
 CAMLYACC ?= ../boot/ocamlyacc
 
 CAMLC=$(CAMLRUN) ../ocamlc -nostdlib -I ../stdlib
-COMPFLAGS=-warn-error A -safe-string $(INCLUDES)
+COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A \
+          -safe-string -strict-sequence -strict-formats
 LINKFLAGS=-linkall -I $(UNIXDIR)
 YACCFLAGS=
 CAMLLEX=$(CAMLRUN) ../boot/ocamllex
@@ -26,14 +30,19 @@ INSTALL_BINDIR=$(DESTDIR)$(BINDIR)
 
 INCLUDES=\
   -I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../toplevel \
-  -I $(UNIXDIR)
+  -I ../driver -I $(UNIXDIR)
 
 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 \
@@ -43,12 +52,11 @@ OTHEROBJS=\
   ../typing/envaux.cmo \
   ../bytecomp/runtimedef.cmo ../bytecomp/bytesections.cmo \
   ../bytecomp/dll.cmo ../bytecomp/meta.cmo ../bytecomp/symtable.cmo \
-  ../bytecomp/opcodes.cmo \
+  ../bytecomp/opcodes.cmo ../driver/compdynlink.cmo \
   ../toplevel/genprintval.cmo
 
 
 OBJS=\
-	dynlink.cmo \
 	int64ops.cmo \
 	primitives.cmo \
 	unix_tools.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)
@@ -102,7 +110,7 @@ clean::
 	$(CAMLC) -c $(COMPFLAGS) $<
 
 depend: beforedepend
-	$(CAMLDEP) $(DEPFLAGS) *.mli *.ml \
+	$(CAMLDEP) -slash $(DEPFLAGS) *.mli *.ml \
 	| sed -e 's,$(UNIXDIR)/,$$(UNIXDIR)/,' > .depend
 
 lexer.ml: lexer.mll
@@ -117,13 +125,4 @@ clean::
 	rm -f parser.ml parser.mli
 beforedepend:: parser.ml parser.mli
 
-dynlink.ml: ../otherlibs/dynlink/dynlink.ml
-	grep -v 'REMOVE_ME for ../../debugger/dynlink.ml' \
-	     ../otherlibs/dynlink/dynlink.ml >dynlink.ml
-dynlink.mli: ../otherlibs/dynlink/dynlink.mli
-	cp ../otherlibs/dynlink/dynlink.mli .
-clean::
-	rm -f dynlink.ml dynlink.mli
-beforedepend:: dynlink.ml dynlink.mli
-
 include .depend
diff --git a/debugger/breakpoints.ml b/debugger/breakpoints.ml
index de4c95bd5a..edba042844 100644
--- a/debugger/breakpoints.ml
+++ b/debugger/breakpoints.ml
@@ -1,22 +1,24 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                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 ***************************)
 
 open Checkpoints
 open Debugcom
 open Instruct
-open Primitives
 open Printf
 
 (*** Debugging. ***)
@@ -134,7 +136,7 @@ let execute_without_breakpoints f =
       f ();
       change_version version pos
     with
-      x ->
+      _ ->
         change_version version pos
 
 (* Add a position in the position list. *)
diff --git a/debugger/breakpoints.mli b/debugger/breakpoints.mli
index ef5188529c..d0e76c3675 100644
--- a/debugger/breakpoints.mli
+++ b/debugger/breakpoints.mli
@@ -1,19 +1,21 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                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 ***************************)
 
-open Primitives
 open Instruct
 
 (*** Debugging. ***)
diff --git a/debugger/checkpoints.ml b/debugger/checkpoints.ml
index f0df238903..7ab8de728f 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 95eaf1b088..f3ca13808b 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 c9af4558af..b48c9cded8 100644
--- a/debugger/command_line.ml
+++ b/debugger/command_line.ml
@@ -1,4 +1,4 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                OCaml                                *)
 (*                                                                     *)
@@ -6,10 +6,13 @@
 (*          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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
 
@@ -151,8 +154,8 @@ let convert_module mdle =
   | Some m ->
       (* Strip .ml extension if any, and capitalize *)
       String.capitalize_ascii(if Filename.check_suffix m ".ml"
-                              then Filename.chop_suffix m ".ml"
-                              else m)
+                        then Filename.chop_suffix m ".ml"
+                        else m)
   | None ->
       try
         (get_current_event ()).ev_module
@@ -176,7 +179,7 @@ let interprete_line ppf line =
               i.instr_action ppf lexbuf;
               resume_user_input ();
               i.instr_repeat
-          | l ->
+          | _ ->
               error "Ambiguous command."
           end
       | None ->
@@ -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 =
@@ -213,7 +216,7 @@ let line_loop ppf line_buffer =
         error ("System error: " ^ s) *)
 
 (** Instructions. **)
-let instr_cd ppf lexbuf =
+let instr_cd _ppf lexbuf =
   let dir = argument_eol argument lexbuf in
     if ask_kill_program () then
       try
@@ -222,7 +225,7 @@ let instr_cd ppf lexbuf =
       | Sys_error s ->
           error s
 
-let instr_shell ppf lexbuf =
+let instr_shell _ppf lexbuf =
   let cmdarg = argument_list_eol argument lexbuf in
   let cmd = String.concat " " cmdarg in
   (* perhaps we should use $SHELL -c ? *)
@@ -230,7 +233,7 @@ let instr_shell ppf lexbuf =
   if (err != 0) then
     eprintf "Shell command %S failed with exit code %d\n%!" cmd err
 
-let instr_env ppf lexbuf =
+let instr_env _ppf lexbuf =
   let cmdarg = argument_list_eol argument lexbuf in
   let cmdarg = string_trim (String.concat " " cmdarg) in
   if cmdarg <> "" then
@@ -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_ascii 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'
@@ -283,7 +286,7 @@ let instr_dir ppf lexbuf =
                  dirs)
       Debugger_config.load_path_for
 
-let instr_kill ppf lexbuf =
+let instr_kill _ppf lexbuf =
   eol lexbuf;
   if not !loaded then error "The program is not being run.";
   if (yes_or_no "Kill the program being debugged") then begin
@@ -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 ();
@@ -385,7 +393,7 @@ let print_info_list ppf =
   let pr_infos ppf = List.iter (fun i -> fprintf ppf "%s@ " i.info_name)  in
   fprintf ppf "List of info commands: %a@." pr_infos !info_list
 
-let instr_complete ppf lexbuf =
+let instr_complete _ppf lexbuf =
   let ppf = Format.err_formatter in
   let rec print_list l =
     try
@@ -457,7 +465,7 @@ let instr_help ppf lexbuf =
           find_variable
             (fun v _ _ ->
                print_help ("show " ^ v.var_name) ("show " ^ v.var_help))
-            (fun v ->
+            (fun _v ->
                print_help "show" "display debugger variable.";
                print_variable_list ppf)
             ppf
@@ -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 =
@@ -553,8 +585,8 @@ let instr_source ppf lexbuf =
 
 let instr_set =
   find_variable
-    (fun {var_action = (funct, _)} ppf lexbuf -> funct lexbuf)
-    (function ppf -> error "Argument required.")
+    (fun {var_action = (funct, _)} _ppf lexbuf -> funct lexbuf)
+    (function _ppf -> error "Argument required.")
 
 let instr_show =
   find_variable
@@ -568,8 +600,8 @@ let instr_show =
 
 let instr_info =
   find_info
-    (fun i ppf lexbuf -> i.info_action lexbuf)
-    (function ppf ->
+    (fun i _ppf lexbuf -> i.info_action lexbuf)
+    (function _ppf ->
        error "\"info\" must be followed by the name of an info command.")
 
 let instr_break 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,9 +671,9 @@ 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 =
+let instr_delete _ppf lexbuf =
   match integer_list_eol Lexer.lexeme lexbuf with
   | [] ->
       if breakpoints_count () <> 0 && yes_or_no "Delete all breakpoints"
@@ -739,7 +771,7 @@ let instr_last ppf lexbuf =
     go_to (History.previous_time count);
     show_current_event ppf
 
-let instr_list ppf lexbuf =
+let instr_list _ppf lexbuf =
   let (mo, beg, e) = list_arguments_eol Lexer.lexeme lexbuf in
     let (curr_mod, line, column) =
       try
@@ -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
@@ -830,9 +866,9 @@ let loading_mode_variable ppf =
   (find_ident
      "loading mode"
      (matching_elements (ref loading_modes) fst)
-     (fun (_, mode) ppf lexbuf ->
+     (fun (_, mode) _ppf lexbuf ->
         eol lexbuf; set_launching_function mode)
-     (function ppf -> error "Syntax error.")
+     (function _ppf -> error "Syntax error.")
      ppf),
   function ppf ->
     let rec find = function
@@ -910,7 +946,7 @@ let info_breakpoints ppf lexbuf =
   end
 ;;
 
-let info_events ppf lexbuf =
+let info_events _ppf lexbuf =
   ensure_loaded ();
   let mdle =
     convert_module (module_of_longident (opt_longident_eol Lexer.lexeme lexbuf))
@@ -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";
@@ -1168,7 +1210,7 @@ It can be either:\n\
        var_action = follow_fork_variable;
        var_help =
 "process to follow after forking.\n\
-It can be either :
+It can be either :\n\
   child: the newly created process.\n\
   parent: the process that called fork.\n" }];
 
diff --git a/debugger/command_line.mli b/debugger/command_line.mli
index f7fb160573..dc3a8d512f 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 8bfd3aaba3..caba942a9f 100644
--- a/debugger/debugcom.ml
+++ b/debugger/debugcom.ml
@@ -1,4 +1,4 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                OCaml                                *)
 (*                                                                     *)
@@ -6,10 +6,13 @@
 (*          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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -279,7 +282,7 @@ module Remote_value =
       Remote(input_remote_value !conn.io_in)
 
     let closure_code = function
-    | Local obj -> assert false
+    | Local _ -> assert false
     | Remote v ->
         output_char !conn.io_out 'C';
         output_remote_value !conn.io_out v;
@@ -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 3dce2abb41..6f94df5c3b 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 a16fdca232..194a13dd05 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 ab935d9324..74c6d5f331 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 1d1ab38865..e6baa80b47 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
@@ -58,12 +61,12 @@ let rec path event = function
         | None ->
             raise(Error(Unbound_identifier id))
         end
-  | Pdot(root, fieldname, pos) ->
+  | Pdot(root, _fieldname, pos) ->
       let v = path event root in
       if not (Debugcom.Remote_value.is_block v) then
         raise(Error(Not_initialized_yet root));
       Debugcom.Remote_value.field v pos
-  | Papply(p1, p2) ->
+  | Papply _ ->
       fatal_error "Eval.path: Papply"
 
 let rec expression event env = function
@@ -132,10 +135,10 @@ let rec expression event env = function
   | E_field(arg, lbl) ->
       let (v, ty) = expression event env arg in
       begin match (Ctype.repr(Ctype.expand_head_opt env ty)).desc with
-        Tconstr(path, args, _) ->
+        Tconstr(path, _, _) ->
           let tydesc = Env.find_type path env in
           begin match tydesc.type_kind with
-            Type_record(lbl_list, repr) ->
+            Type_record(lbl_list, _repr) ->
               let (pos, ty_res) =
                 find_label lbl env ty path tydesc 0 lbl_list in
               (Debugcom.Remote_value.field v pos, ty_res)
diff --git a/debugger/eval.mli b/debugger/eval.mli
index c5e04f3315..51d27136c0 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 c622f67226..a50eae0d60 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 e593be03c4..f50f156e44 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 931c0a9199..df940165e5 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 *)
 
@@ -17,7 +20,7 @@ let interrupted = ref false
 
 let is_protected = ref false
 
-let break signum =
+let break _signum =
   if !is_protected
   then interrupted := true
   else raise Sys.Break
diff --git a/debugger/exec.mli b/debugger/exec.mli
index a820589b59..05e2e5f8d4 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 d3456284d1..96b7ce1531 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 **********************************)
 
@@ -122,6 +125,6 @@ let do_backtrace action =
 
 let stack_depth () =
   let num_frames = ref 0 in
-  do_backtrace (function Some ev -> incr num_frames; true
+  do_backtrace (function Some _ev -> incr num_frames; true
                        | None -> num_frames := -1; false);
   !num_frames
diff --git a/debugger/frames.mli b/debugger/frames.mli
index fa652b0ceb..514aa2e361 100644
--- a/debugger/frames.mli
+++ b/debugger/frames.mli
@@ -1,20 +1,22 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                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 *********************************)
 
 open Instruct
-open Primitives
 
 (* Current frame number *)
 val current_frame : int ref
diff --git a/debugger/history.ml b/debugger/history.ml
index 4d08f587c8..0ece812b3e 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 121c732fb8..a184e7b99b 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 f3bd57b633..91f4cc5020 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 66db47f15f..e333c785d7 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 527bdcef0f..7f6df61842 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 5491c8f702..29d69bd170 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 7508bedd8f..41424dd2d4 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 721645c856..8570b152a8 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 }
   | "-"
@@ -71,7 +78,7 @@ and lexeme =    (* Read a lexeme *)
   | "."
       { DOT }
   | "#"
-      { SHARP }
+      { HASH }
   | "@"
       { AT }
   | "$"
diff --git a/debugger/loadprinter.ml b/debugger/loadprinter.ml
index 16d6e9f2b4..a1c2fcfed6 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 *)
 
@@ -20,7 +23,7 @@ open Types
 (* Error report *)
 
 type error =
-  | Load_failure of Dynlink.error
+  | Load_failure of Compdynlink.error
   | Unbound_identifier of Longident.t
   | Unavailable_module of string * Longident.t
   | Wrong_type of Longident.t
@@ -38,8 +41,8 @@ let use_debugger_symtable fn arg =
   let old_symtable = Symtable.current_state() in
   begin match !debugger_symtable with
   | None ->
-      Dynlink.init();
-      Dynlink.allow_unsafe_modules true;
+      Compdynlink.init();
+      Compdynlink.allow_unsafe_modules true;
       debugger_symtable := Some(Symtable.current_state())
   | Some st ->
       Symtable.restore_state st
@@ -60,7 +63,7 @@ open Format
 let rec loadfiles ppf name =
   try
     let filename = find_in_path !Config.load_path name in
-    use_debugger_symtable Dynlink.loadfile filename;
+    use_debugger_symtable Compdynlink.loadfile filename;
     let d = Filename.dirname name in
     if d <> Filename.current_dir_name then begin
       if not (List.mem d !Config.load_path) then
@@ -69,14 +72,17 @@ let rec loadfiles ppf name =
     fprintf ppf "File %s loaded@." filename;
     true
   with
-  | Dynlink.Error (Dynlink.Unavailable_unit unit) ->
+  | Compdynlink.Error (Compdynlink.Unavailable_unit unit) ->
       loadfiles ppf (String.uncapitalize_ascii unit ^ ".cmo")
         &&
       loadfiles ppf name
   | Not_found ->
       fprintf ppf "Cannot find file %s@." name;
       false
-  | Dynlink.Error e ->
+  | Sys_error msg ->
+      fprintf ppf "%s: %s@." name msg;
+      false
+  | Compdynlink.Error e ->
       raise(Error(Load_failure e))
 
 let loadfile ppf name =
@@ -88,8 +94,8 @@ let loadfile ppf name =
 
 let rec eval_path = function
     Pident id -> Symtable.get_global_value id
-  | Pdot(p, s, pos) -> Obj.field (eval_path p) pos
-  | Papply(p1, p2) -> fatal_error "Loadprinter.eval_path"
+  | Pdot(p, _, pos) -> Obj.field (eval_path p) pos
+  | Papply _ -> fatal_error "Loadprinter.eval_path"
 
 (* Install, remove a printer (as in toplevel/topdirs) *)
 
@@ -103,7 +109,7 @@ let () =
   ignore (Env.read_signature "Topdirs" topdirs)
 
 let match_printer_type desc typename =
-  let (printer_type, _) =
+  let printer_type =
     try
       Env.lookup_type (Ldot(Lident "Topdirs", typename)) Env.empty
     with Not_found ->
@@ -140,13 +146,13 @@ let install_printer ppf lid =
       raise(Error(Unavailable_module(s, lid))) in
   let print_function =
     if is_old_style then
-      (fun formatter repr -> Obj.obj v (Obj.obj repr))
+      (fun _formatter repr -> Obj.obj v (Obj.obj repr))
     else
       (fun formatter repr -> Obj.obj v formatter (Obj.obj repr)) in
   Printval.install_printer path ty_arg ppf print_function
 
 let remove_printer lid =
-  let (ty_arg, path, is_old_style) = find_printer_type lid in
+  let (_ty_arg, path, _is_old_style) = find_printer_type lid in
   try
     Printval.remove_printer path
   with Not_found ->
@@ -159,7 +165,7 @@ open Format
 let report_error ppf = function
   | Load_failure e ->
       fprintf ppf "@[Error during code loading: %s@]@."
-        (Dynlink.error_message e)
+        (Compdynlink.error_message e)
   | Unbound_identifier lid ->
       fprintf ppf "@[Unbound identifier %a@]@."
       Printtyp.longident lid
diff --git a/debugger/loadprinter.mli b/debugger/loadprinter.mli
index 4851a4d521..c645e8d211 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 *)
 
@@ -21,7 +24,7 @@ val remove_printer : Longident.t -> unit
 (* Error report *)
 
 type error =
-  | Load_failure of Dynlink.error
+  | Load_failure of Compdynlink.error
   | Unbound_identifier of Longident.t
   | Unavailable_module of string * Longident.t
   | Wrong_type of Longident.t
diff --git a/debugger/main.ml b/debugger/main.ml
index 60cd96a89a..b98676381a 100644
--- a/debugger/main.ml
+++ b/debugger/main.ml
@@ -1,4 +1,4 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                OCaml                                *)
 (*                                                                     *)
@@ -6,10 +6,13 @@
 (*          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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
@@ -26,7 +29,7 @@ open Primitives
 
 let line_buffer = Lexing.from_function read_user_input
 
-let rec loop ppf = line_loop ppf line_buffer
+let loop ppf = line_loop ppf line_buffer
 
 let current_duration = ref (-1L)
 
diff --git a/debugger/parameters.ml b/debugger/parameters.ml
index d8c85efe00..a4d647c498 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 *)
 
@@ -17,7 +20,6 @@ open Primitives
 open Config
 open Debugger_config
 
-let program_loaded = ref false
 let program_name = ref ""
 let socket_name = ref ""
 let arguments = ref ""
diff --git a/debugger/parameters.mli b/debugger/parameters.mli
index 44c850d5c7..388fb94d85 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 1d394e3452..36864b042f 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 %{
 
@@ -28,7 +31,7 @@ open Parser_aux
 %token          STAR                    /* *  */
 %token          MINUS                   /* -  */
 %token          DOT                     /* . */
-%token          SHARP                   /* #  */
+%token          HASH                    /* #  */
 %token          AT                      /* @  */
 %token          DOLLAR                  /* $ */
 %token          BANG                    /* ! */
@@ -235,7 +238,7 @@ break_argument_eol :
   | integer_eol                                 { BA_pc $1 }
   | expression end_of_line                      { BA_function $1 }
   | AT opt_longident INTEGER opt_integer_eol    { BA_pos1 ($2, (to_int $3), $4)}
-  | AT opt_longident SHARP integer_eol          { BA_pos2 ($2, $4) }
+  | AT opt_longident HASH integer_eol           { BA_pos2 ($2, $4) }
 ;
 
 /* Arguments for list */
diff --git a/debugger/parser_aux.mli b/debugger/parser_aux.mli
index 542affbd04..67c8446278 100644
--- a/debugger/parser_aux.mli
+++ b/debugger/parser_aux.mli
@@ -1,19 +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.               *)
-(*                                                                     *)
-(***********************************************************************)
-
-(*open Globals*)
-
-open Primitives
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 type expression =
     E_ident of Longident.t              (* x or Mod.x *)
diff --git a/debugger/pattern_matching.ml b/debugger/pattern_matching.ml
index 7b297869d7..f44d16ee47 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 71e88c0542..35b541e629 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 c9e93280d8..cc164e68da 100644
--- a/debugger/pos.ml
+++ b/debugger/pos.ml
@@ -1,20 +1,21 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                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;;
 open Location;;
-open Primitives;;
-open Source;;
 
 let get_desc ev =
   let loc = ev.ev_loc in
diff --git a/debugger/pos.mli b/debugger/pos.mli
index 4eacab788d..f5c376502c 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 8cbc5387cb..ac69513714 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 *********************)
 
@@ -92,23 +95,6 @@ let isprefix s1 s2 =
   let l1 = String.length s1 and l2 = String.length s2 in
   (l1 = l2 && s1 = s2) || (l1 < l2 && s1 = String.sub s2 0 l1)
 
-(* Split a string at the given delimiter char *)
-
-let split_string sep str =
-  let rec split i j =
-    if j >= String.length str then
-      if i >= j then [] else [String.sub str i (j-i)]
-    else if str.[j] = sep then
-      if i >= j
-      then skip_sep (j+1)
-      else String.sub str i (j-i) :: skip_sep (j+1)
-    else
-      split i (j+1)
-  and skip_sep j =
-    if j < String.length str && str.[j] = sep
-    then skip_sep (j+1)
-    else split j j
-  in split 0 0
 
 (*** I/O channels ***)
 
diff --git a/debugger/primitives.mli b/debugger/primitives.mli
index 0e36b414da..2be9032f9f 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 ***********************)
 
@@ -47,9 +50,6 @@ val string_trim : string -> string
 (* isprefix s1 s2 returns true if s1 is a prefix of s2. *)
 val isprefix : string -> string -> bool
 
-(* Split a string at the given delimiter char *)
-val split_string : char -> string -> string list
-
 (*** I/O channels ***)
 
 type io_channel = {
diff --git a/debugger/printval.ml b/debugger/printval.ml
index 5170ef3b24..1175a96c77 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 *)
 
@@ -37,7 +40,7 @@ let name_value v ty =
 let find_named_value name =
   Hashtbl.find named_values name
 
-let check_depth ppf depth obj ty =
+let check_depth depth obj ty =
   if depth <= 0 then begin
     let n = name_value obj ty in
     Some (Outcometree.Oval_stuff ("$" ^ string_of_int n))
@@ -54,19 +57,19 @@ module EvalPath =
         with Symtable.Error _ ->
           raise Error
         end
-    | Pdot(root, fieldname, pos) ->
+    | Pdot(root, _fieldname, pos) ->
         let v = eval_path env root in
         if not (Debugcom.Remote_value.is_block v)
         then raise Error
         else Debugcom.Remote_value.field v pos
-    | Papply(p1, p2) ->
+    | Papply _ ->
         raise Error
     let same_value = Debugcom.Remote_value.same
   end
 
 module Printer = Genprintval.Make(Debugcom.Remote_value)(EvalPath)
 
-let install_printer path ty ppf fn =
+let install_printer path ty _ppf fn =
   Printer.install_printer path ty
     (fun ppf remote_val ->
        try
@@ -87,7 +90,7 @@ let print_exception ppf obj =
 let print_value max_depth env obj (ppf : Format.formatter) ty =
   let t =
     Printer.outval_of_value !max_printer_steps max_depth
-      (check_depth ppf) env obj ty in
+      check_depth env obj ty in
   !Oprint.out_value ppf t
 
 let print_named_value max_depth exp env obj ppf ty =
diff --git a/debugger/printval.mli b/debugger/printval.mli
index ba6c25ad48..53c0ee4e41 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 1ebbd1e821..d804b88eb3 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 23ea47a600..cb4c216158 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 48118573ee..c8d81e434a 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 0b8a09b863..aca1cddcd6 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 f17227b9be..32daa640b4 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 d8e50ef9b8..75f22555da 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 690645dfe2..9e34b61c5f 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 45329be41d..88c51379fd 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 db2484f521..357132da72 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
@@ -20,18 +23,23 @@ open Source
 
 (* Print a line; return the beginning of the next line *)
 let print_line buffer line_number start point before =
-  let next = next_linefeed buffer start
+  let linefeed = next_linefeed buffer start
   and content = buffer_content buffer
   in
     printf "%i " line_number;
-    if point <= next && point >= start then
+    let line_end =
+      if linefeed > 0 && content.[linefeed - 1] = '\r' then
+        linefeed - 1
+      else
+        linefeed in
+    if point <= line_end && point >= start then
       (print_string (String.sub content start (point - start));
        print_string (if before then event_mark_before else event_mark_after);
-       print_string (String.sub content point (next - point)))
+       print_string (String.sub content point (line_end - point)))
     else
-      print_string (String.sub content start (next - start));
+      print_string (String.sub content start (line_end - start));
     print_newline ();
-    next
+    linefeed
 
 (* Tell Emacs we are nowhere in the source. *)
 let show_no_point () =
diff --git a/debugger/show_source.mli b/debugger/show_source.mli
index c1aa204efb..2d77caa800 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 fa2b3c7e46..cd2e9897f8 100644
--- a/debugger/source.ml
+++ b/debugger/source.ml
@@ -1,4 +1,4 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                OCaml                                *)
 (*                                                                     *)
@@ -6,10 +6,13 @@
 (*          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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 ****************************)
 
@@ -64,8 +67,6 @@ type buffer = string * (int * int) list ref
 
 let buffer_max_count = ref 10
 
-let cache_size = 30
-
 let buffer_list =
   ref ([] : (string * buffer) list)
 
@@ -98,7 +99,7 @@ let insert_pos buffer ((position, line) as pair) =
     function
       [] ->
         [(position, line)]
-    | ((pos, lin) as a::l) as l' ->
+    | ((_pos, lin) as a::l) as l' ->
         if lin < line then
           pair::l'
         else if lin = line then
@@ -138,13 +139,13 @@ let line_of_pos buffer position =
           raise Out_of_range
         else
           (0, 1)
-    | ((pos, line) as pair)::l ->
+    | ((pos, _line) as pair)::l ->
         if pos > position then
           find l
         else
           pair
   and find_line previous =
-    let (pos, line) as next = next_line buffer previous in
+    let (pos, _line) as next = next_line buffer previous in
       if pos <= position then
         find_line next
       else
@@ -163,7 +164,7 @@ let pos_of_line buffer line =
           raise Out_of_range
         else
           (0, 1)
-    | ((pos, lin) as pair)::l ->
+    | ((_pos, lin) as pair)::l ->
         if lin > line then
           find l
         else
diff --git a/debugger/source.mli b/debugger/source.mli
index 640ebc858a..119d6704a7 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 1be7253328..dd20d8f913 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) *)
 
@@ -59,7 +62,7 @@ let read_symbols' bytecode_file =
   let num_eventlists = input_binary_int ic in
   let dirs = ref StringSet.empty in
   let eventlists = ref [] in
-  for i = 1 to num_eventlists do
+  for _i = 1 to num_eventlists do
     let orig = input_binary_int ic in
     let evl = (input_value ic : debug_event list) in
     (* Relocate events in event list *)
@@ -179,7 +182,7 @@ let event_near_pos md char =
 (* Flip "event" bit on all instructions *)
 let set_all_events () =
   Hashtbl.iter
-    (fun pc ev ->
+    (fun _pc ev ->
        match ev.ev_kind with
          Event_pseudo -> ()
        | _            -> Debugcom.set_event ev.ev_pos)
diff --git a/debugger/symbols.mli b/debugger/symbols.mli
index 883b81aa3e..b1fc9d6f91 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 c55c754019..ec72413b07 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 ******************************)
 
@@ -268,7 +271,7 @@ let rec stop_on_event report =
         None   -> find_event ()
       | Some _ -> ()
       end
-  | {rep_type = Trap_barrier; rep_stack_pointer = trap_frame} ->
+  | {rep_type = Trap_barrier} ->
       (* No event at current position. *)
       find_event ()
   | _ ->
@@ -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 () =
@@ -447,7 +452,7 @@ let go_to time =
 
 (* Return the time of the last breakpoint *)
 (* between current time and `max_time'. *)
-let rec find_last_breakpoint max_time =
+let find_last_breakpoint max_time =
   let rec find break =
     let time = current_time () in
     step_forward (max_time -- time);
@@ -554,14 +559,14 @@ let next_1 () =
     None ->                             (* Beginning of the program. *)
       step _1
   | Some event1 ->
-      let (frame1, pc1) = initial_frame() in
+      let (frame1, _pc1) = initial_frame() in
       step _1;
       if not !interrupted then begin
         Symbols.update_current_event ();
         match !current_event with
           None -> ()
         | Some event2 ->
-            let (frame2, pc2) = initial_frame() in
+            let (frame2, _pc2) = initial_frame() in
             (* Call `finish' if we've entered a function. *)
             if frame1 >= 0 && frame2 >= 0 &&
                frame2 - event2.ev_stacksize > frame1 - event1.ev_stacksize
@@ -622,14 +627,14 @@ let previous_1 () =
     None ->                             (* End of the program. *)
       step _minus1
   | Some event1 ->
-      let (frame1, pc1) = initial_frame() in
+      let (frame1, _pc1) = initial_frame() in
       step _minus1;
       if not !interrupted then begin
         Symbols.update_current_event ();
         match !current_event with
           None -> ()
         | Some event2 ->
-            let (frame2, pc2) = initial_frame() in
+            let (frame2, _pc2) = initial_frame() in
             (* Call `start' if we've entered a function. *)
             if frame1 >= 0 && frame2 >= 0 &&
                frame2 - event2.ev_stacksize > frame1 - event1.ev_stacksize
diff --git a/debugger/time_travel.mli b/debugger/time_travel.mli
index 2d3523203a..e25bad9fcc 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 ce5fe7625f..33dfb04f21 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 239c12a657..7ff28631e9 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 8cefd37e0d..4771253b0d 100644
--- a/debugger/unix_tools.ml
+++ b/debugger/unix_tools.ml
@@ -1,21 +1,23 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                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 *************************************)
 
 open Misc
 open Unix
-open Primitives
 
 (*** Convert a socket name into a socket address. ***)
 let convert_address address =
diff --git a/debugger/unix_tools.mli b/debugger/unix_tools.mli
index b1ac62dbc5..db3af072cc 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/compdynlink.mlno b/driver/compdynlink.mlno
new file mode 100644
index 0000000000..d7d685bb70
--- /dev/null
+++ b/driver/compdynlink.mlno
@@ -0,0 +1,57 @@
+#2 "driver/compdynlink.mlno"
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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 *)
+
+type linking_error =
+    Undefined_global of string
+  | Unavailable_primitive of string
+  | Uninitialized_global of string
+
+type error =
+    Not_a_bytecode_file of string
+  | Inconsistent_import of string
+  | Unavailable_unit of string
+  | Unsafe_file
+  | Linking_error of string * linking_error
+  | Corrupted_interface of string
+  | File_not_found of string
+  | Cannot_open_dll of string
+  | Inconsistent_implementation of string
+
+exception Error of error
+
+let not_available _ =
+  failwith "No support for native dynlink on this OS"
+
+let default_available_units = not_available
+
+let init = not_available
+
+let loadfile = not_available
+let loadfile_private = not_available
+let allow_only = not_available
+let prohibit = not_available
+
+let digest_interface = not_available
+let add_interfaces = not_available
+let add_available_units = not_available
+let clear_available_units = not_available
+let allow_unsafe_modules = not_available
+let error_message = not_available
+
+let is_native = true
+let adapt_filename f = Filename.chop_extension f ^ ".cmxs"
diff --git a/driver/compenv.ml b/driver/compenv.ml
index 3f1729ebeb..5fa82d1b7d 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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' -> ()
     | _ ->
@@ -92,16 +96,17 @@ let module_of_filename ppf inputfile outputprefix =
   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 ',' *)
 exception SyntaxError of string
 
 let parse_args s =
-  let args = Misc.split s ',' in
+  let args = String.split_on_char ',' s in
   let rec iter is_after args before after =
     match args with
       [] ->
@@ -137,24 +142,51 @@ 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 load_plugin = ref (fun _ -> ())
+
+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_OCAMLPARAM ppf position =
-  try
-    let s = Sys.getenv "OCAMLPARAM" in
-    let (before, after) =
-      try
-        parse_args s
-      with SyntaxError s ->
-         Location.print_warning Location.none ppf
-           (Warnings.Bad_env_variable ("OCAMLPARAM", s));
-         [],[]
-    in
+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
-    List.iter (fun (name, v) ->
       match name with
       | "g" -> set "g" [ Clflags.debug ] v
       | "p" -> set "p" [ Clflags.gprofile ] v
@@ -173,6 +205,7 @@ let read_OCAMLPARAM ppf position =
       | "strict-sequence" -> set "strict-sequence" [ strict_sequence ] v
       | "strict-formats" -> set "strict-formats" [ strict_formats ] v
       | "thread" -> set "thread" [ use_threads ] v
+  | "unboxed-types" -> set "unboxed-types" [ unboxed_types ] v
       | "unsafe" -> set "unsafe" [ fast ] v
       | "verbose" -> set "verbose" [ verbose ] v
       | "nopervasives" -> set "nopervasives" [ nopervasives ] v
@@ -185,12 +218,15 @@ let read_OCAMLPARAM ppf position =
       | "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
       | "stack-slop" -> stack_slop := 8 * int_of_string v
 
+  | "clambda-checks" -> set "clambda-checks" [ clambda_checks ] v
+
       (* assembly sources *)
       |  "s" ->
         set "s" [ Clflags.keep_asm_file ; Clflags.keep_startup_file ] v
@@ -205,12 +241,102 @@ let read_OCAMLPARAM ppf position =
       | "wwe" ->               Warnings.parse_options false v
 
       (* inlining *)
-      | "inline" -> begin try
-          inline_threshold := 8 * int_of_string v
-        with _ ->
+  | "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",
-                                        "non-integer parameter for \"inline\""))
+           "bad value for \"color\", \
+            (expected \"auto\", \"always\" or \"never\")"))
+      | Some setting -> color := setting
         end
 
       | "intf-suffix" -> Config.interface_suffix := v
@@ -218,14 +344,14 @@ let read_OCAMLPARAM ppf position =
       | "I" -> begin
           match position with
           | Before_args -> first_include_dirs := v :: !first_include_dirs
-          | Before_link | Before_compile ->
+      | Before_link | Before_compile _ ->
             last_include_dirs := v :: !last_include_dirs
         end
 
       | "cclib" ->
         begin
           match position with
-          | Before_compile -> ()
+      | Before_compile _ -> ()
           | Before_link | Before_args ->
             ccobjs := Misc.rev_split_words v @ !ccobjs
         end
@@ -233,7 +359,7 @@ let read_OCAMLPARAM ppf position =
       | "ccopts" ->
         begin
           match position with
-          | Before_link | Before_compile ->
+      | Before_link | Before_compile _ ->
             last_ccopts := v :: !last_ccopts
           | Before_args ->
             first_ccopts := v :: !first_ccopts
@@ -242,7 +368,7 @@ let read_OCAMLPARAM ppf position =
       | "ppx" ->
         begin
           match position with
-          | Before_link | Before_compile ->
+      | Before_link | Before_compile _ ->
             last_ppx := v :: !last_ppx
           | Before_args ->
             first_ppx := v :: !first_ppx
@@ -253,7 +379,7 @@ let read_OCAMLPARAM ppf position =
         if not !native_code then
         begin
           match position with
-          | Before_link | Before_compile ->
+      | Before_link | Before_compile _ ->
             last_objfiles := v ::! last_objfiles
           | Before_args ->
             first_objfiles := v :: !first_objfiles
@@ -263,15 +389,23 @@ let read_OCAMLPARAM ppf position =
         if !native_code then
         begin
           match position with
-          | Before_link | Before_compile ->
+      | 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
+
+  | "plugin" -> !load_plugin v
+
       | _ ->
         if not (List.mem name !can_discard) then begin
           can_discard := name :: !can_discard;
@@ -279,19 +413,224 @@ let read_OCAMLPARAM ppf position =
             "Warning: discarding value of variable %S in OCAMLPARAM\n%!"
             name
         end
-    ) (match position with
+
+let read_OCAMLPARAM ppf position =
+  try
+    let s = Sys.getenv "OCAMLPARAM" in
+    let (before, after) =
+      try
+        parse_args s
+      with SyntaxError s ->
+         Location.print_warning Location.none ppf
+           (Warnings.Bad_env_variable ("OCAMLPARAM", s));
+         [],[]
+    in
+    List.iter (fun (name, v) -> read_one_param ppf position name v)
+      (match position with
         Before_args -> before
-      | Before_compile | Before_link -> after)
+       | 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
 
-let get_objfiles () =
+let get_objfiles ~with_ocamlparam =
+  if with_ocamlparam then
   List.rev (!last_objfiles @ !objfiles @ !first_objfiles)
+  else
+    List.rev !objfiles
+
+
+
+
+
+
+type deferred_action =
+  | ProcessImplementation of string
+  | ProcessInterface of string
+  | ProcessCFile of string
+  | ProcessOtherFile of string
+  | ProcessObjects of string list
+  | ProcessDLLs of string list
+
+let c_object_of_filename name =
+  Filename.chop_suffix (Filename.basename name) ".c" ^ Config.ext_obj
+
+let process_action
+    (ppf, implementation, interface, ocaml_mod_ext, ocaml_lib_ext) action =
+  match action with
+  | ProcessImplementation name ->
+      readenv ppf (Before_compile name);
+      let opref = output_prefix name in
+      implementation ppf name opref;
+      objfiles := (opref ^ ocaml_mod_ext) :: !objfiles
+  | ProcessInterface name ->
+      readenv ppf (Before_compile name);
+      let opref = output_prefix name in
+      interface ppf name opref;
+      if !make_package then objfiles := (opref ^ ".cmi") :: !objfiles
+  | ProcessCFile name ->
+      readenv ppf (Before_compile name);
+      Location.input_name := name;
+      if Ccomp.compile_file name <> 0 then exit 2;
+      ccobjs := c_object_of_filename name :: !ccobjs
+  | ProcessObjects names ->
+      ccobjs := names @ !ccobjs
+  | ProcessDLLs names ->
+      dllibs := names @ !dllibs
+  | ProcessOtherFile name ->
+      if Filename.check_suffix name ocaml_mod_ext
+      || Filename.check_suffix name ocaml_lib_ext then
+        objfiles := name :: !objfiles
+      else if Filename.check_suffix name ".cmi" && !make_package then
+        objfiles := name :: !objfiles
+      else if Filename.check_suffix name Config.ext_obj
+           || Filename.check_suffix name Config.ext_lib then
+        ccobjs := name :: !ccobjs
+      else if not !native_code && Filename.check_suffix name Config.ext_dll then
+        dllibs := name :: !dllibs
+      else
+        raise(Arg.Bad("don't know what to do with " ^ name))
+
+
+let action_of_file name =
+  if Filename.check_suffix name ".ml"
+  || Filename.check_suffix name ".mlt" then
+    ProcessImplementation name
+  else if Filename.check_suffix name !Config.interface_suffix then
+    ProcessInterface name
+  else if Filename.check_suffix name ".c" then
+    ProcessCFile name
+  else
+    ProcessOtherFile name
+
+let deferred_actions = ref []
+let defer action =
+  deferred_actions := action :: !deferred_actions
+
+let anonymous filename = defer (action_of_file filename)
+let impl filename = defer (ProcessImplementation filename)
+let intf filename = defer (ProcessInterface filename)
+
+let process_deferred_actions env =
+  let final_output_name = !output_name in
+  (* Make sure the intermediate products don't clash with the final one
+     when we're invoked like: ocamlopt -o foo bar.c baz.ml. *)
+  if not !compile_only then output_name := None;
+  begin
+    match final_output_name with
+    | None -> ()
+    | Some output_name ->
+        if !compile_only then begin
+          if List.filter (function
+              | ProcessCFile name -> c_object_of_filename name <> output_name
+              | _ -> false) !deferred_actions <> [] then
+            fatal "Options -c and -o are incompatible when compiling C files";
+
+          if List.length (List.filter (function
+              | ProcessImplementation _
+              | ProcessInterface _
+              | _ -> false) !deferred_actions) > 1 then
+            fatal "Options -c -o are incompatible with compiling multiple files"
+        end;
+  end;
+  if !make_archive && List.exists (function
+      | ProcessOtherFile name -> Filename.check_suffix name ".cmxa"
+      | _ -> false) !deferred_actions then
+    fatal "Option -a cannot be used with .cmxa input files.";
+  List.iter (process_action env) (List.rev !deferred_actions);
+  output_name := final_output_name;
diff --git a/driver/compenv.mli b/driver/compenv.mli
index 59cd10124f..4c0b147bcc 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
 
@@ -27,11 +30,18 @@ val first_include_dirs : string list ref
 val last_include_dirs : string list ref
 val implicit_modules : string list ref
 
+(* function to call on plugin=XXX *)
+val load_plugin : (string -> unit) ref
+
 (* return the list of objfiles, after OCAMLPARAM and List.rev *)
-val get_objfiles : unit -> string list
+val get_objfiles : with_ocamlparam:bool -> string list
+val last_objfiles : string list ref
+val first_objfiles : string list ref
+
+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
 
@@ -41,3 +51,28 @@ val is_unit_name : string -> bool
 (* [check_unit_name ppf filename name] prints a warning in [filename]
    on [ppf] if [name] should not be used as a module name. *)
 val check_unit_name : Format.formatter -> string -> string -> unit
+
+(* Deferred actions of the compiler, while parsing arguments *)
+
+type deferred_action =
+  | ProcessImplementation of string
+  | ProcessInterface of string
+  | ProcessCFile of string
+  | ProcessOtherFile of string
+  | ProcessObjects of string list
+  | ProcessDLLs of string list
+
+val c_object_of_filename : string -> string
+
+val defer : deferred_action -> unit
+val anonymous : string -> unit
+val impl : string -> unit
+val intf : string -> unit
+
+val process_deferred_actions :
+  Format.formatter *
+  (Format.formatter -> string -> string -> unit) * (* compile implementation *)
+  (Format.formatter -> string -> string -> unit) * (* compile interface *)
+  string * (* ocaml module extension *)
+  string -> (* ocaml library extension *)
+  unit
diff --git a/driver/compile.ml b/driver/compile.ml
index 9edfb80456..ec79879e94 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -29,9 +32,10 @@ let interface ppf sourcefile outputprefix =
   Env.set_unit_name modulename;
   let initial_env = Compmisc.initial_env () in
   let ast = Pparse.parse_interface ~tool_name ppf sourcefile in
+
   if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast;
   if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast;
-  let tsg = Typemod.type_interface initial_env ast in
+  let tsg = Typemod.type_interface sourcefile initial_env ast in
   if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg;
   let sg = tsg.sig_type in
   if !Clflags.print_types then
@@ -42,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
@@ -65,7 +72,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
@@ -73,20 +81,25 @@ let implementation ppf sourcefile outputprefix =
       Warnings.check_fatal ();
       Stypes.dump (Some (outputprefix ^ ".annot"))
     end else begin
-      let bytecode =
+      let bytecode, required_globals =
         (typedtree, coercion)
-        ++ 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.(time (Transl sourcefile))
+            (Translmod.transl_implementation modulename)
+        ++ Timings.(accumulate_time (Generate sourcefile))
+            (fun { Lambda.code = lambda; required_globals } ->
+              print_if ppf Clflags.dump_rawlambda Printlambda.lambda lambda
+              ++ Simplif.simplify_lambda sourcefile
+              ++ print_if ppf Clflags.dump_lambda Printlambda.lambda
+              ++ Bytegen.compile_implementation modulename
+              ++ print_if ppf Clflags.dump_instr Printinstr.instrlist
+              ++ fun bytecode -> bytecode, required_globals)
       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 ~required_globals);
         Warnings.check_fatal ();
         close_out oc;
         Stypes.dump (Some (outputprefix ^ ".annot"))
@@ -98,7 +111,3 @@ let implementation ppf sourcefile outputprefix =
   with x ->
     Stypes.dump (Some (outputprefix ^ ".annot"));
     raise x
-
-let c_file name =
-  Location.input_name := name;
-  if Ccomp.compile_file name <> 0 then exit 2
diff --git a/driver/compile.mli b/driver/compile.mli
index 00f9029a59..defc101be3 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 *)
 
@@ -16,4 +19,3 @@ open Format
 
 val interface: formatter -> string -> string -> unit
 val implementation: formatter -> string -> string -> unit
-val c_file: string -> unit
diff --git a/driver/compmisc.ml b/driver/compmisc.ml
index a2bc4b83a5..90a4699354 100644
--- a/driver/compmisc.ml
+++ b/driver/compmisc.ml
@@ -1,36 +1,40 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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
       "+vmthreads" :: !Clflags.include_dirs
     else
-      !last_include_dirs @
-      !Clflags.include_dirs @
-      !first_include_dirs
+      !Clflags.include_dirs
+  in
+  let dirs =
+    !last_include_dirs @ dirs @ Config.flexdll_dirs @ !first_include_dirs
   in
   let exp_dirs =
     List.map (Misc.expand_directory Config.standard_library) dirs in
-  Config.load_path := "" ::
+  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 032e9fe4aa..ade4761a00 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/compplugin.ml b/driver/compplugin.ml
new file mode 100644
index 0000000000..481692c14f
--- /dev/null
+++ b/driver/compplugin.ml
@@ -0,0 +1,49 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* A table to avoid double linking of plugins, especially with OCAMLPARAM *)
+let plugins = Hashtbl.create 13
+
+let load plugin_name =
+
+  let plugin_name =
+    try
+      Compdynlink.adapt_filename plugin_name
+    with Invalid_argument _ -> plugin_name
+  in
+
+  let plugin_file =
+    if Filename.is_implicit plugin_name then
+      try
+        Compmisc.init_path !Clflags.native_code;
+        Misc.find_in_path !Config.load_path plugin_name
+      with Not_found ->
+        raise (Compdynlink.Error (Compdynlink.File_not_found plugin_name))
+    else plugin_name
+  in
+
+  if not (Hashtbl.mem plugins plugin_file) then begin
+    Compdynlink.loadfile plugin_file;
+    Hashtbl.add plugins plugin_file (); (* plugin loaded *)
+  end
+
+let () =
+  Location.register_error_of_exn (function
+  | Compdynlink.Error error ->
+    Some (Location.error (
+      Printf.sprintf "%s while loading argument of -plugin"
+        (Compdynlink.error_message error)))
+  | _ -> None);
+  Compenv.load_plugin := load
diff --git a/driver/compplugin.mli b/driver/compplugin.mli
new file mode 100644
index 0000000000..a1103f64bf
--- /dev/null
+++ b/driver/compplugin.mli
@@ -0,0 +1,16 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+val load : string -> unit
diff --git a/driver/errors.ml b/driver/errors.ml
index bda1a30ac8..96fa0240b5 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 c9f1ee95bb..f5608931f6 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 e3c59c9e7f..ed6a965125 100644
--- a/driver/main.ml
+++ b/driver/main.ml
@@ -1,68 +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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 process_implementation_file ppf name =
-  let opref = output_prefix name in
-  Compile.implementation ppf name opref;
-  objfiles := (opref ^ ".cmo") :: !objfiles
-
-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
-  else if Filename.check_suffix name ".cmo"
-       || Filename.check_suffix name ".cma" then
-    objfiles := name :: !objfiles
-  else if Filename.check_suffix name ".cmi" && !make_package then
-    objfiles := name :: !objfiles
-  else if Filename.check_suffix name ext_obj
-       || Filename.check_suffix name ext_lib then
-    ccobjs := name :: !ccobjs
-  else if Filename.check_suffix name ext_dll then
-    dllibs := name :: !dllibs
-  else if Filename.check_suffix name ".c" then begin
-    Compile.c_file name;
-    ccobjs := (Filename.chop_suffix (Filename.basename name) ".c" ^ ext_obj)
-              :: !ccobjs
-  end
-  else
-    raise(Arg.Bad("don't know what to do with " ^ name))
-
 let usage = "Usage: ocamlc  \nOptions are:"
 
-let ppf = Format.err_formatter
-
 (* Error messages to standard error formatter *)
-let anonymous filename =
-  readenv ppf Before_compile; process_file ppf filename;;
-let impl filename =
-  readenv ppf Before_compile; process_implementation_file ppf filename;;
-let intf filename =
-  readenv ppf Before_compile; process_interface_file ppf filename;;
+let ppf = Format.err_formatter
 
 let show_config () =
   Config.print_config stdout;
@@ -78,13 +35,13 @@ module Options = Main_args.Make_bytecomp_options (struct
   let _binannot = set binary_annotations
   let _c = set compile_only
   let _cc s = c_compiler := Some s
-  let _cclib s = ccobjs := Misc.rev_split_words s @ !ccobjs
+  let _cclib s = Compenv.defer (ProcessObjects (Misc.rev_split_words s))
   let _ccopt s = first_ccopts := s :: !first_ccopts
   let _compat_32 = set bytecode_compatible_32
   let _config = show_config
   let _custom = set custom_runtime
   let _no_check_prims = set no_check_prims
-  let _dllib s = dllibs := Misc.rev_split_words s @ !dllibs
+  let _dllib s = defer (ProcessDLLs (Misc.rev_split_words s))
   let _dllpath s = dllpaths := !dllpaths @ [s]
   let _for_pack s = for_package := Some s
   let _g = set debug
@@ -94,34 +51,48 @@ 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 _plugin p = Compplugin.load p
   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 _unboxed_types = set unboxed_types
+  let _no_unboxed_types = unset unboxed_types
   let _unsafe = set fast
   let _unsafe_string = set unsafe_string
   let _use_prims s = use_prims := s
@@ -132,6 +103,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 +117,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)
 
@@ -148,6 +125,20 @@ let main () =
   try
     readenv ppf Before_args;
     Arg.parse Options.list anonymous usage;
+    begin try
+      Compenv.process_deferred_actions
+        (ppf,
+         Compile.implementation,
+         Compile.interface,
+         ".cmo",
+         ".cma");
+    with Arg.Bad msg ->
+      begin
+        prerr_endline msg;
+        Arg.usage Options.list usage;
+        exit 2
+      end
+    end;
     readenv ppf Before_link;
     if
       List.length (List.filter (fun x -> !x)
@@ -161,14 +152,15 @@ let main () =
     if !make_archive then begin
       Compmisc.init_path false;
 
-      Bytelibrarian.create_archive ppf  (Compenv.get_objfiles ())
+      Bytelibrarian.create_archive ppf
+                                   (Compenv.get_objfiles ~with_ocamlparam:false)
                                    (extract_output !output_name);
       Warnings.check_fatal ();
     end
     else if !make_package then begin
       Compmisc.init_path false;
       let extracted_output = extract_output !output_name in
-      let revd = get_objfiles () in
+      let revd = get_objfiles ~with_ocamlparam:false in
       Bytepackager.package_files ppf (Compmisc.initial_env ())
         revd (extracted_output);
       Warnings.check_fatal ();
@@ -191,16 +183,14 @@ let main () =
           default_output !output_name
       in
       Compmisc.init_path false;
-      Bytelink.link ppf (get_objfiles ()) target;
+      Bytelink.link ppf (get_objfiles ~with_ocamlparam:true) 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 b2176ff92f..ec43cbd7c9 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 61f18ed6af..c44e549b3c 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 =
+  "-no-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 "
 ;;
@@ -253,14 +385,34 @@ let mk_ppx f =
   "  Pipe abstract syntax trees through preprocessor "
 ;;
 
+let mk_plugin f =
+  "-plugin", Arg.String f,
+  "  Load dynamic plugin "
+;;
+
 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"
@@ -271,7 +423,9 @@ let mk_S f =
 ;;
 
 let mk_safe_string f =
-  "-safe-string", Arg.Unit f, " Make strings immutable"
+  "-safe-string", Arg.Unit f,
+  if Config.safe_string then " Make strings immutable (default)"
+  else " Make strings immutable"
 ;;
 
 let mk_shared f =
@@ -290,6 +444,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"
@@ -300,12 +459,46 @@ 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_unboxed_types f =
+  "-unboxed-types", Arg.Unit f,
+  " unannotated unboxable types will be unboxed"
+;;
+
+let mk_no_unboxed_types f =
+  "-no-unboxed-types", Arg.Unit f,
+  " unannotated unboxable types will not be unboxed (default)"
+;;
+
 let mk_unsafe f =
   "-unsafe", Arg.Unit f,
   " Do not compile bounds checking on array and string access"
 ;;
 
 let mk_unsafe_string f =
+  if Config.safe_string then
+    let err () =
+      raise (Arg.Bad "OCaml has been configured with -safe-string: \
+                      -unsafe-string is not available")
+    in
+    "-unsafe-string", Arg.Unit err, " (option not available)"
+  else
   "-unsafe-string", Arg.Unit f, " Make strings mutable (default)"
 ;;
 
@@ -332,6 +525,14 @@ 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_no_version f =
+  "-no-version", Arg.Unit f, " Do not print version at startup"
+;;
+
 let mk_vmthread f =
   "-vmthread", Arg.Unit f,
   " Generate code that supports the threads library with VM-level\n\
@@ -368,6 +569,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"
 ;;
@@ -400,10 +614,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)"
 ;;
@@ -475,8 +716,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 =
@@ -488,7 +737,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
@@ -496,11 +747,17 @@ 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 _unboxed_types : unit -> unit
+  val _no_unboxed_types : unit -> unit
   val _unsafe : unit -> unit
   val _unsafe_string : unit -> unit
   val _version : unit -> unit
@@ -516,7 +773,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
@@ -534,15 +791,20 @@ 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 _plugin : string -> 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
@@ -551,7 +813,22 @@ 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
+;;
+
+module type Toplevel_options = sig
+  include Common_options
+  val _init : string -> unit
+  val _noinit : unit -> unit
+  val _no_version : unit -> unit
+  val _noprompt : unit -> unit
+  val _nopromptcont : unit -> unit
+  val _plugin : string -> unit
+  val _stdin : unit -> unit
 end
 ;;
 
@@ -573,20 +850,42 @@ module type Bytecomp_options = sig
 end;;
 
 module type Bytetop_options = sig
-  include Common_options
-  val _init : string -> unit
-  val _noinit : unit -> unit
-  val _noprompt : unit -> unit
-  val _nopromptcont : unit -> unit
-  val _stdin : unit -> unit
-
+  include Toplevel_options
   val _dinstr : unit -> unit
 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
@@ -619,14 +918,10 @@ module type Optcomp_options = sig
 end;;
 
 module type Opttop_options = sig
-  include Common_options
+  include Toplevel_options
   include Optcommon_options
-  val _init : string -> unit
-  val _noinit : unit -> unit
-  val _noprompt : unit -> unit
-  val _nopromptcont : unit -> unit
+  val _verbose : unit -> unit
   val _S : unit -> unit
-  val _stdin : unit -> unit
 end;;
 
 module type Ocamldoc_options = sig
@@ -643,7 +938,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
@@ -660,6 +955,7 @@ 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;
@@ -676,13 +972,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;
@@ -690,20 +990,28 @@ 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;
     mk_pack_byt F._pack;
     mk_pp F._pp;
     mk_ppx F._ppx;
+    mk_plugin F._plugin;
     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_unboxed_types F._unboxed_types;
+    mk_no_unboxed_types F._no_unboxed_types;
     mk_unsafe F._unsafe;
     mk_unsafe_string F._unsafe_string;
     mk_use_runtime F._use_runtime;
@@ -711,6 +1019,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;
@@ -727,6 +1036,7 @@ struct
     mk_drawlambda F._drawlambda;
     mk_dlambda F._dlambda;
     mk_dinstr F._dinstr;
+    mk_dtimings F._dtimings;
   ]
 end;;
 
@@ -737,7 +1047,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;
@@ -747,16 +1059,25 @@ struct
     mk_nostdlib F._nostdlib;
     mk_open F._open;
     mk_ppx F._ppx;
+    mk_plugin F._plugin;
     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_unboxed_types F._unboxed_types;
+    mk_no_unboxed_types F._no_unboxed_types;
     mk_unsafe F._unsafe;
     mk_unsafe_string F._unsafe_string;
     mk_version F._version;
+    mk__version F._version;
+    mk_no_version F._no_version;
     mk_vnum F._vnum;
     mk_w F._w;
     mk_warn_error F._warn_error;
@@ -779,10 +1100,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;
@@ -792,13 +1117,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;
@@ -806,16 +1144,26 @@ 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;
     mk_p F._p;
     mk_pack_opt F._pack;
+    mk_plugin F._plugin;
     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;
@@ -823,13 +1171,21 @@ struct
     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_unboxed_types F._unboxed_types;
+    mk_no_unboxed_types F._no_unboxed_types;
     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;
@@ -843,7 +1199,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;
@@ -858,7 +1220,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;;
 
@@ -869,8 +1232,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;
@@ -878,19 +1255,36 @@ 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_plugin F._plugin;
     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_unboxed_types F._unboxed_types;
+    mk_no_unboxed_types F._no_unboxed_types;
     mk_unsafe F._unsafe;
     mk_unsafe_string F._unsafe_string;
+    mk_verbose F._verbose;
     mk_version F._version;
+    mk__version F._version;
+    mk_no_version F._no_version;
     mk_vnum F._vnum;
     mk_w F._w;
     mk_warn_error F._warn_error;
@@ -901,7 +1295,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;
@@ -916,6 +1313,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;;
 
@@ -930,7 +1328,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;
@@ -939,16 +1339,23 @@ 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_unboxed_types F._unboxed_types;
+    mk_no_unboxed_types F._no_unboxed_types;
     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 601444f32a..cefd7c8952 100644
--- a/driver/main_args.mli
+++ b/driver/main_args.mli
@@ -1,14 +1,20 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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. *)
 
 (* 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 +23,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 +33,17 @@ 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 _unboxed_types : unit -> unit
+  val _no_unboxed_types : unit -> unit
   val _unsafe : unit -> unit
   val _unsafe_string : unit -> unit
   val _version : unit -> unit
@@ -45,7 +59,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
@@ -63,15 +77,20 @@ 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 _plugin : string -> 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 +99,22 @@ 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
+;;
+
+module type Toplevel_options = sig
+  include Common_options
+  val _init : string -> unit
+  val _noinit : unit -> unit
+  val _no_version : unit -> unit
+  val _noprompt : unit -> unit
+  val _nopromptcont : unit -> unit
+  val _plugin : string -> unit
+  val _stdin : unit -> unit
 end
 ;;
 
@@ -103,20 +136,42 @@ module type Bytecomp_options = sig
 end;;
 
 module type Bytetop_options = sig
-  include Common_options
-  val _init : string -> unit
-  val _noinit : unit -> unit
-  val _noprompt : unit -> unit
-  val _nopromptcont : unit -> unit
-  val _stdin : unit -> unit
-
+  include Toplevel_options
   val _dinstr : unit -> unit
 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
@@ -149,14 +204,10 @@ module type Optcomp_options = sig
 end;;
 
 module type Opttop_options = sig
-  include Common_options
+  include Toplevel_options
   include Optcommon_options
-  val _init : string -> unit
-  val _noinit : unit -> unit
-  val _noprompt : unit -> unit
-  val _nopromptcont : unit -> unit
+  val _verbose : unit -> unit
   val _S : unit -> unit
-  val _stdin : unit -> unit
 end;;
 
 module type Ocamldoc_options =  sig
@@ -173,7 +224,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 fc0a8e113f..fb011c8b70 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 9a5f3b9357..1814ba14da 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -32,7 +35,7 @@ let interface ppf sourcefile outputprefix =
   let ast = Pparse.parse_interface ~tool_name ppf sourcefile in
   if !Clflags.dump_parsetree then fprintf ppf "%a@." Printast.interface ast;
   if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.signature ast;
-  let tsg = Typemod.type_interface initial_env ast in
+  let tsg = Typemod.type_interface sourcefile initial_env ast in
   if !Clflags.dump_typedtree then fprintf ppf "%a@." Printtyped.interface tsg;
   let sg = tsg.sig_type in
   if !Clflags.print_types then
@@ -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 ~backend ppf sourcefile outputprefix =
+  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,57 @@ 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
     in
     if not !Clflags.print_types then begin
-      (typedtree, coercion)
-      ++ Translmod.transl_store_implementation modulename
+      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))
+        ++ Timings.time (Timings.Generate sourcefile)
+          (fun { Lambda.module_ident; main_module_block_size;
+                 required_globals; code } ->
+          ((module_ident, main_module_block_size), code)
       +++ print_if ppf Clflags.dump_rawlambda Printlambda.lambda
-      +++ Simplif.simplify_lambda
+          +++ Simplif.simplify_lambda sourcefile
       +++ print_if ppf Clflags.dump_lambda Printlambda.lambda
-      ++ Asmgen.compile_implementation outputprefix ppf;
-      Compilenv.save_unit_info cmxfile;
+          ++ (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 ~required_globals ~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 program ->
+              { program with
+                Lambda.code = Simplif.simplify_lambda sourcefile
+                  program.Lambda.code }
+              ++ 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"))
@@ -92,6 +138,3 @@ let implementation ppf sourcefile outputprefix =
     remove_file objfile;
     remove_file cmxfile;
     raise x
-
-let c_file name =
-  if Ccomp.compile_file name <> 0 then exit 2
diff --git a/driver/optcompile.mli b/driver/optcompile.mli
index 00f9029a59..3f3081383d 100644
--- a/driver/optcompile.mli
+++ b/driver/optcompile.mli
@@ -1,19 +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 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 c_file: string -> unit
+
+val implementation:
+   backend:(module Backend_intf.S)
+   -> formatter
+  -> string
+  -> string
+  -> unit
diff --git a/driver/opterrors.ml b/driver/opterrors.ml
index bda1a30ac8..96fa0240b5 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 6267091bd1..75827239a1 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 f0827a0b6c..f451ab5aab 100644
--- a/driver/optmain.ml
+++ b/driver/optmain.ml
@@ -1,68 +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 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
-open Config
 open Clflags
 open Compenv
 
-let process_interface_file ppf name =
-  Optcompile.interface ppf name (output_prefix name)
+module Backend = struct
+  (* See backend_intf.mli. *)
 
-let process_implementation_file ppf name =
-  let opref = output_prefix name in
-  Optcompile.implementation ppf name opref;
-  objfiles := (opref ^ ".cmx") :: !objfiles
+  let symbol_for_global' = Compilenv.symbol_for_global'
+  let closure_symbol = Compilenv.closure_symbol
 
-let cmxa_present = ref false;;
+  let really_import_approx = Import_approx.really_import_approx
+  let import_symbol = Import_approx.import_symbol
 
-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 ".cmx" then
-    objfiles := name :: !objfiles
-  else if Filename.check_suffix name ".cmxa" then begin
-    cmxa_present := true;
-    objfiles := name :: !objfiles
-  end else if Filename.check_suffix name ".cmi" && !make_package then
-    objfiles := name :: !objfiles
-  else if Filename.check_suffix name ext_obj
-       || Filename.check_suffix name ext_lib then
-    ccobjs := name :: !ccobjs
-  else if Filename.check_suffix name ".c" then begin
-    Optcompile.c_file name;
-    ccobjs := (Filename.chop_suffix (Filename.basename name) ".c" ^ ext_obj)
-              :: !ccobjs
+  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
-  else
-    raise(Arg.Bad("don't know what to do with " ^ name))
+let backend = (module Backend : Backend_intf.S)
 
 let usage = "Usage: ocamlopt  \nOptions are:"
 
-let ppf = Format.err_formatter
-
-(* Error messages to standard error formatter *)
-let anonymous filename =
-  readenv ppf Before_compile; process_file ppf filename;;
-let impl filename =
-  readenv ppf Before_compile; process_implementation_file ppf filename;;
-let intf filename =
-  readenv ppf Before_compile; process_interface_file ppf filename;;
-
 let show_config () =
   Config.print_config stdout;
   exit 0;
@@ -78,8 +51,9 @@ module Options = Main_args.Make_optcomp_options (struct
   let _binannot = set binary_annotations
   let _c = set compile_only
   let _cc s = c_compiler := Some s
-  let _cclib s = ccobjs := Misc.rev_split_words s @ !ccobjs
+  let _cclib s = defer (ProcessObjects (Misc.rev_split_words s))
   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 +61,64 @@ 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
+      "Syntax: -inline  | =[,...]"  inline_threshold
+  let _inline_toplevel spec =
+    Int_arg_helper.parse spec
+      "Syntax: -inline-toplevel  | =[,...]"
+      inline_toplevel_threshold
+  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
+      "Syntax: -inline-max-unroll  | =[,...]"
+      inline_max_unroll
+  let _classic_inlining () = classic_inlining := true
+  let _inline_call_cost spec =
+    Int_arg_helper.parse spec
+      "Syntax: -inline-call-cost  | =[,...]"
+      inline_call_cost
+  let _inline_alloc_cost spec =
+    Int_arg_helper.parse spec
+      "Syntax: -inline-alloc-cost  | =[,...]"
+       inline_alloc_cost
+  let _inline_prim_cost spec =
+    Int_arg_helper.parse spec
+      "Syntax: -inline-prim-cost  | =[,...]"
+       inline_prim_cost
+  let _inline_branch_cost spec =
+    Int_arg_helper.parse spec
+      "Syntax: -inline-branch-cost  | =[,...]"
+       inline_branch_cost
+  let _inline_indirect_cost spec =
+    Int_arg_helper.parse spec
+      "Syntax: -inline-indirect-cost  | =[,...]"
+       inline_indirect_cost
+  let _inline_lifting_benefit spec =
+    Int_arg_helper.parse spec
+      "Syntax: -inline-lifting-benefit  | =[,...]"
+      inline_lifting_benefit
+  let _inline_branch_factor spec =
+    Float_arg_helper.parse spec
+      "Syntax: -inline-branch-factor  | =[,...]"
+       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
+      "Syntax: -inline-max-depth  | =[,...]"
+       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,26 +126,56 @@ 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 _stack_slop n = stack_slop := n * 8
   let _pack = set make_package
+  let _plugin p = Compplugin.load p
   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 _unboxed_types = set unboxed_types
+  let _no_unboxed_types = clear unboxed_types
   let _unsafe = set fast
   let _unsafe_string = set unsafe_string
   let _v () = print_version_and_library "native-code compiler"
@@ -131,6 +185,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
@@ -139,7 +198,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
@@ -154,6 +221,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
@@ -164,7 +232,22 @@ let main () =
   let ppf = Format.err_formatter in
   try
     readenv ppf Before_args;
-    Arg.parse (Arch.command_line_options @ Options.list) anonymous usage;
+    let spec = Arch.command_line_options @ Options.list in
+    Arg.parse spec anonymous usage;
+    begin try
+      Compenv.process_deferred_actions
+        (ppf,
+         Optcompile.implementation ~backend,
+         Optcompile.interface,
+         ".cmx",
+         ".cmxa");
+    with Arg.Bad msg ->
+      begin
+        prerr_endline msg;
+        Arg.usage spec usage;
+        exit 2
+      end
+    end;
     readenv ppf Before_link;
     if
       List.length (List.filter (fun x -> !x)
@@ -173,24 +256,22 @@ let main () =
     then
       fatal "Please specify at most one of -pack, -a, -shared, -c, -output-obj";
     if !make_archive then begin
-      if !cmxa_present then
-        fatal "Option -a cannot be used with .cmxa input files.";
       Compmisc.init_path true;
       let target = extract_output !output_name in
-      Asmlibrarian.create_archive (get_objfiles ()) target;
+      Asmlibrarian.create_archive (get_objfiles ~with_ocamlparam:false) target;
       Warnings.check_fatal ();
     end
     else if !make_package then begin
       Compmisc.init_path true;
       let target = extract_output !output_name in
       Asmpackager.package_files ppf (Compmisc.initial_env ())
-        (get_objfiles ()) target;
+        (get_objfiles ~with_ocamlparam:false) target ~backend;
       Warnings.check_fatal ();
     end
     else if !shared then begin
       Compmisc.init_path true;
       let target = extract_output !output_name in
-      Asmlink.link_shared ppf (get_objfiles ()) target;
+      Asmlink.link_shared ppf (get_objfiles ~with_ocamlparam:false) target;
       Warnings.check_fatal ();
     end
     else if not !compile_only && !objfiles <> [] then begin
@@ -210,12 +291,14 @@ let main () =
           default_output !output_name
       in
       Compmisc.init_path true;
-      Asmlink.link ppf (get_objfiles ()) target;
+      Asmlink.link ppf (get_objfiles ~with_ocamlparam:true) 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 d43cb760fb..f0911ceaf9 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 b67c1805d3..26574eaf30 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 =
@@ -42,20 +47,26 @@ let remove_preprocessed inputfile =
     None -> ()
   | Some _ -> Misc.remove_file inputfile
 
+type 'a ast_kind =
+| Structure : Parsetree.structure ast_kind
+| Signature : Parsetree.signature ast_kind
+
+let magic_of_kind : type a . a ast_kind -> string = function
+  | Structure -> Config.ast_impl_magic_number
+  | Signature -> Config.ast_intf_magic_number
 
 (* Note: some of the functions here should go to Ast_mapper instead,
    which would encapsulate the "binary AST" protocol. *)
 
-let write_ast magic ast =
-  let fn = Filename.temp_file "camlppx" "" in
+let write_ast (type a) (kind : a ast_kind) fn (ast : a) =
   let oc = open_out_bin fn in
-  output_string oc magic;
-  output_value oc !Location.input_name;
-  output_value oc ast;
-  close_out oc;
-  fn
+  output_string oc (magic_of_kind kind);
+  output_value oc (!Location.input_name : string);
+  output_value oc (ast : a);
+  close_out oc
 
-let apply_rewriter magic fn_in ppx =
+let apply_rewriter kind fn_in ppx =
+  let magic = magic_of_kind kind in
   let fn_out = Filename.temp_file "camlppx" "" in
   let comm =
     Printf.sprintf "%s %s %s" ppx (Filename.quote fn_in) (Filename.quote fn_out)
@@ -79,13 +90,14 @@ let apply_rewriter magic fn_in ppx =
   end;
   fn_out
 
-let read_ast magic fn =
+let read_ast (type a) (kind : a ast_kind) fn : a =
   let ic = open_in_bin fn in
   try
+    let magic = magic_of_kind kind in
     let buffer = really_input_string ic (String.length magic) in
     assert(buffer = magic); (* already checked by apply_rewriter *)
-    Location.input_name := input_value ic;
-    let ast = input_value ic in
+    Location.input_name := (input_value ic : string);
+    let ast = (input_value ic : a) in
     close_in ic;
     Misc.remove_file fn;
     ast
@@ -94,34 +106,37 @@ let read_ast magic fn =
     Misc.remove_file fn;
     raise exn
 
-let rewrite magic ast ppxs =
-  read_ast magic
-    (List.fold_left (apply_rewriter magic) (write_ast magic ast)
-       (List.rev ppxs))
+let rewrite kind ppxs ast =
+  let fn = Filename.temp_file "camlppx" "" in
+  write_ast kind fn ast;
+  let fn = List.fold_left (apply_rewriter kind) fn (List.rev ppxs) in
+  read_ast kind fn
 
 let apply_rewriters_str ?(restore = true) ~tool_name ast =
   match !Clflags.all_ppx with
   | [] -> ast
   | ppxs ->
-      let ast = Ast_mapper.add_ppx_context_str ~tool_name ast in
-      let ast = rewrite Config.ast_impl_magic_number ast ppxs in
-      Ast_mapper.drop_ppx_context_str ~restore ast
+      ast
+      |> Ast_mapper.add_ppx_context_str ~tool_name
+      |> rewrite Structure ppxs
+      |> Ast_mapper.drop_ppx_context_str ~restore
 
 let apply_rewriters_sig ?(restore = true) ~tool_name ast =
   match !Clflags.all_ppx with
   | [] -> ast
   | ppxs ->
-      let ast = Ast_mapper.add_ppx_context_sig ~tool_name ast in
-      let ast = rewrite Config.ast_intf_magic_number ast ppxs in
-      Ast_mapper.drop_ppx_context_sig ~restore ast
-
-let apply_rewriters ?restore ~tool_name magic ast =
-  if magic = Config.ast_impl_magic_number then
-    Obj.magic (apply_rewriters_str ?restore ~tool_name (Obj.magic ast))
-  else if magic = Config.ast_intf_magic_number then
-    Obj.magic (apply_rewriters_sig ?restore ~tool_name (Obj.magic ast))
-  else
-    assert false
+      ast
+      |> Ast_mapper.add_ppx_context_sig ~tool_name
+      |> rewrite Signature ppxs
+      |> Ast_mapper.drop_ppx_context_sig ~restore
+
+let apply_rewriters ?restore ~tool_name
+    (type a) (kind : a ast_kind) (ast : a) : a =
+  match kind with
+  | Structure ->
+      apply_rewriters_str ?restore ~tool_name ast
+  | Signature ->
+      apply_rewriters_sig ?restore ~tool_name ast
 
 (* Parse a file or get a dumped syntax tree from it *)
 
@@ -143,7 +158,14 @@ let open_and_check_magic inputfile ast_magic =
   in
   (ic, is_ast_file)
 
-let file ppf ~tool_name inputfile parse_fun ast_magic =
+let parse (type a) (kind : a ast_kind) lexbuf : a =
+  match kind with
+  | Structure -> Parse.implementation lexbuf
+  | Signature -> Parse.interface lexbuf
+
+let file_aux ppf ~tool_name inputfile (type a) parse_fun invariant_fun
+             (kind : a ast_kind) =
+  let ast_magic = magic_of_kind kind in
   let (ic, is_ast_file) = open_and_check_magic inputfile ast_magic in
   let ast =
     try
@@ -152,8 +174,8 @@ let file ppf ~tool_name inputfile parse_fun ast_magic =
           (* FIXME make this a proper warning *)
           fprintf ppf "@[Warning: %s@]@."
             "option -unsafe used with a preprocessor returning a syntax tree";
-        Location.input_name := input_value ic;
-        input_value ic
+        Location.input_name := (input_value ic : string);
+        (input_value ic : a)
       end else begin
         seek_in ic 0;
         Location.input_name := inputfile;
@@ -164,8 +186,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 kind ast in
+  if is_ast_file || !Clflags.all_ppx <> [] then invariant_fun ast;
+  ast
 
+let file ppf ~tool_name inputfile parse_fun ast_kind =
+  file_aux ppf ~tool_name inputfile parse_fun ignore ast_kind
 
 let report_error ppf = function
   | CannotRun cmd ->
@@ -182,21 +208,30 @@ let () =
       | _ -> None
     )
 
-let parse_all ~tool_name parse_fun magic ppf sourcefile =
+let parse_file ~tool_name invariant_fun apply_hooks kind ppf sourcefile =
   Location.input_name := sourcefile;
   let inputfile = preprocess sourcefile in
   let ast =
-    try file ppf ~tool_name inputfile parse_fun magic
+    let parse_fun = Timings.(time (Parsing sourcefile)) (parse kind) in
+    try file_aux ppf ~tool_name inputfile parse_fun invariant_fun kind
     with exn ->
       remove_preprocessed inputfile;
       raise exn
   in
   remove_preprocessed inputfile;
+  let ast = apply_hooks { Misc.sourcefile } ast in
   ast
 
+module ImplementationHooks = Misc.MakeHooks(struct
+    type t = Parsetree.structure
+  end)
+module InterfaceHooks = Misc.MakeHooks(struct
+    type t = Parsetree.signature
+  end)
+
 let parse_implementation ppf ~tool_name sourcefile =
-  parse_all ~tool_name Parse.implementation
-    Config.ast_impl_magic_number ppf sourcefile
+  parse_file ~tool_name Ast_invariants.structure
+    ImplementationHooks.apply_hooks Structure ppf sourcefile
 let parse_interface ppf ~tool_name sourcefile =
-  parse_all ~tool_name Parse.interface
-    Config.ast_intf_magic_number ppf sourcefile
+  parse_file ~tool_name Ast_invariants.signature
+    InterfaceHooks.apply_hooks Signature ppf sourcefile
diff --git a/driver/pparse.mli b/driver/pparse.mli
index 6497698939..9491ad2139 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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,22 +23,40 @@ 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 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. *)
 
-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
+type 'a ast_kind =
+| Structure : Parsetree.structure ast_kind
+| Signature : Parsetree.signature ast_kind
 
+val read_ast : 'a ast_kind -> string -> 'a
+val write_ast : 'a ast_kind -> string -> 'a -> unit
+
+val file : formatter -> tool_name:string -> string ->
+  (Lexing.lexbuf -> 'a) -> 'a ast_kind -> 'a
+
+val apply_rewriters: ?restore:bool -> tool_name:string ->
+  'a ast_kind -> 'a -> 'a
+  (** 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 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
 val open_and_check_magic : string -> string -> in_channel * bool
-val read_ast : string -> string -> 'a
+
+module ImplementationHooks : Misc.HookSig with type t = Parsetree.structure
+module InterfaceHooks : Misc.HookSig with type t = Parsetree.signature
diff --git a/emacs/.ignore b/emacs/.ignore
deleted file mode 100644
index ba5f96cd34..0000000000
--- a/emacs/.ignore
+++ /dev/null
@@ -1,2 +0,0 @@
-ocamltags
-*.elc
diff --git a/emacs/Makefile b/emacs/Makefile
index 22b2a19bae..93b2d7d738 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 a5cff879ea..782d2d47f8 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 7166d1a878..13f72c46b9 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 7456e8c583..674beb680c 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 40bee0a3a8..ac339744f0 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 82defadc01..6b1abc653b 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 13735594fd..03d6465c52 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 0af667bdd2..36fcb030b3 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.
 
@@ -19,6 +21,12 @@
       (require 'caml-xemacs)
     (require 'caml-emacs)))
 
+(defun caml-types-feedback (info format)
+  "Displays INFO using the given FORMAT."
+  (message (format format info))
+  (with-current-buffer caml-types-buffer
+    (erase-buffer)
+    (insert info)))
 
 (defvar caml-types-build-dirs '("_build" "_obuild")
   "List of possible compilation directories created by build systems.
@@ -63,8 +71,7 @@ Their format is:
   and second nums.
 
 The current list of keywords is:
-type call ident"
-)
+type call ident")
 
 (defvar caml-types-position-re nil)
 
@@ -125,24 +132,25 @@ type call ident"
 (make-variable-buffer-local 'caml-types-annotation-date)
 
 (defvar caml-types-buffer-name "*caml-types*"
-  "Name of buffer for displaying caml types")
+  "Name of buffer for displaying caml types.")
 (defvar caml-types-buffer nil
-  "buffer for displaying caml types")
+  "Buffer for displaying caml types.")
 
 (defun caml-types-show-type (arg)
   "Show the type of expression or pattern at point.
+
    The smallest expression or pattern that contains point is
    temporarily highlighted.  Its type is highlighted in the .annot
-   file and the mark is set to the beginning of the type.
-   The type is also displayed in the mini-buffer.
+file and the mark is set to the beginning of the type.  The type
+is also displayed in the mini-buffer.
 
    Hints on using the type display:
    . If you want the type of an identifier, put point within any
      occurrence of this identifier.
-   . If you want the result type of a function application, put point
-     at the first space after the function name.
-   . If you want the type of a list, put point on a bracket, on a
-     semicolon, or on the :: constructor.
+. If you want the result type of a function application, put
+point at the first space after the function name.  . If you want
+the type of a list, put point on a bracket, on a semicolon, or on
+the :: constructor.
    . Even if type checking fails, you can still look at the types
      in the file, up to where the type checker failed.
 
@@ -150,8 +158,7 @@ Types are also displayed in the buffer *caml-types*, which is
 displayed when the command is called with Prefix argument 4.
 
 See also `caml-types-explore' for exploration by mouse dragging.
-See `caml-types-location-re' for annotation file format.
-"
+See `caml-types-location-re' for annotation file format."
   (interactive "p")
   (let* ((target-buf (current-buffer))
          (target-file (file-name-nondirectory (buffer-file-name)))
@@ -173,31 +180,26 @@ See `caml-types-location-re' for annotation file format.
               (right (caml-types-get-pos target-buf (elt node 1)))
               (type (cdr (assoc "type" (elt node 2)))))
           (move-overlay caml-types-expr-ovl left right target-buf)
-          (with-current-buffer caml-types-buffer
-            (erase-buffer)
-            (insert type)
-            (message (format "type: %s" type)))
-          ))))
+          (caml-types-feedback type "type: %s")))))
     (if (and (= arg 4)
              (not (window-live-p (get-buffer-window caml-types-buffer))))
         (display-buffer caml-types-buffer))
     (unwind-protect
         (caml-sit-for 60)
-      (delete-overlay caml-types-expr-ovl)
-      )))
+      (delete-overlay caml-types-expr-ovl))))
 
 (defun caml-types-show-call (arg)
   "Show the kind of call at point.
-   The smallest function call that contains point is
-   temporarily highlighted.  Its kind is highlighted in the .annot
-   file and the mark is set to the beginning of the kind.
-   The kind is also displayed in the mini-buffer.
+
+The smallest function call that contains point is temporarily
+highlighted.  Its kind is highlighted in the .annot file and the
+mark is set to the beginning of the kind.  The kind is also
+displayed in the mini-buffer.
 
 The kind is also displayed in the buffer *caml-types*, which is
 displayed when the command is called with Prefix argument 4.
 
-See `caml-types-location-re' for annotation file format.
-"
+See `caml-types-location-re' for annotation file format."
   (interactive "p")
   (let* ((target-buf (current-buffer))
          (target-file (file-name-nondirectory (buffer-file-name)))
@@ -219,31 +221,26 @@ See `caml-types-location-re' for annotation file format.
               (right (caml-types-get-pos target-buf (elt node 1)))
               (kind (cdr (assoc "call" (elt node 2)))))
           (move-overlay caml-types-expr-ovl left right target-buf)
-          (with-current-buffer caml-types-buffer
-            (erase-buffer)
-            (insert kind)
-            (message (format "%s call" kind)))
-          ))))
+          (caml-types-feedback kind "%s call")))))
     (if (and (= arg 4)
              (not (window-live-p (get-buffer-window caml-types-buffer))))
         (display-buffer caml-types-buffer))
     (unwind-protect
         (caml-sit-for 60)
-      (delete-overlay caml-types-expr-ovl)
-      )))
+      (delete-overlay caml-types-expr-ovl))))
 
 (defun caml-types-show-ident (arg)
   "Show the binding of identifier at point.
-   The identifier that contains point is
-   temporarily highlighted.  Its binding is highlighted in the .annot
-   file and the mark is set to the beginning of the binding.
-   The binding is also displayed in the mini-buffer.
+
+The identifier that contains point is temporarily highlighted.
+Its binding is highlighted in the .annot file and the mark is set
+to the beginning of the binding.  The binding is also displayed
+in the mini-buffer.
 
 The binding is also displayed in the buffer *caml-types*, which is
 displayed when the command is called with Prefix argument 4.
 
-See `caml-types-location-re' for annotation file format.
-"
+See `caml-types-location-re' for annotation file format."
   (interactive "p")
   (let* ((target-buf (current-buffer))
          (target-file (file-name-nondirectory (buffer-file-name)))
@@ -319,11 +316,7 @@ See `caml-types-location-re' for annotation file format.
                                    var-name l-line (- l-cnum l-bol))))))
              ((string-match external-re kind)
               (let ((fullname (match-string 1 kind)))
-                (with-current-buffer caml-types-buffer
-                  (erase-buffer)
-                  (insert fullname)
-                  (message (format "external ident: %s" fullname)))))))
-          ))))
+                (caml-types-feedback fullname "external ident: %s")))))))))
     (if (and (= arg 4)
              (not (window-live-p (get-buffer-window caml-types-buffer))))
         (display-buffer caml-types-buffer))
@@ -331,8 +324,7 @@ See `caml-types-location-re' for annotation file format.
         (caml-sit-for 60)
       (delete-overlay caml-types-expr-ovl)
       (delete-overlay caml-types-def-ovl)
-      (delete-overlay caml-types-scope-ovl)
-      )))
+      (delete-overlay caml-types-scope-ovl))))
 
 (defun caml-types-preprocess (target-path)
   (let* ((type-path (caml-types-locate-type-file target-path))
@@ -355,14 +347,13 @@ See `caml-types-location-re' for annotation file format.
         (setq caml-types-annotation-tree tree
               caml-types-annotation-date type-date)
         (kill-buffer type-buf)
-        (message "done"))
-      )))
+        (message "done")))))
 
 (defun caml-types-parent-dir (d) (file-name-directory (directory-file-name d)))
 
 (defun caml-types-locate-type-file (target-path)
-  "Given the path to an OCaml file, this function tries to locate
-and return the corresponding .annot file."
+  "Given the path to an OCaml file, try to locate and return the
+corresponding .annot file."
   (let ((sibling (concat (file-name-sans-extension target-path) ".annot")))
     (if (file-exists-p sibling)
         sibling
@@ -412,8 +403,7 @@ and return the corresponding .annot file."
   (if (re-search-forward "^[a-z\"]" () t)
       (forward-char -1)
     (goto-char (point-max)))
-  (looking-at "[a-z]")
-)
+  (looking-at "[a-z]"))
 
 ; tree of intervals
 ; each node is a vector
@@ -454,7 +444,7 @@ and return the corresponding .annot file."
                                              accu)))
             (setq stack (cons node stack))))))
     (if (null stack)
-        (error "no annotations found for this source file")
+        (error "No annotations found for this source file")
       (let* ((left-pos (elt (car (last stack)) 0))
              (right-pos (elt (car stack) 1)))
         (if (null (cdr stack))
@@ -592,15 +582,12 @@ and return the corresponding .annot file."
     (unless (verify-visited-file-modtime buf)
       (if (buffer-modified-p buf)
           (find-file-noselect name)
-        (with-current-buffer buf (revert-buffer t t)))
-      ))
+        (with-current-buffer buf (revert-buffer t t)))))
    ((and (file-readable-p name)
          (setq buf (find-file-noselect name)))
-     (with-current-buffer buf (toggle-read-only 1))
-     )
+     (with-current-buffer buf (toggle-read-only 1)))
    (t
-    (error (format "Can't read the annotation file `%s'" name)))
-    )
+    (error (format "Can't read the annotation file `%s'" name))))
   buf))
 
 (defun caml-types-mouse-ignore (event)
@@ -622,8 +609,7 @@ The function uses two overlays.
  . One overlay delimits the largest region whose all subnodes
    are well-typed.
  . Another overlay delimits the current node under the mouse (whose type
-   annotation is being displayed).
-"
+   annotation is being displayed)."
   (interactive "e")
   (set-buffer (window-buffer (caml-event-window event)))
   (let* ((target-buf (current-buffer))
@@ -636,8 +622,7 @@ The function uses two overlays.
          target-tree
          (speed 100)
          (last-time (caml-types-time))
-         (original-event event)
-         )
+         (original-event event))
     (select-window window)
     (unwind-protect
         (progn
@@ -663,15 +648,13 @@ The function uses two overlays.
                           (top (nth 1 win))
                           (bottom (- (nth 3 win) 1))
                           mouse
-                          time
-                          )
+                          time)
                      (while (and
                              (caml-sit-for 0 (/ 500 speed))
                              (setq time (caml-types-time))
                              (> (- time last-time) (/ 500 speed))
                              (setq mouse (caml-mouse-vertical-position))
-                             (or (< mouse top) (>= mouse bottom))
-                             )
+                             (or (< mouse top) (>= mouse bottom)))
                        (setq last-time time)
                        (cond
                         ((< mouse top)
@@ -683,10 +666,8 @@ The function uses two overlays.
                          (setq speed (+ 1 (- mouse bottom)))
                          (condition-case nil
                              (scroll-up 1)
-                           (error (message "End of buffer!"))))
-                        )
-                       (setq speed (* speed speed))
-                       )))
+                           (error (message "End of buffer!")))))
+                       (setq speed (* speed speed)))))
                   ;; main action, when the motion is inside the window
                   ;; or on orginal button down event
                   ((or (caml-mouse-movement-p event)
@@ -735,23 +716,15 @@ The function uses two overlays.
                          (setq limits
                                (caml-types-find-interval target-buf
                                                          target-pos node)
-                               type (cdr (assoc "type" (elt node 2))))
-                         ))
-                        )
+                               type (cdr (assoc "type" (elt node 2)))))))
                        (setq mes (format "type: %s" type))
-                       (insert type)
-                       ))
-                   (message mes)
-                   )
-                  )
+                       (insert type)))
+                   (message mes)))
                  ;; we read next event, unless it is nil, and loop back.
-                 (if event (setq event (caml-read-event)))
-                 )
-               )
+                 (if event (setq event (caml-read-event)))))
             ;; delete overlays at end of exploration
             (delete-overlay caml-types-expr-ovl)
-            (delete-overlay caml-types-typed-ovl)
-            ))
+            (delete-overlay caml-types-typed-ovl)))
       ;; When an error occurs, the mouse release event has not been read.
       ;; We could wait for mouse release to prevent execution of
       ;; a binding of mouse release, such as cut or paste.
@@ -761,8 +734,7 @@ The function uses two overlays.
       ;; Not sure it is robust to loop for mouse release after an error
       ;; occured, as is done for exploration.
       ;; So far, we just ignore next event. (Next line also be uncommenting.)
-      (if event (caml-read-event))
-      )))
+      (if event (caml-read-event)))))
 
 (defun caml-types-typed-make-overlay (target-buf pos)
   (interactive "p")
@@ -774,20 +746,17 @@ The function uses two overlays.
         (if (and (equal target-buf (current-buffer))
                  (setq left (caml-types-get-pos target-buf (elt node 0))
                        right (caml-types-get-pos target-buf (elt node 1)))
-                 (<= left pos) (> right pos)
-                 )
+                 (<= left pos) (> right pos))
             (setq start (min start left)
-                  end (max end right))
-             ))
+                  end (max end right))))
       (move-overlay caml-types-typed-ovl
                     (max (point-min) (- start 1))
                     (min (point-max) (+ end 1)) target-buf)
     (cons start end)))
 
 (defun caml-types-version ()
-  "internal version number of caml-types.el"
+  "Internal version number of caml-types.el."
   (interactive)
-  (message "4")
-)
+  (message "4"))
 
 (provide 'caml-types)
diff --git a/emacs/caml-xemacs.el b/emacs/caml-xemacs.el
index f74c883c8d..110817ff81 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 6ad464ae2b..e91417d2a3 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
 
@@ -801,12 +803,18 @@ variable caml-mode-indentation."
 
 ;; Newer emacs versions support line/char ranges
 ;; We will adapt OCaml to output error messages in a compatible format.
-;; In the meantime we add the new format here in addition to the old one.
+;; In the meantime we add new formats here in addition to the old one.
 (defconst caml-error-regexp-newstyle
   (concat "^[ A-\377]+ \"\\([^\"\n]+\\)\", line \\([0-9]+\\),"
           "char \\([0-9]+\\) to line \\([0-9]+\\), char \\([0-9]+\\):")
   "Regular expression matching the error messages produced by ocamlc/ocamlopt.")
 
+(defconst caml-error-regexp-new-newstyle
+  (concat "^[ A-\377]+ \"\\([^\"\n]+\\)\", line \\([0-9]+\\), "
+          "characters \\([0-9]+\\)-\\([0-9]+\\):")
+  "Regular expression matching the error messages produced by ocamlc/ocamlopt.")
+
+
 (if (boundp 'compilation-error-regexp-alist)
     (progn
       (or (assoc caml-error-regexp
@@ -818,6 +826,11 @@ variable caml-mode-indentation."
                  compilation-error-regexp-alist)
           (setq compilation-error-regexp-alist
                 (cons (list caml-error-regexp-newstyle 1 '(2 . 4) '(3 . 5))
+                      compilation-error-regexp-alist)))
+      (or (assoc caml-error-regexp-new-newstyle
+                 compilation-error-regexp-alist)
+          (setq compilation-error-regexp-alist
+                (cons (list caml-error-regexp-new-newstyle 1 2 '(3 . 4))
                       compilation-error-regexp-alist)))))
 
 ;; A regexp to extract the range info
diff --git a/emacs/camldebug.el b/emacs/camldebug.el
index 6e83bacccc..674cd32089 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 8a7757729a..05bf318fb6 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 7b1f41cf0c..4be9e79db7 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/experimental/doligez/checkheaders b/experimental/doligez/checkheaders
index 5de153292c..4c1494643b 100755
--- a/experimental/doligez/checkheaders
+++ b/experimental/doligez/checkheaders
@@ -1,16 +1,19 @@
 #!/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.               #
-#                                                                     #
-#######################################################################
+#**************************************************************************
+#*                                                                        *
+#*                                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.          *
+#*                                                                        *
+#**************************************************************************
 
 (
 case $# in
diff --git a/experimental/garrigue/show_types.diff b/experimental/garrigue/show_types.diff
index f59105ee96..96477c9b41 100644
--- a/experimental/garrigue/show_types.diff
+++ b/experimental/garrigue/show_types.diff
@@ -57,19 +57,19 @@ Index: parsing/parser.mly
  /* Toplevel directives */
  
  toplevel_directive:
--    SHARP ident                 { Ptop_dir($2, Pdir_none) }
--  | SHARP ident STRING          { Ptop_dir($2, Pdir_string $3) }
--  | SHARP ident INT             { Ptop_dir($2, Pdir_int $3) }
--  | SHARP ident val_longident   { Ptop_dir($2, Pdir_ident $3) }
--  | SHARP ident FALSE           { Ptop_dir($2, Pdir_bool false) }
--  | SHARP ident TRUE            { Ptop_dir($2, Pdir_bool true) }
-+    SHARP ident                                 { Ptop_dir($2, Pdir_none) }
-+  | SHARP ident STRING                          { Ptop_dir($2, Pdir_string $3) }
-+  | SHARP ident INT                             { Ptop_dir($2, Pdir_int $3) }
-+  | SHARP ident val_longident                   { Ptop_dir($2, Pdir_ident (mkrhs $3 3)) }
-+  | SHARP ident ident_kind any_longident        { Ptop_dir($2, Pdir_show ($3, mkrhs $4 4)) }
-+  | SHARP ident FALSE                           { Ptop_dir($2, Pdir_bool false) }
-+  | SHARP ident TRUE                            { Ptop_dir($2, Pdir_bool true) }
+-    HASH ident                 { Ptop_dir($2, Pdir_none) }
+-  | HASH ident STRING          { Ptop_dir($2, Pdir_string $3) }
+-  | HASH ident INT             { Ptop_dir($2, Pdir_int $3) }
+-  | HASH ident val_longident   { Ptop_dir($2, Pdir_ident $3) }
+-  | HASH ident FALSE           { Ptop_dir($2, Pdir_bool false) }
+-  | HASH ident TRUE            { Ptop_dir($2, Pdir_bool true) }
++    HASH ident                                 { Ptop_dir($2, Pdir_none) }
++  | HASH ident STRING                          { Ptop_dir($2, Pdir_string $3) }
++  | HASH ident INT                             { Ptop_dir($2, Pdir_int $3) }
++  | HASH ident val_longident                   { Ptop_dir($2, Pdir_ident (mkrhs $3 3)) }
++  | HASH ident ident_kind any_longident        { Ptop_dir($2, Pdir_show ($3, mkrhs $4 4)) }
++  | HASH ident FALSE                           { Ptop_dir($2, Pdir_bool false) }
++  | HASH ident TRUE                            { Ptop_dir($2, Pdir_bool true) }
  ;
  
  /* Miscellaneous */
diff --git a/flexdll b/flexdll
new file mode 160000
index 0000000000..3453457496
--- /dev/null
+++ b/flexdll
@@ -0,0 +1 @@
+Subproject commit 3453457496f5e676437652bf25ba004802e1bb93
diff --git a/lex/.depend b/lex/.depend
index 455421e708..4c22eeb9d0 100644
--- a/lex/.depend
+++ b/lex/.depend
@@ -1,34 +1,34 @@
-common.cmi : syntax.cmi lexgen.cmi
-compact.cmi : lexgen.cmi
-cset.cmi :
-lexer.cmi : parser.cmi
-lexgen.cmi : syntax.cmi
-output.cmi : syntax.cmi lexgen.cmi compact.cmi common.cmi
-outputbis.cmi : syntax.cmi lexgen.cmi common.cmi
-parser.cmi : syntax.cmi
-syntax.cmi : cset.cmi
-table.cmi :
 common.cmo : syntax.cmi lexgen.cmi common.cmi
 common.cmx : syntax.cmx lexgen.cmx common.cmi
+common.cmi : syntax.cmi lexgen.cmi
 compact.cmo : table.cmi lexgen.cmi compact.cmi
 compact.cmx : table.cmx lexgen.cmx compact.cmi
+compact.cmi : lexgen.cmi
 cset.cmo : cset.cmi
 cset.cmx : cset.cmi
+cset.cmi :
 lexer.cmo : syntax.cmi parser.cmi lexer.cmi
 lexer.cmx : syntax.cmx parser.cmx lexer.cmi
+lexer.cmi : parser.cmi
 lexgen.cmo : table.cmi syntax.cmi cset.cmi lexgen.cmi
 lexgen.cmx : table.cmx syntax.cmx cset.cmx lexgen.cmi
+lexgen.cmi : syntax.cmi
 main.cmo : syntax.cmi parser.cmi outputbis.cmi output.cmi lexgen.cmi \
     lexer.cmi cset.cmi compact.cmi common.cmi
 main.cmx : syntax.cmx parser.cmx outputbis.cmx output.cmx lexgen.cmx \
     lexer.cmx cset.cmx compact.cmx common.cmx
 output.cmo : lexgen.cmi compact.cmi common.cmi output.cmi
 output.cmx : lexgen.cmx compact.cmx common.cmx output.cmi
+output.cmi : syntax.cmi lexgen.cmi compact.cmi common.cmi
 outputbis.cmo : lexgen.cmi common.cmi outputbis.cmi
 outputbis.cmx : lexgen.cmx common.cmx outputbis.cmi
+outputbis.cmi : syntax.cmi lexgen.cmi common.cmi
 parser.cmo : syntax.cmi cset.cmi parser.cmi
 parser.cmx : syntax.cmx cset.cmx parser.cmi
+parser.cmi : syntax.cmi
 syntax.cmo : cset.cmi syntax.cmi
 syntax.cmx : cset.cmx syntax.cmi
+syntax.cmi : cset.cmi
 table.cmo : table.cmi
 table.cmx : table.cmi
+table.cmi :
diff --git a/lex/.ignore b/lex/.ignore
deleted file mode 100644
index 9f4f308da4..0000000000
--- 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 3691cb2b3f..5e3848fbca 100644
--- a/lex/Makefile
+++ b/lex/Makefile
@@ -1,23 +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 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
 CAMLRUN ?= ../boot/ocamlrun
 CAMLYACC ?= ../boot/ocamlyacc
 
-CAMLC=$(CAMLRUN) ../boot/ocamlc -strict-sequence -nostdlib -I ../boot
+ROOTDIR=..
+
+ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" ""
+export OCAML_FLEXLINK:=
+else
+export OCAML_FLEXLINK:=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe
+endif
+
+CAMLC=$(CAMLRUN) ../boot/ocamlc -strict-sequence -nostdlib -I ../boot \
+      -use-prims ../byterun/primitives
 CAMLOPT=$(CAMLRUN) ../ocamlopt -nostdlib -I ../stdlib
-COMPFLAGS=-w +33..39 -warn-error A -bin-annot -safe-string
+COMPFLAGS=$(INCLUDES) -absname -w +a-4-9-41-42-44-45-48 -warn-error A \
+          -safe-string -strict-sequence -strict-formats -bin-annot
 LINKFLAGS=
 YACCFLAGS=-v
 CAMLLEX=$(CAMLRUN) ../boot/ocamllex
@@ -38,7 +51,7 @@ ocamllex.opt: $(OBJS:.cmo=.cmx)
 
 clean::
 	rm -f ocamllex ocamllex.opt
-	rm -f *.cmo *.cmi *.cmx *.cmt *.cmti *.o *~
+	rm -f *.cmo *.cmi *.cmx *.cmt *.cmti *.$(O) *~
 
 parser.ml parser.mli: parser.mly
 	$(CAMLYACC) $(YACCFLAGS) parser.mly
@@ -69,6 +82,6 @@ beforedepend:: lexer.ml
 	$(CAMLOPT) -c $(COMPFLAGS) $<
 
 depend: beforedepend
-	$(CAMLDEP) *.mli *.ml > .depend
+	$(CAMLDEP) -slash *.mli *.ml > .depend
 
 include .depend
diff --git a/lex/Makefile.nt b/lex/Makefile.nt
index 6bd8560406..ed9900bb9a 100644
--- a/lex/Makefile.nt
+++ b/lex/Makefile.nt
@@ -1,75 +1,16 @@
-#########################################################################
-#                                                                       #
-#                                 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.                #
-#                                                                       #
-#########################################################################
-
-# The lexer generator
-
-include ../config/Makefile
-CAMLRUN ?= ../boot/ocamlrun
-CAMLYACC ?= ../boot/ocamlyacc
-
-CAMLC=$(CAMLRUN) ../boot/ocamlc -I ../boot
-CAMLOPT=$(CAMLRUN) ../ocamlopt -I ../stdlib
-COMPFLAGS=-warn-error A
-LINKFLAGS=
-YACCFLAGS=-v
-CAMLLEX=$(CAMLRUN) ../boot/ocamllex
-CAMLDEP=$(CAMLRUN) ../tools/ocamldep
-DEPFLAGS=
-
-OBJS=cset.cmo syntax.cmo parser.cmo lexer.cmo table.cmo lexgen.cmo \
-     compact.cmo common.cmo output.cmo outputbis.cmo main.cmo
-
-all: ocamllex syntax.cmo
-allopt: ocamllex.opt
-
-ocamllex: $(OBJS)
-	$(CAMLC) $(LINKFLAGS) -compat-32 -o ocamllex $(OBJS)
-
-ocamllex.opt: $(OBJS:.cmo=.cmx)
-	$(CAMLOPT) -o ocamllex.opt $(OBJS:.cmo=.cmx)
-
-clean::
-	rm -f ocamllex ocamllex.opt
-	rm -f *.cmo *.cmi *.cmx *.$(O)
-
-parser.ml parser.mli: parser.mly
-	$(CAMLYACC) $(YACCFLAGS) parser.mly
-
-clean::
-	rm -f parser.ml parser.mli
-
-beforedepend:: parser.ml parser.mli
-
-lexer.ml: lexer.mll
-	$(CAMLLEX) lexer.mll
-
-clean::
-	rm -f lexer.ml
-
-beforedepend:: lexer.ml
-
-.SUFFIXES:
-.SUFFIXES: .ml .cmo .mli .cmi .cmx
-
-.ml.cmo:
-	$(CAMLC) -c $(COMPFLAGS) $<
-
-.mli.cmi:
-	$(CAMLC) -c $(COMPFLAGS) $<
-
-.ml.cmx:
-	$(CAMLOPT) -c $(COMPFLAGS) $<
-
-depend: beforedepend
-	$(CAMLDEP) *.mli *.ml > .depend
-
-include .depend
+#**************************************************************************
+#*                                                                        *
+#*                                 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
diff --git a/lex/common.ml b/lex/common.ml
index 9b86ba111f..5024c829f8 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
@@ -136,7 +139,7 @@ let output_env ic oc tr env =
           env in
 
       List.iter
-        (fun ((x,pos),v) ->
+        (fun ((_,pos),v) ->
           fprintf oc "%s\n" !pref ;
           copy_chunk ic oc tr pos false ;
           begin match v with
diff --git a/lex/common.mli b/lex/common.mli
index de23959cae..f00b50d7f9 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 f468a557d6..38119c2b98 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -126,7 +129,7 @@ let do_pack state_num orig compact =
     done;
     let rec try_pack = function
       [] -> b
-    | (pos, v) :: rem ->
+    | (pos, _v) :: rem ->
         if compact.c_check.(b + pos) = -1 then
           try_pack rem
         else pack_from (b+1) in
diff --git a/lex/compact.mli b/lex/compact.mli
index 90f2ed99c6..936835ebc0 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 f4581ba374..e3f73de38b 100644
--- a/lex/cset.ml
+++ b/lex/cset.ml
@@ -1,4 +1,4 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                OCaml                                *)
 (*                                                                     *)
@@ -6,10 +6,13 @@
 (*                         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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 daad6e59f1..527d53d173 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 ca8e4c490a..28d00eaabe 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 eebd7115ea..748f5e16c4 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! *)
 
@@ -60,8 +63,6 @@ let handle_lexical_error fn lexbuf =
   with Lexical_error (msg, "", 0, 0) ->
     raise(Lexical_error(msg, file, line, column))
 
-let get_input_name () = Sys.argv.(Array.length Sys.argv - 1)
-
 let warning lexbuf msg =
   let p = Lexing.lexeme_start_p lexbuf in
   Printf.eprintf "ocamllex warning:\nFile \"%s\", line %d, character %d: %s.\n"
@@ -187,7 +188,7 @@ rule main = parse
   | ')'  { Trparen }
   | '^'  { Tcaret }
   | '-'  { Tdash }
-  | '#'  { Tsharp }
+  | '#'  { Thash }
   | eof  { Tend }
   | _
     { raise_lexical_error lexbuf
@@ -226,7 +227,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 +301,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 503b08fa49..7f85bc8736 100644
--- a/lex/lexgen.ml
+++ b/lex/lexgen.ml
@@ -1,21 +1,23 @@
-(***********************************************************************)
+(**************************************************************************)
 (*                                                                     *)
 (*                                OCaml                                *)
 (*                                                                     *)
-(*            Xavier Leroy, projet Cristal,                            *)
-(*            Luc Maranget, projet Moscova,                            *)
-(*                  INRIA Rocquencourt                                 *)
+(*           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 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Compiling a lexer definition *)
 
 open Syntax
-open Printf
+(*open Printf*)
 
 exception Memory_overflow
 
@@ -93,9 +95,6 @@ module TagMap =
 module IdSet =
   Set.Make (struct type t = ident let compare = id_compare end)
 
-module IdMap =
-  Map.Make (struct type t =  ident let compare = id_compare end)
-
 (*********************)
 (* Variable cleaning *)
 (*********************)
@@ -303,15 +302,6 @@ let rec encode_regexp char_vars act = function
       a previous similar tag.
 *)
 
-let incr_pos = function
-  | None   -> None
-  | Some i -> Some (i+1)
-
-let decr_pos = function
-  | None -> None
-  | Some i -> Some (i-1)
-
-
 let opt = true
 
 let mk_seq r1 r2 = match r1,r2  with
@@ -551,7 +541,7 @@ let rec nullable = function
   | Chars (_,_)|Action _ -> false
   | Seq(r1,r2) -> nullable r1 && nullable r2
   | Alt(r1,r2) -> nullable r1 || nullable r2
-  | Star r     -> true
+  | Star _     -> true
 
 let rec emptymatch = function
   | Empty | Chars (_,_) | Action _ -> Tags.empty
@@ -628,6 +618,7 @@ type 'a dfa_state =
    others : ('a * int TagMap.t) MemMap.t}
 
 
+(*
 let dtag oc t =
   fprintf oc "%s<%s>" t.id (if t.start then "s" else "e")
 
@@ -654,6 +645,7 @@ let dstate {final=(act,(_,m)) ; others=o} =
       dtag_map (fun x -> eprintf "%d" x) (fun () -> prerr_string " ,") m)
     (fun () -> prerr_endline "")
     o
+*)
 
 
 let dfa_state_empty =
@@ -856,7 +848,7 @@ let create_init_state pos =
       (fun (t,tags) st ->
         match t with
         | ToAction n ->
-            let on,otags = st.final in
+            let on,_otags = st.final in
             if n < on then
               {st with final = (n, (0,create_mem_map tags gen))}
             else
@@ -881,10 +873,12 @@ let get_map t st = match t with
 let dest = function | Copy (d,_) | Set d  -> d
 and orig = function | Copy (_,o) -> o | Set _ -> -1
 
+(*
 let pmv oc mv = fprintf oc "%d <- %d" (dest mv) (orig mv)
 let pmvs oc mvs =
   List.iter (fun mv -> fprintf oc "%a " pmv  mv) mvs ;
   output_char oc '\n' ; flush oc
+*)
 
 
 (* Topological sort << a la louche >> *)
@@ -1103,6 +1097,7 @@ let translate_state shortest_match tags chars follow st =
     reachs chars follow st.others)
   end
 
+(*
 let dtags chan tags =
   Tags.iter
     (fun t -> fprintf chan " %a" dtag t)
@@ -1124,6 +1119,7 @@ let dfollow t =
     dtransset t.(i)
   done ;
   prerr_endline "]"
+*)
 
 
 let make_tag_entry id start act a r = match a with
diff --git a/lex/lexgen.mli b/lex/lexgen.mli
index 3fc8c905af..306f475a46 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 076873f103..fd01325d3b 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. *)
 
@@ -74,11 +77,11 @@ let main () =
     let (entries, transitions) = Lexgen.make_dfa def.entrypoints in
     if !ml_automata then begin
       Outputbis.output_lexdef
-        source_name ic oc tr
+        ic oc tr
         def.header def.refill_handler entries transitions def.trailer
     end else begin
        let tables = Compact.compact_tables transitions in
-       Output.output_lexdef source_name ic oc tr
+       Output.output_lexdef ic oc tr
          def.header def.refill_handler tables entries def.trailer
     end;
     close_in ic;
diff --git a/lex/output.ml b/lex/output.ml
index 638260c2b4..9ee8ef33ed 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -69,7 +72,7 @@ let output_tables oc tbl =
 
 (* Output the entries *)
 
-let output_entry sourcefile ic oc has_refill oci e =
+let output_entry ic oc has_refill oci e =
   let init_num, init_moves = e.auto_initial_state in
   fprintf oc "%s %alexbuf =\
 \n  %a%a  __ocaml_lex_%s_rec %alexbuf %d\n"
@@ -112,7 +115,7 @@ let output_entry sourcefile ic oc has_refill oci e =
 
 exception Table_overflow
 
-let output_lexdef sourcefile ic oc oci header rh tables entry_points trailer =
+let output_lexdef ic oc oci header rh tables entry_points trailer =
   if not !Common.quiet_mode then
     Printf.printf "%d states, %d transitions, table size %d bytes\n"
       (Array.length tables.tbl_base)
@@ -138,11 +141,11 @@ let output_lexdef sourcefile ic oc oci header rh tables entry_points trailer =
     [] -> ()
   | entry1 :: entries ->
     output_string oc "let rec ";
-    output_entry sourcefile ic oc has_refill oci entry1;
+    output_entry ic oc has_refill oci entry1;
       List.iter
         (fun e ->
            output_string oc "and ";
-           output_entry sourcefile ic oc has_refill oci e)
+           output_entry ic oc has_refill oci e)
         entries;
       output_string oc ";;\n\n";
   end;
diff --git a/lex/output.mli b/lex/output.mli
index 9d0bd9fc80..13956aa93f 100644
--- a/lex/output.mli
+++ b/lex/output.mli
@@ -1,19 +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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Output the DFA tables and its entry points *)
 
 val output_lexdef:
-      string -> in_channel -> out_channel -> Common.line_tracker ->
+      in_channel -> out_channel -> Common.line_tracker ->
       Syntax.location ->
       Syntax.location option ->
       Compact.lex_tables ->
diff --git a/lex/outputbis.ml b/lex/outputbis.ml
index 709ec0eec8..261b38e6c1 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 *)
 
@@ -34,14 +37,14 @@ let output_auto_defs oc has_refill =
 \n    if lexbuf.Lexing.lex_eof_reached then\
 \n      state lexbuf k 256\
 \n    else begin\
-\n      __ocaml_lex_refill (fun lexbuf ->
+\n      __ocaml_lex_refill (fun lexbuf ->\
 \n          lexbuf.Lexing.refill_buff lexbuf ;\
 \n          __ocaml_lex_next_char lexbuf state k)\
 \n        lexbuf\
 \n    end\
 \n  end else begin\
 \n    let i = lexbuf.Lexing.lex_curr_pos in\
-\n    let c = lexbuf.Lexing.lex_buffer.[i] in\
+\n    let c = Bytes.get lexbuf.Lexing.lex_buffer i in\
 \n    lexbuf.Lexing.lex_curr_pos <- i+1 ;\
 \n    state lexbuf k (Char.code c)\
 \n  end\
@@ -58,7 +61,7 @@ let output_auto_defs oc has_refill =
 \n    end\
 \n  end else begin\
 \n    let i = lexbuf.Lexing.lex_curr_pos in\
-\n    let c = lexbuf.Lexing.lex_buffer.[i] in\
+\n    let c = Bytes.get lexbuf.Lexing.lex_buffer i in\
 \n    lexbuf.Lexing.lex_curr_pos <- i+1 ;\
 \n    Char.code c\
 \n  end\
@@ -185,7 +188,7 @@ let output_automata oc has_refill auto =
 
 (* Output the entries *)
 
-let output_entry sourcefile ic oc has_refill tr e =
+let output_entry ic oc has_refill tr e =
   let init_num, init_moves = e.auto_initial_state in
   fprintf oc "%s %alexbuf =\n  __ocaml_lex_init_lexbuf lexbuf %d; %a"
     e.auto_name output_args e.auto_args
@@ -218,7 +221,7 @@ let output_entry sourcefile ic oc has_refill tr e =
 
 (* Main output function *)
 
-let output_lexdef sourcefile ic oc tr header rh
+let output_lexdef ic oc tr header rh
                   entry_points transitions trailer =
 
   copy_chunk ic oc tr header false;
@@ -228,10 +231,10 @@ let output_lexdef sourcefile ic oc tr header rh
     [] -> ()
   | entry1 :: entries ->
     output_string oc "let rec ";
-    output_entry sourcefile ic oc has_refill tr entry1;
+    output_entry ic oc has_refill tr entry1;
       List.iter
         (fun e -> output_string oc "and ";
-          output_entry sourcefile ic oc has_refill tr e)
+          output_entry ic oc has_refill tr e)
         entries;
       output_string oc ";;\n\n";
   end;
diff --git a/lex/outputbis.mli b/lex/outputbis.mli
index fb51cdec7c..44eb0e47c7 100644
--- a/lex/outputbis.mli
+++ b/lex/outputbis.mli
@@ -1,17 +1,19 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                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 ->
   in_channel ->
   out_channel ->
   Common.line_tracker ->
diff --git a/lex/parser.mly b/lex/parser.mly
index 459b787077..0a1bb5d966 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 */
 
@@ -50,13 +53,13 @@ let as_cset = function
 %token  Taction
 %token Trule Tparse Tparse_shortest Tand Tequal Tend Tor Tunderscore Teof
        Tlbracket Trbracket Trefill
-%token Tstar Tmaybe Tplus Tlparen Trparen Tcaret Tdash Tlet Tas Tsharp
+%token Tstar Tmaybe Tplus Tlparen Trparen Tcaret Tdash Tlet Tas Thash
 
 %right Tas
 %left Tor
 %nonassoc CONCAT
 %nonassoc Tmaybe Tstar Tplus
-%left Tsharp
+%left Thash
 %nonassoc Tident Tchar Tstring Tunderscore Teof Tlbracket Tlparen
 
 %start lexer_definition
@@ -142,7 +145,7 @@ regexp:
         { Alternative(Epsilon, $1) }
   | regexp Tplus
         { Sequence(Repetition (remove_as $1), $1) }
-  | regexp Tsharp regexp
+  | regexp Thash regexp
         {
           let s1 = as_cset $1
           and s2 = as_cset $3 in
diff --git a/lex/syntax.ml b/lex/syntax.ml
index b2993eaa02..61a9d793fd 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 6871dd118d..eb0acefa36 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 715d90758d..bfb9ce4817 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.               *)
+(*     en Automatique.                                                    *)
 (*                                                                     *)
-(***********************************************************************)
+(*   All rights reserved.  This file is distributed 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 8d9938cbff..492626b9e6 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 c1c2df3752..7008b95138 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 5c839ea61d..6b715cf597 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.               *
+.\"*     en Automatique.                                                    *
 .\"*                                                                     *
-.\"***********************************************************************
+.\"*   All rights reserved.  This file is distributed 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
 
@@ -35,7 +38,7 @@
 read-eval-print loop. In this mode, the system repeatedly reads OCaml
 phrases from the input, then typechecks, compiles and evaluates
 them, then prints the inferred type and result value, if any. The
-system prints a # (sharp) prompt before reading each phrase.
+system prints a # (hash) prompt before reading each phrase.
 
 A toplevel phrase can span several lines. It is terminated by ;; (a
 double-semicolon). The syntax of toplevel phrases is as follows.
@@ -93,11 +96,7 @@
 .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 @@
 .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.
@@ -139,6 +142,11 @@
 options are given, they are processed in order, just as if
 the statements open! module1;; ... open! moduleN;; were input.
 .TP
+.BI \-plugin \ plugin
+Dynamically load the code of the given
+.I plugin
+(a .cmo or .cma file) in the toplevel.
+.TP
 .BI \-ppx \ command
 After parsing, pipe the abstract syntax tree through the preprocessor
 .IR command .
@@ -182,6 +190,17 @@
 .B \-strict\-sequence
 Force the left-hand part of each sequence to have type unit.
 .TP
+.B \-unboxed\-types
+When a type is unboxable (i.e. a record with a single argument or a
+concrete datatype with a single constructor of one argument) it will
+be unboxed unless annotated with
+.BR [@@ocaml.boxed] .
+.TP
+.B \-no-unboxed\-types
+When a type is unboxable  it will be boxed unless annotated with
+.BR [@@ocaml.unboxed] .
+This is the default.
+.TP
 .B \-unsafe
 Turn bound checking off on array and string accesses (the
 .BR v.(i) and s.[i]
@@ -203,6 +222,9 @@ Turn bound checking off on array and string accesses (the
 .B \-vnum
 Print short version number and exit.
 .TP
+.B \-no\-version
+Do not print the version banner at startup.
+.TP
 .BI \-w \ warning\-list
 Enable or disable warnings according to the argument
 .IR warning-list .
@@ -235,6 +257,26 @@ Note that a warning is not triggered (and does not trigger an error) if
 .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 adb280927f..9d3f421e64 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.               *
+.\"*     en Automatique.                                                    *
 .\"*                                                                     *
-.\"***********************************************************************
+.\"*   All rights reserved.  This file is distributed 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
 
@@ -41,7 +44,7 @@
 .BR ocamlc (1)
 command has a command-line interface similar to the one of
 most C compilers. It accepts several types of arguments and processes them
-sequentially:
+sequentially, after all options have been processed:
 
 Arguments ending in .mli are taken to be source files for
 compilation unit interfaces. Interfaces specify the names exported by
@@ -190,7 +193,7 @@ Build a library (.cma file) with the object files (.cmo files) given
 .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 @@ Dump detailed information about the compilation (types, bindings,
 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 @@ standard search path (the one corresponding to the
 .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
@@ -494,6 +526,15 @@ Build a bytecode object file (.cmo file) and its associated compiled
 contents can be referenced as P.A, P.B and P.C in the remainder
 of the program.
 .TP
+.BI \-plugin \ plugin
+Dynamically load the code of the given
+.I plugin
+(a .cmo, .cma or .cmxs file) in the compiler. The plugin must exist in
+the same kind of code as the compiler (ocamlc.byte must load bytecode
+plugins, while ocamlc.opt must load native code plugins), and
+extension adaptation is done automatically for .cma files (to .cmxs files
+if the compiler is compiled in native code).
+.TP
 .BI \-pp \ command
 Cause the compiler to call the given
 .I command
@@ -561,6 +602,17 @@ Build a bytecode object file (.cmo file) and its associated compiled
 system "threads" library described in
 .IR The\ OCaml\ user's\ manual .
 .TP
+.B \-unboxed\-types
+When a type is unboxable (i.e. a record with a single argument or a
+concrete datatype with a single constructor of one argument) it will
+be unboxed unless annotated with
+.BR [@@ocaml.boxed] .
+.TP
+.B \-no-unboxed\-types
+When a type is unboxable  it will be boxed unless annotated with
+.BR [@@ocaml.unboxed] .
+This is the default.
+.TP
 .B \-unsafe
 Turn bound checking off for array and string accesses (the
 .BR v.(i) and s.[i]
@@ -847,6 +899,15 @@ compilation in any way (even if it is fatal).  If a warning is enabled,
 50
 \ \ Unexpected documentation comment.
 
+59
+\ \ Assignment on non-mutable value.
+
+60
+\ \ Unused module declaration.
+
+61
+\ \ Unannotated unboxable type in primitive declaration.
+
 The letters stand for the following sets of warnings.  Any letter not
 mentioned here corresponds to the empty set.
 
@@ -900,7 +961,7 @@ compilation in any way (even if it is fatal).  If a warning is enabled,
 
 .IP
 The default setting is
-.BR \-w\ +a\-4\-6\-7\-9\-27\-29\-32..39\-41\-42\-44\-45\-48\-50 .
+.BR \-w\ +a\-4\-6\-7\-9\-27\-29\-32..39\-41\-42\-44\-45\-48\-50\-60 .
 Note that warnings
 .BR 5 \ and \ 10
 are not always triggered, depending on the internals of the type checker.
@@ -929,8 +990,8 @@ compilation in any way (even if it is fatal).  If a warning is enabled,
 warnings or modify existing warnings.
 
 The default setting is
-.B \-warn\-error \-a
-(all warnings are non-fatal).
+.B \-warn\-error \-a+31
+(only warning 31 is fatal).
 .TP
 .B \-warn\-help
 Show the description of all available warning numbers.
diff --git a/man/ocamlcp.m b/man/ocamlcp.m
index 7967f25d21..d6c983d167 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 50354d93c5..f03ad60f39 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 @@
 .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 ba7ddb8c3c..ee6a641a53 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 @@
 .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 @@
 .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 @@ causes dependencies on native compiled files (.cmx) to be generated instead
 .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 ca0a233480..dd44b3f0b0 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.               *
+.\"*     en Automatique.                                                    *
 .\"*                                                                     *
-.\"***********************************************************************
+.\"*   All rights reserved.  This file is distributed 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 d59755bab1..58e0362764 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 fd6aaa8231..09a4126c01 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 a541e598d4..c9ebc28977 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.               *
+.\"*     en Automatique.                                                    *
 .\"*                                                                     *
-.\"***********************************************************************
+.\"*   All rights reserved.  This file is distributed 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
 
@@ -41,7 +44,7 @@
 of
 .BR ocamlc (1).
 It accepts the same types of arguments and processes them
-sequentially:
+sequentially, after all options have been processed:
 
 Arguments ending in .mli are taken to be source files for
 compilation unit interfaces. Interfaces specify the names exported by
@@ -453,6 +456,15 @@ Build an object file (.cmx and .o files) and its associated compiled
 .IR "The OCaml user's manual" ,
 chapter "Native-code compilation" for more details.
 .TP
+.BI \-plugin \ plugin
+Dynamically load the code of the given
+.I plugin
+(a .cmo, .cma or .cmxs file) in the compiler. The plugin must exist in
+the same kind of code as the compiler (ocamlopt.byte must load bytecode
+plugins, while ocamlopt.opt must load native code plugins), and
+extension adaptation is done automatically for .cma files (to .cmxs files
+if the compiler is compiled in native code).
+.TP
 .BI \-pp \ command
 Cause the compiler to call the given
 .I command
@@ -536,6 +548,17 @@ apply to the way the extra native objects have been compiled (under
 system threads library described in
 .IR "The OCaml user's manual" .
 .TP
+.B \-unboxed\-types
+When a type is unboxable (i.e. a record with a single argument or a
+concrete datatype with a single constructor of one argument) it will
+be unboxed unless annotated with
+.BR [@@ocaml.boxed] .
+.TP
+.B \-no-unboxed\-types
+When a type is unboxable  it will be boxed unless annotated with
+.BR [@@ocaml.unboxed] .
+This is the default.
+.TP
 .B \-unsafe
 Turn bound checking off for array and string accesses (the
 .BR v.(i) and s.[i]
@@ -603,8 +626,8 @@ Print the version number of the compiler in short form (e.g. "3.11.0"),
 warnings or modify existing warnings.
 
 The default setting is
-.B \-warn\-error \-a
-(all warnings are non-fatal).
+.B \-warn\-error \-a+31
+(only warning 31 is fatal).
 .TP
 .B \-warn\-help
 Show the description of all available warning numbers.
diff --git a/man/ocamlprof.m b/man/ocamlprof.m
index a3bac2c600..97d5671441 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 810f525887..2b4f14d6f3 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.               *
+.\"*     en Automatique.                                                    *
 .\"*                                                                     *
-.\"***********************************************************************
+.\"*   All rights reserved.  This file is distributed 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 @@ in the OCAMLRUNPARAM environment variable (see below).
 .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 @@ Startup messages (loading the bytecode executable file, resolving
 .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 @@ Startup messages (loading the bytecode executable file, resolving
 .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 133994e206..f522d5cc26 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
 
@@ -76,6 +79,9 @@ Parsing functions take as arguments a lexical analyzer (a function
 .B \-q
 This option has no effect.
 .TP
+.B \--strict
+Reject grammars with conflicts.
+.TP
 .B \-v
 Generate a description of the parsing tables and a report on conflicts
 resulting from ambiguities in the grammar. The description is put in
diff --git a/manual/LICENSE-for-the-manual b/manual/LICENSE-for-the-manual
new file mode 100644
index 0000000000..c104a053b3
--- /dev/null
+++ b/manual/LICENSE-for-the-manual
@@ -0,0 +1,20 @@
+The present documentation is copyright Institut National de Recherche
+en Informatique et en Automatique (INRIA).
+
+The OCaml documentation and user's manual may be reproduced and
+distributed in whole or in part, subject to the following conditions:
+
+- The copyright notice above and this permission notice must be
+  preserved complete on all complete or partial copies.
+
+- Any translation or derivative work of the OCaml documentation and
+  user's manual must be approved by the authors in writing before
+  distribution.
+
+- If you distribute the OCaml documentation and user's manual in part,
+  instructions for obtaining the complete version of this manual must
+  be included, and a means for obtaining a complete version provided.
+
+- Small portions may be reproduced as illustrations for reviews or
+  quotes in other works without this permission notice if proper
+  citation is given.
diff --git a/manual/Makefile b/manual/Makefile
new file mode 100644
index 0000000000..6ff0ca0f69
--- /dev/null
+++ b/manual/Makefile
@@ -0,0 +1,16 @@
+all: tools
+	cd manual; ${MAKE} all
+#	cd fpcl; ${MAKE} all
+
+clean:
+	cd manual; ${MAKE} clean
+	cd tools; ${MAKE} clean
+#	cd fpcl; ${MAKE} clean
+
+release:
+	cd manual; ${MAKE} release
+#	cd fpcl; ${MAKE} release
+
+.PHONY: tools
+tools:
+	cd tools; ${MAKE} clean; ${MAKE} all
diff --git a/manual/README.md b/manual/README.md
new file mode 100644
index 0000000000..f8e93399b1
--- /dev/null
+++ b/manual/README.md
@@ -0,0 +1,179 @@
+OCAML DOCUMENTATION
+===================
+
+Prerequisites
+-------------
+
+- Any prerequisites required to build OCaml from sources.
+
+- The Unix editor 'ed', no longer installed by default on some systems.
+
+- A LaTeX installation.
+
+- The HeVeA LaTeX-to-HTML convertor (available in OPAM):
+  
+
+Note that you must make sure `hevea.sty` is installed into TeX properly. Your
+package manager may not do this for you. Run `kpsewhich hevea.sty` to check.
+
+
+Building
+--------
+
+0. Install the OCaml distribution.
+
+1. Run `make` in the manual.
+
+NB: If you already set `LD_LIBRARY_PATH` (OS X: `DYLD_LIBRARY_PATH`)
+ in your environment don't forget to add
+ `otherlibs/unix:otherlibs/str` to it in an absolute way.
+
+Outputs
+-------
+
+In the manual:
+
+- The HTML Manual is in directory `htmlman`. The main file is `index.html`.
+
+- The plain text manual is in directory `textman` as file `manual.txt`.
+
+- The Info manual is in directory `infoman`.
+
+- The DVI manual is in directory `texstuff` as file `manual.dvi`.
+
+- The PDF manual is in directory `texstuff` as file `pdfmanual.pdf`.
+
+Source files
+------------
+The manual is written in an extended dialect of latex and is split in many
+source files. During the build process, the sources files are converted into
+classical latex file using the tools available in `tools`. These files are
+then converted to the different output formats using either latex or hevea.
+
+Each part of the manual corresponds to a specific directory, and each distinct
+chapters (or sometimes sections) are mapped to a distinct `.etex` file:
+
+- Part I, Introduction to OCaml: `tutorials`
+  - The core language: `coreexamples.etex`
+  - The module system: `moduleexamples.etex`
+  - Objects in OCaml: `objectexamples.etex`
+  - Labels and variants: `lablexamples.etex`
+  - Advanced examples with classes and modules: `advexamples.etex`
+
+- Part II, The OCaml language: `refman`
+  This part is separated in two very distinct  chapters; the
+  `OCaml language` chapter and the `Language extensions` chapter.
+
+  - The OCaml language: `refman.etex`
+    This chapter consists in a technical description of the OCaml language.
+    Each section of this chapter is mapped to a separated latex file:
+     - `lex.etex`, `values.etex`, `names.etex`, `types.etex`, `const.etex`,
+     `patterns.etex`, `expr.etex`, `typedecl.etex`, `classes.etex`,
+     `modtypes.etex`, `compunit.etex`
+
+  - Language extensions: `exten.etex`
+  This chapter contains a description of all recent features of the OCaml
+  language.
+
+- Part III, The OCaml tools: 'cmds'
+    - Batch compilation (ocamlc): `comp.etex`
+    - The toplevel system (ocaml): `top.etex`
+    - The runtime system (ocamlrun): `runtime.etex`
+    - Native-code compilation (ocamlopt): `native.etex`
+    - Lexer and parser generators (ocamllex, ocamlyacc): `lexyacc.etex`
+    - Dependency generator (ocamldep): `ocamldoc.etex`
+    - The browser/editor (ocamlbrowser): `browser.etex`
+    - The documentation generator (ocamldoc): `ocamdoc.etex`
+    - The debugger (ocamldebug): `debugger.etex`
+    - Profiling (ocamlprof): `profil.etex`
+    - The ocamlbuild compilation manager: `ocamlbuild.etex`
+    - Interfacing C with OCaml: `intf-c.etex`
+    - Optimisation with Flambda: `flambda.etex`
+    - Memory profiling with Spacetime: `spacetime.etex`
+
+- Part IV, The OCaml library: 'libref'
+ This parts contains an brief presentation of all libraries bundled with the
+ compilers and the api documentation generated for these libraries.
+    - The core library: `core.etex`
+    - The standard library: `stdlib.etex`
+    - The compiler front-end: `compilerlibs.etex`
+    - The unix library: Unix system calls: `libunix.etex`
+    - The num library: arbitrary-precision rational arithmetic: `libnum.etex`
+    - The str library: regular expressions and string processing: `libstr.etex`
+    - The threads library: `libthreads.etex`
+    - The graphics library: `libgraph.etex`
+    - The dynlink library: dynamic loading and linking of object files:
+      `libdynlink.etex`
+    - The bigarray library: `libbigarray.etex`
+
+Latex extensions
+----------------
+
+###Caml environments
+The tool `tool/caml-tex2` is used to generate the latex code for the examples
+in the introduction part of the manual. It implements two pseudo-environments:
+`caml_example` and `caml_eval`.
+
+The pseudo-environment `caml_example` evaluates its contents using an ocaml
+interpreter and then translates both the input code and the interpreter output
+to latex code, e.g.
+```latex
+\begin{caml_example}
+let f x = x
+\end{caml_example}
+```
+Note that the toplevel output can be suppressed by using a `*` suffix:
+```latex
+\begin{caml_example*}
+let f x = x
+\end{caml_example*}
+```
+The `caml_eval` environment is a companion environment to `caml_example`
+and can be used to evaluate OCaml expressions in the toplevel without
+printing anything:
+```latex
+\begin{caml_eval}
+let pi = 4. *. atan 1.
+\end{caml_eval}
+\begin{caml_example}
+let f x = x +. pi
+\end{caml_example}
+```
+Beware that the detection code for these pseudo-environments is quite brittle
+and the environments must start and end at the beginning of the line.
+
+###Quoting
+The tool `tools/texquote2` provides support for verbatim-like quotes using
+`\"` delimiters. More precisely, outside of caml environments and verbatim
+environments, `texquote2` translates double quotes `"text"` to
+`\machine{escaped_text}`.
+
+###BNF grammar notation
+The tool `tools/transf` provides support for BNF grammar notations and a special
+quotation for non-terminal. When transf is used, the environment `syntax` can
+be used to describe grammars using BNF notation:
+```latex
+\begin{syntax}
+expr:
+    value-path
+  | constant
+  | '(' expr ')'
+  | 'begin' expr 'end'
+  | '(' expr ':' typexpr ')'
+  | expr {{',' expr}}
+  | constr expr
+  | "`"tag-name expr
+  | expr '::' expr
+  | '[' expr { ';' expr } [';'] ']'
+  | '[|' expr { ';' expr } [';'] '|]'
+  | '{' field [':' typexpr] '=' expr%
+    { ';' field [':' typexpr] '=' expr } [';'] '}'
+\end{syntax}
+```
+Notice that terminal symbols are quoted using `'` delimiters.
+Moreover, outside of the syntax environment, `@`-quotes can be used
+to introduce fragment of grammar: `@'(' module-expr ')'@`. As a consequence,
+when this extension is used `@` characters must be escaped as `\@`.
+This extension is used mainly in the language reference part of the manual.
+and a more complete description of the notation used is available in the
+first subsection of `refman/refman.etex`.
diff --git a/manual/manual/.gitignore b/manual/manual/.gitignore
new file mode 100644
index 0000000000..71605a704d
--- /dev/null
+++ b/manual/manual/.gitignore
@@ -0,0 +1,8 @@
+allfiles.tex
+biblio.tex
+foreword.tex
+version.tex
+warnings.etex
+warnings.tex
+foreword.htex
+manual.html
diff --git a/manual/manual/Makefile b/manual/manual/Makefile
new file mode 100644
index 0000000000..945c6ba3d5
--- /dev/null
+++ b/manual/manual/Makefile
@@ -0,0 +1,157 @@
+# $Id$
+
+FILES=allfiles.tex biblio.tex foreword.tex version.tex warnings-help.etex
+TEXINPUTS=.:..:../refman:../library:../cmds:../tutorials:../../styles:
+TEXFONTS=../../styles:
+RELEASE=$$HOME/release/$${RELEASENAME}
+HEVEA=hevea
+HACHA=hacha
+INFO=-fix -exec xxdate.exe -info -w 79
+HTML=-fix -exec xxdate.exe -O
+TEXT=-fix -exec xxdate.exe -text -w 79
+SRC = $(abspath ../../)
+
+export LD_LIBRARY_PATH ?= $(SRC)/otherlibs/unix/:$(SRC)/otherlibs/str/
+export DYLD_LIBRARY_PATH ?= $(SRC)/otherlibs/unix/:$(SRC)/otherlibs/str/
+
+OCAMLDOC=$(SRC)/byterun/ocamlrun $(SRC)/ocamldoc/ocamldoc -hide Pervasives
+MLIS=$(SRC)/stdlib/*.mli \
+	$(SRC)/utils/*.mli \
+	$(SRC)/parsing/*.mli \
+	$(SRC)/otherlibs/bigarray/bigarray.mli \
+	$(SRC)/otherlibs/dynlink/dynlink.mli \
+	$(SRC)/otherlibs/graph/graphics.mli \
+	$(SRC)/otherlibs/graph/graphicsX11.mli \
+	$(SRC)/otherlibs/num/num.mli \
+	$(SRC)/otherlibs/num/arith_status.mli \
+	$(SRC)/otherlibs/num/big_int.mli \
+	$(SRC)/otherlibs/num/ratio.mli \
+	$(SRC)/otherlibs/str/*.mli \
+	$(SRC)/otherlibs/systhreads/*.mli \
+	$(SRC)/otherlibs/unix/*.mli
+
+manual: files
+	cd texstuff; \
+	TEXINPUTS=$(TEXINPUTS) latex manual.tex
+
+labltk: cmds/browser.tex library/liblabltk.tex library/tk.mli
+	cd library; $(MAKE) Tk.tex RELEASEDIR=$(SRC)
+	cd texstuff; \
+	TEXINPUTS=$(TEXINPUTS) latex labltk.tex
+
+index::
+	cd texstuff && \
+	  ../../tools/fix_index.sh manual.idx && \
+	  makeindex manual.idx
+	cd texstuff; makeindex manual.kwd.idx
+
+pdfmanual: files
+	cd texstuff; \
+	TEXINPUTS=$(TEXINPUTS) pdflatex pdfmanual.tex
+
+index::
+	cd texstuff && \
+	  ../../tools/fix_index.sh pdfmanual.idx && \
+	  makeindex pdfmanual.idx
+	cd texstuff; makeindex pdfmanual.kwd.idx
+
+html: files
+	cd htmlman; \
+	mkdir -p libref ; \
+	$(OCAMLDOC) -colorize-code -sort -html \
+	-d libref \
+	-I $(SRC)/stdlib  \
+	-I $(SRC)/utils  \
+	-I $(SRC)/parsing \
+	-I $(SRC)/otherlibs/bigarray \
+	-I $(SRC)/otherlibs/dynlink \
+	-I $(SRC)/otherlibs/graph \
+	-I $(SRC)/otherlibs/num \
+	-I $(SRC)/otherlibs/str \
+	-I $(SRC)/otherlibs/systhreads \
+	-I $(SRC)/otherlibs/unix \
+	$(MLIS) ; \
+	cp -f ../style.css libref ; \
+	${HEVEA} ${HTML} -I .. -I ../refman -I ../library -I ../cmds \
+	         -I ../tutorials -I ../../styles -I ../texstuff manual.hva \
+	         -e macros.tex ../manual.tex ; \
+	${HACHA} -tocter manual.html ; \
+
+
+info: files
+	cd infoman; rm -f ocaml.info*; \
+	${HEVEA} ${INFO} -o ocaml.info.body -I .. -I ../refman -I ../library \
+	         -I ../cmds -I ../tutorials -I ../../styles -I ../texstuff \
+	         ../manual.inf -e macros.tex ../manual.tex
+	cat manual.info.header infoman/ocaml.info.body > infoman/ocaml.info
+	cd infoman; rm -f ocaml.info.tmp ocaml.info.body ; gzip -9 ocaml.info*
+
+text: files
+	cd textman; \
+	${HEVEA} ${TEXT} -I .. -I ../refman -I ../library -I ../cmds \
+	         -I ../tutorials -I ../../styles -I ../texstuff \
+	         ../manual.inf -e macros.tex ../manual.tex
+
+files: $(FILES)
+	cd refman; $(MAKE) all RELEASEDIR=$(SRC)
+	cd library; $(MAKE) all RELEASEDIR=$(SRC)
+	cd cmds; $(MAKE) all RELEASEDIR=$(SRC)
+	cd tutorials; $(MAKE) all RELEASEDIR=$(SRC)
+
+all:
+	$(MAKE) manual pdfmanual RELEASEDIR=$(SRC)
+	$(MAKE) manual pdfmanual RELEASEDIR=$(SRC)
+	$(MAKE) index RELEASEDIR=$(SRC)
+	$(MAKE) manual pdfmanual RELEASEDIR=$(SRC)
+	$(MAKE) html text info RELEASEDIR=$(SRC)
+
+clean:
+	rm -f $(FILES)
+	cd refman; $(MAKE) clean
+	cd library; $(MAKE) clean
+	cd cmds; $(MAKE) clean
+	cd tutorials; $(MAKE) clean
+	-rm -f texstuff/*
+	cd htmlman; rm -rf libref index.html manual*.html *.haux *.hind
+	cd textman; rm -f manual.txt *.haux *.hind
+	cd infoman; rm -f ocaml.info ocaml.info-*  *.haux *.hind
+	rm -f warnings-help.etex
+
+release:
+	gzip < texstuff/manual.dvi > $(RELEASE)refman.dvi.gz
+	dvips -o '!gzip > $(RELEASE)refman.ps.gz' texstuff/manual.dvi
+	cp htmlman/manual.html $(RELEASE)refman.html
+	rm -f htmlman/manual.{html,haux,hmanual*,htoc}
+	tar zcf $(RELEASE)refman-html.tar.gz htmlman/*.* htmlman/libref
+	zip -8 $(RELEASE)refman-html.zip htmlman/*.* htmlman/libref/*.*
+	cp texstuff/pdfmanual.pdf $(RELEASE)refman.pdf
+	cp textman/manual.txt $(RELEASE)refman.txt
+	tar cf - infoman/ocaml.info* | gzip > $(RELEASE)refman.info.tar.gz
+
+.SUFFIXES:
+.SUFFIXES: .tex .etex .htex
+
+.etex.tex:
+	../tools/texquote2 < $*.etex > $*.tex
+
+version.tex: $(SRC)/VERSION
+	sed -n -e '1s/^\([0-9]*\.[0-9]*\).*$$/\\def\\ocamlversion{\1}/p' \
+	    $(SRC)/VERSION > version.tex
+
+warnings-help.etex: $(SRC)/utils/warnings.ml $(SRC)/ocamlc
+	(echo "% This file is generated from (ocamlc -warn-help)";\
+	 echo "% according to a rule in manual/manual/Makefile.";\
+	 echo "% In particular, the reference to documentation sections";\
+	 echo "% are inserted through the Makefile, which should be updated";\
+	 echo "% when a new warning is documented.";\
+	 echo "%";\
+	$(SRC)/boot/ocamlrun $(SRC)/ocamlc -warn-help \
+	| sed -e 's/^ *\([0-9A-Z][0-9]*\)\(.*\)/\\item[\1] \2/'\
+	) >$@
+#	sed --inplace is not portable, emulate
+	for i in 52 57; do\
+		sed\
+		  s'/\\item\['$$i'\]/\\item\['$$i' (see \\ref{ss:warn'$$i'})\]/'\
+                  $@ > $@.tmp;\
+		mv $@.tmp $@;\
+	done
diff --git a/manual/manual/allfiles.etex b/manual/manual/allfiles.etex
new file mode 100644
index 0000000000..aee6cc7254
--- /dev/null
+++ b/manual/manual/allfiles.etex
@@ -0,0 +1,107 @@
+\makeindex{\jobname}
+\makeindex{\jobname.kwd}
+
+\setlength{\emergencystretch}{50pt}  % pour que TeX resolve les overfull hbox lui-meme
+
+\begin{document}
+
+\thispagestyle{empty}
+\begin{center}
+~\vfill
+\Huge           The OCaml system \\
+                release \ocamlversion \\[1cm]
+\Large          Documentation and user's manual \\[1cm]
+\large          Xavier Leroy, \\
+                Damien Doligez, Alain Frisch, Jacques Garrigue, Didier R�my and J�r�me Vouillon \\[1cm]
+                \today \\
+                ~
+\vfill
+\normalsize     Copyright \copyright\ \number\year\ Institut National de
+                Recherche en Informatique et en Automatique
+\end{center}
+\cleardoublepage
+\setcounter{page}{1}
+
+
+\begin{htmlonly}
+\begin{quote}
+\rule{}{}
+This manual is also available in
+\ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman.pdf}{PDF}.
+\ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman.ps.gz}{Postscript},
+\ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman.dvi.gz}{DVI},
+\ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman.txt}{plain text},
+as a
+\ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman-html.tar.gz}{bundle of HTML files},
+and as a
+\ahref{http://caml.inria.fr/distrib/ocaml-\ocamlversion/ocaml-\ocamlversion-refman.info.tar.gz}{bundle of Emacs Info files}.
+\rule{}{}
+\end{quote}
+\end{htmlonly}
+
+\tableofcontents
+
+\input{foreword.tex}
+
+\part{An introduction to OCaml}
+\label{p:tutorials}
+\input{coreexamples.tex}
+\input{moduleexamples.tex}
+\input{objectexamples.tex}
+\input{lablexamples.tex}
+\input{advexamples.tex}
+
+\part{The OCaml language}
+\label{p:refman}
+\input{refman.tex}
+\input{exten.tex}
+
+\part{The OCaml tools}
+\label{p:commands}
+
+\input{comp.tex}
+\input{top.tex}
+\input{runtime.tex}
+\input{native.tex}
+\input{lexyacc.tex}
+\input{depend.tex}
+\input{browser.tex}
+\input{ocamldoc.tex}
+\input{debugger.tex}
+\input{profil.tex}
+\input{ocamlbuild.tex}
+% \input emacs.tex
+\input{intf-c.tex}
+\input{flambda.tex}
+\input{spacetime.tex}
+
+\part{The OCaml library}
+\label{p:library}
+\input{core.tex}
+\input{stdlib.tex}
+\input{compilerlibs.tex}
+\input{libunix.tex}
+\input{libnum.tex}
+\input{libstr.tex}
+\input{libthreads.tex}
+\input{libgraph.tex}
+\input{libdynlink.tex}
+\input{libbigarray.tex}
+
+\part{Appendix}
+\label{p:appendix}
+
+\ifouthtml
+\begin{links}
+\item \ahref{libref/index_modules.html}{Index of modules}
+\item \ahref{libref/index_module_types.html}{Index of module types}
+\item \ahref{libref/index_types.html}{Index of types}
+\item \ahref{libref/index_exceptions.html}{Index of exceptions}
+\item \ahref{libref/index_values.html}{Index of values}
+\end{links}
+\else
+\printindex{\jobname}{Index to the library}
+\fi
+\printindex{\jobname.kwd}{Index of keywords}
+
+\end{document}
diff --git a/manual/manual/biblio.etex b/manual/manual/biblio.etex
new file mode 100644
index 0000000000..dd4c26dd92
--- /dev/null
+++ b/manual/manual/biblio.etex
@@ -0,0 +1,240 @@
+\chapter{Further reading}
+
+For the interested reader, we list below some references to books and
+reports related (sometimes loosely) to Caml Light.
+
+\section{Programming in ML}
+
+The books below are programming courses taught in ML. Their main goal
+is to teach programming, not to describe ML in full details --- though
+most contain fairly good introductions to the ML language. Some of
+those books use the Standard ML dialect instead of the Caml dialect,
+so you will have to keep in mind the differences in syntax and in
+semantics.
+
+\begin{itemize}
+
+\item Pierre Weis and Xavier Leroy. {\it Le langage Caml.}
+Inter�ditions, 1993.
+
+The natural companion to this manual, provided you read French. This
+book is a step-by-step introduction to programming in Caml, and
+presents many realistic examples of Caml programs.
+
+\item  Guy Cousineau and Michel Mauny. {\it Approche fonctionnelle de
+la programmation}. Ediscience, 1995.
+
+Another Caml programming course written in French, with many original
+examples.
+
+\item Lawrence C.\ Paulson. {\it ML for the working programmer.}
+Cambridge University Press, 1991.
+
+A good introduction to programming in Standard ML. Develops a
+theorem prover as a complete example. Contains a presentation of
+the module system of Standard ML.
+
+\item Jeffrey D.\ Ullman. {\it Elements of ML programming.}
+Prentice Hall, 1993.
+
+Another good introduction to programming in Standard ML. No realistic
+examples, but a very detailed presentation of the language constructs.
+
+\item Ryan Stansifer. {\em ML primer.} Prentice-Hall, 1992.
+
+A short, but nice introduction to programming in Standard ML.
+
+\item Th�r�se Accart Hardin and V�ronique Donzeau-Gouge Vigui�. {\em
+Concepts et outils de la programmation. Du fonctionnel �
+l'imp�ratif avec Caml et Ada.} Inter�ditions, 1992.
+
+A first course in programming, that first introduces the main programming
+notions in Caml, then shows them underlying Ada. Intended for
+beginners; slow-paced for the others.
+
+\item Rachel Harrison. {\em Abstract Data Types in Standard ML}.
+John Wiley \& Sons, 1993.
+
+A presentation of Standard ML from the standpoint of abstract data
+types. Uses intensively the Standard ML module system.
+
+\item Harold Abelson and Gerald Jay Sussman.
+{\em Structure and Interpretation of Computer Programs.} The MIT
+press, 1985.  (French translation: {\em Structure et interpr�tation
+des programmes informatiques}, Inter�ditions, 1989.)
+
+An outstanding course on programming, taught in Scheme, the modern
+dialect of Lisp. Well worth reading, even if you are more interested
+in ML than in Lisp.
+
+\end{itemize}
+
+\section{Descriptions of ML dialects}
+
+The books and reports below are descriptions of various programming
+languages from the ML family. They assume some familiarity with ML.
+
+\begin{itemize}
+
+\item Xavier Leroy and Pierre Weis. {\em Manuel de r�f�rence du
+langage Caml.} Inter�ditions, 1993.
+
+The French edition of the present reference manual and user's manual.
+
+\item Robert Harper. {\em Introduction to Standard ML.} Technical
+report ECS-LFCS-86-14, University of Edinburgh, 1986.
+
+An overview of Standard ML, including the module system. Terse, but
+still readable.
+
+\item Robin Milner, Mads Tofte and Robert Harper. {\em The definition
+of Standard ML.} The MIT press, 1990.
+
+A complete formal definition of Standard ML, in the framework of
+structured operational semantics. This book is probably the most
+mathematically precise definition of a programming language ever
+written. It is heavy on formalism and extremely terse, so
+even readers who are thoroughly familiar with ML will have
+major difficulties with it.
+
+\item Robin Milner and Mads Tofte. {\em Commentary on Standard ML.}
+The MIT Press, 1991.
+
+A commentary on the book above, that attempts to explain the most
+delicate parts and motivate the design choices. Easier to read than the
+Definition, but still rather involving.
+
+\item Guy Cousineau and G�rard Huet. {\em The CAML primer.} Technical
+report~122, INRIA, 1990.
+
+A short description of the original Caml system, from which Caml Light
+has evolved. Some familiarity with Lisp is assumed.
+
+\item Pierre Weis et al. {\em The CAML reference manual, version
+2.6.1.} Technical report~121, INRIA, 1990.
+
+The manual for the original Caml system, from which Caml Light
+has evolved.  
+
+\item Michael J.\ Gordon, Arthur J.\ Milner and Christopher P.\ Wadsworth.
+{\em Edinburgh LCF.} Lecture Notes in Computer Science
+volume~78, Springer-Verlag, 1979.
+
+This is the first published description of the ML language, at the
+time when it was nothing more than the control language for the LCF
+system, a theorem prover. This book is now obsolete, since the ML
+language has much evolved since then; but it is still of historical
+interest.
+
+\item Paul Hudak, Simon Peyton-Jones and Philip Wadler. {\em
+Report on the programming language Haskell, version 1.1.} Technical
+report, Yale University, 1991.
+
+Haskell is a purely functional language with lazy semantics that
+shares many important points with ML (full functionality, polymorphic
+typing), but has interesting features of its own (dynamic overloading,
+also called type classes).
+
+\end{itemize}
+
+\section{Implementing functional programming languages}
+
+The references below are intended for those who are curious to learn
+how a language like Caml Light is compiled and implemented.
+
+\begin{itemize}
+
+\item Xavier Leroy. {\em The ZINC experiment: an economical
+implementation of the ML language.} Technical report~117, INRIA, 1990.
+(Available by anonymous FTP on "ftp.inria.fr".)
+
+A description of the ZINC implementation, the prototype ML
+implementation that has evolved into Caml Light. Large parts of this
+report still apply to the current Caml Light system, in particular the
+description of the execution model and abstract machine. Other parts
+are now obsolete. Yet this report still gives a complete overview of the
+implementation techniques used in Caml Light.
+
+\item Simon Peyton-Jones. {\em The implementation of functional
+programming languages.} Prentice-Hall, 1987. (French translation:
+{\em Mise en \oe uvre des langages fonctionnels de programmation},
+Masson, 1990.)
+
+An excellent description of the implementation of purely functional
+languages with lazy semantics, using the technique known as graph
+reduction. The part of the book that deals with the transformation
+from ML to enriched lambda-calculus directly applies to Caml Light.
+You will find a good description of how pattern-matching is compiled
+and how types are inferred. The remainder of the book does not apply
+directly to Caml Light, since Caml Light is not purely functional (it
+has side-effects), has strict semantics, and does not use graph
+reduction at all.
+
+\item Andrew W.\ Appel. {\em Compiling with continuations.} Cambridge
+University Press, 1992.
+
+A complete description of an optimizing compiler for Standard ML,
+based on an intermediate representation called continuation-passing
+style. Shows how many advanced program optimizations can be applied to
+ML. Not directly relevant to the Caml Light system, since Caml Light
+does not use continuation-passing style at all, and makes little
+attempts at optimizing programs.
+
+\end{itemize}
+
+\section{Applications of ML}
+
+The following reports show ML at work in various, sometimes
+unexpected, areas.
+
+\begin{itemize}
+
+\item Emmanuel Chailloux and Guy Cousineau. {\em The MLgraph primer.}
+Technical report 92-15, �cole Normale Sup�rieure, 1992. (Available by
+anonymous FTP on "ftp.ens.fr".)
+%, r�pertoire "biblio", fichier
+% "liens-92-15.A4.300dpi.ps.Z".)
+
+Describes a Caml Light library that produces Postscript pictures
+through high-level drawing functions.
+
+\item Xavier Leroy. {\em Programmation du syst�me Unix en Caml Light.}
+Technical report~147, INRIA, 1992. (Available by anonymous FTP on
+"ftp.inria.fr".)
+%, r�pertoire "INRIA/publication", fichier "RT-0147.ps.Z".)
+
+A Unix systems programming course, demonstrating the use of the Caml
+Light library that gives access to Unix system calls.
+
+\item John H.\ Reppy. {\em Concurrent programming with events --- The
+concurrent ML manual.} Cornell University, 1990.
+(Available by anonymous FTP on "research.att.com".)
+%, r�pertoire "dist/ml", fichier "CML-0.9.8.tar.Z".)
+
+Concurrent ML extends Standard ML of New Jersey with concurrent
+processes that communicate through channels and events.
+
+\item Jeannette M. Wing, Manuel Faehndrich, J.\ Gregory Morrisett and
+Scottt Nettles. {\em Extensions to Standard ML to support
+transactions.} Technical report CMU-CS-92-132, Carnegie-Mellon
+University, 1992. (Available by anonymous FTP on
+"reports.adm.cs.cmu.edu".)
+% , r�pertoire "1992", fichier "CMU-CS-92-132.ps".)
+
+How to integrate the basic database operations to Standard ML.
+
+\item Emden R.\ Gansner and John H.\ Reppy. {\em eXene.} Bell Labs,
+1991. (Available by anonymous FTP on "research.att.com".)
+%, r�pertoire "dist/ml", fichier "eXene-0.4.tar.Z".)
+
+An interface between Standard ML of New Jersey and the X Windows
+windowing system.
+
+%% \item Daniel de Rauglaudre. {\em X toolkit in Caml Light.} INRIA,
+%% 1992. (Included in the Caml Light distribution.)
+%% % Disponible par FTP anonyme sur
+%% % "ftp.inria.fr", r�pertoire "lang/caml-light", fichier "rt5.tar.Z".)
+%% 
+%% An interface between Caml Light and the X Windows windowing system. 
+
+\end{itemize}
diff --git a/manual/manual/cmds/.gitignore b/manual/manual/cmds/.gitignore
new file mode 100644
index 0000000000..0d45900b3a
--- /dev/null
+++ b/manual/manual/cmds/.gitignore
@@ -0,0 +1,3 @@
+*.tex
+*.htex
+warnings.etex
diff --git a/manual/manual/cmds/Makefile b/manual/manual/cmds/Makefile
new file mode 100644
index 0000000000..26da7bc34a
--- /dev/null
+++ b/manual/manual/cmds/Makefile
@@ -0,0 +1,49 @@
+FILES=comp.tex top.tex runtime.tex native.tex lexyacc.tex intf-c.tex \
+  depend.tex profil.tex debugger.tex browser.tex ocamldoc.tex \
+  warnings-help.tex ocamlbuild.tex flambda.tex spacetime.tex
+
+TOPDIR=../../..
+include $(TOPDIR)/Makefile.tools
+
+TRANSF=$(OCAMLRUN) ../../tools/transf
+TEXQUOTE=../../tools/texquote2
+FORMAT=../../tools/format-intf
+
+all: $(FILES)
+
+clean::
+	rm -f $(FILES)
+	rm -f *~ #*#
+
+.SUFFIXES:
+.SUFFIXES: .tex .etex
+
+.etex.tex:
+	$(TEXQUOTE) < $*.etex > $*.tex
+
+ocamldoc.tex: ocamldoc.etex $(TRANSF)
+	$(TRANSF) < ocamldoc.etex | $(TEXQUOTE) > ocamldoc.tex
+
+top.tex: top.etex $(TRANSF)
+	$(TRANSF) < top.etex | $(TEXQUOTE) > top.tex
+
+intf-c.tex: intf-c.etex $(TRANSF)
+	$(TRANSF) < intf-c.etex | $(TEXQUOTE) > intf-c.tex
+
+flambda.tex: flambda.etex $(TRANSF)
+	$(TRANSF) < flambda.etex | $(TEXQUOTE) > flambda.tex
+
+spacetime.tex: spacetime.etex $(TRANSF)
+	$(TRANSF) < spacetime.etex | $(TEXQUOTE) > spacetime.tex
+
+lexyacc.tex: lexyacc.etex $(TRANSF)
+	$(TRANSF) < lexyacc.etex | $(TEXQUOTE) > lexyacc.tex
+
+debugger.tex: debugger.etex $(TRANSF)
+	$(TRANSF) < debugger.etex | $(TEXQUOTE) > debugger.tex
+
+warnings-help.etex: ../warnings-help.etex
+	cp ../warnings-help.etex .
+
+clean::
+	rm -f warnings-help.etex
diff --git a/manual/manual/cmds/browser.etex b/manual/manual/cmds/browser.etex
new file mode 100644
index 0000000000..5eb5a4fff7
--- /dev/null
+++ b/manual/manual/cmds/browser.etex
@@ -0,0 +1,7 @@
+\chapter{The browser/editor (ocamlbrowser)} \label{c:browser}
+\pdfchapter{The browser/editor (ocamlbrowser)}
+%HEVEA\cutname{browser.html}
+
+Since OCaml version 4.02, the OCamlBrowser tool and the Labltk library
+are distributed separately from the OCaml compiler. The project is now
+hosted at \url{https://forge.ocamlcore.org/projects/labltk/}.
diff --git a/manual/manual/cmds/comp.etex b/manual/manual/cmds/comp.etex
new file mode 100644
index 0000000000..36b57f579c
--- /dev/null
+++ b/manual/manual/cmds/comp.etex
@@ -0,0 +1,927 @@
+\chapter{Batch compilation (ocamlc)} \label{c:camlc}
+\pdfchapter{Batch compilation (ocamlc)}
+%HEVEA\cutname{comp.html}
+
+This chapter describes the OCaml batch compiler "ocamlc",
+which compiles OCaml source files to bytecode object files and links
+these object files to produce standalone bytecode executable files.
+These executable files are then run by the bytecode interpreter
+"ocamlrun".
+
+\section{Overview of the compiler}
+
+The "ocamlc" command has a command-line interface similar to the one of
+most C compilers. It accepts several types of arguments and processes them
+sequentially, after all options have been processed:
+
+\begin{itemize}
+\item
+Arguments ending in ".mli" are taken to be source files for
+compilation unit interfaces. Interfaces specify the names exported by
+compilation units: they declare value names with their types, define
+public data types, declare abstract data types, and so on. From the
+file \var{x}".mli", the "ocamlc" compiler produces a compiled interface
+in the file \var{x}".cmi".
+
+\item
+Arguments ending in ".ml" are taken to be source files for compilation
+unit implementations. Implementations provide definitions for the
+names exported by the unit, and also contain expressions to be
+evaluated for their side-effects.  From the file \var{x}".ml", the "ocamlc"
+compiler produces compiled object bytecode in the file \var{x}".cmo".
+
+If the interface file \var{x}".mli" exists, the implementation
+\var{x}".ml" is checked against the corresponding compiled interface
+\var{x}".cmi", which is assumed to exist. If no interface
+\var{x}".mli" is provided, the compilation of \var{x}".ml" produces a
+compiled interface file \var{x}".cmi" in addition to the compiled
+object code file \var{x}".cmo". The file \var{x}".cmi" produced
+corresponds to an interface that exports everything that is defined in
+the implementation \var{x}".ml".
+
+\item
+Arguments ending in ".cmo" are taken to be compiled object bytecode.  These
+files are linked together, along with the object files obtained
+by compiling ".ml" arguments (if any), and the OCaml standard
+library, to produce a standalone executable program. The order in
+which ".cmo" and ".ml" arguments are presented on the command line is
+relevant: compilation units are initialized in that order at
+run-time, and it is a link-time error to use a component of a unit
+before having initialized it. Hence, a given \var{x}".cmo" file must come
+before all ".cmo" files that refer to the unit \var{x}.
+
+\item
+Arguments ending in ".cma" are taken to be libraries of object bytecode.
+A library of object bytecode packs in a single file a set of object
+bytecode files (".cmo" files). Libraries are built with "ocamlc -a"
+(see the description of the "-a" option below). The object files
+contained in the library are linked as regular ".cmo" files (see
+above), in the order specified when the ".cma" file was built. The
+only difference is that if an object file contained in a library is
+not referenced anywhere in the program, then it is not linked in.
+
+\item
+Arguments ending in ".c" are passed to the C compiler, which generates
+a ".o" object file (".obj" under Windows). This object file is linked
+with the program if the "-custom" flag is set (see the description of
+"-custom" below).
+
+\item
+Arguments ending in ".o" or ".a" (".obj" or ".lib" under Windows)
+are assumed to be C object files and libraries. They are passed to the
+C linker when linking in "-custom" mode (see the description of
+"-custom" below).
+
+\item
+Arguments ending in ".so" (".dll" under Windows)
+are assumed to be C shared libraries (DLLs).  During linking, they are
+searched for external C functions referenced from the OCaml code,
+and their names are written in the generated bytecode executable.
+The run-time system "ocamlrun" then loads them dynamically at program
+start-up time.
+
+\end{itemize}
+
+The output of the linking phase is a file containing compiled bytecode
+that can be executed by the OCaml bytecode interpreter:
+the command named "ocamlrun". If "a.out" is the name of the file
+produced by the linking phase, the command
+\begin{alltt}
+        ocamlrun a.out \nth{arg}{1} \nth{arg}{2} \ldots \nth{arg}{n}
+\end{alltt}
+executes the compiled code contained in "a.out", passing it as
+arguments the character strings \nth{arg}{1} to \nth{arg}{n}.
+(See chapter~\ref{c:runtime} for more details.)
+
+On most systems, the file produced by the linking
+phase can be run directly, as in:
+\begin{alltt}
+        ./a.out \nth{arg}{1} \nth{arg}{2} \ldots \nth{arg}{n}
+\end{alltt}
+The produced file has the executable bit set, and it manages to launch
+the bytecode interpreter by itself.
+
+\section{Options}\label{s:comp-options}
+
+The following command-line options are recognized by "ocamlc".
+The options "-pack", "-a", "-c" and "-output-obj" are mutually exclusive.
+
+
+\begin{options}
+
+\item["-a"]
+Build a library (".cma" file) with the object files (".cmo" files)
+given on the command line, instead of linking them into an executable
+file. The name of the library must be set with the "-o" option.
+
+If "-custom", "-cclib" or "-ccopt" options are passed on the command
+line, these options are stored in the resulting ".cma" library.  Then,
+linking with this library automatically adds back the "-custom",
+"-cclib" and "-ccopt" options as if they had been provided on the
+command line, unless the "-noautolink" option is given.
+
+\item["-absname"]
+Force error messages to show absolute paths for file names.
+
+\item["-annot"]
+Dump detailed information about the compilation (types, bindings,
+tail-calls, etc).  The information for file \var{src}".ml"
+is put into file \var{src}".annot".  In case of a type error, dump
+all the information inferred by the type-checker before the error.
+The \var{src}".annot" file can be used with the emacs commands given in
+"emacs/caml-types.el" to display types and other annotations
+interactively.
+
+\item["-bin-annot"]
+Dump detailed information about the compilation (types, bindings,
+tail-calls, etc) in binary format. The information for file \var{src}".ml"
+is put into file \var{src}".cmt".  In case of a type error, dump
+all the information inferred by the type-checker before the error.
+The "*.cmt" files produced by "-bin-annot" contain more information
+and are much more compact than the files produced by "-annot".
+
+\item["-c"]
+Compile only. Suppress the linking phase of the
+compilation. Source code files are turned into compiled files, but no
+executable file is produced. This option is useful to
+compile modules separately.
+
+\item["-cc" \var{ccomp}]
+Use \var{ccomp} as the C linker when linking in ``custom runtime''
+mode (see the "-custom" option)
+and as the C compiler for compiling ".c" source files.
+
+\item["-cclib" "-l"\var{libname}]
+Pass the "-l"\var{libname} option to the C linker when linking in
+``custom runtime'' mode (see the "-custom" option). This causes the
+given C library to be linked with the program.
+
+\item["-ccopt" \var{option}]
+Pass the given option to the C compiler and linker. When linking in
+``custom runtime'' mode, for instance,
+"-ccopt -L"\var{dir} causes the C linker to search for C libraries in
+directory \var{dir}.   (See the "-custom" option.)
+
+\item["-color" \var{mode}]
+Enable or disable colors in compiler messages (especially warnings and errors).
+The following modes are supported:
+\begin{description}
+  \item["auto"] use heuristics to enable colors only if the output supports them (an ANSI-compatible tty terminal);
+  \item["always"] enable colors unconditionally;
+  \item["never"] disable color output.
+\end{description}
+The default setting is 'auto', and the current heuristic
+checks that the "TERM" environment variable exists and is
+not empty or "dumb", and that \verb!isatty(stderr)! holds.
+
+
+\item["-compat-32"]
+Check that the generated bytecode executable can run on 32-bit
+platforms and signal an error if it cannot. This is useful when
+compiling bytecode on a 64-bit machine.
+
+\item["-config"]
+Print the version number of "ocamlc" and a detailed summary of its
+configuration, then exit.
+
+\item["-custom"]
+Link in ``custom runtime'' mode. In the default linking mode, the
+linker produces bytecode that is intended to be executed with the
+shared runtime system, "ocamlrun". In the custom runtime mode, the
+linker produces an output file that contains both the runtime system
+and the bytecode for the program. The resulting file is larger, but it
+can be executed directly, even if the "ocamlrun" command is not
+installed. Moreover, the ``custom runtime'' mode enables static
+linking of OCaml code with user-defined C functions, as described in
+chapter~\ref{c:intf-c}.
+\begin{unix}
+Never use the "strip" command on executables produced by "ocamlc -custom",
+this would remove the bytecode part of the executable.
+\end{unix}
+
+\item["-dllib" "-l"\var{libname}]
+Arrange for the C shared library "dll"\var{libname}".so"
+("dll"\var{libname}".dll" under Windows) to be loaded dynamically
+by the run-time system "ocamlrun" at program start-up time.
+
+\item["-dllpath" \var{dir}]
+Adds the directory \var{dir} to the run-time search path for shared
+C libraries.  At link-time, shared libraries are searched in the
+standard search path (the one corresponding to the "-I" option).
+The "-dllpath" option simply stores \var{dir} in the produced
+executable file, where "ocamlrun" can find it and use it as
+described in section~\ref{s-ocamlrun-dllpath}.
+
+\item["-for-pack" \var{module-path}]
+Generate an object file (".cmo") that can later be
+included
+as a sub-module (with the given access path) of a compilation unit
+constructed with "-pack".  For instance, "ocamlc -for-pack P -c A.ml"
+will generate "a.cmo" that can later be used with
+"ocamlc -pack -o P.cmo a.cmo".
+Note: you can still pack a module that was compiled without
+"-for-pack"
+but in this case exceptions will be printed with the wrong names.
+
+\item["-g"]
+Add debugging information while compiling and linking. This option is
+required in order to be able to debug the program with "ocamldebug"
+(see chapter~\ref{c:debugger}), and to produce stack backtraces when
+the program terminates on an uncaught exception (see
+section~\ref{ocamlrun-options}).
+
+\item["-i"]
+Cause the compiler to print all defined names (with their inferred
+types or their definitions) when compiling an implementation (".ml"
+file).  No compiled files (".cmo" and ".cmi" files) are produced.
+This can be useful to check the types inferred by the
+compiler. Also, since the output follows the syntax of interfaces, it
+can help in writing an explicit interface (".mli" file) for a file:
+just redirect the standard output of the compiler to a ".mli" file,
+and edit that file to remove all declarations of unexported names.
+
+\item["-I" \var{directory}]
+Add the given directory to the list of directories searched for
+compiled interface files (".cmi"), compiled object code files
+(".cmo"), libraries (".cma"), and C libraries specified with
+"-cclib -lxxx".  By default, the current directory is
+searched first, then the standard library directory. Directories added
+with "-I" are searched after the current directory, in the order in
+which they were given on the command line, but before the standard
+library directory. See also option "-nostdlib".
+
+If the given directory starts with "+", it is taken relative to the
+standard library directory.  For instance, "-I +labltk" adds the
+subdirectory "labltk" of the standard library to the search path.
+
+\item["-impl" \var{filename}]
+Compile the file \var{filename} as an implementation file, even if its
+extension is not ".ml".
+
+\item["-intf" \var{filename}]
+Compile the file \var{filename} as an interface file, even if its
+extension is not ".mli".
+
+\item["-intf-suffix" \var{string}]
+Recognize file names ending with \var{string} as interface files
+(instead of the default ".mli").
+
+\item["-labels"]
+Labels are not ignored in types, labels may be used in applications,
+and labelled parameters can be given in any order.  This is the default.
+
+\item["-linkall"]
+Force all modules contained in libraries to be linked in. If this
+flag is not given, unreferenced modules are not linked in. When
+building a library (option "-a"), setting the "-linkall" option forces all
+subsequent links of programs involving that library to link all the
+modules contained in the library.
+
+\item["-make-runtime"]
+Build a custom runtime system (in the file specified by option "-o")
+incorporating the C object files and libraries given on the command
+line.  This custom runtime system can be used later to execute
+bytecode executables produced with the
+"ocamlc -use-runtime" \var{runtime-name} option.
+See section~\ref{s:custom-runtime} for more information.
+
+\item["-no-alias-deps"]
+Do not record dependencies for module aliases. See
+section~\ref{s:module-alias} for more information.
+
+\item["-no-app-funct"]
+Deactivates the applicative behaviour of functors. With this option,
+each functor application generates new types in its result and
+applying the same functor twice to the same argument yields two
+incompatible structures.
+
+\item["-noassert"]
+Do not compile assertion checks.  Note that the special form
+"assert false" is always compiled because it is typed specially.
+This flag has no effect when linking already-compiled files.
+
+\item["-noautolink"]
+When linking ".cma" libraries, ignore "-custom", "-cclib" and "-ccopt"
+options potentially contained in the libraries (if these options were
+given when building the libraries).  This can be useful if a library
+contains incorrect specifications of C libraries or C options; in this
+case, during linking, set "-noautolink" and pass the correct C
+libraries and options on the command line.
+
+\item["-nolabels"]
+Ignore non-optional labels in types. Labels cannot be used in
+applications, and parameter order becomes strict.
+
+\item["-nostdlib"]
+Do not include the standard library directory in the list of
+directories searched for
+compiled interface files (".cmi"), compiled object code files
+(".cmo"), libraries (".cma"), and C libraries specified with
+"-cclib -lxxx". See also option "-I".
+
+\item["-o" \var{exec-file}]
+Specify the name of the output file produced by the compiler. The
+default output name is "a.out" under Unix and "camlprog.exe" under
+Windows. If the "-a" option is given, specify the name of the library
+produced.  If the "-pack" option is given, specify the name of the
+packed object file produced.  If the "-output-obj" option is given,
+specify the name of the output file produced.  If the "-c" option is
+given, specify the name of the object file produced for the {\em next}
+source file that appears on the command line.
+
+\item["-open" \var{Module}]
+Opens the given module before processing the interface or
+implementation files. If several "-open" options are given,
+they are processed in order, just as if
+the statements "open!" \var{Module1}";;" "..." "open!" \var{ModuleN}";;"
+were added at the top of each file.
+
+\item["-output-obj"]
+Cause the linker to produce a C object file instead of a bytecode
+executable file. This is useful to wrap OCaml code as a C library,
+callable from any C program. See chapter~\ref{c:intf-c},
+section~\ref{s:embedded-code}. The name of the output object file
+must be set with the "-o" option. This
+option can also be used to produce a C source file (".c" extension) or
+a compiled shared/dynamic library (".so" extension, ".dll" under Windows).
+
+\item["-pack"]
+Build a bytecode object file (".cmo" file) and its associated compiled
+interface (".cmi") that combines the object
+files given on the command line, making them appear as sub-modules of
+the output ".cmo" file.  The name of the output ".cmo" file must be
+given with the "-o" option.  For instance,
+\begin{verbatim}
+        ocamlc -pack -o p.cmo a.cmo b.cmo c.cmo
+\end{verbatim}
+generates compiled files "p.cmo" and "p.cmi" describing a compilation
+unit having three sub-modules "A", "B" and "C", corresponding to the
+contents of the object files "a.cmo", "b.cmo" and "c.cmo".  These
+contents can be referenced as "P.A", "P.B" and "P.C" in the remainder
+of the program.
+
+\item["-plugin" \var{plugin}]
+Dynamically load the code of the given \var{plugin}
+(a ".cmo", ".cma" or ".cmxs" file) in the compiler. \var{plugin} must exist in
+the same kind of code as the compiler ("ocamlc.byte" must load bytecode
+plugins, while "ocamlc.opt" must load native code plugins), and
+extension adaptation is done automatically for ".cma" files (to ".cmxs" files
+if the compiler is compiled in native code).
+
+\item["-pp" \var{command}]
+Cause the compiler to call the given \var{command} as a preprocessor
+for each source file. The output of \var{command} is redirected to
+an intermediate file, which is compiled. If there are no compilation
+errors, the intermediate file is deleted afterwards.
+
+\item["-ppx" \var{command}]
+After parsing, pipe the abstract syntax tree through the preprocessor
+\var{command}. The module "Ast_mapper", described in
+chapter~\ref{Ast-underscoremapper}, implements the external interface
+of a preprocessor.
+
+\item["-principal"]
+Check information path during type-checking, to make sure that all
+types are derived in a principal way.  When using labelled arguments
+and/or polymorphic methods, this flag is required to ensure future
+versions of the compiler will be able to infer types correctly, even
+if internal algorithms change.
+All programs accepted in "-principal" mode are also accepted in the
+default mode with equivalent types, but different binary signatures,
+and this may slow down type checking; yet it is a good idea to
+use it once before publishing source code.
+
+\item["-rectypes"]
+Allow arbitrary recursive types during type-checking.  By default,
+only recursive types where the recursion goes through an object type
+are supported. Note that once you have created an interface using this
+flag, you must use it again for all dependencies.
+
+\item["-runtime-variant" \var{suffix}]
+Add the \var{suffix} string to the name of the runtime library used by
+the program.  Currently, only one such suffix is supported: "d", and
+only if the OCaml compiler was configured with option
+"-with-debug-runtime".  This suffix gives the debug version of the
+runtime, which is useful for debugging pointer problems in low-level
+code such as C stubs.
+
+\item["-safe-string"]
+Enforce the separation between types "string" and "bytes",
+thereby making strings read-only. This will become the default in
+a future version of OCaml.
+
+\item["-short-paths"]
+When a type is visible under several module-paths, use the shortest
+one when printing the type's name in inferred interfaces and error and
+warning messages. Identifier names starting with an underscore "_" or
+containing double underscores "__" incur a penalty of $+10$ when computing
+their length.
+
+\item["-strict-sequence"]
+Force the left-hand part of each sequence to have type unit.
+
+\item["-strict-formats"]
+Reject invalid formats that were accepted in legacy format
+implementations. You should use this flag to detect and fix such
+invalid formats, as they will be rejected by future OCaml versions.
+
+\item["-thread"]
+Compile or link multithreaded programs, in combination with the
+system "threads" library described in chapter~\ref{c:threads}.
+
+\item["-unboxed-types"]
+When a type is unboxable (i.e. a record with a single argument or a
+concrete datatype with a single constructor of one argument) it will
+be unboxed unless annotated with "[@@ocaml.boxed]".
+
+\item["-no-unboxed-types"]
+When a type is unboxable  it will be boxed unless annotated with
+"[@@ocaml.unboxed]". This is the default.
+
+\item["-unsafe"]
+Turn bound checking off for array and string accesses (the "v.(i)" and
+"s.[i]" constructs). Programs compiled with "-unsafe" are therefore
+slightly faster, but unsafe: anything can happen if the program
+accesses an array or string outside of its bounds.
+
+\item["-unsafe-string"]
+Identify the types "string" and "bytes",
+thereby making strings writable. For reasons of backward compatibility,
+this is the default setting for the moment, but this will change in a future
+version of OCaml.
+
+\item["-use-runtime" \var{runtime-name}]
+Generate a bytecode executable file that can be executed on the custom
+runtime system \var{runtime-name}, built earlier with
+"ocamlc -make-runtime" \var{runtime-name}.
+See section~\ref{s:custom-runtime} for more information.
+
+\item["-v"]
+Print the version number of the compiler and the location of the
+standard library directory, then exit.
+
+\item["-verbose"]
+Print all external commands before they are executed, in particular
+invocations of the C compiler and linker in "-custom" mode.  Useful to
+debug C library problems.
+
+\item["-vmthread"]
+Compile or link multithreaded programs, in combination with the
+VM-level "threads" library described in chapter~\ref{c:threads}.
+
+\item["-version" or "-vnum"]
+Print the version number of the compiler in short form (e.g. "3.11.0"),
+then exit.
+
+\item["-w" \var{warning-list}]
+Enable, disable, or mark as fatal the warnings specified by the argument
+\var{warning-list}.
+Each warning can be {\em enabled} or {\em disabled}, and each warning
+can be {\em fatal} or {\em non-fatal}.
+If a warning is disabled, it isn't displayed and doesn't affect
+compilation in any way (even if it is fatal).  If a warning is
+enabled, it is displayed normally by the compiler whenever the source
+code triggers it.  If it is enabled and fatal, the compiler will also
+stop with an error after displaying it.
+
+The \var{warning-list} argument is a sequence of warning specifiers,
+with no separators between them.  A warning specifier is one of the
+following:
+
+\begin{options}
+\item["+"\var{num}] Enable warning number \var{num}.
+\item["-"\var{num}] Disable warning number \var{num}.
+\item["@"\var{num}] Enable and mark as fatal warning number \var{num}.
+\item["+"\var{num1}..\var{num2}] Enable warnings in the given range.
+\item["-"\var{num1}..\var{num2}] Disable warnings in the given range.
+\item["@"\var{num1}..\var{num2}] Enable and mark as fatal warnings in
+the given range.
+\item["+"\var{letter}] Enable the set of warnings corresponding to
+\var{letter}. The letter may be uppercase or lowercase.
+\item["-"\var{letter}] Disable the set of warnings corresponding to
+\var{letter}. The letter may be uppercase or lowercase.
+\item["@"\var{letter}] Enable and mark as fatal the set of warnings
+corresponding to \var{letter}. The letter may be uppercase or
+lowercase.
+\item[\var{uppercase-letter}] Enable the set of warnings corresponding
+to \var{uppercase-letter}.
+\item[\var{lowercase-letter}] Disable the set of warnings corresponding
+to \var{lowercase-letter}.
+\end{options}
+
+Warning numbers and letters which are out of the range of warnings
+that are currently defined are ignored. The warnings are as follows.
+\begin{options}
+\input{warnings-help.tex}
+\end{options}
+Some warnings are described in more detail in section~\ref{s:comp-warnings}.
+
+The default setting is "-w +a-4-6-7-9-27-29-32..39-41..42-44-45-48-50".
+It is displayed by "ocamlc -help".
+Note that warnings 5 and 10 are not always triggered, depending on
+the internals of the type checker.
+
+\item["-warn-error" \var{warning-list}]
+Mark as fatal the warnings specified in the argument \var{warning-list}.
+The compiler will stop with an error when one of these warnings is
+emitted. The \var{warning-list} has the same meaning as for
+the "-w" option: a "+" sign (or an uppercase letter) marks the
+corresponding warnings as fatal, a "-"
+sign (or a lowercase letter) turns them back into non-fatal warnings, and a
+"@" sign both enables and marks as fatal the corresponding warnings.
+
+Note: it is not recommended to use warning sets (i.e. letters) as
+arguments to "-warn-error"
+in production code, because this can break your build when future versions
+of OCaml add some new warnings.
+
+The default setting is "-warn-error -a+31" (only warning 31 is fatal).
+
+\item["-warn-help"]
+Show the description of all available warning numbers.
+
+\item["-where"]
+Print the location of the standard library, then exit.
+
+\item["-" \var{file}]
+Process \var{file} as a file name, even if it starts with a dash ("-")
+character.
+
+\item["-help" or "--help"]
+Display a short usage summary and exit.
+%
+\end{options}
+
+\paragraph{Contextual control of command-line options}
+
+The compiler command line can be modified ``from the outside''
+with the following mechanisms. These are experimental
+and subject to change. They should be used only for experimental and
+development work, not in released packages.
+
+\begin{options}
+\item["OCAMLPARAM" \rm(environment variable)]
+Arguments that will be inserted before or after the arguments from the
+command line.
+\item["ocaml_compiler_internal_params" \rm(file in the stdlib directory)]
+A mapping of file names to lists of arguments that
+will be added to the command line (and "OCAMLPARAM") arguments.
+\item["OCAML_FLEXLINK" \rm(environment variable)]
+Alternative executable to use on native
+Windows for "flexlink" instead of the
+configured value. Primarily used for bootstrapping.
+\end{options}
+
+\section{Modules and the file system}
+
+This short section is intended to clarify the relationship between the
+names of the modules corresponding to compilation units and the names
+of the files that contain their compiled interface and compiled
+implementation.
+
+The compiler always derives the module name by taking the capitalized
+base name of the source file (".ml" or ".mli" file).  That is, it
+strips the leading directory name, if any, as well as the ".ml" or
+".mli" suffix; then, it set the first letter to uppercase, in order to
+comply with the requirement that module names must be capitalized.
+For instance, compiling the file "mylib/misc.ml" provides an
+implementation for the module named "Misc". Other compilation units
+may refer to components defined in "mylib/misc.ml" under the names
+"Misc."\var{name}; they can also do "open Misc", then use unqualified
+names \var{name}.
+
+The ".cmi" and ".cmo" files produced by the compiler have the same
+base name as the source file. Hence, the compiled files always have
+their base name equal (modulo capitalization of the first letter) to
+the name of the module they describe (for ".cmi" files) or implement
+(for ".cmo" files).
+
+When the compiler encounters a reference to a free module identifier
+"Mod", it looks in the search path for a file named "Mod.cmi" or "mod.cmi"
+and loads the compiled interface
+contained in that file. As a consequence, renaming ".cmi" files is not
+advised: the name of a ".cmi" file must always correspond to the name
+of the compilation unit it implements. It is admissible to move them
+to another directory, if their base name is preserved, and the correct
+"-I" options are given to the compiler. The compiler will flag an
+error if it loads a ".cmi" file that has been renamed.
+
+Compiled bytecode files (".cmo" files), on the other hand, can be
+freely renamed once created. That's because the linker never attempts
+to find by itself the ".cmo" file that implements a module with a
+given name: it relies instead on the user providing the list of ".cmo"
+files by hand.
+
+\section{Common errors} \label{s:comp-errors}
+
+This section describes and explains the most frequently encountered
+error messages.
+
+\begin{options}
+
+\item[Cannot find file \var{filename}]
+The named file could not be found in the current directory, nor in the
+directories of the search path. The \var{filename} is either a
+compiled interface file (".cmi" file), or a compiled bytecode file
+(".cmo" file). If \var{filename} has the format \var{mod}".cmi", this
+means you are trying to compile a file that references identifiers
+from module \var{mod}, but you have not yet compiled an interface for
+module \var{mod}. Fix: compile \var{mod}".mli" or \var{mod}".ml"
+first, to create the compiled interface \var{mod}".cmi".
+
+If \var{filename} has the format \var{mod}".cmo", this
+means you are trying to link a bytecode object file that does not
+exist yet. Fix: compile \var{mod}".ml" first.
+
+If your program spans several directories, this error can also appear
+because you haven't specified the directories to look into. Fix: add
+the correct "-I" options to the command line.
+
+\item[Corrupted compiled interface \var{filename}]
+The compiler produces this error when it tries to read a compiled
+interface file (".cmi" file) that has the wrong structure. This means
+something went wrong when this ".cmi" file was written: the disk was
+full, the compiler was interrupted in the middle of the file creation,
+and so on. This error can also appear if a ".cmi" file is modified after
+its creation by the compiler. Fix: remove the corrupted ".cmi" file,
+and rebuild it.
+
+\item[This expression has type \nth{t}{1}, but is used with type \nth{t}{2}]
+This is by far the most common type error in programs. Type \nth{t}{1} is
+the type inferred for the expression (the part of the program that is
+displayed in the error message), by looking at the expression itself.
+Type \nth{t}{2} is the type expected by the context of the expression; it
+is deduced by looking at how the value of this expression is used in
+the rest of the program. If the two types \nth{t}{1} and \nth{t}{2} are not
+compatible, then the error above is produced.
+
+In some cases, it is hard to understand why the two types \nth{t}{1} and
+\nth{t}{2} are incompatible. For instance, the compiler can report that
+``expression of type "foo" cannot be used with type "foo"'', and it
+really seems that the two types "foo" are compatible. This is not
+always true. Two type constructors can have the same name, but
+actually represent different types. This can happen if a type
+constructor is redefined. Example:
+\begin{verbatim}
+        type foo = A | B
+        let f = function A -> 0 | B -> 1
+        type foo = C | D
+        f C
+\end{verbatim}
+This result in the error message ``expression "C" of type "foo" cannot
+be used with type "foo"''.
+
+\item[The type of this expression, \var{t}, contains type variables
+      that cannot be generalized]
+Type variables ("'a", "'b", \ldots) in a type \var{t} can be in either
+of two states: generalized (which means that the type \var{t} is valid
+for all possible instantiations of the variables) and not generalized
+(which means that the type \var{t} is valid only for one instantiation
+of the variables). In a "let" binding "let "\var{name}" = "\var{expr},
+the type-checker normally generalizes as many type variables as
+possible in the type of \var{expr}. However, this leads to unsoundness
+(a well-typed program can crash) in conjunction with polymorphic
+mutable data structures. To avoid this, generalization is performed at
+"let" bindings only if the bound expression \var{expr} belongs to the
+class of ``syntactic values'', which includes constants, identifiers,
+functions, tuples of syntactic values, etc. In all other cases (for
+instance, \var{expr} is a function application), a polymorphic mutable
+could have been created and generalization is therefore turned off for
+all variables occurring in contravariant or non-variant branches of the
+type. For instance, if the type of a non-value is "'a list" the
+variable is generalizable ("list" is a covariant type constructor),
+but not in "'a list -> 'a list" (the left branch of "->" is
+contravariant) or "'a ref" ("ref" is non-variant).
+
+Non-generalized type variables in a type cause no difficulties inside
+a given structure or compilation unit (the contents of a ".ml" file,
+or an interactive session), but they cannot be allowed inside
+signatures nor in compiled interfaces (".cmi" file), because they
+could be used inconsistently later. Therefore, the compiler
+flags an error when a structure or compilation unit defines a value
+\var{name} whose type contains non-generalized type variables. There
+are two ways to fix this error:
+\begin{itemize}
+\item Add a type constraint or a ".mli" file to give a monomorphic
+type (without type variables) to \var{name}. For instance, instead of
+writing
+\begin{verbatim}
+    let sort_int_list = Sort.list (<)
+    (* inferred type 'a list -> 'a list, with 'a not generalized *)
+\end{verbatim}
+write
+\begin{verbatim}
+    let sort_int_list = (Sort.list (<) : int list -> int list);;
+\end{verbatim}
+\item If you really need \var{name} to have a polymorphic type, turn
+its defining expression into a function by adding an extra parameter.
+For instance, instead of writing
+\begin{verbatim}
+    let map_length = List.map Array.length
+    (* inferred type 'a array list -> int list, with 'a not generalized *)
+\end{verbatim}
+write
+\begin{verbatim}
+    let map_length lv = List.map Array.length lv
+\end{verbatim}
+\end{itemize}
+
+\item[Reference to undefined global \var{mod}]
+This error appears when trying to link an incomplete or incorrectly
+ordered set of files. Either you have forgotten to provide an
+implementation for the compilation unit named \var{mod} on the command line
+(typically, the file named \var{mod}".cmo", or a library containing
+that file). Fix: add the missing ".ml" or ".cmo" file to the command
+line.  Or, you have provided an implementation for the module named
+\var{mod}, but it comes too late on the command line: the
+implementation of \var{mod} must come before all bytecode object files
+that reference \var{mod}. Fix: change the order of ".ml" and ".cmo"
+files on the command line.
+
+Of course, you will always encounter this error if you have mutually
+recursive functions across modules. That is, function "Mod1.f" calls
+function "Mod2.g", and function "Mod2.g" calls function "Mod1.f".
+In this case, no matter what permutations you perform on the command
+line, the program will be rejected at link-time. Fixes:
+\begin{itemize}
+\item Put "f" and "g" in the same module.
+\item Parameterize one function by the other.
+That is, instead of having
+\begin{verbatim}
+mod1.ml:    let f x = ... Mod2.g ...
+mod2.ml:    let g y = ... Mod1.f ...
+\end{verbatim}
+define
+\begin{verbatim}
+mod1.ml:    let f g x = ... g ...
+mod2.ml:    let rec g y = ... Mod1.f g ...
+\end{verbatim}
+and link "mod1.cmo" before "mod2.cmo".
+\item Use a reference to hold one of the two functions, as in :
+\begin{verbatim}
+mod1.ml:    let forward_g =
+                ref((fun x -> failwith "forward_g") : )
+            let f x = ... !forward_g ...
+mod2.ml:    let g y = ... Mod1.f ...
+            let _ = Mod1.forward_g := g
+\end{verbatim}
+\end{itemize}
+
+\item[The external function \var{f} is not available]
+This error appears when trying to link code that calls external
+functions written in C.  As explained in
+chapter~\ref{c:intf-c}, such code must be linked with C libraries that
+implement the required \var{f} C function.  If the C libraries in
+question are not shared libraries (DLLs), the code must be linked in
+``custom runtime'' mode.  Fix: add the required C libraries to the
+command line, and possibly the "-custom" option.
+
+\end{options}
+
+\section{Warning reference} \label{s:comp-warnings}
+
+This section describes and explains in detail some warnings:
+
+\subsection{Warning 52: fragile constant pattern}
+\label{ss:warn52}
+
+  Some constructors, such as the exception constructors "Failure" and
+  "Invalid_argument", take as parameter a "string" value holding
+  a text message intended for the user.
+
+  These text messages are usually not stable over time: call sites
+  building these constructors may refine the message in a future
+  version to make it more explicit, etc. Therefore, it is dangerous to
+  match over the precise value of the message. For example, until
+  OCaml 4.02, "Array.iter2" would raise the exception
+\begin{verbatim}
+  Invalid_argument "arrays must have the same length"
+\end{verbatim}
+  Since 4.03 it raises the more helpful message
+\begin{verbatim}
+  Invalid_argument "Array.iter2: arrays must have the same length"
+\end{verbatim}
+  but this means that any code of the form
+\begin{verbatim}
+  try ...
+  with Invalid_argument "arrays must have the same length" -> ...
+\end{verbatim}
+  is now broken and may suffer from uncaught exceptions.
+
+  Warning 52 is there to prevent users from writing such fragile code
+  in the first place. It does not occur on every matching on a literal
+  string, but only in the case in which library authors expressed
+  their intent to possibly change the constructor parameter value in
+  the future, by using the attribute "ocaml.warn_on_literal_pattern"
+  (see the manual section on builtin attributes in
+  \ref{ss:builtin-attributes}):
+\begin{verbatim}
+  type t =
+    | Foo of string [@ocaml.warn_on_literal_pattern]
+    | Bar of string
+
+  let no_warning = function
+    | Bar "specific value" -> 0
+    | _ -> 1
+
+  let warning = function
+    | Foo "specific value" -> 0
+    | _ -> 1
+
+>    | Foo "specific value" -> 0
+>          ^^^^^^^^^^^^^^^^
+> Warning 52: Code should not depend on the actual values of
+> this constructor's arguments. They are only for information
+> and may change in future versions. (See manual section 8.5)
+\end{verbatim}
+
+  In particular, all built-in exceptions with a string argument have
+  this attribute set: "Invalid_argument", "Failure", "Sys_error" will
+  all raise this warning if you match for a specific string argument.
+
+  If your code raises this warning, you should {\em not} change the
+  way you test for the specific string to avoid the warning (for
+  example using a string equality inside the right-hand-side instead
+  of a literal pattern), as your code would remain fragile. You should
+  instead enlarge the scope of the pattern by matching on all possible
+  values.
+
+\begin{verbatim}
+
+let warning = function
+  | Foo _ -> 0
+  | _ -> 1
+\end{verbatim}
+
+  This may require some care: if the scrutinee may return several
+  different cases of the same pattern, or raise distinct instances of
+  the same exception, you may need to modify your code to separate
+  those several cases.
+
+  For example,
+\begin{verbatim}
+try (int_of_string count_str, bool_of_string choice_str) with
+  | Failure "int_of_string" -> (0, true)
+  | Failure "bool_of_string" -> (-1, false)
+\end{verbatim}
+  should be rewritten into more atomic tests. For example,
+  using the "exception" patterns documented in Section~\ref{s:exception-match},
+  one can write:
+\begin{verbatim}
+match int_of_string count_str with
+  | exception (Failure _) -> (0, true)
+  | count ->
+    begin match bool_of_string choice_str with
+    | exception (Failure _) -> (-1, false)
+    | choice -> (count, choice)
+    end
+\end{verbatim}
+
+The only case where that transformation is not possible is if a given
+function call may raises distinct exceptions with the same constructor
+but different string values. In this case, you will have to check for
+specific string values. This is dangerous API design and it should be
+discouraged: it's better to define more precise exception constructors
+than store useful information in strings.
+
+\subsection{Warning 57: Ambiguous or-pattern variables under guard}
+\label{ss:warn57}
+
+  The semantics of or-patterns in OCaml is specified with
+  a left-to-right bias: a value \var{v} matches the pattern \var{p} "|" \var{q}
+  if it matches \var{p} or \var{q}, but if it matches both,
+  the environment captured by the match is the environment captured by
+  \var{p}, never the one captured by \var{q}.
+
+  While this property is generally intuitive, there is at least one specific
+  case where a different semantics might be expected.
+  Consider a pattern followed by a when-guard:
+  "|"~\var{p}~"when"~\var{g}~"->"~\var{e}, for example:
+\begin{verbatim}
+     | ((Const x, _) | (_, Const x)) when is_neutral x -> branch
+\end{verbatim}
+  The semantics is clear:
+  match the scrutinee against the pattern, if it matches, test the guard,
+  and if the guard passes, take the branch.
+  In particular, consider the input "(Const"~\var{a}", Const"~\var{b}")", where
+  \var{a} fails the test "is_neutral"~\var{a}, while \var{b} passes the test
+  "is_neutral"~\var{b}.  With the left-to-right semantics, the clause above is
+  {\em not} taken by its input: matching "(Const"~\var{a}", Const"~\var{b}")"
+  against the or-pattern succeeds in the left branch, it returns the
+  environment \var{x}~"->"~\var{a}, and then the guard
+  "is_neutral"~\var{a} is tested and fails, the branch is not taken.
+
+  However, another semantics may be considered more natural here:
+  any pair that has one side passing the test will take the branch. With this
+  semantics the previous code fragment would be equivalent to
+\begin{verbatim}
+     | (Const x, _) when is_neutral x -> branch
+     | (_, Const x) when is_neutral x -> branch
+\end{verbatim}
+  This is {\em not} the semantics adopted by OCaml.
+
+ Warning 57 is dedicated to these confusing 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.
+ More precisely, it warns when guard uses ``ambiguous'' variables, that are bound
+ to different parts of the scrutinees by different sides of a or-pattern.
diff --git a/manual/manual/cmds/debugger.etex b/manual/manual/cmds/debugger.etex
new file mode 100644
index 0000000000..31a2ad6517
--- /dev/null
+++ b/manual/manual/cmds/debugger.etex
@@ -0,0 +1,674 @@
+\chapter{The debugger (ocamldebug)} \label{c:debugger}
+\pdfchapter{The debugger (ocamldebug)}
+%HEVEA\cutname{debugger.html}
+
+This chapter describes the OCaml source-level replay debugger
+"ocamldebug".
+
+\begin{unix} The debugger is available on Unix systems that provide
+BSD sockets.
+\end{unix}
+
+\begin{windows} The debugger is available under the Cygwin port of
+OCaml, but not under the native Win32 ports.
+\end{windows}
+
+\section{Compiling for debugging}
+
+Before the debugger can be used, the program must be compiled and
+linked with the "-g" option: all ".cmo" and ".cma" files that are part
+of the program should have been created with "ocamlc -g", and they
+must be linked together with "ocamlc -g".
+
+Compiling with "-g" entails no penalty on the running time of
+programs: object files and bytecode executable files are bigger and
+take longer to produce, but the executable files run at
+exactly the same speed as if they had been compiled without "-g".
+
+\section{Invocation}
+
+\subsection{Starting the debugger}
+
+The OCaml debugger is invoked by running the program
+"ocamldebug" with the name of the bytecode executable file as first
+argument:
+\begin{alltt}
+        ocamldebug \optvar{options} \var{program} \optvar{arguments}
+\end{alltt}
+The arguments following \var{program} are optional, and are passed as
+command-line arguments to the program being debugged. (See also the
+"set arguments" command.)
+
+The following command-line options are recognized:
+\begin{options}
+\item["-c " \var{count}]
+Set the maximum number of simultaneously live checkpoints to \var{count}.
+
+\item["-cd " \var{dir}]
+Run the debugger program from the working directory \var{dir},
+instead of the current directory. (See also the "cd" command.)
+
+\item["-emacs"]
+Tell the debugger it is executed under Emacs. (See
+section~\ref{s:inf-debugger} for information on how to run the
+debugger under Emacs.)
+
+\item["-I "\var{directory}]
+Add \var{directory} to the list of directories searched for source
+files and compiled files. (See also the "directory" command.)
+
+\item["-s "\var{socket}]
+Use \var{socket} for communicating with the debugged program. See the
+description of the command "set socket" (section~\ref{s:communication})
+for the format of \var{socket}.
+
+\item["-version"]
+Print version string and exit.
+
+\item["-vnum"]
+Print short version number and exit.
+
+\item["-help" or "--help"]
+Display a short usage summary and exit.
+%
+\end{options}
+
+\subsection{Initialization file}
+
+On start-up, the debugger will read commands from an initialization
+file before giving control to the user. The default file is
+".ocamldebug" in the current directory if it exists, otherwise
+".ocamldebug" in the user's home directory.
+
+\subsection{Exiting the debugger}
+
+The command "quit" exits the debugger. You can also exit the debugger
+by typing an end-of-file character (usually "ctrl-D").
+
+Typing an interrupt character (usually "ctrl-C") will not exit the
+debugger, but will terminate the action of any debugger command that is in
+progress and return to the debugger command level. 
+
+\section{Commands} \label{s:debugger-commands}
+
+A debugger command is a single line of input. It starts with a command
+name, which is followed by arguments depending on this name. Examples:
+\begin{verbatim}
+        run
+        goto 1000
+        set arguments arg1 arg2
+\end{verbatim}
+
+A command name can be truncated as long as there is no ambiguity. For
+instance, "go 1000" is understood as "goto 1000", since there are no
+other commands whose name starts with "go". For the most frequently
+used commands, ambiguous abbreviations are allowed. For instance, "r"
+stands for "run" even though there are others commands starting with
+"r". You can test the validity of an abbreviation using the "help" command.
+
+If the previous command has been successful, a blank line (typing just
+"RET") will repeat it.
+
+\subsection{Getting help}
+
+The OCaml debugger has a simple on-line help system, which gives
+a brief description of each command and variable.
+
+\begin{options}
+\item["help"]
+Print the list of commands.
+
+\item["help "\var{command}]
+Give help about the command \var{command}.
+
+\item["help set "\var{variable}, "help show "\var{variable}]
+Give help about the variable \var{variable}. The list of all debugger
+variables can be obtained with "help set".
+
+\item["help info "\var{topic}]
+Give help about \var{topic}. Use "help info" to get a list of known topics.
+\end{options}
+
+\subsection{Accessing the debugger state}
+
+\begin{options}
+\item["set "\var{variable} \var{value}]
+Set the debugger variable \var{variable} to the value \var{value}.
+
+\item["show "\var{variable}]
+Print the value of the debugger variable \var{variable}.
+
+\item["info "\var{subject}]
+Give information about the given subject.
+For instance, "info breakpoints" will print the list of all breakpoints.
+\end{options}
+
+\section{Executing a program}
+
+\subsection{Events}
+
+Events are ``interesting'' locations in the source code, corresponding
+to the beginning or end of evaluation of ``interesting''
+sub-expressions. Events are the unit of single-stepping (stepping goes
+to the next or previous event encountered in the program execution).
+Also, breakpoints can only be set at events. Thus, events play the
+role of line numbers in debuggers for conventional languages.
+
+During program execution, a counter is incremented at each event
+encountered. The value of this counter is referred as the {\em current
+time}. Thanks to reverse execution, it is possible to jump back and
+forth to any time of the execution.
+
+Here is where the debugger events (written \event) are located in
+the source code:
+\begin{itemize}
+\item Following a function application:
+\begin{alltt}
+(f arg)\event
+\end{alltt}
+\item On entrance to a function:
+\begin{alltt}
+fun x y z -> \event ...
+\end{alltt}
+\item On each case of a pattern-matching definition (function,
+"match"\ldots"with" construct, "try"\ldots"with" construct):
+\begin{alltt}
+function pat1 -> \event expr1
+       | ...
+       | patN -> \event exprN
+\end{alltt}
+\item Between subexpressions of a sequence:
+\begin{alltt}
+expr1; \event expr2; \event ...; \event exprN
+\end{alltt}
+\item In the two branches of a conditional expression:
+\begin{alltt}
+if cond then \event expr1 else \event expr2
+\end{alltt}
+\item At the beginning of each iteration of a loop:
+\begin{alltt}
+while cond do \event body done
+for i = a to b do \event body done
+\end{alltt}
+\end{itemize}
+Exceptions: A function application followed by a function return is replaced
+by the compiler by a jump (tail-call optimization). In this case, no
+event is put after the function application.
+% Also, no event is put after a function application when the function
+% is external (written in C).
+
+\subsection{Starting the debugged program}
+
+The debugger starts executing the debugged program only when needed.
+This allows setting breakpoints or assigning debugger variables before
+execution starts. There are several ways to start execution:
+\begin{options}
+\item["run"] Run the program until a breakpoint is hit, or the program
+terminates.
+\item["goto 0"] Load the program and stop on the first event.
+\item["goto "\var{time}] Load the program and execute it until the
+given time. Useful when you already know approximately at what time
+the problem appears. Also useful to set breakpoints on function values
+that have not been computed at time 0 (see section~\ref{s:breakpoints}).
+\end{options}
+
+The execution of a program is affected by certain information it
+receives when the debugger starts it, such as the command-line
+arguments to the program and its working directory. The debugger
+provides commands to specify this information ("set arguments" and "cd").
+These commands must be used before program execution starts. If you try
+to change the arguments or the working directory after starting your
+program, the debugger will kill the program (after asking for confirmation).
+
+\subsection{Running the program}
+
+The following commands execute the program forward or backward,
+starting at the current time. The execution will stop either when
+specified by the command or when a breakpoint is encountered.
+
+\begin{options}
+\item["run"] Execute the program forward from current time. Stops at
+next breakpoint or when the program terminates.
+\item["reverse"] Execute the program backward from current time.
+Mostly useful to go to the last breakpoint encountered before the
+current time.
+\item["step "\optvar{count}] Run the program and stop at the next
+event. With an argument, do it \var{count} times. If \var{count} is 0,
+run until the program terminates or a breakpoint is hit.
+\item["backstep "\optvar{count}] Run the program backward and stop at
+the previous event. With an argument, do it \var{count} times.
+\item["next "\optvar{count}] Run the program and stop at the next
+event, skipping over function calls. With an argument, do it
+\var{count} times.
+\item["previous "\optvar{count}] Run the program backward and stop at
+the previous event, skipping over function calls. With an argument, do
+it \var{count} times.
+\item["finish"] Run the program until the current function returns.
+\item["start"] Run the program backward and stop at the first event
+before the current function invocation.
+\end{options}
+
+\subsection{Time travel}
+
+You can jump directly to a given time, without stopping on
+breakpoints, using the "goto" command.
+
+As you move through the program, the debugger maintains an history of
+the successive times you stop at. The "last" command can be used to
+revisit these times: each "last" command moves one step back through
+the history. That is useful mainly to undo commands such as "step"
+and "next".
+
+\begin{options}
+\item["goto "\var{time}]
+Jump to the given time.
+\item["last "\optvar{count}]
+Go back to the latest time recorded in the execution history. With an
+argument, do it \var{count} times.
+\item["set history "\var{size}]
+Set the size of the execution history.
+\end{options}
+
+\subsection{Killing the program}
+
+\begin{options}
+\item["kill"] Kill the program being executed. This command is mainly
+useful if you wish to recompile the program without leaving the debugger.
+\end{options}
+
+\section{Breakpoints} \label{s:breakpoints}
+
+A breakpoint causes the program to stop whenever a certain point in
+the program is reached. It can be set in several ways using the
+"break" command. Breakpoints are assigned numbers when set, for
+further reference. The most comfortable way to set breakpoints is
+through the Emacs interface (see section~\ref{s:inf-debugger}).
+
+\begin{options}
+\item["break"]
+Set a breakpoint at the current position in the program execution. The
+current position must be on an event (i.e., neither at the beginning,
+nor at the end of the program).
+
+\item["break "\var{function}]
+Set a breakpoint at the beginning of \var{function}. This works only
+when the functional value of the identifier \var{function} has been
+computed and assigned to the identifier. Hence this command cannot be
+used at the very beginning of the program execution, when all
+identifiers are still undefined; use "goto" \var{time} to advance
+execution until the functional value is available.
+
+\item["break \@" \optvar{module} \var{line}]
+Set a breakpoint in module \var{module} (or in the current module if
+\var{module} is not given), at the first event of line \var{line}.
+
+\item["break \@" \optvar{module} \var{line} \var{column}]
+Set a breakpoint in module \var{module} (or in the current module if
+\var{module} is not given), at the event closest to line \var{line},
+column \var{column}.
+
+\item["break \@" \optvar{module} "#" \var{character}]
+Set a breakpoint in module \var{module} at the event closest to
+character number \var{character}.
+
+\item["break "\var{address}]
+Set a breakpoint at the code address \var{address}.
+
+\item["delete "\optvar{breakpoint-numbers}]
+Delete the specified breakpoints. Without argument, all breakpoints
+are deleted (after asking for confirmation).
+
+\item["info breakpoints"] Print the list of all breakpoints.
+\end{options}
+
+\section{The call stack}
+
+Each time the program performs a function application, it saves the
+location of the application (the return address) in a block of data
+called a stack frame. The frame also contains the local variables of
+the caller function. All the frames are allocated in a region of
+memory called the call stack. The command "backtrace" (or "bt")
+displays parts of the call stack.
+
+At any time, one of the stack frames is ``selected'' by the debugger; several
+debugger commands refer implicitly to the selected frame. In particular,
+whenever you ask the debugger for the value of a local variable, the
+value is found in the selected frame. The commands "frame", "up" and "down"
+select whichever frame you are interested in.
+
+When the program stops, the debugger automatically selects the
+currently executing frame and describes it briefly as the "frame"
+command does.
+
+\begin{options}
+\item["frame"]
+Describe the currently selected stack frame.
+
+\item["frame" \var{frame-number}]
+Select a stack frame by number and describe it. The frame currently
+executing when the program stopped has number 0; its caller has number
+1; and so on up the call stack.
+
+\item["backtrace "\optvar{count}, "bt "\optvar{count}]
+Print the call stack. This is useful to see which sequence of function
+calls led to the currently executing frame. With a positive argument,
+print only the innermost \var{count} frames.
+With a negative argument, print only the outermost -\var{count} frames.
+
+\item["up" \optvar{count}]
+Select and display the stack frame just ``above'' the selected frame,
+that is, the frame that called the selected frame. An argument says how
+many frames to go up.
+
+\item["down "\optvar{count}]
+Select and display the stack frame just ``below'' the selected frame,
+that is, the frame that was called by the selected frame. An argument
+says how many frames to go down.
+\end{options}
+
+\section{Examining variable values}
+
+The debugger can print the current value of simple expressions. The
+expressions can involve program variables: all the identifiers that
+are in scope at the selected program point can be accessed.
+
+Expressions that can be printed are a subset of OCaml
+expressions, as described by the following grammar:
+\begin{syntax}
+simple-expr:
+    lowercase-ident
+  | { capitalized-ident '.' } lowercase-ident
+  | '*'
+  | '$' integer
+  | simple-expr '.' lowercase-ident
+  | simple-expr '.(' integer ')'
+  | simple-expr '.[' integer ']'
+  | '!' simple-expr
+  | '(' simple-expr ')'
+\end{syntax}
+The first two cases refer to a value identifier, either unqualified or
+qualified by the path to the structure that define it.
+"*" refers to the result just computed (typically, the value of a
+function application), and is valid only if the selected event is an
+``after'' event (typically, a function application).
+@'$' integer@ refer to a previously printed value. The remaining four
+forms select part of an expression: respectively, a record field, an
+array element, a string element, and the current contents of a
+reference.
+
+\begin{options}
+\item["print "\var{variables}]
+Print the values of the given variables. "print" can be abbreviated as
+"p".
+\item["display "\var{variables}]
+Same as "print", but limit the depth of printing to 1. Useful to
+browse large data structures without printing them in full.
+"display" can be abbreviated as "d".
+\end{options}
+
+When printing a complex expression, a name of the form "$"\var{integer}
+is automatically assigned to its value. Such names are also assigned
+to parts of the value that cannot be printed because the maximal
+printing depth is exceeded. Named values can be printed later on
+with the commands "p $"\var{integer} or "d $"\var{integer}.
+Named values are valid only as long as the program is stopped. They
+are forgotten as soon as the program resumes execution.
+
+\begin{options}
+\item["set print_depth" \var{d}]
+Limit the printing of values to a maximal depth of \var{d}. 
+\item["set print_length" \var{l}]
+Limit the printing of values to at most \var{l} nodes printed.
+\end{options}
+
+\section{Controlling the debugger}
+
+\subsection{Setting the program name and arguments}
+
+\begin{options}
+\item["set program" \var{file}]
+Set the program name to \var{file}.
+\item["set arguments" \var{arguments}]
+Give \var{arguments} as command-line arguments for the program.
+\end{options}
+
+A shell is used to pass the arguments to the debugged program. You can
+therefore use wildcards, shell variables, and file redirections inside
+the arguments. To debug programs that read from standard input, it is
+recommended to redirect their input from a file (using
+"set arguments < input-file"), otherwise input to the program and
+input to the debugger are not properly separated, and inputs are not
+properly replayed when running the program backwards.
+
+\subsection{How programs are loaded}
+
+The "loadingmode" variable controls how the program is executed.
+
+\begin{options}
+\item["set loadingmode direct"]
+The program is run directly by the debugger. This is the default mode.
+\item["set loadingmode runtime"]
+The debugger execute the OCaml runtime "ocamlrun" on the program.
+Rarely useful; moreover it prevents the debugging of programs compiled
+in ``custom runtime'' mode.
+\item["set loadingmode manual"]
+The user starts manually the program, when asked by the debugger.
+Allows remote debugging (see section~\ref{s:communication}).
+\end{options}
+
+\subsection{Search path for files}
+
+The debugger searches for source files and compiled interface files in
+a list of directories, the search path. The search path initially
+contains the current directory "." and the standard library directory.
+The "directory" command adds directories to the path.
+
+Whenever the search path is modified, the debugger will clear any
+information it may have cached about the files.
+
+\begin{options}
+\item["directory" \var{directorynames}]
+Add the given directories to the search path. These directories are
+added at the front, and will therefore be searched first.
+
+\item["directory" \var{directorynames} "for" \var{modulename}]
+Same as "directory" \var{directorynames}, but the given directories will be
+searched only when looking for the source file of a module that has 
+been packed into \var{modulename}.
+
+\item["directory"]
+Reset the search path. This requires confirmation.
+\end{options}
+
+\subsection{Working directory}
+
+Each time a program is started in the debugger, it inherits its working
+directory from the current working directory of the debugger.  This
+working directory is initially whatever it inherited from its parent
+process (typically the shell), but you can specify a new working
+directory in the debugger with the "cd" command or the "-cd"
+command-line option.
+
+\begin{options}
+\item["cd" \var{directory}]
+Set the working directory for "ocamldebug" to \var{directory}.
+
+\item["pwd"]
+Print the working directory for "ocamldebug".
+\end{options}
+
+\subsection{Turning reverse execution on and off}
+
+In some cases, you may want to turn reverse execution off. This speeds
+up the program execution, and is also sometimes useful for interactive
+programs.
+
+Normally, the debugger takes checkpoints of the program state from
+time to time. That is, it makes a copy of the current state of the
+program (using the Unix system call "fork"). If the variable
+\var{checkpoints} is set to "off", the debugger will not take any
+checkpoints.
+
+\begin{options}
+\item["set checkpoints" \var{on/off}]
+Select whether the debugger makes checkpoints or not.
+\end{options}
+
+\subsection{Communication between the debugger and the program}
+\label{s:communication}
+
+The debugger communicate with the program being debugged through a
+Unix socket. You may need to change the socket name, for example if
+you need to run the debugger on a machine and your program on another.
+
+\begin{options}
+\item["set socket" \var{socket}]
+Use \var{socket} for communication with the program. \var{socket} can be
+either a file name, or an Internet port specification
+\var{host}:\var{port}, where \var{host} is a host name or an Internet
+address in dot notation, and \var{port} is a port number on the host.
+\end{options}
+
+On the debugged program side, the socket name is passed through the
+"CAML_DEBUG_SOCKET" environment variable.
+
+\subsection{Fine-tuning the debugger} \label{s:fine-tuning}
+
+Several variables enables to fine-tune the debugger. Reasonable
+defaults are provided, and you should normally not have to change them.
+
+\begin{options}
+\item["set processcount" \var{count}]
+Set the maximum number of checkpoints to \var{count}. More checkpoints
+facilitate going far back in time, but use more memory and create more
+Unix processes.
+\end{options}
+
+As checkpointing is quite expensive, it must not be done too often. On
+the other hand, backward execution is faster when checkpoints are
+taken more often. In particular, backward single-stepping is more
+responsive when many checkpoints have been taken just before the
+current time. To fine-tune the checkpointing strategy, the debugger
+does not take checkpoints at the same frequency for long displacements
+(e.g. "run") and small ones (e.g. "step"). The two variables "bigstep"
+and "smallstep" contain the number of events between two checkpoints
+in each case.
+
+\begin{options}
+\item["set bigstep" \var{count}]
+Set the number of events between two checkpoints for long displacements.
+\item["set smallstep" \var{count}]
+Set the number of events between two checkpoints for small
+displacements.
+\end{options}
+
+The following commands display information on checkpoints and events:
+
+\begin{options}
+\item["info checkpoints"]
+Print a list of checkpoints.
+\item["info events" \optvar{module}]
+Print the list of events in the given module (the current module, by default).
+\end{options}
+
+\subsection{User-defined printers}
+
+Just as in the toplevel system (section~\ref{s:toplevel-directives}),
+the user can register functions for printing values of certain types.
+For technical reasons, the debugger cannot call printing functions
+that reside in the program being debugged. The code for the printing
+functions must therefore be loaded explicitly in the debugger.
+
+\begin{options}
+\item["load_printer \""\var{file-name}"\""]
+Load in the debugger the indicated ".cmo" or ".cma" object file.  The
+file is loaded in an environment consisting only of the OCaml
+standard library plus the definitions provided by object files
+previously loaded using "load_printer".  If this file depends on other
+object files not yet loaded, the debugger automatically loads them if
+it is able to find them in the search path.  The loaded file does not
+have direct access to the modules of the program being debugged.
+
+\item["install_printer "\var{printer-name}]
+Register the function named \var{printer-name} (a
+value path) as a printer for objects whose types match the argument
+type of the function. That is, the debugger will call
+\var{printer-name} when it has such an object to print.
+The printing function \var{printer-name} must use the "Format" library
+module to produce its output, otherwise its output will not be
+correctly located in the values printed by the toplevel loop.
+
+The value path \var{printer-name} must refer to one of the functions
+defined by the object files loaded using "load_printer". It cannot
+reference the functions of the program being debugged.
+
+\item["remove_printer "\var{printer-name}]
+Remove the named function from the table of value printers.
+\end{options}
+
+\section{Miscellaneous commands}
+
+\begin{options}
+\item["list" \optvar{module} \optvar{beginning} \optvar{end}]
+List the source of module \var{module}, from line number
+\var{beginning} to line number \var{end}. By default, 20 lines of the
+current module are displayed, starting 10 lines before the current
+position.
+\item["source" \var{filename}]
+Read debugger commands from the script \var{filename}.
+\end{options}
+
+\section{Running the debugger under Emacs} \label{s:inf-debugger}
+
+The most user-friendly way to use the debugger is to run it under Emacs.
+See the file "emacs/README" in the distribution for information on how
+to load the Emacs Lisp files for OCaml support.
+
+The OCaml debugger is started under Emacs by the command "M-x
+camldebug", with argument the name of the executable file
+\var{progname} to debug.  Communication with the debugger takes place
+in an Emacs buffer named  "*camldebug-"\var{progname}"*". The editing
+and history facilities of Shell mode are available for interacting
+with the debugger.
+
+In addition, Emacs displays the source files containing the current
+event (the current position in the program execution) and highlights
+the location of the event. This display is updated synchronously with
+the debugger action.
+
+The following bindings for the most common debugger commands are
+available in the "*camldebug-"\var{progname}"*" buffer:
+
+\begin{options}
+\item["C-c C-s"] (command "step"): execute the program one step forward.
+\item["C-c C-k"] (command "backstep"): execute the program one step backward.
+\item["C-c C-n"] (command "next"): execute the program one step
+forward, skipping over function calls.
+\item[Middle mouse button] (command "display"): display named value.
+"$"\var{n} under mouse cursor (support incremental browsing of large
+data structures).
+\item["C-c C-p"] (command "print"): print value of identifier at point.
+\item["C-c C-d"] (command "display"): display value of identifier at point.
+\item["C-c C-r"] (command "run"): execute the program forward to next
+breakpoint.
+\item["C-c C-v"] (command "reverse"): execute the program backward to
+latest breakpoint.
+\item["C-c C-l"] (command "last"): go back one step in the command history.
+\item["C-c C-t"] (command "backtrace"): display backtrace of function calls.
+\item["C-c C-f"] (command "finish"): run forward till the current
+function returns.
+\item["C-c <"]   (command "up"): select the stack frame below the
+current frame.
+\item["C-c >"]   (command "down"): select the stack frame above the
+current frame.
+\end{options}
+
+In all buffers in OCaml editing mode, the following debugger commands
+are also available:
+
+\begin{options}
+\item["C-x C-a C-b"] (command "break"): set a breakpoint at event closest
+to point
+\item["C-x C-a C-p"] (command "print"): print value of identifier at point
+\item["C-x C-a C-d"] (command "display"): display value of identifier at point
+\end{options}
diff --git a/manual/manual/cmds/depend.etex b/manual/manual/cmds/depend.etex
new file mode 100644
index 0000000000..f366b03959
--- /dev/null
+++ b/manual/manual/cmds/depend.etex
@@ -0,0 +1,204 @@
+\chapter{Dependency generator (ocamldep)} \label{c:camldep}
+\pdfchapter{Dependency generator (ocamldep)}
+%HEVEA\cutname{depend.html}
+
+The "ocamldep" command scans a set of OCaml source files
+(".ml" and ".mli" files) for references to external compilation units,
+and outputs dependency lines in a format suitable for the "make"
+utility. This ensures that "make" will compile the source files in the
+correct order, and recompile those files that need to when a source
+file is modified.
+
+The typical usage is:
+\begin{alltt}
+        ocamldep \var{options} *.mli *.ml > .depend
+\end{alltt}
+where "*.mli *.ml" expands to all source files in the current
+directory and ".depend" is the file that should contain the
+dependencies. (See below for a typical "Makefile".)
+
+Dependencies are generated both for compiling with the bytecode
+compiler "ocamlc" and with the native-code compiler "ocamlopt".
+
+\section{Options}
+
+The following command-line options are recognized by "ocamldep".
+
+\begin{options}
+
+\item["-absname"]
+Show absolute filenames in error messages.
+
+\item["-all"]
+Generate dependencies on all required files, rather than assuming
+implicit dependencies.
+
+\item["-allow-approx"]
+Allow falling back on a lexer-based approximation when parsing fails.
+
+\item["-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.
+
+\item["-debug-map"]
+Dump the delayed dependency map for each map file.
+
+\item["-I" \var{directory}]
+Add the given directory to the list of directories searched for
+source files. If a source file "foo.ml" mentions an external
+compilation unit "Bar", a dependency on that unit's interface
+"bar.cmi" is generated only if the source for "bar" is found in the
+current directory or in one of the directories specified with "-I".
+Otherwise, "Bar" is assumed to be a module from the standard library,
+and no dependencies are generated. For programs that span multiple
+directories, it is recommended to pass "ocamldep" the same "-I" options
+that are passed to the compiler.
+
+\item["-impl" \var{file}]
+Process \var{file} as a ".ml" file.
+
+\item["-intf" \var{file}]
+Process \var{file} as a ".mli" file.
+
+\item["-map" \var{file}]
+Read an propagate the delayed dependencies for module aliases in
+\var{file}, so that the following files will depend on the
+exported aliased modules if they use them. See the example below.
+
+\item["-ml-synonym" \var{.ext}]
+Consider the given extension (with leading dot) to be a synonym for .ml.
+
+\item["-mli-synonym" \var{.ext}]
+Consider the given extension (with leading dot) to be a synonym for .mli.
+
+\item["-modules"]
+Output raw dependencies of the form
+\begin{verbatim}
+      filename: Module1 Module2 ... ModuleN
+\end{verbatim}
+where "Module1", \ldots, "ModuleN" are the names of the compilation
+units referenced within the file "filename", but these names are not
+resolved to source file names.  Such raw dependencies cannot be used
+by "make", but can be post-processed by other tools such as "Omake".
+
+\item["-native"]
+Generate dependencies for a pure native-code program (no bytecode
+version).  When an implementation file (".ml" file) has no explicit
+interface file (".mli" file), "ocamldep" generates dependencies on the
+bytecode compiled file (".cmo" file) to reflect interface changes.
+This can cause unnecessary bytecode recompilations for programs that
+are compiled to native-code only.  The flag "-native" 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.)
+
+\item["-one-line"]
+Output one line per file, regardless of the length.
+
+\item["-open" \var{module}]
+Assume that module \var{module} is opened before parsing each of the
+following files.
+
+\item["-pp" \var{command}]
+Cause "ocamldep" to call the given \var{command} as a preprocessor
+for each source file.
+
+\item["-ppx" \var{command}]
+Pipe abstract syntax trees through preprocessor \var{command}.
+
+\item["-slash"]
+Under Windows, use a forward slash (/) as the path separator instead
+of the usual backward slash ($\backslash$).  Under Unix, this option does
+nothing.
+
+\item["-sort"]
+Sort files according to their dependencies.
+
+\item["-version"]
+Print version string and exit.
+
+\item["-vnum"]
+Print short version number and exit.
+
+\item["-help" or "--help"]
+Display a short usage summary and exit.
+%
+\end{options}
+
+\section{A typical Makefile}
+
+Here is a template "Makefile" for a OCaml program.
+
+\begin{verbatim}
+OCAMLC=ocamlc
+OCAMLOPT=ocamlopt
+OCAMLDEP=ocamldep
+INCLUDES=                 # all relevant -I options here
+OCAMLFLAGS=$(INCLUDES)    # add other options for ocamlc here
+OCAMLOPTFLAGS=$(INCLUDES) # add other options for ocamlopt here
+
+# prog1 should be compiled to bytecode, and is composed of three
+# units: mod1, mod2 and mod3.
+
+# The list of object files for prog1
+PROG1_OBJS=mod1.cmo mod2.cmo mod3.cmo
+
+prog1: $(PROG1_OBJS)
+        $(OCAMLC) -o prog1 $(OCAMLFLAGS) $(PROG1_OBJS)
+
+# prog2 should be compiled to native-code, and is composed of two
+# units: mod4 and mod5.
+
+# The list of object files for prog2
+PROG2_OBJS=mod4.cmx mod5.cmx
+
+prog2: $(PROG2_OBJS)
+        $(OCAMLOPT) -o prog2 $(OCAMLFLAGS) $(PROG2_OBJS)
+
+# Common rules
+.SUFFIXES: .ml .mli .cmo .cmi .cmx
+
+.ml.cmo:
+        $(OCAMLC) $(OCAMLFLAGS) -c $<
+
+.mli.cmi:
+        $(OCAMLC) $(OCAMLFLAGS) -c $<
+
+.ml.cmx:
+        $(OCAMLOPT) $(OCAMLOPTFLAGS) -c $<
+
+# Clean up
+clean:
+        rm -f prog1 prog2
+        rm -f *.cm[iox]
+
+# Dependencies
+depend:
+        $(OCAMLDEP) $(INCLUDES) *.mli *.ml > .depend
+
+include .depend
+\end{verbatim}
+
+If you use module aliases to give shorter names to modules, you need
+to change the above definitions. Assuming that your map file is called
+"mylib.mli", here are minimal modifications.
+\begin{verbatim}
+OCAMLFLAGS=$(INCLUDES) -open Mylib
+
+mylib.cmi: mylib.mli
+        $(OCAMLC) $(INCLUDES) -no-alias-deps -w -49 -c $<
+
+depend:
+        $(OCAMLDEP) $(INCLUDES) -map mylib.mli $(PROG1_OBJS:.cmo=.ml) > .depend
+\end{verbatim}
+Note that in this case you should not compute dependencies for
+"mylib.mli" together with the other files, hence the need to pass
+explicitly the list of files to process.
+If "mylib.mli" itself has dependencies, you should compute them using
+"-as-map".
diff --git a/manual/manual/cmds/flambda.etex b/manual/manual/cmds/flambda.etex
new file mode 100644
index 0000000000..a30a5b299b
--- /dev/null
+++ b/manual/manual/cmds/flambda.etex
@@ -0,0 +1,1343 @@
+\chapter{Optimisation with Flambda}
+\pdfchapterfold{-9}{Optimisation with Flambda}
+%HEVEA\cutname{flambda.html}
+
+\section{Overview}
+
+{\em Flambda} is the term used to describe a series of optimisation passes
+provided by the native code compilers as of OCaml 4.03.
+
+Flambda aims to make it easier to write idiomatic OCaml code without
+incurring performance penalties.
+
+To use the Flambda optimisers it is necessary to pass the {\tt -flambda}
+option to the OCaml {\tt configure} script.  (There is no support for a
+single compiler that can operate in both Flambda and non-Flambda modes.)
+Code compiled with Flambda
+cannot be linked into the same program as code compiled without Flambda.
+Attempting to do this will result in a compiler error.
+
+Whether or not a particular {\tt ocamlopt} uses Flambda may be
+determined by invoking it with the {\tt -config} option and looking
+for any line starting with ``{\tt flambda:}''.  If such a line is present
+and says ``{\tt true}'', then Flambda is supported, otherwise it is not.
+
+Flambda provides full optimisation across different compilation units,
+so long as the {\tt .cmx} files for the dependencies of the unit currently
+being compiled are available.  (A compilation unit corresponds to a
+single {\tt .ml} source file.)  However it does not yet act entirely as
+a whole-program compiler: for example, elimination of dead code across
+a complete set of compilation units is not supported.
+
+Optimisation with Flambda is not currently supported when generating
+bytecode.
+
+Flambda should not in general affect the semantics of existing programs.
+Two exceptions to this rule are: possible elimination of pure code
+that is being benchmarked (see section\ \ref{inhibition}) and changes in
+behaviour of code using unsafe operations (see section\ \ref{unsafe}).
+
+Flambda does not yet optimise array or string bounds checks.  Neither
+does it take hints for optimisation from any assertions written by the
+user in the code.
+
+Consult the {\em Glossary} at the end of this chapter for definitions of
+technical terms used below.
+
+\section{Command-line flags}
+
+The Flambda optimisers provide a variety of command-line flags that may
+be used to control their behaviour.  Detailed descriptions of each flag
+are given in the referenced sections.  Those sections also describe any
+arguments which the particular flags take.
+
+Commonly-used options:
+\begin{options}
+\item[\machine{-O2}] Perform more optimisation than usual.  Compilation
+times may be lengthened.  (This flag is an abbreviation for a certain
+set of parameters described in section\ \ref{defaults}.)
+\item[\machine{-O3}] Perform even more optimisation than usual, possibly
+including unrolling of recursive functions.  Compilation times may be
+significantly lengthened.
+\item[\machine{-Oclassic}] Make inlining decisions at the point of
+definition of a function rather than at the call site(s).  This mirrors
+the behaviour of OCaml compilers not using Flambda.  Compared to compilation
+using the new Flambda inlining heuristics (for example at {\tt -O2}) it
+produces
+smaller {\tt .cmx} files, shorter compilation times and code that probably
+runs rather slower.  When using {\tt -Oclassic}, only the following options
+described in this section are relevant: {\tt -inlining-report} and
+{\tt -inline}.  If any other of the options described in this section are
+used, the behaviour is undefined and may cause an error in future versions
+of the compiler.
+\item[\machine{-inlining-report}] Emit {\tt .inlining} files (one per
+round of optimisation) showing all of the inliner's decisions.
+\end{options}
+
+Less commonly-used options:
+\begin{options}
+\item[\machine{-remove-unused-arguments}] Remove unused function arguments
+even when the argument is not specialised.  This may have a small
+performance penalty.
+See section\ \ref{remove-unused-args}.
+\item[\machine{-unbox-closures}] Pass free variables via specialised arguments
+rather than closures (an optimisation for reducing allocation).  See
+section\ \ref{unbox-closures}.  This may have a small performance penalty.
+\end{options}
+
+Advanced options, only needed for detailed tuning:
+\begin{options}
+\item[\machine{-inline}] The behaviour depends on whether {\tt -Oclassic}
+is used.
+\begin{itemize}
+\item When not in {\tt -Oclassic} mode, {\tt -inline} limits the total
+size of functions considered for inlining during any speculative inlining
+search.  (See section\ \ref{speculation}.)  Note that 
+this parameter does
+{\bf not} control the assessment as to whether any particular function may
+be inlined.  Raising it to excessive amounts will not necessarily cause
+more functions to be inlined.
+\item When in {\tt -Oclassic} mode, {\tt -inline} behaves as in
+previous versions of the compiler: it is the maximum size of function to
+be considered for inlining.  See section\ \ref{classic}.
+\end{itemize}
+\item[\machine{-inline-toplevel}] The equivalent of {\tt -inline} but used
+when speculative inlining starts at toplevel.  See
+section\ \ref{speculation}.
+Not used in {\tt -Oclassic} mode.
+\item[\machine{-inline-branch-factor}] Controls how the inliner assesses
+whether a code path is likely to be hot or cold.  See
+section\ \ref{assessment-inlining}.
+\item[\machine{-inline-alloc-cost},
+  \machine{-inline-branch-cost},
+  \machine{-inline-call-cost}] Controls how the inliner assesses the runtime
+  performance penalties associated with various operations.  See
+  section\ \ref{assessment-inlining}.
+\item[\machine{-inline-indirect-cost},
+  \machine{-inline-prim-cost}] Likewise.
+\item[\machine{-inline-lifting-benefit}] Controls inlining of functors
+at toplevel.  See section\ \ref{assessment-inlining}.
+\item[\machine{-inline-max-depth}] The maximum depth of any
+speculative inlining search.  See section\ \ref{speculation}.
+\item[\machine{-inline-max-unroll}] The maximum depth of any unrolling of
+recursive functions during any speculative inlining search.
+See section\ \ref{speculation}.
+\item[\machine{-no-unbox-free-vars-of-closures}] %
+Do not unbox closure variables.  See section\ \ref{unbox-fvs}.
+\item[\machine{-no-unbox-specialised-args}] %
+Do not unbox arguments to which functions have been specialised.  See
+section\ \ref{unbox-spec-args}.
+\item[\machine{-rounds}] How many rounds of optimisation to perform.
+See section\ \ref{rounds}.
+\item[\machine{-unbox-closures-factor}] Scaling factor for benefit
+calculation when using {\tt -unbox-closures}.  See
+section\ \ref{unbox-closures}.
+\end{options}
+
+\paragraph{Notes}
+\begin{itemize}
+\item The set of command line flags relating to optimisation should typically
+be specified to be the same across an entire project.  Flambda does not
+currently record the requested flags in the {\tt .cmx} files.  As such,
+inlining of functions from previously-compiled units will subject their code
+to the optimisation parameters of the unit currently being compiled, rather
+than those specified when they were previously compiled.  It is hoped to
+rectify this deficiency in the future.
+
+\item Flambda-specific flags do not affect linking with the exception of
+affecting the optimisation of code in the startup file (containing
+generated functions such as currying helpers).  Typically such optimisation
+will not be significant, so eliding such flags at link time might be
+reasonable.
+
+\item Flambda-specific flags are silently accepted even when the
+{\tt -flambda} option was not provided to the {\tt configure} script.
+(There is no means provided to change this behaviour.)
+This is intended to make it more
+straightforward to run benchmarks with and without the Flambda optimisers
+in effect.
+\item Some of the Flambda flags may be subject to change in future
+releases.
+\end{itemize}
+
+\subsection{Specification of optimisation parameters by round}\label{rounds}
+
+Flambda operates in {\em rounds}: one round consists of a certain sequence
+of transformations that may then be repeated in order to achieve more
+satisfactory results.  The number of rounds can be set manually using the
+{\tt -rounds} parameter (although this is not necessary when using
+predefined optimisation levels such as with {\tt -O2} and {\tt -O3}).
+For high optimisation the number of rounds might be set at 3 or 4.
+
+Command-line flags that may apply per round, for example those with
+{\tt "-cost"} in the name, accept arguments of the form:
+\begin{center}
+{\em n}{\tt\ |\ }{\em round}{\tt =}{\em n}[{\tt,}...]
+\end{center}
+\begin{itemize}
+\item If the first form is used, with a single integer specified,
+the value will apply to all rounds.
+\item If the second form is used, zero-based {\em round} integers specify
+values which are to be used only for those rounds.
+\end{itemize}
+
+The flags {\tt -Oclassic}, {\tt -O2} and {\tt -O3} are applied before all
+other flags, meaning that certain parameters may be overridden without
+having to specify every parameter usually invoked by the given optimisation
+level.
+
+\section{Inlining}
+
+{\em Inlining} refers to the copying of the code of a function to a
+place where the function is called.
+The code of the function will be surrounded by bindings of its parameters
+to the corresponding arguments.
+
+The aims of inlining are:
+\begin{itemize}
+\item to reduce the runtime overhead caused by function calls (including
+setting up for such calls and returning afterwards);
+\item to reduce instruction cache misses by expressing frequently-taken
+paths through the program using fewer machine instructions; and
+\item to reduce the amount of allocation (especially of closures).
+\end{itemize}
+These goals are often reached not just by inlining itself but also by
+other optimisations that the compiler is able to perform as a result of
+inlining.
+
+When a recursive call to a function (within the definition of that function
+or another in the same mutually-recursive group) is inlined, the procedure is
+also known as {\em unrolling}.  This is somewhat akin to loop peeling.
+For example, given the following code:
+\begin{verbatim}
+let rec fact x =
+  if x = 0 then
+    1
+  else
+    x * fact (x - 1)
+
+let n = fact 4
+\end{verbatim}
+unrolling once at the call site {\tt fact 4} produces (with the body of
+{\tt fact} unchanged):
+\begin{verbatim}
+let n =
+  if 4 = 0 then
+    1
+  else
+    4 * fact (4 - 1)
+\end{verbatim}
+This simplifies to:
+\begin{verbatim}
+let n = 4 * fact 3
+\end{verbatim}
+
+%% CR pchambart: A specific section for unrolling might be worth (telling
+%% when this is beneficial)
+
+Flambda provides significantly enhanced inlining capabilities relative to
+previous versions of the compiler.
+
+\subsubsection{Aside: when inlining is performed}
+
+Inlining is performed together with all of the other Flambda optimisation
+passes, that is to say, after closure conversion.  This has three particular
+advantages over a potentially more straightforward implementation prior to
+closure conversion:
+\begin{itemize}
+\item It permits higher-order inlining, for example when a non-inlinable
+function always returns the same function yet with different environments
+of definition.  Not all such cases are supported yet, but it is intended
+that such support will be improved in future.
+\item It is easier to integrate with cross-module optimisation, since
+imported information about other modules is already in the correct
+intermediate language.
+\item It becomes more straightforward to optimise closure allocations since
+the layout of closures does not have to be estimated in any way: it is
+known.  Similarly,
+it becomes more straightforward to control which variables end up
+in which closures, helping to avoid closure bloat.
+\end{itemize}
+
+\subsection{Classic inlining heuristic}\label{classic}
+
+In {\tt -Oclassic} mode the behaviour of the Flambda inliner
+mimics previous versions
+of the compiler.  (Code may still be subject to further optimisations not
+performed by previous versions of the compiler: functors may be inlined,
+constants are lifted and unused code is eliminated all as described elsewhere
+in this chapter.  See sections \ref{functors},\ \ref{lift-const} %
+and\ \ref{remove-unused}.
+At the definition site of a function, the body of the
+function is measured.  It will then be marked as eligible for inlining
+(and hence inlined at every direct call site) if:
+\begin{itemize}
+\item the measured size (in unspecified units) is smaller than that of a
+function call plus the argument of the {\tt -inline} command-line flag; and
+\item the function is not recursive.
+\end{itemize}
+
+Non-Flambda versions of the compiler cannot inline functions that
+contain a definition of another function.  However {\tt -Oclassic} does
+permit this.  Further, non-Flambda versions also cannot inline functions
+that are only themselves exposed as a result of a previous pass of inlining,
+but again this is permitted by {\tt -Oclassic}.
+For example:
+\begin{verbatim}
+module M : sig
+  val i : int
+end = struct
+  let f x =
+    let g y = x + y in
+    g
+  let h = f 3
+  let i = h 4  (* h is correctly discovered to be g and inlined *)
+end
+\end{verbatim}
+
+All of this contrasts with the normal Flambda mode, that is to say
+without {\tt -Oclassic}, where:
+\begin{itemize}
+\item the inlining decision is made at the {\bf call site}; and
+\item recursive functions can be handled, by {\em specialisation} (see
+below).
+\end{itemize}
+The Flambda mode is described in the next section.
+
+\subsection{Overview of ``Flambda'' inlining heuristics}
+
+The Flambda inlining heuristics, used whenever the compiler is configured
+for Flambda and {\tt -Oclassic} was not specified, make inlining decisions
+at call sites.  This helps in situations where the context is important.
+For example:
+\begin{verbatim}
+let f b x =
+  if b then
+    x
+  else
+    ... big expression ...
+
+let g x = f true x
+\end{verbatim}
+In this case, we would like to inline {\tt f} into {\tt g}, because a
+conditional jump can be eliminated and the code size should reduce.  If the
+inlining decision has been made after the declaration of {\tt f} without
+seeing the use, its size would have probably made it ineligible for
+inlining; but at the call site, its final size can be known.  Further,
+this function should probably not be inlined systematically: if {\tt b}
+is unknown, or indeed {\tt false}, there is little benefit to trade off
+against a large increase in code size.  In the existing non-Flambda inliner
+this isn't a great problem because chains of inlining were cut off fairly
+quickly.  However it has led to excessive use of overly-large inlining
+parameters such as {\tt -inline 10000}.
+
+In more detail, at each call site the following procedure is followed:
+\begin{itemize}
+\item Determine whether it is clear that inlining would be beneficial
+without, for the moment, doing any inlining within the function itself.
+(The exact assessment of {\em benefit} is described below.)  If so, the
+function is inlined.
+\item If inlining the function is not clearly beneficial, then inlining
+will be performed {\em speculatively} inside the function itself.  The
+search for speculative inlining possibilities is controlled by two
+parameters: the {\em inlining threshold} and the {\em inlining depth}.
+(These are described in more detail below.)
+\begin{itemize}
+\item If such speculation shows that performing some inlining inside the
+function would be beneficial, then such inlining is performed and the
+resulting function inlined at the original call site.
+\item Otherwise, nothing happens.
+\end{itemize}
+\end{itemize}
+Inlining within recursive functions of calls to other
+functions in the same mutually-recursive group is kept in check by
+an {\em unrolling depth}, described below.  This ensures that functions are
+not unrolled to excess.  (Unrolling is only enabled
+if {\tt -O3} optimisation level is selected and/or the
+{\tt -inline-max-unroll}
+flag is passed with an argument greater than zero.)
+
+\subsection{Handling of specific language constructs}
+
+\subsubsection{Functors}\label{functors}
+
+There is nothing particular about functors that inhibits inlining compared
+to normal functions.  To the inliner, these both look the same, except
+that functors are marked as such.
+
+Applications of functors at toplevel are biased in favour of inlining.
+(This bias may be adjusted:
+see the documentation for {\tt -inline-lifting-benefit} below.)
+
+Applications of functors not at toplevel, for example in a local module
+inside some other expression, are treated by the inliner identically to
+normal function calls.
+
+\subsubsection{First-class modules}
+
+The inliner will be able to consider inlining a call to a function in a first
+class module if it knows which particular function is going to be called.
+The presence of the first-class module record that wraps the set of functions
+in the module does not per se inhibit inlining.
+
+\subsubsection{Objects}
+
+Method calls to objects are not at present inlined by Flambda.
+
+\subsection{Inlining reports}
+
+If the {\tt -inlining-report} option is provided to the compiler then a file
+will be emitted corresponding to each round of optimisation.  For the
+OCaml source file {\em basename}{\tt .ml} the files
+are named {\em basename}{\tt .}{\em round}{\tt.inlining.org},
+with {\em round} a
+zero-based integer.  Inside the files, which are formatted as ``org mode'',
+will be found English prose describing the decisions that the inliner took.
+
+\subsection{Assessment of inlining benefit}\label{assessment-inlining}
+
+Inlining typically
+results in an increase in code size, which if left unchecked, may not only
+lead to grossly large executables and excessive compilation times but also
+a decrease in performance due to worse locality.  As such, the
+Flambda inliner trades off the change in code size against
+the expected runtime performance benefit, with the benefit being computed
+based on the number of operations that the compiler observes may be removed
+as a result of inlining.
+
+For example given the following code:
+\begin{verbatim}
+let f b x =
+  if b then
+    x
+  else
+    ... big expression ...
+
+let g x = f true x
+\end{verbatim}
+it would be observed that inlining of {\tt f} would remove:
+\begin{itemize}
+\item one direct call;
+\item one conditional branch.
+\end{itemize}
+
+Formally, an estimate of runtime performance benefit is computed by
+first summing
+the cost of the operations that are known to be removed as a result of the
+inlining and subsequent simplification of the inlined body.
+The individual costs for the various kinds of operations may be adjusted
+using the various {\tt -inline-...-cost} flags as follows.  Costs are
+specified as integers.  All of these flags accept a single argument
+describing such integers using the conventions
+detailed in section\ \ref{rounds}.
+\begin{options}
+\item[\machine{-inline-alloc-cost}] The cost of an allocation.
+\item[\machine{-inline-branch-cost}] The cost of a branch.
+\item[\machine{-inline-call-cost}] The cost of a direct function call.
+\item[\machine{-inline-indirect-cost}] The cost of an indirect function call.
+\item[\machine{-inline-prim-cost}] The cost of a {\em primitive}.  Primitives
+encompass operations including arithmetic and memory access.
+\end{options}
+(Default values are described in section\ \ref{defaults} below.)
+
+The initial benefit value is then scaled by a factor that attempts to
+compensate for the fact that the current point in the code, if under some
+number of conditional branches, may be cold.  (Flambda does not currently
+compute hot and cold paths.)  The factor---the estimated probability that
+the inliner really is on a {\em hot} path---is calculated as
+$(\frac{1}{1 + f})^{d}$, where $f$ is set by
+{\tt -inline-branch-factor} and $d$ is the nesting depth of branches
+at the current point.  As the inliner descends into more deeply-nested
+branches, the benefit of inlining thus lessens.
+
+The resulting benefit value is known as the {\em estimated benefit}.
+
+The change in code size is also estimated: morally speaking it should be the
+change in machine code size, but since that is not available to the inliner,
+an approximation is used.
+
+If the estimated benefit exceeds the increase in code size then the inlined
+version of the function will be kept.  Otherwise the function will not be
+inlined.
+
+Applications of functors at toplevel will be given
+an additional benefit (which may be controlled by the
+{\tt -inline-lifting-benefit} flag) to bias inlining in such situations
+towards keeping the inlined version.
+
+\subsection{Control of speculation}\label{speculation}
+
+As described above, there are three parameters that restrict the search
+for inlining opportunities during speculation:
+\begin{itemize}
+\item the {\em inlining threshold};
+\item the {\em inlining depth};
+\item the {\em unrolling depth}.
+\end{itemize}
+These parameters are ultimately bounded by the arguments provided to
+the corresponding command-line flags (or their default values):
+\begin{itemize}
+\item {\tt -inline} (or, if the call site that triggered speculation is
+at toplevel, {\tt -inline-toplevel});
+\item {\tt -inline-max-depth};
+\item {\tt -inline-max-unroll}.
+\end{itemize}
+{\bf Note in particular} that {\tt -inline} does not have the meaning that
+it has in the previous compiler or in {\tt -Oclassic} mode.  In both of those
+situations {\tt -inline} was effectively some kind of basic assessment of
+inlining benefit.  However in Flambda inlining mode it corresponds to a
+constraint on the search; the assessment of benefit is independent, as
+described above.
+
+When speculation starts the inlining threshold starts at the value set
+by {\tt -inline} (or {\tt -inline-toplevel} if appropriate, see above).
+Upon making a speculative inlining decision the
+threshold is reduced by the code size of the function being inlined.
+If the threshold becomes exhausted, at or below zero, no further speculation
+will be performed.
+
+The inlining depth starts at zero
+and is increased by one every time the inliner
+descends into another function.  It is then decreased by one every time the
+inliner leaves such function.  If the depth exceeds the value set by
+{\tt -inline-max-depth} then speculation stops.  This parameter is intended
+as a general backstop for situations where the inlining
+threshold does not control the search sufficiently.
+
+The unrolling depth applies to calls within the same mutually-recursive
+group of functions.  Each time an inlining of such a call is performed
+the depth is incremented by one when examining the resulting body.  If the
+depth reaches the limit set by {\tt -inline-max-unroll} then speculation
+stops.
+
+\section{Specialisation}\label{specialisation}
+
+The inliner may discover a call site to a recursive function where
+something is known about the arguments: for example, they may be equal to
+some other variables currently in scope.  In this situation it may be
+beneficial to {\em specialise} the function to those arguments.  This is
+done by copying the declaration of the function (and any others involved
+in any same mutually-recursive declaration) and noting the extra information
+about the arguments.  The arguments augmented by this information are known
+as {\em specialised arguments}.  In order to try to ensure that specialisation
+is not performed uselessly, arguments are only specialised if it can be shown
+that they are {\em invariant}: in other words, during the execution of the
+recursive function(s) themselves, the arguments never change.
+
+Unless overridden by an attribute (see below), specialisation of a function
+will not be attempted if:
+\begin{itemize}
+\item the compiler is in {\tt -Oclassic} mode;
+\item the function is not obviously recursive;
+\item the function is not closed.
+\end{itemize}
+
+The compiler can prove invariance of function arguments across multiple
+functions within a recursive group (although this has some limitations,
+as shown by the example below).
+
+It should be noted that the {\em unboxing of closures} pass (see below)
+can introduce specialised arguments on non-recursive functions.  (No other
+place in the compiler currently does this.)
+
+\paragraph{Example: the well-known {\tt List.iter} function}
+This function might be written like so:
+\begin{verbatim}
+let rec iter f l =
+  match l with
+  | [] -> ()
+  | h :: t ->
+    f h;
+    iter f t
+\end{verbatim}
+and used like this:
+\begin{verbatim}
+let print_int x =
+  print_endline (string_of_int x)
+
+let run xs =
+  iter print_int (List.rev xs)
+\end{verbatim}
+The argument {\tt f} to {\tt iter} is invariant so the function may be
+specialised:
+\begin{verbatim}
+let run xs =
+  let rec iter' f l =
+    (* The compiler knows: f holds the same value as foo throughout iter'. *)
+    match l with
+    | [] -> ()
+    | h :: t ->
+      f h;
+      iter' f t
+  in
+  iter' print_int (List.rev xs)
+\end{verbatim}
+The compiler notes down that for the function {\tt iter'}, the argument
+{\tt f} is specialised to the constant closure {\tt print\_int}.  This
+means that the body of {\tt iter'} may be simplified:
+\begin{verbatim}
+let run xs =
+  let rec iter' f l =
+    (* The compiler knows: f holds the same value as foo throughout iter'. *)
+    match l with
+    | [] -> ()
+    | h :: t ->
+      print_int h;  (* this is now a direct call *)
+      iter' f t
+  in
+  iter' print_int (List.rev xs)
+\end{verbatim}
+The call to {\tt print\_int} can indeed be inlined:
+\begin{verbatim}
+let run xs =
+  let rec iter' f l =
+    (* The compiler knows: f holds the same value as foo throughout iter'. *)
+    match l with
+    | [] -> ()
+    | h :: t ->
+      print_endline (string_of_int h);
+      iter' f t
+  in
+  iter' print_int (List.rev xs)
+\end{verbatim}
+The unused specialised argument {\tt f} may now be removed, leaving:
+\begin{verbatim}
+let run xs =
+  let rec iter' l =
+    match l with
+    | [] -> ()
+    | h :: t ->
+      print_endline (string_of_int h);
+      iter' t
+  in
+  iter' (List.rev xs)
+\end{verbatim}
+
+\paragraph{Aside on invariant parameters.} The compiler cannot currently
+detect invariance in cases such as the following.
+\begin{verbatim}
+let rec iter_swap f g l =
+  match l with
+  | [] -> ()
+  | 0 :: t ->
+    iter_swap g f l
+  | h :: t ->
+    f h;
+    iter_swap f g t
+\end{verbatim}
+
+\subsection{Assessment of specialisation benefit}
+
+The benefit of specialisation is assessed in a similar way as for inlining.
+Specialised argument information may mean that the body of the function
+being specialised can be simplified: the removed operations are accumulated
+into a benefit.  This, together with the size of the duplicated (specialised)
+function declaration, is then assessed against the size of the call to the
+original function.
+
+\section{Default settings of parameters}\label{defaults}
+
+The default settings (when not using {\tt -Oclassic}) are for one
+round of optimisation using the following parameters.
+% CR-soon mshinwell: for 4.04, let's autogenerate these.
+
+\begin{tableau}{|l|l|}{Parameter}{Setting}
+\entree{{\tt -inline}}{10}
+\entree{{\tt -inline-branch-factor}}{0.1}
+\entree{{\tt -inline-alloc-cost}}{7}
+\entree{{\tt -inline-branch-cost}}{5}
+\entree{{\tt -inline-call-cost}}{5}
+\entree{{\tt -inline-indirect-cost}}{4}
+\entree{{\tt -inline-prim-cost}}{3}
+\entree{{\tt -inline-lifting-benefit}}{1300}
+\entree{{\tt -inline-toplevel}}{160}
+\entree{{\tt -inline-max-depth}}{1}
+\entree{{\tt -inline-max-unroll}}{0}
+\entree{{\tt -unbox-closures-factor}}{10}
+\end{tableau}
+
+\subsection{Settings at -O2 optimisation level}
+
+When {\tt -O2} is specified two rounds of optimisation are performed.
+The first round uses the default parameters (see above).  The second uses
+the following parameters.
+
+\begin{tableau}{|l|l|}{Parameter}{Setting}
+\entree{{\tt -inline}}{25}
+\entree{{\tt -inline-branch-factor}}{Same as default}
+\entree{{\tt -inline-alloc-cost}}{Double the default}
+\entree{{\tt -inline-branch-cost}}{Double the default}
+\entree{{\tt -inline-call-cost}}{Double the default}
+\entree{{\tt -inline-indirect-cost}}{Double the default}
+\entree{{\tt -inline-prim-cost}}{Double the default}
+\entree{{\tt -inline-lifting-benefit}}{Same as default}
+\entree{{\tt -inline-toplevel}}{400}
+\entree{{\tt -inline-max-depth}}{2}
+\entree{{\tt -inline-max-unroll}}{Same as default}
+\entree{{\tt -unbox-closures-factor}}{Same as default}
+\end{tableau}
+
+\subsection{Settings at -O3 optimisation level}
+
+When {\tt -O3} is specified three rounds of optimisation are performed.
+The first two rounds are as for {\tt -O2}.  The third round uses
+the following parameters.
+
+\begin{tableau}{|l|l|}{Parameter}{Setting}
+\entree{{\tt -inline}}{50}
+\entree{{\tt -inline-branch-factor}}{Same as default}
+\entree{{\tt -inline-alloc-cost}}{Triple the default}
+\entree{{\tt -inline-branch-cost}}{Triple the default}
+\entree{{\tt -inline-call-cost}}{Triple the default}
+\entree{{\tt -inline-indirect-cost}}{Triple the default}
+\entree{{\tt -inline-prim-cost}}{Triple the default}
+\entree{{\tt -inline-lifting-benefit}}{Same as default}
+\entree{{\tt -inline-toplevel}}{800}
+\entree{{\tt -inline-max-depth}}{3}
+\entree{{\tt -inline-max-unroll}}{1}
+\entree{{\tt -unbox-closures-factor}}{Same as default}
+\end{tableau}
+
+\section{Manual control of inlining and specialisation}
+
+Should the inliner prove recalcitrant and refuse to inline a particular
+function, or if the observed inlining decisions are not to the programmer's
+satisfaction for some other reason, inlining behaviour can be dictated by the
+programmer directly in the source code.
+One example where this might be appropriate is when the programmer,
+but not the compiler, knows that a particular function call is on a cold
+code path.  It might be desirable to prevent inlining of the function so
+that the code size along the hot path is kept smaller, so as to increase
+locality.
+
+The inliner is directed using attributes.
+For non-recursive functions (and one-step unrolling of recursive functions,
+although {\tt \@unroll} is more clear for this purpose)
+the following are supported:
+\begin{options}
+\item[{\machine{\@\@inline always}} or {\machine{\@\@inline never}}] Attached
+to a {\em declaration} of a function or functor, these direct the inliner to
+either
+always or never inline, irrespective of the size/benefit calculation.  (If
+the function is recursive then the body is substituted and no special
+action is taken for the recursive call site(s).)
+{\machine{\@\@inline}} with no argument is equivalent to
+{\machine{\@\@inline always}}.
+\item[{\machine{\@inlined always}} or {\machine{\@inlined never}}] Attached
+to a function {\em application}, these direct the inliner likewise.  These
+attributes at call sites override any other attribute that may be present
+on the corresponding declaration.
+{\machine{\@inlined}} with no argument is equivalent to
+{\machine{\@inlined always}}.
+\end{options}
+
+For recursive functions the relevant attributes are:
+\begin{options}
+\item[{\machine{\@\@specialise always}} or {\machine{\@\@specialise never}}]%
+Attached to a declaration of a function
+or functor, this directs the inliner to either always or never
+specialise the function so
+long as it has appropriate contextual knowledge, irrespective of the
+size/benefit calculation.
+{\machine{\@\@specialise}} with no argument is equivalent to
+{\machine{\@\@specialise always}}.
+\item[{\machine{\@specialised always}} or {\machine{\@specialised never}}]%
+Attached to a function application, this
+directs the inliner likewise.  This attribute at a call site overrides any
+other attribute that may be present on the corresponding declaration.
+(Note that the function will still only be specialised if there exist
+one or more invariant parameters whose values are known.)
+{\machine{\@specialised}} with no argument is equivalent to
+{\machine{\@specialised always}}.
+\item[{\machine{\@unrolled }}$n$] This attribute is attached to a function
+application and always takes an integer argument.  Each time the inliner sees
+the attribute it behaves as follows:
+\begin{itemize}
+\item If $n$ is zero or less, nothing happens.
+\item Otherwise the function being called is substituted at the call site
+with its body having been rewritten such that 
+any recursive calls to that function {\em or
+any others in the same mutually-recursive group} are annotated with the
+attribute {\tt unrolled(}$n - 1${\tt )}.  Inlining may continue on that body.
+\end{itemize}
+As such, $n$ behaves as the ``maximum depth of unrolling''.
+\end{options}
+
+A compiler warning will be emitted if it was found impossible to obey an
+annotation from an {\tt \@inlined} or {\tt \@specialised} attribute.
+
+\paragraph{Example showing correct placement of attributes}
+\begin{verbatim}
+module F (M : sig type t end) = struct
+  let[@inline never] bar x =
+    x * 3
+
+  let foo x =
+    (bar [@inlined]) (42 + x)
+end [@@inline never]
+
+module X = F [@inlined] (struct type t = int end)
+\end{verbatim}
+
+\section{Simplification}
+
+Simplification, which is run in conjunction with inlining,
+propagates information (known as {\em approximations}) about which
+variables hold what values at runtime.  Certain relationships between
+variables and symbols are also tracked: for example, some variable may be
+known to always hold the same value as some other variable; or perhaps
+some variable may be known to always hold the value pointed to by some
+symbol.
+
+The propagation can help to eliminate allocations in cases such as:
+\begin{verbatim}
+let f x y =
+  ...
+  let p = x, y in
+  ...
+  ... (fst p) ... (snd p) ...
+\end{verbatim}
+The projections from {\tt p} may be replaced by uses of the variables
+{\tt x} and {\tt y}, potentially meaning that {\tt p} becomes unused.
+
+The propagation performed by the simplification pass is also important for
+discovering which functions flow to indirect call sites.  This can enable
+the transformation of such call sites into direct call sites, which makes
+them eligible for an inlining transformation.
+
+Note that no information is propagated about the contents of strings,
+even in {\tt safe-string} mode, because it cannot yet be guaranteed
+that they are immutable throughout a given program.
+
+\section{Other code motion transformations}
+
+\subsection{Lifting of constants}\label{lift-const}
+
+Expressions found to be constant will be lifted to symbol
+bindings---that is to say, they will be statically allocated in the
+object file---when
+they evaluate to boxed values.  Such constants may be straightforward numeric
+constants, such as the floating-point number {\tt 42.0}, or more complicated
+values such as constant closures.
+
+Lifting of constants to toplevel reduces allocation at runtime.
+
+The compiler aims to share constants lifted to toplevel such that there
+are no duplicate definitions.  However if {\tt .cmx} files are hidden
+from the compiler then maximal sharing may not be possible.
+
+\paragraph{Notes about float arrays} %
+The following language semantics apply specifically to constant float arrays.
+(By ``constant float array'' is meant an array consisting entirely of floating
+point numbers that are known at compile time.  A common case is a literal
+such as {\tt [| 42.0; 43.0; |]}.
+\begin{itemize}
+\item Constant float arrays at the toplevel are mutable and never shared.
+(That is to say, for each
+such definition there is a distinct symbol in the data section of the object
+file pointing at the array.)
+\item Constant float arrays not at toplevel are mutable and are created each
+time the expression is evaluated.  This can be thought of as an operation that
+takes an immutable array (which in the source code has no associated name; let
+us call it the {\em initialising array}) and
+duplicates it into a fresh mutable array.
+\begin{itemize}
+\item If the array is of size four or less, the expression will create a
+fresh block and write the values into it one by one.  There is no reference
+to the initialising array as a whole.
+
+\item Otherwise, the initialising array is lifted out and subject to the
+normal constant sharing procedure;
+creation of the array consists of bulk copying the initialising array
+into a fresh value on the OCaml heap.
+\end{itemize}
+\end{itemize}
+
+\subsection{Lifting of toplevel let bindings}
+
+Toplevel {\tt let}-expressions may be lifted to symbol bindings to ensure
+that the corresponding bound variables are not captured by closures.  If the
+defining expression of a given binding is found to be constant, it is bound
+as such (the technical term is a {\em let-symbol} binding).
+
+Otherwise, the symbol is bound to a (statically-allocated)
+{\em preallocated block} containing one field.  At runtime, the defining
+expression will be evaluated and the first field of the block filled with
+the resulting value.  This {\em initialise-symbol} binding
+causes one extra indirection but ensures, by
+virtue of the symbol's address being known at compile time, that uses of the
+value are not captured by closures.
+
+It should be noted that the blocks corresponding to initialise-symbol
+bindings are kept alive forever, by virtue of them occurring in a static
+table of GC roots within the object file.  This extended lifetime of
+expressions may on occasion be surprising.  If it is desired to create
+some non-constant value (for example when writing GC tests) that does not
+have this
+extended lifetime, then it may be created and used inside a function,
+with the application point of that function (perhaps at toplevel)---or
+indeed the function declaration itself---marked
+as to never be inlined.  This technique prevents lifting of the definition
+of the value in question (assuming of course that it is not constant).
+
+\section{Unboxing transformations}
+
+The transformations in this section relate to the splitting apart of
+{\em boxed} (that is to say, non-immediate) values.  They are largely
+intended to reduce allocation, which tends to result in a runtime
+performance profile with lower variance and smaller tails.
+
+\subsection{Unboxing of closure variables}\label{unbox-fvs}
+
+This transformation is enabled unless
+{\tt -no-unbox-free-vars-of-closures} is provided.
+
+Variables that appear in closure environments may themselves be boxed
+values.  As such, they may be split into further closure variables, each
+of which corresponds to some projection from the original closure variable(s).
+This transformation is called {\em unboxing of closure variables} or
+{\em unboxing of free variables of closures}.  It is only applied when
+there is
+reasonable certainty that there are no uses of the boxed free variable itself
+within the corresponding function bodies.
+% CR-someday mshinwell: Actually, we probably don't check this carefully
+% enough.  It needs a global analysis in case there is an out-of-scope
+% projection.
+
+\paragraph{Example:} In the following code, the compiler observes that
+the closure returned from the function {\tt f} contains a variable {\tt pair}
+(free in the body of {\tt f}) that may be split into two separate variables.
+\begin{verbatim}
+let f x0 x1 =
+  let pair = x0, x1 in
+  Printf.printf "foo\n";
+  fun y ->
+    fst pair + snd pair + y
+\end{verbatim}
+After some simplification one obtains:
+\begin{verbatim}
+let f x0 x1 =
+  let pair_0 = x0 in
+  let pair_1 = x1 in
+  Printf.printf "foo\n";
+  fun y ->
+    pair_0 + pair_1 + y
+\end{verbatim}
+and then:
+\begin{verbatim}
+let f x0 x1 =
+  Printf.printf "foo\n";
+  fun y ->
+    x0 + x1 + y
+\end{verbatim}
+The allocation of the pair has been eliminated.
+
+This transformation does not operate if it would cause the closure to
+contain more than twice as many closure variables as it did beforehand.
+
+\subsection{Unboxing of specialised arguments}\label{unbox-spec-args}
+
+This transformation is enabled unless
+{\tt -no-unbox-specialised-args} is provided.
+
+It may become the case during compilation that one or more invariant arguments
+to a function become specialised to a particular value.  When such values are
+themselves boxed the corresponding specialised arguments may be split into
+more specialised arguments corresponding to the projections out of the boxed
+value that occur within the function body.  This transformation is called
+{\em unboxing of specialised arguments}.  It is only applied when there is
+reasonable certainty that the boxed argument itself is unused within the
+function.
+
+If the function in question is involved in a recursive group then unboxing
+of specialised arguments may be immediately replicated across the group
+based on the dataflow between invariant arguments.
+
+\paragraph{Example:} Having been given the following code, the compiler
+will inline {\tt loop} into {\tt f}, and then observe {\tt inv}
+being invariant and always the pair formed by adding {\tt 42} and {\tt 43}
+to the argument {\tt x} of the function {\tt f}.
+\begin{verbatim}
+let rec loop inv xs =
+  match xs with
+  | [] -> fst inv + snd inv
+  | x::xs -> x + loop2 xs inv
+and loop2 ys inv =
+  match ys with
+  | [] -> 4
+  | y::ys -> y - loop inv ys
+
+let f x =
+  Printf.printf "%d\n" (loop (x + 42, x + 43) [1; 2; 3])
+\end{verbatim}
+Since the functions have sufficiently few arguments, more specialised
+arguments will be added.  After some simplification one obtains:
+\begin{verbatim}
+let f x =
+  let rec loop' xs inv_0 inv_1 =
+    match xs with
+    | [] -> inv_0 + inv_1
+    | x::xs -> x + loop2' xs inv_0 inv_1
+  and loop2' ys inv_0 inv_1 =
+    match ys with
+    | [] -> 4
+    | y::ys -> y - loop' ys inv_0 inv_1
+  in
+  Printf.printf "%d\n" (loop' (x + 42) (x + 43) [1; 2; 3])
+\end{verbatim}
+The allocation of the pair within {\tt f} has been removed.  (Since the
+two closures for {\tt loop'} and {\tt loop2'} are constant they will also be
+lifted to toplevel with no runtime allocation penalty.  This
+would also happen without having run the transformation to unbox
+specialise arguments.)
+
+The transformation to unbox specialised arguments never introduces extra
+allocation.
+
+The transformation will not unbox arguments if it would result in the
+original function having sufficiently many arguments so as to inhibit
+tail-call optimisation.
+
+The transformation is implemented by creating a wrapper function that
+accepts the original arguments.  Meanwhile, the original function is renamed
+and extra arguments are added corresponding to the unboxed specialised
+arguments; this new function
+is called from the wrapper.  The wrapper will then be inlined
+at direct call sites.  Indeed, all call sites will be direct unless
+{\tt -unbox-closures} is being used, since they will have been generated
+by the compiler when originally specialising the function.  (In the case
+of {\tt -unbox-closures} other functions may appear with specialised
+arguments; in this case there may be indirect calls and these will incur
+a small penalty owing to having to bounce through the wrapper.  The technique
+of {\em direct call surrogates} used for {\tt -unbox-closures} is not
+used by the transformation to unbox specialised arguments.)
+
+\subsection{Unboxing of closures}\label{unbox-closures}
+
+This transformation is {\em not} enabled by default.  It may be enabled
+using the {\tt -unbox-closures} flag.
+
+The transformation replaces closure variables by specialised arguments.
+The aim is to cause more closures to become closed.  It is particularly
+applicable, as a means of reducing allocation, where the function concerned
+cannot be inlined or specialised.  For example, some non-recursive function
+might be too large to inline; or some recursive function might offer
+no opportunities for specialisation perhaps because its only argument is
+one of type {\tt unit}.
+
+At present there may be a small penalty in terms of actual runtime
+performance when this transformation is enabled, although more stable
+performance may be obtained due to reduced allocation.  It is recommended
+that developers experiment to determine whether the option is beneficial
+for their code.  (It is expected that in the future it will be possible
+for the performance degradation to be removed.)
+
+\paragraph{Simple example:} In the following code (which might typically
+occur when {\tt g} is too large to inline) the value of {\tt x} would usually
+be communicated to the application of the {\tt +} function via the closure
+of {\tt g}.
+\begin{verbatim}
+let f x =
+  let g y =
+    x + y
+  in
+  (g [@inlined never]) 42
+\end{verbatim}
+Unboxing of the closure causes the value for {\tt x} inside {\tt g} to
+be passed as an argument to {\tt g} rather than through its closure.  This
+means that the closure of {\tt g} becomes constant and may be lifted to
+toplevel, eliminating the runtime allocation.
+
+The transformation is implemented by adding a new wrapper function in the
+manner of that used when unboxing specialised arguments.  The closure
+variables are still free in the wrapper, but the intention is that when
+the wrapper is inlined at direct call sites, the relevant values are
+passed directly to the main function via the new specialised arguments.
+
+Adding such a wrapper will penalise indirect calls to the function
+(which might exist in arbitrary places; remember that this transformation
+is not for example applied only on functions the compiler has produced
+as a result of specialisation) since such calls will bounce through
+the wrapper.  To
+mitigate this, if a function is small enough when weighed up against
+the number of free variables being removed, it will be duplicated by the
+transformation to obtain two versions: the original (used for indirect calls,
+since we can do no better) and the wrapper/rewritten function pair as
+described in the previous paragraph.  The wrapper/rewritten function pair
+will only be used at direct call sites of the function.  (The wrapper in
+this case is known as a {\em direct call surrogate}, since
+it takes the place of another function---the unchanged version used for
+indirect calls---at direct call sites.)
+
+The {\tt -unbox-closures-factor} command line flag, which takes an
+integer, may be used to adjust the point at which a function is deemed
+large enough to be ineligible for duplication.  The benefit of
+duplication is scaled by the integer before being evaluated against the
+size.
+
+\paragraph{Harder example:} In the following code, there are two closure
+variables that would typically cause closure allocations.  One is called
+{\tt fv} and occurs inside the function {\tt baz}; the other is called
+{\tt z} and occurs inside the function {\tt bar}.
+In this toy (yet sophisticated) example we again use an attribute to
+simulate the typical situation where the first argument of {\tt baz} is
+too large to inline.
+\begin{verbatim}
+let foo c =
+  let rec bar zs fv =
+    match zs with
+    | [] -> []
+    | z::zs ->
+      let rec baz f = function
+        | [] -> []
+        | a::l -> let r = fv + ((f [@inlined never]) a) in r :: baz f l
+      in
+      (map2 (fun y -> z + y) [z; 2; 3; 4]) @ bar zs fv
+  in
+  Printf.printf "%d" (List.length (bar [1; 2; 3; 4] c))
+\end{verbatim}
+The code resulting from applying {\tt -O3 -unbox-closures} to this code
+passes the free variables via function arguments in
+order to eliminate all closure allocation in this example (aside from any
+that might be performed inside {\tt printf}).
+
+\section{Removal of unused code and values}\label{remove-unused}
+
+\subsection{Removal of redundant let expressions}
+
+The simplification pass removes unused {\tt let} bindings so long as
+their corresponding defining expressions have ``no effects''.  See
+the section ``Treatment of effects'' below for the precise definition of
+this term.
+
+\subsection{Removal of redundant program constructs}
+
+This transformation is analogous to the removal of {\tt let}-expressions
+whose defining expressions have no effects.  It operates instead on symbol
+bindings, removing those that have no effects.
+
+\subsection{Removal of unused arguments}\label{remove-unused-args}
+
+This transformation is only enabled by default for specialised arguments.
+It may be enabled for all arguments using the {\tt -remove-unused-arguments}
+flag.
+
+The pass analyses functions to determine which arguments are unused.
+Removal is effected by creating a wrapper function, which will be inlined
+at every direct call site, that accepts the original arguments and then
+discards the unused ones before calling the original function.  As a
+consequence, this transformation may be detrimental if the original
+function is usually indirectly called, since such calls will now bounce
+through the wrapper.  (The technique of {\em direct call surrogates} used
+to reduce this penalty during unboxing of closure variables (see above)
+does not yet apply to the pass that removes unused arguments.)
+
+\subsection{Removal of unused closure variables}
+
+This transformation performs an analysis across
+the whole compilation unit to determine whether there exist closure variables
+that are never used.  Such closure variables are then eliminated.  (Note that
+this has to be a whole-unit analysis because a projection of a closure
+variable from some particular closure may have propagated to an arbitrary
+location within the code due to inlining.)
+
+\section{Other code transformations}
+
+\subsection{Transformation of non-escaping references into mutable variables}
+
+Flambda performs a simple analysis analogous to that performed elsewhere
+in the compiler that can transform {\tt ref}s into mutable variables
+that may then be held in registers (or on the stack as appropriate) rather
+than being allocated on the OCaml heap.  This only happens so long as the
+reference concerned can be shown to not escape from its defining scope.
+
+\subsection{Substitution of closure variables for specialised arguments}
+
+This transformation discovers closure variables that are known to be
+equal to specialised arguments.  Such closure variables are replaced by
+the specialised arguments; the closure variables may then be removed by
+the ``removal of unused closure variables'' pass (see below).
+
+\section{Treatment of effects}
+
+The Flambda optimisers classify expressions in order to determine whether
+an expression:
+\begin{itemize}
+\item does not need to be evaluated at all; and/or
+\item may be duplicated.
+\end{itemize}
+
+This is done by forming judgements on the {\em effects} and the {\em coeffects}
+that might be performed were the expression to be executed.  Effects talk
+about how the expression might affect the world; coeffects talk about how
+the world might affect the expression.
+
+Effects are classified as follows:
+\begin{options}
+\item[{\bf No effects:}] The expression 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 {\em not} classed as having
+``no effects'' (see below).
+\begin{itemize}
+\item It is assumed in the compiler that expressions with no
+effects, whose results are not used, may be eliminated.  (This typically
+happens where the expression in question is the defining expression of a
+{\tt let}; in such cases the {\tt let}-expression will be
+eliminated.) It is further
+assumed that such expressions with no effects may be
+duplicated (and thus possibly executed more than once).
+\item 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.
+\end{itemize}
+\item[{\bf Only generative effects:}] The expression does not change the
+observable state of the world save for possibly affecting the state of
+the garbage collector by performing an allocation.  Expressions
+that only have generative effects and whose results are unused
+may be eliminated by the compiler.  However, unlike expressions with
+``no effects'', such expressions will never be eligible for duplication.
+\item[{\bf Arbitrary effects:}] All other expressions.
+\end{options}
+
+There is a single classification for coeffects:
+\begin{options}
+\item[{\bf No coeffects:}] The expression 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.
+\end{options}
+
+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.
+
+\section{Compilation of statically-allocated modules}
+
+Compilation of modules that are able to be statically allocated (for example,
+the module corresponding to an entire compilation unit, as opposed to a first
+class module dependent on values computed at runtime) initially follows the
+strategy used for bytecode.  A sequence of {\tt let}-bindings, which may be
+interspersed with arbitrary effects, surrounds a record creation that becomes
+the module block.  The Flambda-specific transformation follows: these bindings
+are lifted to toplevel symbols, as described above.
+
+\section{Inhibition of optimisation}\label{inhibition}
+
+Especially when writing benchmarking suites that run non-side-effecting
+algorithms in loops, it may be found that the optimiser entirely
+elides the code being benchmarked.  This behaviour can be prevented by
+using the {\tt Sys.opaque\_identity} function (which indeed behaves as a
+normal OCaml function and does not possess any ``magic'' semantics).  The
+documentation of the {\tt Sys} module should be consulted for further details.
+
+\section{Use of unsafe operations}\label{unsafe}
+
+The behaviour of the Flambda simplification pass means that certain unsafe
+operations, which may without Flambda or when using previous versions of
+the compiler be safe, must not be used.  This specifically refers to
+functions found in the {\tt Obj} module.
+
+In particular, it is forbidden to change any value (for example using
+{\tt Obj.set\_field} or {\tt Obj.set\_tag}) that is not mutable.
+(Values returned from C stubs
+are always treated as mutable.)  The compiler will emit warning 59 if it
+detects such a write---but it cannot warn in all cases.  Here is an example
+of code that will trigger the warning:
+\begin{verbatim}
+let f x =
+  let a = 42, x in
+  (Obj.magic a : int ref) := 1;
+  fst a
+\end{verbatim}
+The reason this is unsafe is because the simplification pass believes that
+{\tt fst a} holds the value {\tt 42}; and indeed it must, unless type
+soundness has been broken via unsafe operations.
+
+If it must be the case that code has to be written that triggers warning 59,
+but the code is known to actually be correct (for some definition of
+correct), then {\tt Sys.opaque\_identity} may be used to wrap the value
+before unsafe operations are performed upon it.  Great care must be taken
+when doing this to ensure that the opacity is added at the correct place.
+It must be emphasised that this use of {\tt Sys.opaque\_identity} is only
+for {\bf exceptional} cases.  It should not be used in normal code or to
+try to guide the optimiser.
+
+As an example, this code will return the integer {\tt 1}:
+\begin{verbatim}
+let f x =
+  let a = Sys.opaque_identity (42, x) in
+  (Obj.magic a : int ref) := 1;
+  fst a
+\end{verbatim}
+However the following code will still return {\tt 42}:
+\begin{verbatim}
+let f x =
+  let a = 42, x in
+  Sys.opaque_identity (Obj.magic a : int ref) := 1;
+  fst a
+\end{verbatim}
+
+High levels of inlining performed by Flambda may expose bugs in code
+thought previously to be correct.  Take care, for example, not
+to add type annotations that claim some mutable value is always immediate
+if it might be possible for an unsafe operation to update it to a boxed
+value.
+
+\section{Glossary}
+
+The following terminology is used in this chapter of the manual.
+
+\begin{options}
+\item[{\bf Call site}] See {\em direct call site} and %
+{\em indirect call site} below.
+\item[{\bf Closed function}] A function whose body has no free variables
+except its parameters and any to which are bound other functions within
+the same (possibly mutually-recursive) declaration.
+\item[{\bf Closure}] The runtime representation of a function.  This
+includes pointers to the code of the function
+together with the values of any variables that are used in the body of
+the function but actually defined outside of the function, in the
+enclosing scope.
+The values of such variables, collectively known as the
+{\em environment}, are required because the function may be
+invoked from a place where the original bindings of such variables are
+no longer in scope.  A group of possibly
+mutually-recursive functions defined using {\em let rec} all share a
+single closure.  (Note to developers: in the Flambda source code a
+{\em closure} always corresponds to a single function; a
+{\em set of closures} refers to a group of such.)
+\item[{\bf Closure variable}]  A member of the environment held within the
+closure of a given function.
+\item[{\bf Constant}]  Some entity (typically an expression) the value of which
+is known by the compiler at compile time.  Constantness may be explicit from
+the source code or inferred by the Flambda optimisers.
+\item[{\bf Constant closure}] A closure that is statically allocated in an
+object file.  It is almost always the case that the environment portion of
+such a closure is empty.
+\item[{\bf Defining expression}]  The expression {\tt e} in %
+{\tt let x = e in e'}.
+\item[{\bf Direct call site}]  A place in a program's code where a function is
+called and it is known at compile time which function it will always be.
+\item[{\bf Indirect call site}]  A place in a program's code where a function
+is called but is not known to be a {\em direct call site}.
+\item[{\bf Program}]  A collection of {\em symbol bindings} forming the
+definition of a single compilation unit (i.e. {\tt .cmx} file).
+\item[{\bf Specialised argument}]  An argument to a function that is known
+to always hold a particular value at runtime.  These are introduced by the
+inliner when specialising recursive functions; and the {\tt unbox-closures}
+pass.  (See section\ \ref{specialisation}.)
+\item[{\bf Symbol}]  A name referencing a particular place in an object file
+or executable image.  At that particular place will be some constant value.
+Symbols may be examined using operating system-specific tools (for
+example {\tt objdump} on Linux).
+\item[{\bf Symbol binding}]  Analogous to a {\tt let}-expression but working
+at the level of symbols defined in the object file.  The address of a symbol is
+fixed, but it may be bound to both constant and non-constant expressions.
+\item[{\bf Toplevel}]  An expression in the current program which is not
+enclosed within any function declaration.
+\item[{\bf Variable}]  A named entity to which some OCaml value is bound by a
+{\tt let} expression, pattern-matching construction, or similar.
+\end{options}
diff --git a/manual/manual/cmds/intf-c.etex b/manual/manual/cmds/intf-c.etex
new file mode 100644
index 0000000000..2bbd095951
--- /dev/null
+++ b/manual/manual/cmds/intf-c.etex
@@ -0,0 +1,2346 @@
+\chapter{Interfacing\label{c:intf-c} C with OCaml}
+\pdfchapterfold{-9}{Interfacing C with OCaml}
+%HEVEA\cutname{intfc.html}
+
+This chapter describes how user-defined primitives, written in C, can
+be linked with OCaml code and called from OCaml functions, and how
+these C functions can call back to OCaml code.
+
+\section{Overview and compilation information}
+\pdfsection{Overview and compilation information}
+
+\subsection{Declaring primitives}
+
+\begin{syntax}
+definition: ...
+            | 'external' value-name ':' typexpr '=' external-declaration
+;
+external-declaration: string-literal [ string-literal [ string-literal ] ]
+\end{syntax}
+
+User primitives are declared in an implementation file or
+@"struct"\ldots"end"@ module expression using the @"external"@ keyword:
+\begin{alltt}
+        external \var{name} : \var{type} = \var{C-function-name}
+\end{alltt}
+This defines the value name \var{name} as a function with type
+\var{type} that executes by calling the given C function.
+For instance, here is how the "input" primitive is declared in the
+standard library module "Pervasives":
+\begin{verbatim}
+        external input : in_channel -> bytes -> int -> int -> int
+                       = "input"
+\end{verbatim}
+Primitives with several arguments are always curried. The C function
+does not necessarily have the same name as the ML function.
+
+External functions thus defined can be specified in interface files or
+@"sig"\ldots"end"@ signatures either as regular values
+\begin{alltt}
+        val \var{name} : \var{type}
+\end{alltt}
+thus hiding their implementation as C functions, or explicitly as
+``manifest'' external functions
+\begin{alltt}
+        external \var{name} : \var{type} = \var{C-function-name}
+\end{alltt}
+The latter is slightly more efficient, as it allows clients of the
+module to call directly the C function instead of going through the
+corresponding OCaml function. On the other hand, it should not be used
+in library modules if they have side-effects at toplevel, as this
+direct call interferes with the linker's algorithm for removing unused
+modules from libraries at link-time.
+
+The arity (number of arguments) of a primitive is automatically
+determined from its OCaml type in the "external" declaration, by
+counting the number of function arrows in the type.  For instance,
+"input" above has arity 4, and the "input" C function is called with
+four arguments.  Similarly,
+\begin{verbatim}
+    external input2 : in_channel * bytes * int * int -> int = "input2"
+\end{verbatim}
+has arity 1, and the "input2" C function receives one argument (which
+is a quadruple of OCaml values).
+
+Type abbreviations are not expanded when determining the arity of a
+primitive.  For instance,
+\begin{verbatim}
+        type int_endo = int -> int
+        external f : int_endo -> int_endo = "f"
+        external g : (int -> int) -> (int -> int) = "f"
+\end{verbatim}
+"f" has arity 1, but "g" has arity 2.  This allows a primitive to
+return a functional value (as in the "f" example above): just remember
+to name the functional return type in a type abbreviation.
+
+The language accepts external declarations with one or two
+flag strings in addition to the C function's name.  These flags are
+reserved for the implementation of the standard library.
+
+\subsection{Implementing primitives}
+
+User primitives with arity $n \leq 5$ are implemented by C functions
+that take $n$ arguments of type "value", and return a result of type
+"value". The type "value" is the type of the representations for OCaml
+values. It encodes objects of several base types (integers,
+floating-point numbers, strings,~\ldots) as well as OCaml data
+structures. The type "value" and the associated conversion
+functions and macros are described in detail below.  For instance,
+here is the declaration for the C function implementing the "input"
+primitive:
+\begin{verbatim}
+CAMLprim value input(value channel, value buffer, value offset, value length)
+{
+  ...
+}
+\end{verbatim}
+When the primitive function is applied in an OCaml program, the C
+function is called with the values of the expressions to which the
+primitive is applied as arguments. The value returned by the function is
+passed back to the OCaml program as the result of the function
+application.
+
+User primitives with arity greater than 5 should be implemented by two
+C functions. The first function, to be used in conjunction with the
+bytecode compiler "ocamlc", receives two arguments: a pointer to an
+array of OCaml values (the values for the arguments), and an
+integer which is the number of arguments provided. The other function,
+to be used in conjunction with the native-code compiler "ocamlopt",
+takes its arguments directly. For instance, here are the two C
+functions for the 7-argument primitive "Nat.add_nat":
+\begin{verbatim}
+CAMLprim value add_nat_native(value nat1, value ofs1, value len1,
+                              value nat2, value ofs2, value len2,
+                              value carry_in)
+{
+  ...
+}
+CAMLprim value add_nat_bytecode(value * argv, int argn)
+{
+  return add_nat_native(argv[0], argv[1], argv[2], argv[3],
+                        argv[4], argv[5], argv[6]);
+}
+\end{verbatim}
+The names of the two C functions must be given in the primitive
+declaration, as follows:
+\begin{alltt}
+        external \var{name} : \var{type} =
+                 \var{bytecode-C-function-name} \var{native-code-C-function-name}
+\end{alltt}
+For instance, in the case of "add_nat", the declaration is:
+\begin{verbatim}
+        external add_nat: nat -> int -> int -> nat -> int -> int -> int -> int
+                        = "add_nat_bytecode" "add_nat_native"
+\end{verbatim}
+
+Implementing a user primitive is actually two separate tasks: on the
+one hand, decoding the arguments to extract C values from the given
+OCaml values, and encoding the return value as an OCaml
+value; on the other hand, actually computing the result from the arguments.
+Except for very simple primitives, it is often preferable to have two
+distinct C functions to implement these two tasks. The first function
+actually implements the primitive, taking native C values as
+arguments and returning a native C value. The second function,
+often called the ``stub code'', is a simple wrapper around the first
+function that converts its arguments from OCaml values to C values,
+call the first function, and convert the returned C value to OCaml
+value. For instance, here is the stub code for the "input"
+primitive:
+\begin{verbatim}
+CAMLprim value input(value channel, value buffer, value offset, value length)
+{
+  return Val_long(getblock((struct channel *) channel,
+                           &Byte(buffer, Long_val(offset)),
+                           Long_val(length)));
+}
+\end{verbatim}
+(Here, "Val_long", "Long_val" and so on are conversion macros for the
+type "value", that will be described later.  The "CAMLprim" macro
+expands to the required compiler directives to ensure that the
+function is exported and accessible from OCaml.)
+The hard work is performed by the function "getblock", which is
+declared as:
+\begin{verbatim}
+long getblock(struct channel * channel, char * p, long n)
+{
+  ...
+}
+\end{verbatim}
+
+To write C code that operates on OCaml values, the following
+include files are provided:
+\begin{tableau}{|l|p{12cm}|}{Include file}{Provides}
+\entree{"caml/mlvalues.h"}{definition of the "value" type, and conversion
+macros}
+\entree{"caml/alloc.h"}{allocation functions (to create structured OCaml
+objects)}
+\entree{"caml/memory.h"}{miscellaneous memory-related functions
+and macros (for GC interface, in-place modification of structures, etc).}
+\entree{"caml/fail.h"}{functions for raising exceptions
+(see section~\ref{s:c-exceptions})}
+\entree{"caml/callback.h"}{callback from C to OCaml (see
+section~\ref{s:callback}).}
+\entree{"caml/custom.h"}{operations on custom blocks (see
+section~\ref{s:custom}).}
+\entree{"caml/intext.h"}{operations for writing user-defined
+serialization and deserialization functions for custom blocks
+(see section~\ref{s:custom}).}
+\entree{"caml/threads.h"}{operations for interfacing in the presence
+  of multiple threads (see section~\ref{s:C-multithreading}).}
+\end{tableau}
+These files reside in the "caml/" subdirectory of the OCaml
+standard library directory, which is returned by the command
+"ocamlc -where" (usually "/usr/local/lib/ocaml" or "/usr/lib/ocaml").
+
+By default, header files in the "caml/" subdirectory give only access
+to the public interface of the OCaml runtime. It is possible to define
+the macro "CAML_INTERNALS" to get access to a lower-level interface,
+but this lower-level interface is more likely to change and break
+programs that use it.
+
+{\bf Note:} It is recommended to define the macro "CAML_NAME_SPACE"
+before including these header files. If you do not define it, the
+header files will also define short names (without the "caml_" prefix)
+for most functions, which usually produce clashes with names defined
+by other C libraries that you might use. Including the header files
+without "CAML_NAME_SPACE" is only supported for backward
+compatibility.
+
+\subsection{Statically linking C code with OCaml code}
+\label{staticlink-c-code}
+
+The OCaml runtime system comprises three main parts: the bytecode
+interpreter, the memory manager, and a set of C functions that
+implement the primitive operations. Some bytecode instructions are
+provided to call these C functions, designated by their offset in a
+table of functions (the table of primitives).
+
+In the default mode, the OCaml linker produces bytecode for the
+standard runtime system, with a standard set of primitives. References
+to primitives that are not in this standard set result in the
+``unavailable C primitive'' error.  (Unless dynamic loading of C
+libraries is supported -- see section~\ref{dynlink-c-code} below.)
+
+In the ``custom runtime'' mode, the OCaml linker scans the
+object files and determines the set of required primitives. Then, it
+builds a suitable runtime system, by calling the native code linker with:
+\begin{itemize}
+\item the table of the required primitives;
+\item a library that provides the bytecode interpreter, the
+memory manager, and the standard primitives;
+\item libraries and object code files (".o" files) mentioned on the
+command line for the OCaml linker, that provide implementations
+for the user's primitives.
+\end{itemize}
+This builds a runtime system with the required primitives. The OCaml
+linker generates bytecode for this custom runtime system. The
+bytecode is appended to the end of the custom runtime system, so that
+it will be automatically executed when the output file (custom
+runtime + bytecode) is launched.
+
+To link in ``custom runtime'' mode, execute the "ocamlc" command with:
+\begin{itemize}
+\item the "-custom" option;
+\item the names of the desired OCaml object files (".cmo" and ".cma" files) ;
+\item the names of the C object files and libraries (".o" and ".a"
+files) that implement the required primitives. Under Unix and Windows,
+a library named "lib"\var{name}".a" (respectively, ".lib") residing in one of
+the standard library directories can also be specified as "-cclib -l"\var{name}.
+\end{itemize}
+
+If you are using the native-code compiler "ocamlopt", the "-custom"
+flag is not needed, as the final linking phase of "ocamlopt" always
+builds a standalone executable.  To build a mixed OCaml/C executable,
+execute the "ocamlopt" command with:
+\begin{itemize}
+\item the names of the desired OCaml native object files (".cmx" and
+".cmxa" files);
+\item the names of the C object files and libraries (".o", ".a",
+".so" or ".dll" files) that implement the required primitives.
+\end{itemize}
+
+Starting with Objective Caml 3.00, it is possible to record the
+"-custom" option as well as the names of C libraries in an OCaml
+library file ".cma" or ".cmxa".  For instance, consider an OCaml library
+"mylib.cma", built from the OCaml object files "a.cmo" and "b.cmo",
+which reference C code in "libmylib.a".  If the library is
+built as follows:
+\begin{alltt}
+        ocamlc -a -o mylib.cma -custom a.cmo b.cmo -cclib -lmylib
+\end{alltt}
+users of the library can simply link with "mylib.cma":
+\begin{alltt}
+        ocamlc -o myprog mylib.cma ...
+\end{alltt}
+and the system will automatically add the "-custom" and "-cclib
+-lmylib" options, achieving the same effect as
+\begin{alltt}
+        ocamlc -o myprog -custom a.cmo b.cmo ... -cclib -lmylib
+\end{alltt}
+The alternative is of course to build the library without extra
+options:
+\begin{alltt}
+        ocamlc -a -o mylib.cma a.cmo b.cmo
+\end{alltt}
+and then ask users to provide the "-custom" and "-cclib -lmylib"
+options themselves at link-time:
+\begin{alltt}
+        ocamlc -o myprog -custom mylib.cma ... -cclib -lmylib
+\end{alltt}
+The former alternative is more convenient for the final users of the
+library, however.
+
+\subsection{Dynamically linking C code with OCaml code}
+\label{dynlink-c-code}
+
+Starting with Objective Caml 3.03, an alternative to static linking of C code
+using the "-custom" code is provided.  In this mode, the OCaml linker
+generates a pure bytecode executable (no embedded custom runtime
+system) that simply records the names of dynamically-loaded libraries
+containing the C code.  The standard OCaml runtime system "ocamlrun"
+then loads dynamically these libraries, and resolves references to the
+required primitives, before executing the bytecode.
+
+This facility is currently supported and known to work well under
+Linux, MacOS~X, and Windows.  It is supported, but not
+fully tested yet, under FreeBSD, Tru64, Solaris and Irix.  It is not
+supported yet under other Unixes.
+
+To dynamically link C code with OCaml code, the C code must first be
+compiled into a shared library (under Unix) or DLL (under Windows).
+This involves 1- compiling the C files with appropriate C compiler
+flags for producing position-independent code (when required by the
+operating system), and 2- building a
+shared library from the resulting object files.  The resulting shared
+library or DLL file must be installed in a place where "ocamlrun" can
+find it later at program start-up time (see
+section~\ref{s-ocamlrun-dllpath}).
+Finally (step 3), execute the "ocamlc" command with
+\begin{itemize}
+\item the names of the desired OCaml object files (".cmo" and ".cma" files) ;
+\item the names of the C shared libraries (".so" or ".dll" files) that
+implement the required primitives.  Under Unix and Windows,
+a library named "dll"\var{name}".so" (respectively, ".dll") residing
+in one of the standard library directories can also be specified as
+"-dllib -l"\var{name}.
+\end{itemize}
+Do {\em not} set the "-custom" flag, otherwise you're back to static linking
+as described in section~\ref{staticlink-c-code}.
+The "ocamlmklib" tool (see section~\ref{s-ocamlmklib})
+automates steps 2 and 3.
+
+As in the case of static linking, it is possible (and recommended) to
+record the names of C libraries in an OCaml ".cma" library archive.
+Consider again an OCaml library
+"mylib.cma", built from the OCaml object files "a.cmo" and "b.cmo",
+which reference C code in "dllmylib.so".  If the library is
+built as follows:
+\begin{alltt}
+        ocamlc -a -o mylib.cma a.cmo b.cmo -dllib -lmylib
+\end{alltt}
+users of the library can simply link with "mylib.cma":
+\begin{alltt}
+        ocamlc -o myprog mylib.cma ...
+\end{alltt}
+and the system will automatically add the "-dllib -lmylib" option,
+achieving the same effect as
+\begin{alltt}
+        ocamlc -o myprog a.cmo b.cmo ... -dllib -lmylib
+\end{alltt}
+Using this mechanism, users of the library "mylib.cma" do not need to
+known that it references C code, nor whether this C code must be
+statically linked (using "-custom") or dynamically linked.
+
+\subsection{Choosing between static linking and dynamic linking}
+
+After having described two different ways of linking C code with OCaml
+code, we now review the pros and cons of each, to help developers of
+mixed OCaml/C libraries decide.
+
+The main advantage of dynamic linking is that it preserves the
+platform-independence of bytecode executables.  That is, the bytecode
+executable contains no machine code, and can therefore be compiled on
+platform $A$ and executed on other platforms $B$, $C$, \ldots, as long
+as the required shared libraries are available on all these
+platforms.  In contrast, executables generated by "ocamlc -custom" run
+only on the platform on which they were created, because they embark a
+custom-tailored runtime system specific to that platform.  In
+addition, dynamic linking results in smaller executables.
+
+Another advantage of dynamic linking is that the final users of the
+library do not need to have a C compiler, C linker, and C runtime
+libraries installed on their machines.  This is no big deal under
+Unix and Cygwin, but many Windows users are reluctant to install
+Microsoft Visual C just to be able to do "ocamlc -custom".
+
+There are two drawbacks to dynamic linking.  The first is that the
+resulting executable is not stand-alone: it requires the shared
+libraries, as well as "ocamlrun", to be installed on the machine
+executing the code.  If you wish to distribute a stand-alone
+executable, it is better to link it statically, using "ocamlc -custom
+-ccopt -static" or "ocamlopt -ccopt -static".  Dynamic linking also
+raises the ``DLL hell'' problem: some care must be taken to ensure
+that the right versions of the shared libraries are found at start-up
+time.
+
+The second drawback of dynamic linking is that it complicates the
+construction of the library.  The C compiler and linker flags to
+compile to position-independent code and build a shared library vary
+wildly between different Unix systems.  Also, dynamic linking is not
+supported on all Unix systems, requiring a fall-back case to static
+linking in the Makefile for the library.  The "ocamlmklib" command
+(see section~\ref{s-ocamlmklib}) tries to hide some of these system
+dependencies.
+
+In conclusion: dynamic linking is highly recommended under the native
+Windows port, because there are no portability problems and it is much
+more convenient for the end users.  Under Unix, dynamic linking should
+be considered for mature, frequently used libraries because it
+enhances platform-independence of bytecode executables.  For new or
+rarely-used libraries, static linking is much simpler to set up in a
+portable way.
+
+\subsection{Building standalone custom runtime systems}
+\label{s:custom-runtime}
+
+It is sometimes inconvenient to build a custom runtime system each
+time OCaml code is linked with C libraries, like "ocamlc -custom" does.
+For one thing, the building of the runtime system is slow on some
+systems (that have bad linkers or slow remote file systems); for
+another thing, the platform-independence of bytecode files is lost,
+forcing to perform one "ocamlc -custom" link per platform of interest.
+
+An alternative to "ocamlc -custom" is to build separately a custom
+runtime system integrating the desired C libraries, then generate
+``pure'' bytecode executables (not containing their own runtime
+system) that can run on this custom runtime.  This is achieved by the
+"-make-runtime" and "-use-runtime" flags to "ocamlc".  For example,
+to build a custom runtime system integrating the C parts of the
+``Unix'' and ``Threads'' libraries, do:
+\begin{verbatim}
+        ocamlc -make-runtime -o /home/me/ocamlunixrun unix.cma threads.cma
+\end{verbatim}
+To generate a bytecode executable that runs on this runtime system,
+do:
+\begin{alltt}
+        ocamlc -use-runtime /home/me/ocamlunixrun -o myprog \char92
+                unix.cma threads.cma {\it{your .cmo and .cma files}}
+\end{alltt}
+The bytecode executable "myprog" can then be launched as usual:
+"myprog" \var{args} or "/home/me/ocamlunixrun myprog" \var{args}.
+
+Notice that the bytecode libraries "unix.cma" and "threads.cma" must
+be given twice: when building the runtime system (so that "ocamlc"
+knows which C primitives are required) and also when building the
+bytecode executable (so that the bytecode from "unix.cma" and
+"threads.cma" is actually linked in).
+
+\section{The \texttt{value} type}
+\pdfsection{The value type}
+
+All OCaml objects are represented by the C type "value",
+defined in the include file "caml/mlvalues.h", along with macros to
+manipulate values of that type. An object of type "value" is either:
+\begin{itemize}
+\item an unboxed integer;
+\item a pointer to a block inside the heap (such as the blocks
+allocated through one of the \verb"caml_alloc_*" functions below);
+\item a pointer to an object outside the heap (e.g., a pointer to a block
+allocated by "malloc", or to a C variable).
+   %%% FIXME will change in 4.02.0 (?)
+\end{itemize}
+
+\subsection{Integer values}
+
+Integer values encode 63-bit signed integers (31-bit on 32-bit
+architectures). They are unboxed (unallocated).
+
+\subsection{Blocks}
+
+Blocks in the heap are garbage-collected, and therefore have strict
+structure constraints. Each block includes a header containing the
+size of the block (in words), and the tag of the block.
+The tag governs how the contents of the blocks are structured. A tag
+lower than "No_scan_tag" indicates a structured block, containing
+well-formed values, which is recursively traversed by the garbage
+collector. A tag greater than or equal to "No_scan_tag" indicates a
+raw block, whose contents are not scanned by the garbage collector.
+For the benefit of ad-hoc polymorphic primitives such as equality and
+structured input-output, structured and raw blocks are further
+classified according to their tags as follows:
+\begin{tableau}{|l|p{10cm}|}{Tag}{Contents of the block}
+\entree{0 to $\hbox{"No_scan_tag"}-1$}{A structured block (an array of
+OCaml objects). Each field is a "value".}
+\entree{"Closure_tag"}{A closure representing a functional value. The first
+word is a pointer to a piece of code, the remaining words are
+"value" containing the environment.}
+\entree{"String_tag"}{A character string or a byte sequence.}
+\entree{"Double_tag"}{A double-precision floating-point number.}
+\entree{"Double_array_tag"}{An array or record of double-precision
+floating-point numbers.}
+\entree{"Abstract_tag"}{A block representing an abstract datatype.}
+\entree{"Custom_tag"}{A block representing an abstract datatype
+              with user-defined finalization, comparison, hashing,
+              serialization and deserialization functions atttached.}
+\end{tableau}
+
+\subsection{Pointers outside the heap}
+
+Any word-aligned pointer to an address outside the heap can be safely
+cast to and from the type "value". This includes pointers returned by
+"malloc", and pointers to C variables (of size at least one word)
+obtained with the \verb'&' operator.
+   %%% FIXME will change in 4.02.0 (?)
+
+Caution: if a pointer returned by "malloc" is cast to the type "value"
+and returned to OCaml, explicit deallocation of the pointer using
+"free" is potentially dangerous, because the pointer may still be
+accessible from the OCaml world.  Worse, the memory space deallocated
+by "free" can later be reallocated as part of the OCaml heap; the
+pointer, formerly pointing outside the OCaml heap, now points inside
+the OCaml heap, and this can crash the garbage collector.  To avoid
+these problems, it is preferable to wrap the pointer in a OCaml block
+with tag "Abstract_tag" or "Custom_tag".
+
+\section{Representation of OCaml data types}
+\pdfsection{Representation of OCaml data types}
+
+This section describes how OCaml data types are encoded in the
+"value" type.
+
+\subsection{Atomic types}
+
+\begin{tableau}{|l|l|}{OCaml type}{Encoding}
+\entree{"int"}{Unboxed integer values.}
+\entree{"char"}{Unboxed integer values (ASCII code).}
+\entree{"float"}{Blocks with tag "Double_tag".}
+\entree{"bytes"}{Blocks with tag "String_tag".}
+\entree{"string"}{Blocks with tag "String_tag".}
+\entree{"int32"}{Blocks with tag "Custom_tag".}
+\entree{"int64"}{Blocks with tag "Custom_tag".}
+\entree{"nativeint"}{Blocks with tag "Custom_tag".}
+\end{tableau}
+
+\subsection{Tuples and records}
+\label{ss:tuples-and-records}
+
+Tuples are represented by pointers to blocks, with tag~0.
+
+Records are also represented by zero-tagged blocks. The ordering of
+labels in the record type declaration determines the layout of
+the record fields: the value associated to the label
+declared first is stored in field~0 of the block, the value associated
+to the second label goes in field~1, and so on.
+
+As an optimization, records whose fields all have static type "float"
+are represented as arrays of floating-point numbers, with tag
+"Double_array_tag". (See the section below on arrays.)
+
+As another optimization, unboxable record types are represented
+specially; unboxable record types are the immutable record types that
+have only one field. An unboxable type will be represented in one of
+two ways: boxed or unboxed. Boxed record types are represented as
+described above (by a block with tag 0 or "Double_array_tag"). An
+unboxed record type is represented directly by the value of its field
+(i.e. there is no block to represent the record itself).
+
+The representation is chosen according to the following, in decreasing
+order of priority:
+\begin{itemize}
+\item An attribute ("[\@\@boxed]" or "[\@\@unboxed]") on the type declaration.
+\item A compiler option ("-unboxed-types" or "-no-unboxed-types").
+\item The default representation. In the present version of OCaml, the
+default is the boxed representation.
+\end{itemize}
+
+\subsection{Arrays}
+
+Arrays of integers and pointers are represented like tuples,
+that is, as pointers to blocks tagged~0.  They are accessed with the
+"Field" macro for reading and the "caml_modify" function for writing.
+
+Arrays of floating-point numbers (type "float array")
+have a special, unboxed, more efficient representation.
+These arrays are represented by pointers to blocks with tag
+"Double_array_tag".  They should be accessed with the "Double_field"
+and "Store_double_field" macros.
+
+\subsection{Concrete data types}
+
+Constructed terms are represented either by unboxed integers (for
+constant constructors) or by blocks whose tag encode the constructor
+(for non-constant constructors). The constant constructors and the
+non-constant constructors for a given concrete type are numbered
+separately, starting from 0, in the order in which they appear in the
+concrete type declaration. A constant constructor is represented by
+the unboxed integer equal to its constructor number. A non-constant
+constructor declared with $n$ arguments is represented by
+a block of size $n$, tagged with the constructor number; the $n$
+fields contain its arguments. Example:
+
+\begin{tableau}{|l|p{8cm}|}{Constructed term}{Representation}
+\entree{"()"}{"Val_int(0)"}
+\entree{"false"}{"Val_int(0)"}
+\entree{"true"}{"Val_int(1)"}
+\entree{"[]"}{"Val_int(0)"}
+\entree{"h::t"}{Block with size = 2 and tag = 0; first field
+contains "h", second field "t".}
+\end{tableau}
+
+As a convenience, "caml/mlvalues.h" defines the macros "Val_unit",
+"Val_false" and "Val_true" to refer to "()", "false" and "true".
+
+The following example illustrates the assignment of
+integers and block tags to constructors:
+\begin{verbatim}
+type t =
+  | A             (* First constant constructor -> integer "Val_int(0)" *)
+  | B of string   (* First non-constant constructor -> block with tag 0 *)
+  | C             (* Second constant constructor -> integer "Val_int(1)" *)
+  | D of bool     (* Second non-constant constructor -> block with tag 1 *)
+  | E of t * t    (* Third non-constant constructor -> block with tag 2 *)
+\end{verbatim}
+
+
+As an optimization, unboxable concrete data types are represented
+specially; a concrete data type is unboxable if it has exactly one
+constructor and this constructor has exactly one argument. Unboxable
+concrete data types are represented in the same ways as unboxable
+record types: see the description in
+section~\ref{ss:tuples-and-records}.
+
+\subsection{Objects}
+
+Objects are represented as blocks with tag "Object_tag". The first
+field of the block refers to the object's class and associated method
+suite, in a format that cannot easily be exploited from C. The second
+field contains a unique object ID, used for comparisons. The remaining
+fields of the object contain the values of the instance variables of
+the object. It is unsafe to access directly instance variables, as the
+type system provides no guarantee about the instance variables
+contained by an object.
+% Instance variables are stored in the order in which they
+% appear in the class definition (taking inherited classes into
+% account).
+
+One may extract a public method from an object using the C function
+"caml_get_public_method" (declared in "".)
+Since public method tags are hashed in the same way as variant tags,
+and methods are functions taking self as first argument, if you want
+to do the method call "foo#bar" from the C side, you should call:
+\begin{verbatim}
+  callback(caml_get_public_method(foo, hash_variant("bar")), foo);
+\end{verbatim}
+
+\subsection{Polymorphic variants}
+
+Like constructed terms, polymorphic variant values are represented either
+as integers (for polymorphic variants without argument), or as blocks
+(for polymorphic variants with an argument).  Unlike constructed
+terms, variant constructors are not numbered starting from 0, but
+identified by a hash value (an OCaml integer), as computed by the C function
+"hash_variant" (declared in ""):
+the hash value for a variant constructor named, say, "VConstr"
+is "hash_variant(\"VConstr\")".
+
+The variant value "`VConstr" is represented by
+"hash_variant(\"VConstr\")".  The variant value "`VConstr("\var{v}")" is
+represented by a block of size 2 and tag 0, with field number 0
+containing "hash_variant(\"VConstr\")" and field number 1 containing
+\var{v}.
+
+Unlike constructed values, polymorphic variant values taking several
+arguments are not flattened.
+That is, "`VConstr("\var{v}", "\var{w}")" is represented by a block
+of size 2, whose field number 1 contains the representation of the
+pair "("\var{v}", "\var{w}")", rather than a block of size 3
+containing \var{v} and \var{w} in fields 1 and 2.
+
+\section{Operations on values}
+\pdfsection{Operations on values}
+
+\subsection{Kind tests}
+
+\begin{itemize}
+\item "Is_long("\var{v}")" is true if value \var{v} is an immediate integer,
+false otherwise
+\item "Is_block("\var{v}")" is true if value \var{v} is a pointer to a block,
+and false if it is an immediate integer.
+\end{itemize}
+
+\subsection{Operations on integers}
+
+\begin{itemize}
+\item "Val_long("\var{l}")" returns the value encoding the "long int" \var{l}.
+\item "Long_val("\var{v}")" returns the "long int" encoded in value \var{v}.
+\item "Val_int("\var{i}")" returns the value encoding the "int" \var{i}.
+\item "Int_val("\var{v}")" returns the "int" encoded in value \var{v}.
+\item "Val_bool("\var{x}")" returns the OCaml boolean representing the
+truth value of the C integer \var{x}.
+\item "Bool_val("\var{v}")" returns 0 if \var{v} is the OCaml boolean
+"false", 1 if \var{v} is "true".
+\item "Val_true", "Val_false" represent the OCaml booleans "true" and "false".
+\end{itemize}
+
+\subsection{Accessing blocks}
+
+\begin{itemize}
+\item "Wosize_val("\var{v}")" returns the size of the block \var{v}, in words,
+excluding the header.
+\item "Tag_val("\var{v}")" returns the tag of the block \var{v}.
+\item "Field("\var{v}", "\var{n}")" returns the value contained in the
+$n\th$ field of the structured block \var{v}. Fields are numbered from 0 to
+$\hbox{"Wosize_val"}(v)-1$.
+\item "Store_field("\var{b}", "\var{n}", "\var{v}")" stores the value
+\var{v} in the field number \var{n} of value \var{b}, which must be a
+structured block.
+\item "Code_val("\var{v}")" returns the code part of the closure \var{v}.
+\item "caml_string_length("\var{v}")" returns the length (number of bytes)
+of the string or byte sequence \var{v}.
+\item "Byte("\var{v}", "\var{n}")" returns the $n\th$ byte of the string
+or byte sequence \var{v}, with type "char". Bytes are numbered from 0 to
+$\hbox{"string_length"}(v)-1$.
+\item "Byte_u("\var{v}", "\var{n}")" returns the $n\th$ byte of the string
+or byte sequence \var{v}, with type "unsigned char". Bytes are
+numbered from 0 to $\hbox{"string_length"}(v)-1$.
+\item "String_val("\var{v}")" returns a pointer to the first byte of the string
+or byte sequence \var{v}, with type "char *". This pointer is a valid C
+string: there is a
+null byte after the last byte in the string. However, OCaml
+strings and byte sequences can contain embedded null bytes, which will confuse
+the usual C functions over strings.
+\item "Double_val("\var{v}")" returns the floating-point number contained in
+value \var{v}, with type "double".
+\item "Double_field("\var{v}", "\var{n}")" returns
+the $n\th$ element of the array of floating-point numbers \var{v} (a
+block tagged "Double_array_tag").
+\item "Store_double_field("\var{v}", "\var{n}",
+"\var{d}")" stores the double precision floating-point number \var{d}
+in the $n\th$ element of the array of floating-point numbers \var{v}.
+\item "Data_custom_val("\var{v}")" returns a pointer to the data part
+of the custom block \var{v}.  This pointer has type "void *" and must
+be cast to the type of the data contained in the custom block.
+\item "Int32_val("\var{v}")" returns the 32-bit integer contained
+in the "int32" \var{v}.
+\item "Int64_val("\var{v}")" returns the 64-bit integer contained
+in the "int64" \var{v}.
+\item "Nativeint_val("\var{v}")" returns the long integer contained
+in the "nativeint" \var{v}.
+\item "caml_field_unboxed("\var{v}")" returns the value of the field
+of a value \var{v} of any unboxed type (record or concrete data type).
+\item "caml_field_boxed("\var{v}")" returns the value of the field
+of a value \var{v} of any boxed type (record or concrete data type).
+\item "caml_field_unboxable("\var{v}")" calls either
+"caml_field_unboxed" or "caml_field_boxed" according to the default
+representation of unboxable types in the current version of OCaml.
+\end{itemize}
+The expressions "Field("\var{v}", "\var{n}")",
+"Byte("\var{v}", "\var{n}")" and
+"Byte_u("\var{v}", "\var{n}")"
+are valid l-values. Hence, they can be assigned to, resulting in an
+in-place modification of value \var{v}.
+Assigning directly to "Field("\var{v}", "\var{n}")" must
+be done with care to avoid confusing the garbage collector (see
+below).
+
+\subsection{Allocating blocks}
+
+\subsubsection{Simple interface}
+
+\begin{itemize}
+\item
+"Atom("\var{t}")" returns an ``atom'' (zero-sized block) with tag \var{t}.
+Zero-sized blocks are preallocated outside of the heap. It is
+incorrect to try and allocate a zero-sized block using the functions below.
+For instance, "Atom(0)" represents the empty array.
+\item
+"caml_alloc("\var{n}", "\var{t}")" returns a fresh block of size \var{n}
+with tag \var{t}.  If \var{t} is less than "No_scan_tag", then the
+fields of the block are initialized with a valid value in order to
+satisfy the GC constraints.
+\item
+"caml_alloc_tuple("\var{n}")" returns a fresh block of size
+\var{n} words, with tag 0.
+\item
+"caml_alloc_string("\var{n}")" returns a byte sequence (or string) value of
+length \var{n} bytes. The sequence initially contains uninitialized bytes.
+\item
+"caml_copy_string("\var{s}")" returns a string or byte sequence value
+containing a copy of the null-terminated C string \var{s} (a "char *").
+\item
+"caml_copy_double("\var{d}")" returns a floating-point value initialized
+with the "double" \var{d}.
+\item
+"caml_copy_int32("\var{i}")", "caml_copy_int64("\var{i}")" and
+"caml_copy_nativeint("\var{i}")" return a value of OCaml type "int32",
+"int64" and "nativeint", respectively, initialized with the integer
+\var{i}.
+\item
+"caml_alloc_array("\var{f}", "\var{a}")" allocates an array of values, calling
+function \var{f} over each element of the input array \var{a} to transform it
+into a value. The array \var{a} is an array of pointers terminated by the
+null pointer. The function \var{f} receives each pointer as argument, and
+returns a value. The zero-tagged block returned by
+"alloc_array("\var{f}", "\var{a}")" is filled with the values returned by the
+successive calls to \var{f}.  (This function must not be used to build
+an array of floating-point numbers.)
+\item
+"caml_copy_string_array("\var{p}")" allocates an array of strings or byte
+sequences, copied from the pointer to a string array \var{p}
+(a "char **").  \var{p} must be NULL-terminated.
+\item "caml_alloc_float_array("\var{n}")" allocates an array of floating point
+  numbers of size \var{n}. The array initially contains uninitialized values.
+\item "caml_alloc_unboxed("\var{v}")" returns the value (of any unboxed
+type) whose field is the value \var{v}.
+\item "caml_alloc_boxed("\var{v}")" allocates and returns a value  (of
+any boxed type) whose field is the value \var{v}.
+\item "caml_alloc_unboxable("\var{v}")" calls either
+"caml_alloc_unboxed" or "caml_alloc_boxed" according to the default
+representation of unboxable types in the current version of OCaml.
+\end{itemize}
+
+\subsubsection{Low-level interface}
+
+The following functions are slightly more efficient than "caml_alloc", but
+also much more difficult to use.
+
+From the standpoint of the allocation functions, blocks are divided
+according to their size as zero-sized blocks, small blocks (with size
+less than or equal to \verb"Max_young_wosize"), and large blocks (with
+size greater than \verb"Max_young_wosize"). The constant
+\verb"Max_young_wosize" is declared in the include file "mlvalues.h". It
+is guaranteed to be at least 64 (words), so that any block with
+constant size less than or equal to 64 can be assumed to be small. For
+blocks whose size is computed at run-time, the size must be compared
+against \verb"Max_young_wosize" to determine the correct allocation procedure.
+
+\begin{itemize}
+\item
+"caml_alloc_small("\var{n}", "\var{t}")" returns a fresh small block of size
+$n \leq \hbox{"Max_young_wosize"}$ words, with tag \var{t}.
+If this block is a structured block (i.e. if $t < \hbox{"No_scan_tag"}$), then
+the fields of the block (initially containing garbage) must be initialized
+with legal values (using direct assignment to the fields of the block)
+before the next allocation.
+\item
+"caml_alloc_shr("\var{n}", "\var{t}")" returns a fresh block of size
+\var{n}, with tag \var{t}.
+The size of the block can be greater than \verb"Max_young_wosize". (It
+can also be smaller, but in this case it is more efficient to call
+"caml_alloc_small" instead of "caml_alloc_shr".)
+If this block is a structured block (i.e. if $t < \hbox{"No_scan_tag"}$), then
+the fields of the block (initially containing garbage) must be initialized
+with legal values (using the "caml_initialize" function described below)
+before the next allocation.
+\end{itemize}
+
+\subsection{Raising exceptions} \label{s:c-exceptions}
+
+Two functions are provided to raise two standard exceptions:
+\begin{itemize}
+\item "caml_failwith("\var{s}")", where \var{s} is a null-terminated C string (with
+type \verb"char *"), raises exception "Failure" with argument \var{s}.
+\item "caml_invalid_argument("\var{s}")", where \var{s} is a null-terminated C
+string (with type \verb"char *"), raises exception "Invalid_argument"
+with argument \var{s}.
+\end{itemize}
+
+Raising arbitrary exceptions from C is more delicate: the
+exception identifier is dynamically allocated by the OCaml program, and
+therefore must be communicated to the C function using the
+registration facility described below in section~\ref{s:register-exn}.
+Once the exception identifier is recovered in C, the following
+functions actually raise the exception:
+\begin{itemize}
+\item "caml_raise_constant("\var{id}")" raises the exception \var{id} with
+no argument;
+\item "caml_raise_with_arg("\var{id}", "\var{v}")" raises the exception
+\var{id} with the OCaml value \var{v} as argument;
+\item "caml_raise_with_args("\var{id}", "\var{n}", "\var{v}")"
+raises the exception \var{id} with the OCaml values
+\var{v}"[0]", \ldots, \var{v}"["\var{n}"-1]" as arguments;
+\item "caml_raise_with_string("\var{id}", "\var{s}")", where \var{s} is a
+null-terminated C string, raises the exception \var{id} with a copy of
+the C string \var{s} as argument.
+\end{itemize}
+
+\section{Living in harmony with the garbage collector}
+\pdfsection{Living in harmony with the garbage collector}
+
+Unused blocks in the heap are automatically reclaimed by the garbage
+collector. This requires some cooperation from C code that
+manipulates heap-allocated blocks.
+
+\subsection{Simple interface}
+
+All the macros described in this section are declared in the
+"memory.h" header file.
+
+\begin{gcrule}
+A function that has parameters or local variables of type "value" must
+begin with a call to one of the "CAMLparam" macros and return with
+"CAMLreturn", "CAMLreturn0", or "CAMLreturnT". In particular, "CAMLlocal"
+and "CAMLxparam" can only be called \emph{after} "CAMLparam".
+\end{gcrule}
+
+There are six "CAMLparam" macros: "CAMLparam0" to "CAMLparam5", which
+take zero to five arguments respectively.  If your function has no more
+than 5 parameters of type "value", use the corresponding macros
+with these parameters as arguments.  If your function has more than 5
+parameters of type "value", use "CAMLparam5" with five of these
+parameters, and use one or more calls to the "CAMLxparam" macros for
+the remaining parameters ("CAMLxparam1" to "CAMLxparam5").
+
+The macros "CAMLreturn", "CAMLreturn0", and "CAMLreturnT" are used to
+replace the C
+keyword "return".  Every occurrence of "return x" must be replaced by
+"CAMLreturn (x)" if "x" has type "value", or "CAMLreturnT (t, x)"
+(where "t" is the type of "x"); every occurrence of "return" without
+argument must be
+replaced by "CAMLreturn0".  If your C function is a procedure (i.e. if
+it returns void), you must insert "CAMLreturn0" at the end (to replace
+C's implicit "return").
+
+\paragraph{Note:} some C compilers give bogus warnings about unused
+variables "caml__dummy_xxx" at each use of "CAMLparam" and
+"CAMLlocal".  You should ignore them.
+
+\goodbreak
+
+Example:
+\begin{verbatim}
+void foo (value v1, value v2, value v3)
+{
+  CAMLparam3 (v1, v2, v3);
+  ...
+  CAMLreturn0;
+}
+\end{verbatim}
+
+\paragraph{Note:} if your function is a primitive with more than 5 arguments
+for use with the byte-code runtime, its arguments are not "value"s and
+must not be declared (they have types "value *" and "int").
+
+\begin{gcrule}
+Local variables of type "value" must be declared with one of the
+"CAMLlocal" macros.  Arrays of "value"s are declared with
+"CAMLlocalN".  These macros must be used at the beginning of the
+function, not in a nested block.
+\end{gcrule}
+
+The macros "CAMLlocal1" to "CAMLlocal5" declare and initialize one to
+five local variables of type "value".  The variable names are given as
+arguments to the macros.  "CAMLlocalN("\var{x}", "\var{n}")" declares
+and initializes a local variable of type "value ["\var{n}"]".  You can
+use several calls to these macros if you have more than 5 local
+variables.
+
+Example:
+\begin{verbatim}
+value bar (value v1, value v2, value v3)
+{
+  CAMLparam3 (v1, v2, v3);
+  CAMLlocal1 (result);
+  result = caml_alloc (3, 0);
+  ...
+  CAMLreturn (result);
+}
+\end{verbatim}
+
+\begin{gcrule}
+Assignments to the fields of structured blocks must be done with the
+"Store_field" macro (for normal blocks) or "Store_double_field" macro
+(for arrays and records of floating-point numbers).  Other assignments
+must not use "Store_field" nor "Store_double_field".
+\end{gcrule}
+
+"Store_field ("\var{b}", "\var{n}", "\var{v}")" stores the value
+\var{v} in the field number \var{n} of value \var{b}, which must be a
+block (i.e. "Is_block("\var{b}")" must be true).
+
+Example:
+\begin{verbatim}
+value bar (value v1, value v2, value v3)
+{
+  CAMLparam3 (v1, v2, v3);
+  CAMLlocal1 (result);
+  result = caml_alloc (3, 0);
+  Store_field (result, 0, v1);
+  Store_field (result, 1, v2);
+  Store_field (result, 2, v3);
+  CAMLreturn (result);
+}
+\end{verbatim}
+
+\paragraph{Warning:} The first argument of "Store_field" and
+"Store_double_field" must be a variable declared by "CAMLparam*" or
+a parameter declared by "CAMLlocal*" to ensure that a garbage
+collection triggered by the evaluation of the other arguments will not
+invalidate the first argument after it is computed.
+
+\paragraph{Use with CAMLlocalN:} Arrays of values declared using
+"CAMLlocalN" must not be written to using "Store_field".
+Use the normal C array syntax instead.
+
+\begin{gcrule} Global variables containing values must be registered
+with the garbage collector using the "caml_register_global_root" function.
+\end{gcrule}
+
+Registration of a global variable "v" is achieved by calling
+"caml_register_global_root(&v)" just before or just after a valid
+value is stored in "v" for the first time. You must not call any
+of the OCaml runtime functions or macros between registering and
+storing the value.
+
+A registered global variable "v" can be un-registered by calling
+"caml_remove_global_root(&v)".
+
+If the contents of the global variable "v" are seldom modified after
+registration, better performance can be achieved by calling
+"caml_register_generational_global_root(&v)" to register "v" (after
+its initialization with a valid "value", but before any allocation or
+call to the GC functions),
+and "caml_remove_generational_global_root(&v)" to un-register it. In
+this case, you must not modify the value of "v" directly, but you must
+use "caml_modify_generational_global_root(&v,x)" to set it to "x".
+The garbage collector takes advantage of the guarantee that "v" is not
+modified between calls to "caml_modify_generational_global_root" to scan it
+less often. This improves performance if the
+modifications of "v" happen less often than minor collections.
+
+\paragraph{Note:} The "CAML" macros use identifiers (local variables, type
+identifiers, structure tags) that start with "caml__".  Do not use any
+identifier starting with "caml__" in your programs.
+
+\subsection{Low-level interface}
+
+% Il faudrait simplifier violemment ce qui suit.
+% En gros, dire quand on n'a pas besoin de declarer les variables
+% et dans quels cas on peut se passer de "Store_field".
+
+We now give the GC rules corresponding to the low-level allocation
+functions "caml_alloc_small" and "caml_alloc_shr".  You can ignore those rules
+if you stick to the simplified allocation function "caml_alloc".
+
+\begin{gcrule} After a structured block (a block with tag less than
+"No_scan_tag") is allocated with the low-level functions, all fields
+of this block must be filled with well-formed values before the next
+allocation operation. If the block has been allocated with
+"caml_alloc_small", filling is performed by direct assignment to the fields
+of the block:
+\begin{alltt}
+        Field(\var{v}, \var{n}) = \nth{v}{n};
+\end{alltt}
+If the block has been allocated with "caml_alloc_shr", filling is performed
+through the "caml_initialize" function:
+\begin{alltt}
+        caml_initialize(&Field(\var{v}, \var{n}), \nth{v}{n});
+\end{alltt}
+\end{gcrule}
+
+The next allocation can trigger a garbage collection. The garbage
+collector assumes that all structured blocks contain well-formed
+values. Newly created blocks contain random data, which generally do
+not represent well-formed values.
+
+If you really need to allocate before the fields can receive their
+final value,  first initialize with a constant value (e.g.
+"Val_unit"), then allocate, then modify the fields with the correct
+value (see rule~6).
+
+%% \begin{gcrule} Local variables and function parameters containing
+%% values must be registered with the garbage collector (using the
+%% "Begin_roots" and "End_roots" macros), if they are to survive a call
+%% to an allocation function.
+%% \end{gcrule}
+%%
+%% Registration is performed with the "Begin_roots" set of macros.
+%% "Begin_roots1("\var{v}")" registers variable \var{v} with the garbage
+%% collector.  Generally, \var{v} will be a local variable or a
+%% parameter of your function.  It must be initialized to a valid value
+%% (e.g. "Val_unit") before the first allocation.  Likewise,
+%% "Begin_roots2", \ldots, "Begin_roots5"
+%% let you register up to 5 variables at the same time.  "Begin_root" is
+%% the same as "Begin_roots1".  "Begin_roots_block("\var{ptr}","\var{size}")"
+%% allows you to register an array of roots.  \var{ptr} is a pointer to
+%% the first element, and \var{size} is the number of elements in the
+%% array.
+%%
+%% Once registered, each of your variables (or array element) has the
+%% following properties: if it points to a heap-allocated block, this
+%% block (and its contents) will not be reclaimed; moreover, if this
+%% block is relocated by the garbage collector, the variable is updated
+%% to point to the new location for the block.
+%%
+%% Each of the "Begin_roots" macros open a C block that must be closed
+%% with a matching "End_roots" at the same nesting level.  The block must
+%% be exited normally (i.e. not with "return" or "goto").  However, the
+%% roots are automatically un-registered if an OCaml exception is raised,
+%% so you can exit the block with "failwith", "invalid_argument", or one
+%% of the "raise" functions.
+%%
+%% {\bf Note:} The "Begin_roots" macros use a local variable and a
+%% structure tag named "caml__roots_block".  Do not use this identifier
+%% in your programs.
+
+\begin{gcrule} Direct assignment to a field of a block, as in
+\begin{alltt}
+        Field(\var{v}, \var{n}) = \var{w};
+\end{alltt}
+is safe only if \var{v} is a block newly allocated by "caml_alloc_small";
+that is, if no allocation took place between the
+allocation of \var{v} and the assignment to the field. In all other cases,
+never assign directly. If the block has just been allocated by "caml_alloc_shr",
+use "caml_initialize" to assign a value to a field for the first time:
+\begin{alltt}
+        caml_initialize(&Field(\var{v}, \var{n}), \var{w});
+\end{alltt}
+Otherwise, you are updating a field that previously contained a
+well-formed value; then, call the "caml_modify" function:
+\begin{alltt}
+        caml_modify(&Field(\var{v}, \var{n}), \var{w});
+\end{alltt}
+\end{gcrule}
+
+To illustrate the rules above, here is a C function that builds and
+returns a list containing the two integers given as parameters.
+First, we write it using the simplified allocation functions:
+\begin{verbatim}
+value alloc_list_int(int i1, int i2)
+{
+  CAMLparam0 ();
+  CAMLlocal2 (result, r);
+
+  r = caml_alloc(2, 0);                   /* Allocate a cons cell */
+  Store_field(r, 0, Val_int(i2));         /* car = the integer i2 */
+  Store_field(r, 1, Val_int(0));          /* cdr = the empty list [] */
+  result = caml_alloc(2, 0);              /* Allocate the other cons cell */
+  Store_field(result, 0, Val_int(i1));    /* car = the integer i1 */
+  Store_field(result, 1, r);              /* cdr = the first cons cell */
+  CAMLreturn (result);
+}
+\end{verbatim}
+Here, the registering of "result" is not strictly needed, because no
+allocation takes place after it gets its value, but it's easier and
+safer to simply register all the local variables that have type "value".
+
+Here is the same function written using the low-level allocation
+functions.  We notice that the cons cells are small blocks and can be
+allocated with "caml_alloc_small", and filled by direct assignments on
+their fields.
+\begin{verbatim}
+value alloc_list_int(int i1, int i2)
+{
+  CAMLparam0 ();
+  CAMLlocal2 (result, r);
+
+  r = caml_alloc_small(2, 0);             /* Allocate a cons cell */
+  Field(r, 0) = Val_int(i2);              /* car = the integer i2 */
+  Field(r, 1) = Val_int(0);               /* cdr = the empty list [] */
+  result = caml_alloc_small(2, 0);        /* Allocate the other cons cell */
+  Field(result, 0) = Val_int(i1);         /* car = the integer i1 */
+  Field(result, 1) = r;                   /* cdr = the first cons cell */
+  CAMLreturn (result);
+}
+\end{verbatim}
+In the two examples above, the list is built bottom-up. Here is an
+alternate way, that proceeds top-down. It is less efficient, but
+illustrates the use of "caml_modify".
+\begin{verbatim}
+value alloc_list_int(int i1, int i2)
+{
+  CAMLparam0 ();
+  CAMLlocal2 (tail, r);
+
+  r = caml_alloc_small(2, 0);             /* Allocate a cons cell */
+  Field(r, 0) = Val_int(i1);              /* car = the integer i1 */
+  Field(r, 1) = Val_int(0);               /* A dummy value
+  tail = caml_alloc_small(2, 0);          /* Allocate the other cons cell */
+  Field(tail, 0) = Val_int(i2);           /* car = the integer i2 */
+  Field(tail, 1) = Val_int(0);            /* cdr = the empty list [] */
+  caml_modify(&Field(r, 1), tail);        /* cdr of the result = tail */
+  CAMLreturn (r);
+}
+\end{verbatim}
+It would be incorrect to perform
+"Field(r, 1) = tail" directly, because the allocation of "tail"
+has taken place since "r" was allocated.
+
+
+\section{A complete example}
+\pdfsection{A complete example}
+
+This section outlines how the functions from the Unix "curses" library
+can be made available to OCaml programs. First of all, here is
+the interface "curses.mli" that declares the "curses" primitives and
+data types:
+\begin{verbatim}
+(* File curses.ml -- declaration of primitives and data types *)
+type window                   (* The type "window" remains abstract *)
+external initscr: unit -> window = "caml_curses_initscr"
+external endwin: unit -> unit = "caml_curses_endwin"
+external refresh: unit -> unit = "caml_curses_refresh"
+external wrefresh : window -> unit = "caml_curses_wrefresh"
+external newwin: int -> int -> int -> int -> window = "caml_curses_newwin"
+external addch: char -> unit = "caml_curses_addch"
+external mvwaddch: window -> int -> int -> char -> unit = "caml_curses_mvwaddch"
+external addstr: string -> unit = "caml_curses_addstr"
+external mvwaddstr: window -> int -> int -> string -> unit
+         = "caml_curses_mvwaddstr"
+(* lots more omitted *)
+\end{verbatim}
+To compile this interface:
+\begin{verbatim}
+        ocamlc -c curses.ml
+\end{verbatim}
+
+To implement these functions, we just have to provide the stub code;
+the core functions are already implemented in the "curses" library.
+The stub code file, "curses_stubs.c", looks like this:
+\begin{verbatim}
+/* File curses_stubs.c -- stub code for curses */
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Encapsulation of opaque window handles (of type WINDOW *)
+   as OCaml custom blocks. */
+
+static struct custom_operations curses_window_ops = {
+  "fr.inria.caml.curses_windows",
+  custom_finalize_default,
+  custom_compare_default,
+  custom_hash_default,
+  custom_serialize_default,
+  custom_deserialize_default,
+  custom_compare_ext_default
+};
+
+/* Accessing the WINDOW * part of an OCaml custom block */
+#define Window_val(v) (*((WINDOW **) Data_custom_val(v)))
+
+/* Allocating an OCaml custom block to hold the given WINDOW * */
+static value alloc_window(WINDOW * w)
+{
+  value v = alloc_custom(&curses_window_ops, sizeof(WINDOW *), 0, 1);
+  Window_val(v) = w;
+  return v;
+}
+
+value caml_curses_initscr(value unit)
+{
+  CAMLparam1 (unit);
+  CAMLreturn (alloc_window(initscr()));
+}
+
+value caml_curses_endwin(value unit)
+{
+  CAMLparam1 (unit);
+  endwin();
+  CAMLreturn (Val_unit);
+}
+
+value caml_curses_refresh(value unit)
+{
+  CAMLparam1 (unit);
+  refresh();
+  CAMLreturn (Val_unit);
+}
+
+value caml_curses_wrefresh(value win)
+{
+  CAMLparam1 (win);
+  wrefresh(Window_val(win));
+  CAMLreturn (Val_unit);
+}
+
+value caml_curses_newwin(value nlines, value ncols, value x0, value y0)
+{
+  CAMLparam4 (nlines, ncols, x0, y0);
+  CAMLreturn (alloc_window(newwin(Int_val(nlines), Int_val(ncols),
+                                  Int_val(x0), Int_val(y0))));
+}
+
+value caml_curses_addch(value c)
+{
+  CAMLparam1 (c);
+  addch(Int_val(c));            /* Characters are encoded like integers */
+  CAMLreturn (Val_unit);
+}
+
+value caml_curses_mvwaddch(value win, value x, value y, value c)
+{
+  CAMLparam4 (win, x, y, c);
+  mvwaddch(Window_val(win), Int_val(x), Int_val(y), Int_val(c));
+  CAMLreturn (Val_unit);
+}
+
+value caml_curses_addstr(value s)
+{
+  CAMLparam1 (s);
+  addstr(String_val(s));
+  CAMLreturn (Val_unit);
+}
+
+value caml_curses_mvwaddstr(value win, value x, value y, value s)
+{
+  CAMLparam4 (win, x, y, s);
+  mvwaddstr(Window_val(win), Int_val(x), Int_val(y), String_val(s));
+  CAMLreturn (Val_unit);
+}
+
+/* This goes on for pages. */
+\end{verbatim}
+
+The file "curses_stubs.c" can be compiled with:
+\begin{verbatim}
+        cc -c -I`ocamlc -where` curses_stubs.c
+\end{verbatim}
+or, even simpler,
+\begin{verbatim}
+        ocamlc -c curses_stubs.c
+\end{verbatim}
+(When passed a ".c" file, the "ocamlc" command simply calls the C
+compiler on that file, with the right "-I" option.)
+
+Now, here is a sample OCaml program "prog.ml" that uses the "curses"
+module:
+\begin{verbatim}
+(* File prog.ml -- main program using curses *)
+open Curses;;
+let main_window = initscr () in
+let small_window = newwin 10 5 20 10 in
+  mvwaddstr main_window 10 2 "Hello";
+  mvwaddstr small_window 4 3 "world";
+  refresh();
+  Unix.sleep 5;
+  endwin()
+\end{verbatim}
+To compile and link this program, run:
+\begin{verbatim}
+       ocamlc -custom -o prog unix.cma curses.cmo prog.ml curses_stubs.o -cclib -lcurses
+\end{verbatim}
+(On some machines, you may need to put
+"-cclib -lcurses -cclib -ltermcap" or "-cclib -ltermcap"
+instead of "-cclib -lcurses".)
+
+%% Note by Damien: when I launch the program, it only displays "Hello"
+%% and not "world". Why?
+
+\section{Advanced topic: callbacks from C to OCaml} \label{s:callback}
+\pdfsection{Advanced topic: callbacks from C to OCaml}
+
+So far, we have described how to call C functions from OCaml. In this
+section, we show how C functions can call OCaml functions, either as
+callbacks (OCaml calls C which calls OCaml), or with the main program
+written in C.
+
+\subsection{Applying OCaml closures from C} \label{s:callbacks}
+
+C functions can apply OCaml function values (closures) to OCaml values.
+The following functions are provided to perform the applications:
+\begin{itemize}
+\item "caml_callback("\var{f, a}")" applies the functional value \var{f} to
+the value \var{a} and returns the value returned by~\var{f}.
+\item "caml_callback2("\var{f, a, b}")" applies the functional value \var{f}
+(which is assumed to be a curried OCaml function with two arguments) to
+\var{a} and \var{b}.
+\item "caml_callback3("\var{f, a, b, c}")" applies the functional value \var{f}
+(a curried OCaml function with three arguments) to \var{a}, \var{b} and \var{c}.
+\item "caml_callbackN("\var{f, n, args}")" applies the functional value \var{f}
+to the \var{n} arguments contained in the array of values \var{args}.
+\end{itemize}
+If the function \var{f} does not return, but raises an exception that
+escapes the scope of the application, then this exception is
+propagated to the next enclosing OCaml code, skipping over the C
+code. That is, if an OCaml function \var{f} calls a C function \var{g} that
+calls back an OCaml function \var{h} that raises a stray exception, then the
+execution of \var{g} is interrupted and the exception is propagated back
+into \var{f}.
+
+If the C code wishes to catch exceptions escaping the OCaml function,
+it can use the functions "caml_callback_exn", "caml_callback2_exn",
+"caml_callback3_exn", "caml_callbackN_exn".  These functions take the same
+arguments as their non-"_exn" counterparts, but catch escaping
+exceptions and return them to the C code.  The return value \var{v} of the
+"caml_callback*_exn" functions must be tested with the macro
+"Is_exception_result("\var{v}")".  If the macro returns ``false'', no
+exception occured, and \var{v} is the value returned by the OCaml
+function.  If "Is_exception_result("\var{v}")" returns ``true'',
+an exception escaped, and its value (the exception descriptor) can be
+recovered using "Extract_exception("\var{v}")".
+
+\paragraph{Warning:} If the OCaml function returned with an exception,
+"Extract_exception" should be applied to the exception result prior
+to calling a function that may trigger garbage collection.
+Otherwise, if \var{v} is reachable during garbage collection, the runtime
+can crash since \var{v} does not contain a valid value.
+
+Example:
+\begin{verbatim}
+    value call_caml_f_ex(value closure, value arg)
+    {
+      CAMLparam2(closure, arg);
+      CAMLlocal2(res, tmp);
+      res = caml_callback_exn(closure, arg);
+      if(Is_exception_result(res)) {
+        res = Extract_exception(res);
+        tmp = caml_alloc(3, 0); /* Safe to allocate: res contains valid value. */
+        ...
+      }
+      CAMLreturn (res);
+    }
+\end{verbatim}
+
+\subsection{Obtaining or registering OCaml closures for use in C functions}
+
+There are two ways to obtain OCaml function values (closures) to
+be passed to the "callback" functions described above.  One way is to
+pass the OCaml function as an argument to a primitive function.  For
+example, if the OCaml code contains the declaration
+\begin{verbatim}
+    external apply : ('a -> 'b) -> 'a -> 'b = "caml_apply"
+\end{verbatim}
+the corresponding C stub can be written as follows:
+\begin{verbatim}
+    CAMLprim value caml_apply(value vf, value vx)
+    {
+      CAMLparam2(vf, vx);
+      CAMLlocal1(vy);
+      vy = caml_callback(vf, vx);
+      CAMLreturn(vy);
+    }
+\end{verbatim}
+
+Another possibility is to use the registration mechanism provided by
+OCaml.  This registration mechanism enables OCaml code to register
+OCaml functions under some global name, and C code to retrieve the
+corresponding closure by this global name.
+
+On the OCaml side, registration is performed by evaluating
+"Callback.register" \var{n} \var{v}. Here, \var{n} is the global name
+(an arbitrary string) and \var{v} the OCaml value. For instance:
+\begin{verbatim}
+    let f x = print_string "f is applied to "; print_int x; print_newline()
+    let _ = Callback.register "test function" f
+\end{verbatim}
+
+On the C side, a pointer to the value registered under name \var{n} is
+obtained by calling "caml_named_value("\var{n}")". The returned
+pointer must then be dereferenced to recover the actual OCaml value.
+If no value is registered under the name \var{n}, the null pointer is
+returned. For example, here is a C wrapper that calls the OCaml function "f"
+above:
+\begin{verbatim}
+    void call_caml_f(int arg)
+    {
+        caml_callback(*caml_named_value("test function"), Val_int(arg));
+    }
+\end{verbatim}
+
+The pointer returned by "caml_named_value" is constant and can safely
+be cached in a C variable to avoid repeated name lookups. On the other
+hand, the value pointed to can change during garbage collection and
+must always be recomputed at the point of use. Here is a more
+efficient variant of "call_caml_f" above that calls "caml_named_value"
+only once:
+\begin{verbatim}
+    void call_caml_f(int arg)
+    {
+        static value * closure_f = NULL;
+        if (closure_f == NULL) {
+            /* First time around, look up by name */
+            closure_f = caml_named_value("test function");
+        }
+        caml_callback(*closure_f, Val_int(arg));
+    }
+\end{verbatim}
+
+\subsection{Registering OCaml exceptions for use in C functions} \label{s:register-exn}
+
+The registration mechanism described above can also be used to
+communicate exception identifiers from OCaml to C. The OCaml code
+registers the exception by evaluating
+"Callback.register_exception" \var{n} \var{exn}, where \var{n} is an
+arbitrary name and \var{exn} is an exception value of the
+exception to register. For example:
+\begin{verbatim}
+    exception Error of string
+    let _ = Callback.register_exception "test exception" (Error "any string")
+\end{verbatim}
+The C code can then recover the exception identifier using
+"caml_named_value" and pass it as first argument to the functions
+"raise_constant", "raise_with_arg", and "raise_with_string" (described
+in section~\ref{s:c-exceptions}) to actually raise the exception. For
+example, here is a C function that raises the "Error" exception with
+the given argument:
+\begin{verbatim}
+    void raise_error(char * msg)
+    {
+        caml_raise_with_string(*caml_named_value("test exception"), msg);
+    }
+\end{verbatim}
+
+\subsection{Main program in C} \label{s:main-c}
+
+In normal operation, a mixed OCaml/C program starts by executing the
+OCaml initialization code, which then may proceed to call C
+functions. We say that the main program is the OCaml code. In some
+applications, it is desirable that the C code plays the role of the
+main program, calling OCaml functions when needed. This can be achieved as
+follows:
+\begin{itemize}
+\item The C part of the program must provide a "main" function,
+which will override the default "main" function provided by the OCaml
+runtime system. Execution will start in the user-defined "main" function
+just like for a regular C program.
+
+\item At some point, the C code must call "caml_main(argv)" to
+initialize the OCaml code. The "argv" argument is a C array of strings
+(type "char **"), terminated with a "NULL" pointer,
+which represents the command-line arguments, as
+passed as second argument to "main". The OCaml array "Sys.argv" will
+be initialized from this parameter. For the bytecode compiler,
+"argv[0]" and "argv[1]" are also consulted to find the file containing
+the bytecode.
+
+\item The call to "caml_main" initializes the OCaml runtime system,
+loads the bytecode (in the case of the bytecode compiler), and
+executes the initialization code of the OCaml program. Typically, this
+initialization code registers callback functions using "Callback.register".
+Once the OCaml initialization code is complete, control returns to the
+C code that called "caml_main".
+
+\item The C code can then invoke OCaml functions using the callback
+mechanism (see section~\ref{s:callbacks}).
+\end{itemize}
+
+\subsection{Embedding the OCaml code in the C code} \label{s:embedded-code}
+
+The bytecode compiler in custom runtime mode ("ocamlc -custom")
+normally appends the bytecode to the executable file containing the
+custom runtime. This has two consequences. First, the final linking
+step must be performed by "ocamlc". Second, the OCaml runtime library
+must be able to find the name of the executable file from the
+command-line arguments. When using "caml_main(argv)" as in
+section~\ref{s:main-c}, this means that "argv[0]" or "argv[1]" must
+contain the executable file name.
+
+An alternative is to embed the bytecode in the C code. The
+"-output-obj" option to "ocamlc" is provided for this purpose.  It
+causes the "ocamlc" compiler to output a C object file (".o" file,
+".obj" under Windows) containing the bytecode for the OCaml part of the
+program, as well as a "caml_startup" function. The C object file
+produced by "ocamlc -output-obj" can then be linked with C code using
+the standard C compiler, or stored in a C library.
+
+The "caml_startup" function must be called from the main C program in
+order to initialize the OCaml runtime and execute the OCaml
+initialization code. Just like "caml_main", it takes one "argv"
+parameter containing the command-line parameters. Unlike "caml_main",
+this "argv" parameter is used only to initialize "Sys.argv", but not
+for finding the name of the executable file.
+
+The "-output-obj" option can also be used to obtain the C source file.
+More interestingly, the same option can also produce directly a shared
+library (".so" file, ".dll" under Windows) that contains the OCaml
+code, the OCaml runtime system and any other static C code given to
+"ocamlc" (".o", ".a", respectively, ".obj", ".lib"). This use of
+"-output-obj" is very similar to a normal linking step, but instead of
+producing a main program that automatically runs the OCaml code, it
+produces a shared library that can run the OCaml code on demand. The
+three possible behaviors of "-output-obj" are selected according
+to the extension of the resulting file (given with "-o").
+
+The native-code compiler "ocamlopt" also supports the "-output-obj"
+option, causing it to output a C object file or a shared library
+containing the native code for all OCaml modules on the command-line,
+as well as the OCaml startup code. Initialization is performed by
+calling "caml_startup" as in the case of the bytecode compiler.
+
+For the final linking phase, in addition to the object file produced
+by "-output-obj", you will have to provide the OCaml runtime
+library ("libcamlrun.a" for bytecode, "libasmrun.a" for native-code),
+as well as all C libraries that are required by the OCaml libraries
+used.  For instance, assume the OCaml part of your program uses the
+Unix library.  With "ocamlc", you should do:
+\begin{alltt}
+        ocamlc -output-obj -o camlcode.o unix.cma {\it{other}} .cmo {\it{and}} .cma {\it{files}}
+        cc -o myprog {\it{C objects and libraries}} \char92
+           camlcode.o -L`ocamlc -where` -lunix -lcamlrun
+\end{alltt}
+With "ocamlopt", you should do:
+\begin{alltt}
+        ocamlopt -output-obj -o camlcode.o unix.cmxa {\it{other}} .cmx {\it{and}} .cmxa {\it{files}}
+        cc -o myprog {\it{C objects and libraries}} \char92
+           camlcode.o -L`ocamlc -where` -lunix -lasmrun
+\end{alltt}
+
+% -- This seems completely wrong -- Damien
+% The shared libraries produced by "ocamlc -output-obj" or by "ocamlopt
+% -output-obj" already contains the OCaml runtime library as
+% well as all the needed C libraries.
+
+\paragraph{Warning:} On some ports, special options are required on the final
+linking phase that links together the object file produced by the
+"-output-obj" option and the remainder of the program.  Those options
+are shown in the configuration file "config/Makefile" generated during
+compilation of OCaml, as the variables "BYTECCLINKOPTS"
+(for object files produced by "ocamlc -output-obj") and
+"NATIVECCLINKOPTS" (for object files produced by "ocamlopt
+-output-obj").
+\begin{itemize}
+\item Windows with the MSVC compiler: the object file produced by
+OCaml have been compiled with the "/MD" flag, and therefore
+all other object files linked with it should also be compiled with
+"/MD".
+\item other systems: you may have to add one or more of "-lcurses",
+"-lm", "-ldl", depending on your OS and C compiler.
+\end{itemize}
+
+\paragraph{Stack backtraces.}  When OCaml bytecode produced by
+"ocamlc -g" is embedded in a C program, no debugging information is
+included, and therefore it is impossible to print stack backtraces on
+uncaught exceptions.  This is not the case when native code produced
+by "ocamlopt -g" is embedded in a C program: stack backtrace
+information is available, but the backtrace mechanism needs to be
+turned on programmatically.   This can be achieved from the OCaml side
+by calling "Printexc.record_backtrace true" in the initialization of
+one of the OCaml modules.  This can also be achieved from the C side
+by calling "caml_record_backtrace(Val_int(1));" in the OCaml-C glue code.
+
+\section{Advanced example with callbacks}
+\pdfsection{Advanced example with callbacks}
+
+This section illustrates the callback facilities described in
+section~\ref{s:callback}. We are going to package some OCaml functions
+in such a way that they can be linked with C code and called from C
+just like any C functions. The OCaml functions are defined in the
+following "mod.ml" OCaml source:
+
+\begin{verbatim}
+(* File mod.ml -- some "useful" OCaml functions *)
+
+let rec fib n = if n < 2 then 1 else fib(n-1) + fib(n-2)
+
+let format_result n = Printf.sprintf "Result is: %d\n" n
+
+(* Export those two functions to C *)
+
+let _ = Callback.register "fib" fib
+let _ = Callback.register "format_result" format_result
+\end{verbatim}
+
+Here is the C stub code for calling these functions from C:
+
+\begin{verbatim}
+/* File modwrap.c -- wrappers around the OCaml functions */
+
+#include 
+#include 
+#include 
+#include 
+
+int fib(int n)
+{
+  static value * fib_closure = NULL;
+  if (fib_closure == NULL) fib_closure = caml_named_value("fib");
+  return Int_val(caml_callback(*fib_closure, Val_int(n)));
+}
+
+char * format_result(int n)
+{
+  static value * format_result_closure = NULL;
+  if (format_result_closure == NULL)
+    format_result_closure = caml_named_value("format_result");
+  return strdup(String_val(caml_callback(*format_result_closure, Val_int(n))));
+  /* We copy the C string returned by String_val to the C heap
+     so that it remains valid after garbage collection. */
+}
+\end{verbatim}
+
+We now compile the OCaml code to a C object file and put it in a C
+library along with the stub code in "modwrap.c" and the OCaml runtime system:
+\begin{verbatim}
+        ocamlc -custom -output-obj -o modcaml.o mod.ml
+        ocamlc -c modwrap.c
+        cp `ocamlc -where`/libcamlrun.a mod.a && chmod +w mod.a
+        ar r mod.a modcaml.o modwrap.o
+\end{verbatim}
+(One can also use "ocamlopt -output-obj" instead of "ocamlc -custom
+-output-obj".  In this case, replace "libcamlrun.a" (the bytecode
+runtime library) by "libasmrun.a" (the native-code runtime library).)
+
+Now, we can use the two functions "fib" and "format_result" in any C
+program, just like regular C functions. Just remember to call
+"caml_startup" once before.
+
+\begin{verbatim}
+/* File main.c -- a sample client for the OCaml functions */
+
+#include 
+#include 
+
+extern int fib(int n);
+extern char * format_result(int n);
+
+int main(int argc, char ** argv)
+{
+  int result;
+
+  /* Initialize OCaml code */
+  caml_startup(argv);
+  /* Do some computation */
+  result = fib(10);
+  printf("fib(10) = %s\n", format_result(result));
+  return 0;
+}
+\end{verbatim}
+
+To build the whole program, just invoke the C compiler as follows:
+\begin{verbatim}
+        cc -o prog -I `ocamlc -where` main.c mod.a -lcurses
+\end{verbatim}
+(On some machines, you may need to put "-ltermcap" or
+"-lcurses -ltermcap" instead of "-lcurses".)
+
+\section{Advanced topic: custom blocks} \label{s:custom}
+\pdfsection{Advanced topic: custom blocks}
+
+Blocks with tag "Custom_tag" contain both arbitrary user data and a
+pointer to a C struct, with type "struct custom_operations", that
+associates user-provided finalization, comparison, hashing,
+serialization and deserialization functions to this block.
+
+\subsection{The "struct custom_operations"}
+
+The "struct custom_operations" is defined in "" and
+contains the following fields:
+\begin{itemize}
+\item "char *identifier" \\
+A zero-terminated character string serving as an identifier for
+serialization and deserialization operations.
+
+\item "void  (*finalize)(value v)" \\
+The "finalize" field contains a pointer to a C function that is called
+when the block becomes unreachable and is about to be reclaimed.
+The block is passed as first argument to the function.
+The "finalize" field can also be "custom_finalize_default" to indicate that no
+finalization function is associated with the block.
+
+\item "int (*compare)(value v1, value v2)" \\
+The "compare" field contains a pointer to a C function that is
+called whenever two custom blocks are compared using OCaml's generic
+comparison operators ("=", "<>", "<=", ">=", "<", ">" and
+"compare").  The C function should return 0 if the data contained in
+the two blocks are structurally equal, a negative integer if the data
+from the first block is less than the data from the second block, and
+a positive integer if the data from the first block is greater than
+the data from the second block.
+
+The "compare" field can be set to "custom_compare_default"; this
+default comparison function simply raises "Failure".
+
+\item "int (*compare_ext)(value v1, value v2)" \\
+(Since 3.12.1)
+The "compare_ext" field contains a pointer to a C function that is
+called whenever one custom block and one unboxed integer are compared using OCaml's generic
+comparison operators ("=", "<>", "<=", ">=", "<", ">" and
+"compare").  As in the case of the "compare" field, the C function
+should return 0 if the two arguments are structurally equal, a
+negative integer if the first argument compares less than the second
+argument, and a positive integer if the first argument compares
+greater than the second argument.
+
+The "compare_ext" field can be set to "custom_compare_ext_default"; this
+default comparison function simply raises "Failure".
+
+\item "intnat (*hash)(value v)" \\
+The "hash" field contains a pointer to a C function that is called
+whenever OCaml's generic hash operator (see module "Hashtbl") is
+applied to a custom block.  The C function can return an arbitrary
+integer representing the hash value of the data contained in the
+given custom block.  The hash value must be compatible with the
+"compare" function, in the sense that two structurally equal data
+(that is, two custom blocks for which "compare" returns 0) must have
+the same hash value.
+
+The "hash" field can be set to "custom_hash_default", in which case
+the custom block is ignored during hash computation.
+
+\item "void (*serialize)(value v, uintnat * wsize_32, uintnat * wsize_64)" \\
+The "serialize" field contains a pointer to a C function that is
+called whenever the custom block needs to be serialized (marshaled)
+using the OCaml functions "output_value" or "Marshal.to_...".
+For a custom block, those functions first write the identifier of the
+block (as given by the "identifier" field) to the output stream,
+then call the user-provided "serialize" function.  That function is
+responsible for writing the data contained in the custom block, using
+the "serialize_..." functions defined in "" and listed
+below.  The user-provided "serialize" function must then store in its
+"wsize_32" and "wsize_64" parameters the sizes in bytes of the data
+part of the custom block on a 32-bit architecture and on a 64-bit
+architecture, respectively.
+
+The "serialize" field can be set to "custom_serialize_default",
+in which case the "Failure" exception is raised when attempting to
+serialize the custom block.
+
+\item "uintnat (*deserialize)(void * dst)" \\
+The "deserialize" field contains a pointer to a C function that is
+called whenever a custom block with identifier "identifier" needs to
+be deserialized (un-marshaled) using the OCaml functions "input_value"
+or "Marshal.from_...".  This user-provided function is responsible for
+reading back the data written by the "serialize" operation, using the
+"deserialize_..." functions defined in "" and listed
+below. It must then rebuild the data part of the custom block
+and store it at the pointer given as the "dst" argument.  Finally, it
+returns the size in bytes of the data part of the custom block.
+This size must be identical to the "wsize_32" result of
+the "serialize" operation if the architecture is 32 bits, or
+"wsize_64" if the architecture is 64 bits.
+
+The "deserialize" field can be set to "custom_deserialize_default"
+to indicate that deserialization is not supported.  In this case,
+do not register the "struct custom_operations" with the deserializer
+using "register_custom_operations" (see below).
+\end{itemize}
+
+Note: the "finalize", "compare", "hash", "serialize" and "deserialize"
+functions attached to custom block descriptors must never trigger a
+garbage collection.  Within these functions, do not call any of the
+OCaml allocation functions, and do not perform a callback into OCaml
+code.  Do not use "CAMLparam" to register the parameters to these
+functions, and do not use "CAMLreturn" to return the result.
+
+\subsection{Allocating custom blocks}
+
+Custom blocks must be allocated via the "caml_alloc_custom" function:
+\begin{center}
+"caml_alloc_custom("\var{ops}", "\var{size}", "\var{used}", "\var{max}")"
+\end{center}
+returns a fresh custom block, with room for \var{size} bytes of user
+data, and whose associated operations are given by \var{ops} (a
+pointer to a "struct custom_operations", usually statically allocated
+as a C global variable).
+
+The two parameters \var{used} and \var{max} are used to control the
+speed of garbage collection when the finalized object contains
+pointers to out-of-heap resources.  Generally speaking, the
+OCaml incremental major collector adjusts its speed relative to the
+allocation rate of the program.  The faster the program allocates, the
+harder the GC works in order to reclaim quickly unreachable blocks
+and avoid having large amount of ``floating garbage'' (unreferenced
+objects that the GC has not yet collected).
+
+Normally, the allocation rate is measured by counting the in-heap size
+of allocated blocks.  However, it often happens that finalized
+objects contain pointers to out-of-heap memory blocks and other resources
+(such as file descriptors, X Windows bitmaps, etc.).  For those
+blocks, the in-heap size of blocks is not a good measure of the
+quantity of resources allocated by the program.
+
+The two arguments \var{used} and \var{max} give the GC an idea of how
+much out-of-heap resources are consumed by the finalized block
+being allocated: you give the amount of resources allocated to this
+object as parameter \var{used}, and the maximum amount that you want
+to see in floating garbage as parameter \var{max}.  The units are
+arbitrary: the GC cares only about the ratio $\var{used} / \var{max}$.
+
+For instance, if you are allocating a finalized block holding an X
+Windows bitmap of \var{w} by \var{h} pixels, and you'd rather not
+have more than 1 mega-pixels of unreclaimed bitmaps, specify
+$\var{used} = \var{w} * \var{h}$ and $\var{max} = 1000000$.
+
+Another way to describe the effect of the \var{used} and \var{max}
+parameters is in terms of full GC cycles.  If you allocate many custom
+blocks with $\var{used} / \var{max} = 1 / \var{N}$, the GC will then do one
+full cycle (examining every object in the heap and calling
+finalization functions on those that are unreachable) every \var{N}
+allocations.  For instance, if $\var{used} = 1$ and $\var{max} = 1000$,
+the GC will do one full cycle at least every 1000 allocations of
+custom blocks.
+
+If your finalized blocks contain no pointers to out-of-heap resources,
+or if the previous discussion made little sense to you, just take
+$\var{used} = 0$ and $\var{max} = 1$.  But if you later find that the
+finalization functions are not called ``often enough'', consider
+increasing the $\var{used} / \var{max}$ ratio.
+
+\subsection{Accessing custom blocks}
+
+The data part of a custom block \var{v} can be
+accessed via the pointer "Data_custom_val("\var{v}")".  This pointer
+has type "void *" and should be cast to the actual type of the data
+stored in the custom block.
+
+The contents of custom blocks are not scanned by the garbage
+collector, and must therefore not contain any pointer inside the OCaml
+heap.  In other terms, never store an OCaml "value" in a custom block,
+and do not use "Field", "Store_field" nor "caml_modify" to access the data
+part of a custom block.  Conversely, any C data structure (not
+containing heap pointers) can be stored in a custom block.
+
+\subsection{Writing custom serialization and deserialization functions}
+
+The following functions, defined in "", are provided to
+write and read back the contents of custom blocks in a portable way.
+Those functions handle endianness conversions when e.g. data is
+written on a little-endian machine and read back on a big-endian machine.
+
+\begin{tableau}{|l|p{10cm}|}{Function}{Action}
+\entree{"caml_serialize_int_1"}{Write a 1-byte integer}
+\entree{"caml_serialize_int_2"}{Write a 2-byte integer}
+\entree{"caml_serialize_int_4"}{Write a 4-byte integer}
+\entree{"caml_serialize_int_8"}{Write a 8-byte integer}
+\entree{"caml_serialize_float_4"}{Write a 4-byte float}
+\entree{"caml_serialize_float_8"}{Write a 8-byte float}
+\entree{"caml_serialize_block_1"}{Write an array of 1-byte quantities}
+\entree{"caml_serialize_block_2"}{Write an array of 2-byte quantities}
+\entree{"caml_serialize_block_4"}{Write an array of 4-byte quantities}
+\entree{"caml_serialize_block_8"}{Write an array of 8-byte quantities}
+\entree{"caml_deserialize_uint_1"}{Read an unsigned 1-byte integer}
+\entree{"caml_deserialize_sint_1"}{Read a signed 1-byte integer}
+\entree{"caml_deserialize_uint_2"}{Read an unsigned 2-byte integer}
+\entree{"caml_deserialize_sint_2"}{Read a signed 2-byte integer}
+\entree{"caml_deserialize_uint_4"}{Read an unsigned 4-byte integer}
+\entree{"caml_deserialize_sint_4"}{Read a signed 4-byte integer}
+\entree{"caml_deserialize_uint_8"}{Read an unsigned 8-byte integer}
+\entree{"caml_deserialize_sint_8"}{Read a signed 8-byte integer}
+\entree{"caml_deserialize_float_4"}{Read a 4-byte float}
+\entree{"caml_deserialize_float_8"}{Read an 8-byte float}
+\entree{"caml_deserialize_block_1"}{Read an array of 1-byte quantities}
+\entree{"caml_deserialize_block_2"}{Read an array of 2-byte quantities}
+\entree{"caml_deserialize_block_4"}{Read an array of 4-byte quantities}
+\entree{"caml_deserialize_block_8"}{Read an array of 8-byte quantities}
+\entree{"caml_deserialize_error"}{Signal an error during deserialization;
+"input_value" or "Marshal.from_..." raise a "Failure" exception after
+cleaning up their internal data structures}
+\end{tableau}
+
+Serialization functions are attached to the custom blocks to which
+they apply.  Obviously, deserialization functions cannot be attached
+this way, since the custom block does not exist yet when
+deserialization begins!  Thus, the "struct custom_operations" that
+contain deserialization functions must be registered with the
+deserializer in advance, using the "register_custom_operations"
+function declared in "".  Deserialization proceeds by
+reading the identifier off the input stream, allocating a custom block
+of the size specified in the input stream, searching the registered
+"struct custom_operation" blocks for one with the same identifier, and
+calling its "deserialize" function to fill the data part of the custom block.
+
+\subsection{Choosing identifiers}
+
+Identifiers in "struct custom_operations" must be chosen carefully,
+since they must identify uniquely the data structure for serialization
+and deserialization operations.  In particular, consider including a
+version number in the identifier; this way, the format of the data can
+be changed later, yet backward-compatible deserialisation functions
+can be provided.
+
+Identifiers starting with "_" (an underscore character) are reserved
+for the OCaml runtime system; do not use them for your custom
+data.  We recommend to use a URL
+("http://mymachine.mydomain.com/mylibrary/version-number")
+or a Java-style package name
+("com.mydomain.mymachine.mylibrary.version-number")
+as identifiers, to minimize the risk of identifier collision.
+
+\subsection{Finalized blocks}
+
+Custom blocks generalize the finalized blocks that were present in
+OCaml prior to version 3.00.  For backward compatibility, the
+format of custom blocks is compatible with that of finalized blocks,
+and the "alloc_final" function is still available to allocate a custom
+block with a given finalization function, but default comparison,
+hashing and serialization functions.  "caml_alloc_final("\var{n}",
+"\var{f}", "\var{used}", "\var{max}")" returns a fresh custom block of
+size \var{n} words, with finalization function \var{f}.  The first
+word is reserved for storing the custom operations; the other
+\var{n}-1 words are available for your data.  The two parameters
+\var{used} and \var{max} are used to control the speed of garbage
+collection, as described for "caml_alloc_custom".
+
+\section{Advanced topic: cheaper C call}
+\label{s:C-cheaper-call}
+
+This section describe how to make calling C functions cheaper.
+
+{\bf Note:} this only applies to the native compiler. So whenever you
+use any of these methods, you have to provide an alternative byte-code
+stub that ignores all the special annotations.
+
+\subsection{Passing unboxed values}
+
+We said earlier that all OCaml objects are represented by the C type
+"value", and one has to use macros such as "Int_val" to decode data
+from the "value" type. It is however possible to tell OCaml to do this
+for us and pass arguments unboxed to the C function. Similarly it is
+possible to tell OCaml to expect the result unboxed and box it for us.
+
+The motivation is that, by letting the OCaml compiler deal with
+boxing, it can often decide to suppress it entirely.
+
+For instance let's consider this example:
+
+\begin{verbatim}
+external foo : float -> float -> float = "foo"
+
+let f a b =
+  let len = Array.length a in
+  assert (Array.length b = len);
+  let res = Array.make len 0. in
+  for i = 0 to len - 1 do
+    res.(i) <- foo a.(i) b.(i)
+  done
+\end{verbatim}
+
+Float arrays are unboxed in OCaml, however the C function "foo" expect
+its arguments as boxed floats and returns a boxed float. Hence the
+OCaml compiler has no choice but to box "a.(i)" and "b.(i)" and unbox
+the result of "foo".  This results in the allocation of "3 * len"
+temporary float values.
+
+Now if we annotate the arguments and result with "[\@unboxed]", the
+compiler will be able to avoid all these allocations:
+
+\begin{verbatim}
+external foo
+  :  (float [@unboxed])
+  -> (float [@unboxed])
+  -> (float [@unboxed])
+  = "foo_byte" "foo"
+\end{verbatim}
+
+In this case the C functions must look like:
+
+\begin{verbatim}
+CAMLprim double foo(double a, double b)
+{
+  ...
+}
+
+CAMLprim value foo_byte(value a, value b)
+{
+  return caml_copy_double(foo(Double_val(a), Double_val(b)))
+}
+\end{verbatim}
+
+For convenicence, when all arguments and the result are annotated with
+"[\@unboxed]", it is possible to put the attribute only once on the
+declaration itself. So we can also write instead:
+
+\begin{verbatim}
+external foo : float -> float -> float = "foo_byte" "foo" [@@unboxed]
+\end{verbatim}
+
+The following table summarize what OCaml types can be unboxed, and
+what C types should be used in correspondence:
+
+\begin{tableau}{|l|l|}{OCaml type}{C type}
+\entree{"float"}{"double"}
+\entree{"int32"}{"int32_t"}
+\entree{"int64"}{"int64_t"}
+\entree{"nativeint"}{"intnat"}
+\end{tableau}
+
+Similarly, it is possible to pass untagged OCaml integers between
+OCaml and C. This is done by annotating the arguments and/or result
+with "[\@untagged]":
+
+\begin{verbatim}
+external f : string -> (int [@untagged]) = "f_byte" "f"
+\end{verbatim}
+
+The corresponding C type must be "intnat".
+
+{\bf Note:} do not use the C "int" type in correspondence with "(int
+[\@untagged])". This is because they often differ in size.
+
+\subsection{Direct C call}
+
+In order to be able to run the garbage collector in the middle of a C
+function, the OCaml compiler generates some bookkeeping code around C
+calls. Technically it wraps every C call with the C function
+"caml_c_call" which is part of the OCaml runtime.
+
+For small functions that are called repeatedly, this indirection can
+have a big impact on performances. However this is not needed if we
+know that the C function doesn't allocate and doesn't raise
+exceptions. We can instruct the OCaml compiler of this fact by
+annotating the external declaration with the attribute "[\@\@noalloc]":
+
+\begin{verbatim}
+external bar : int -> int -> int = "foo" [@@noalloc]
+\end{verbatim}
+
+In this case calling "bar" from OCaml is as cheap as calling any other
+OCaml function, except for the fact that the OCaml compiler can't
+inline C functions...
+
+\subsection{Example: calling C library functions without indirection}
+
+Using these attributes, it is possible to call C library functions
+with no indirection. For instance many math functions are defined this
+way in the OCaml standard library:
+
+\begin{verbatim}
+external sqrt : float -> float = "caml_sqrt_float" "sqrt"
+  [@@unboxed] [@@noalloc]
+(** Square root. *)
+
+external exp : float -> float = "caml_exp_float" "exp" [@@unboxed] [@@noalloc]
+(** Exponential. *)
+
+external log : float -> float = "caml_log_float" "log" [@@unboxed] [@@noalloc]
+(** Natural logarithm. *)
+\end{verbatim}
+
+\section{Advanced topic: multithreading}
+\label{s:C-multithreading}
+
+Using multiple threads (shared-memory concurrency) in a mixed OCaml/C
+application requires special precautions, which are described in this
+section.
+
+\subsection{Registering threads created from C}
+
+Callbacks from C to OCaml are possible only if the calling thread is
+known to the OCaml run-time system.  Threads created from OCaml (through
+the "Thread.create" function of the system threads library) are
+automatically known to the run-time system.  If the application
+creates additional threads from C and wishes to callback into OCaml
+code from these threads, it must first register them with the run-time
+system.  The following functions are declared in the include file
+"".
+
+\begin{itemize}
+\item
+"caml_c_thread_register()" registers the calling thread with the OCaml
+run-time system.  Returns 1 on success, 0 on error.  Registering an
+already-register thread does nothing and returns 0.
+\item
+"caml_c_thread_unregister()"  must be called before the thread
+  terminates, to unregister it from the OCaml run-time system.
+Returns 1 on success, 0 on error.  If the calling thread was not
+previously registered, does nothing and returns 0.
+\end{itemize}
+
+\subsection{Parallel execution of long-running C code}
+
+The OCaml run-time system is not reentrant: at any time, at most one
+thread can be executing OCaml code or C code that uses the OCaml
+run-time system.  Technically, this is enforced by a ``master lock''
+that any thread must hold while executing such code.
+
+When OCaml calls the C code implementing a primitive, the master lock
+is held, therefore the C code has full access to the facilities of the
+run-time system.  However, no other thread can execute OCaml code
+concurrently with the C code of the primitive.
+
+If a C primitive runs for a long time or performs potentially blocking
+input-output operations, it can explicitly release the master lock,
+enabling other OCaml threads to run concurrently with its operations.
+The C code must re-acquire the master lock before returning to OCaml.
+This is achieved with the following functions, declared in
+the include file "".
+
+\begin{itemize}
+\item
+"caml_release_runtime_system()"
+The calling thread releases the master lock and other OCaml resources,
+enabling other threads to run OCaml code in parallel with the execution
+of the calling thread.
+\item
+"caml_acquire_runtime_system()"
+The calling thread re-acquires the master lock and other OCaml
+resources.  It may block until no other thread uses the OCaml run-time
+system.
+\end{itemize}
+
+After "caml_release_runtime_system()" was called and until
+"caml_acquire_runtime_system()" is called, the C code must not access
+any OCaml data, nor call any function of the run-time system, nor call
+back into OCaml code.  Consequently, arguments provided by OCaml to the
+C primitive must be copied into C data structures before calling
+"caml_release_runtime_system()", and results to be returned to OCaml
+must be encoded as OCaml values after "caml_acquire_runtime_system()"
+returns.
+
+Example: the following C primitive invokes "gethostbyname" to find the
+IP address of a host name.  The "gethostbyname" function can block for
+a long time, so we choose to release the OCaml run-time system while it
+is running.
+\begin{verbatim}
+CAMLprim stub_gethostbyname(value vname)
+{
+  CAMLparam1 (vname);
+  CAMLlocal1 (vres);
+  struct hostent * h;
+
+  /* Copy the string argument to a C string, allocated outside the
+     OCaml heap. */
+  name = stat_alloc(caml_string_length(vname) + 1);
+  name = caml_strdup (String_val(vname));
+  /* Release the OCaml run-time system */
+  caml_release_runtime_system();
+  /* Resolve the name */
+  h = gethostbyname(name);
+  /* Re-acquire the OCaml run-time system */
+  caml_acquire_runtime_system();
+  /* Encode the relevant fields of h as the OCaml value vres */
+  ... /* Omitted */
+  /* Return to OCaml */
+  CAMLreturn (vres);
+}
+\end{verbatim}
+
+Callbacks from C to OCaml must be performed while holding the master
+lock to the OCaml run-time system.  This is naturally the case if the
+callback is performed by a C primitive that did not release the
+run-time system.  If the C primitive released the run-time system
+previously, or the callback is performed from other C code that was
+not invoked from OCaml (e.g. an event loop in a GUI application), the
+run-time system must be acquired before the callback and released
+after:
+\begin{verbatim}
+  caml_acquire_runtime_system();
+  /* Resolve OCaml function vfun to be invoked */
+  /* Build OCaml argument varg to the callback */
+  vres = callback(vfun, varg);
+  /* Copy relevant parts of result vres to C data structures */
+  caml_release_runtime_system();
+\end{verbatim}
+
+Note: the "acquire" and "release" functions described above were
+introduced in OCaml 3.12.  Older code uses the following historical
+names, declared in "":
+\begin{itemize}
+\item "caml_enter_blocking_section" as an alias for
+  "caml_release_runtime_system"
+\item "caml_leave_blocking_section" as an alias for
+  "caml_acquire_runtime_system"
+\end{itemize}
+Intuition: a ``blocking section'' is a piece of C code that does not
+use the OCaml run-time system, typically a blocking input/output operation.
+
+\section{Building mixed C/OCaml libraries: \texttt{ocamlmklib}}
+\label{s-ocamlmklib}
+
+The "ocamlmklib" command facilitates the construction of libraries
+containing both OCaml code and C code, and usable both in static
+linking and dynamic linking modes.  This command is available under
+Windows since Objective Caml 3.11 and under other operating systems since
+Objective Caml 3.03.
+
+The "ocamlmklib" command takes three kinds of arguments:
+\begin{itemize}
+\item OCaml source files and object files (".cmo", ".cmx", ".ml")
+comprising the OCaml part of the library;
+\item C object files (".o", ".a", respectively, ".obj", ".lib")
+  comprising the C part of the library;
+\item Support libraries for the C part ("-l"\var{lib}).
+\end{itemize}
+It generates the following outputs:
+\begin{itemize}
+\item An OCaml bytecode library ".cma" incorporating the ".cmo" and
+".ml" OCaml files given as arguments, and automatically referencing the
+C library generated with the C object files.
+\item An OCaml native-code library ".cmxa" incorporating the ".cmx" and
+".ml" OCaml files given as arguments, and automatically referencing the
+C library generated with the C object files.
+\item If dynamic linking is supported on the target platform, a
+".so" (respectively, ".dll") shared library built from the C object files given as arguments,
+and automatically referencing the support libraries.
+\item A C static library ".a"(respectively, ".lib") built from the C object files.
+\end{itemize}
+In addition, the following options are recognized:
+\begin{options}
+\item["-cclib", "-ccopt", "-I", "-linkall"]
+These options are passed as is to "ocamlc" or "ocamlopt".
+See the documentation of these commands.
+\item["-rpath", "-R", "-Wl,-rpath", "-Wl,-R"]
+These options are passed as is to the C compiler.  Refer to the
+documentation of the C compiler.
+\item["-custom"] Force the construction of a statically linked library
+only, even if dynamic linking is supported.
+\item["-failsafe"] Fall back to building a statically linked library
+if a problem occurs while building the shared library (e.g. some of
+the support libraries are not available as shared libraries).
+\item["-L"\var{dir}] Add \var{dir} to the search path for support
+libraries ("-l"\var{lib}).
+\item["-ocamlc" \var{cmd}] Use \var{cmd} instead of "ocamlc" to call
+the bytecode compiler.
+\item["-ocamlopt" \var{cmd}] Use \var{cmd} instead of "ocamlopt" to call
+the native-code compiler.
+\item["-o" \var{output}] Set the name of the generated OCaml library.
+"ocamlmklib" will generate \var{output}".cma" and/or \var{output}".cmxa".
+If not specified, defaults to "a".
+\item["-oc" \var{outputc}] Set the name of the generated C library.
+"ocamlmklib" will generate "lib"\var{outputc}".so" (if shared
+libraries are supported) and "lib"\var{outputc}".a".
+If not specified, defaults to the output name given with "-o".
+\end{options}
+
+\noindent
+On native Windows, the following environment variable is also consulted:
+
+\begin{options}
+\item["OCAML_FLEXLINK"]  Alternative executable to use instead of the
+configured value. Primarily used for bootstrapping.
+\end{options}
+
+\paragraph{Example} Consider an OCaml interface to the standard "libz"
+C library for reading and writing compressed files.  Assume this
+library resides in "/usr/local/zlib".  This interface is
+composed of an OCaml part "zip.cmo"/"zip.cmx" and a C part "zipstubs.o"
+containing the stub code around the "libz" entry points.  The
+following command builds the OCaml libraries "zip.cma" and "zip.cmxa",
+as well as the companion C libraries "dllzip.so" and "libzip.a":
+\begin{verbatim}
+ocamlmklib -o zip zip.cmo zip.cmx zipstubs.o -lz -L/usr/local/zlib
+\end{verbatim}
+If shared libraries are supported, this performs the following
+commands:
+\begin{verbatim}
+ocamlc -a -o zip.cma zip.cmo -dllib -lzip \
+        -cclib -lzip -cclib -lz -ccopt -L/usr/local/zlib
+ocamlopt -a -o zip.cmxa zip.cmx -cclib -lzip \
+        -cclib -lzip -cclib -lz -ccopt -L/usr/local/zlib
+gcc -shared -o dllzip.so zipstubs.o -lz -L/usr/local/zlib
+ar rc libzip.a zipstubs.o
+\end{verbatim}
+Note: This example is on a Unix system. The exact command lines
+may be different on other systems.
+
+If shared libraries are not supported, the following commands are
+performed instead:
+\begin{verbatim}
+ocamlc -a -custom -o zip.cma zip.cmo -cclib -lzip \
+        -cclib -lz -ccopt -L/usr/local/zlib
+ocamlopt -a -o zip.cmxa zip.cmx -lzip \
+        -cclib -lz -ccopt -L/usr/local/zlib
+ar rc libzip.a zipstubs.o
+\end{verbatim}
+Instead of building simultaneously the bytecode library, the
+native-code library and the C libraries, "ocamlmklib" can be called
+three times to build each separately.  Thus,
+\begin{verbatim}
+ocamlmklib -o zip zip.cmo -lz -L/usr/local/zlib
+\end{verbatim}
+builds the bytecode library "zip.cma", and
+\begin{verbatim}
+ocamlmklib -o zip zip.cmx -lz -L/usr/local/zlib
+\end{verbatim}
+builds the native-code library "zip.cmxa", and
+\begin{verbatim}
+ocamlmklib -o zip zipstubs.o -lz -L/usr/local/zlib
+\end{verbatim}
+builds the C libraries "dllzip.so" and "libzip.a".  Notice that the
+support libraries ("-lz") and the corresponding options
+("-L/usr/local/zlib") must be given on all three invocations of "ocamlmklib",
+because they are needed at different times depending on whether shared
+libraries are supported.
diff --git a/manual/manual/cmds/lexyacc.etex b/manual/manual/cmds/lexyacc.etex
new file mode 100644
index 0000000000..294767e418
--- /dev/null
+++ b/manual/manual/cmds/lexyacc.etex
@@ -0,0 +1,729 @@
+\chapter{Lexer and parser generators (ocamllex, ocamlyacc)}
+\label{c:ocamlyacc}
+\pdfchapter{Lexer and parser generators (ocamllex, ocamlyacc)}
+%HEVEA\cutname{lexyacc.html}
+
+This chapter describes two program generators: "ocamllex", that
+produces a lexical analyzer from a set of regular expressions with
+associated semantic actions, and "ocamlyacc", that produces a parser
+from a grammar with associated semantic actions.
+
+These program generators are very close to the well-known "lex" and
+"yacc" commands that can be found in most C programming environments.
+This chapter assumes a working knowledge of "lex" and "yacc": while
+it describes the input syntax for "ocamllex" and "ocamlyacc" and the
+main differences with "lex" and "yacc", it does not explain the basics
+of writing a lexer or parser description in "lex" and "yacc". Readers
+unfamiliar with "lex" and "yacc" are referred to  ``Compilers:
+principles, techniques, and tools'' by Aho, Sethi and Ullman
+(Addison-Wesley, 1986), or ``Lex $\&$ Yacc'', by Levine, Mason and
+Brown (O'Reilly, 1992).
+
+\section{Overview of \texttt{ocamllex}}
+
+The "ocamllex" command produces a lexical analyzer from a set of regular
+expressions with attached semantic actions, in the style of
+"lex". Assuming the input file is \var{lexer}".mll", executing
+\begin{alltt}
+        ocamllex \var{lexer}.mll
+\end{alltt}
+produces OCaml code for a lexical analyzer in file \var{lexer}".ml".
+This file defines one lexing function per entry point in the lexer
+definition. These functions have the same names as the entry
+points. Lexing functions take as argument a lexer buffer, and return
+the semantic attribute of the corresponding entry point.
+
+Lexer buffers are an abstract data type implemented in the standard
+library module "Lexing". The functions "Lexing.from_channel",
+"Lexing.from_string" and "Lexing.from_function" create
+lexer buffers that read from an input channel, a character string, or
+any reading function, respectively. (See the description of module
+"Lexing" in chapter~\ref{c:stdlib}.)
+
+When used in conjunction with a parser generated by "ocamlyacc", the
+semantic actions compute a value belonging to the type "token" defined
+by the generated parsing module. (See the description of "ocamlyacc"
+below.)
+
+\subsection{Options}
+The following command-line options are recognized by "ocamllex".
+
+\begin{options}
+
+\item["-ml"]
+Output code that does not use OCaml's built-in automata
+interpreter. Instead, the automaton is encoded by OCaml functions.
+This option mainly is useful for debugging "ocamllex", using it for
+production lexers is not recommended.
+
+\item["-o" \var{output-file}]
+Specify the name of the output file produced by "ocamllex".
+The default is the input file name with its extension replaced by ".ml".
+
+\item["-q"]
+Quiet mode.  "ocamllex" normally outputs informational messages
+to standard output.  They are suppressed if option "-q" is used.
+
+\item["-v" or "-version"]
+Print version string and exit.
+
+\item["-vnum"]
+Print short version number and exit.
+
+\item["-help" or "--help"]
+Display a short usage summary and exit.
+%
+\end{options}
+
+\section{Syntax of lexer definitions}
+
+The format of lexer definitions is as follows:
+\begin{alltt}
+\{ \var{header} \}
+let \var{ident} = \var{regexp} \ldots
+[refill \{ \var{refill-handler} \}]
+rule \var{entrypoint} [\nth{arg}{1}\ldots{} \nth{arg}{n}] =
+  parse \var{regexp} \{ \var{action} \}
+      | \ldots
+      | \var{regexp} \{ \var{action} \}
+and \var{entrypoint} [\nth{arg}{1}\ldots{} \nth{arg}{n}] =
+  parse \ldots
+and \ldots
+\{ \var{trailer} \}
+\end{alltt}
+Comments are delimited by "(*" and "*)", as in OCaml.
+The "parse" keyword, can be replaced by the "shortest" keyword, with
+the semantic consequences explained below.
+
+Refill handlers are a recent (optional) feature introduced in 4.02,
+documented below in subsection~\ref{ss:refill-handlers}.
+
+\subsection{Header and trailer}
+The {\it header} and {\it trailer} sections are arbitrary OCaml
+text enclosed in curly braces. Either or both can be omitted. If
+present, the header text is copied as is at the beginning of the
+output file and the trailer text at the end. Typically, the
+header section contains the "open" directives required
+by the actions, and possibly some auxiliary functions used in the
+actions.
+
+\subsection{Naming regular expressions}
+
+Between the header and the entry points, one can give names to
+frequently-occurring regular expressions.  This is written
+@"let" ident "=" regexp@.
+In regular expressions that follow this declaration, the identifier
+\var{ident} can be used as shorthand for \var{regexp}.
+
+\subsection{Entry points}
+
+The names of the entry points must be valid identifiers for OCaml
+values (starting with a lowercase letter).
+Similarily, the arguments \texttt{\var{arg$_1$}\ldots{}
+\var{arg$_n$}} must be valid identifiers for OCaml.
+Each entry point becomes an
+OCaml function that takes $n+1$ arguments,
+the extra implicit last argument being of type "Lexing.lexbuf".
+Characters are read from the "Lexing.lexbuf" argument and matched
+against the regular expressions provided in the rule, until a prefix
+of the input matches one of the rule.  The corresponding action is
+then evaluated and returned as the result of the function.
+
+
+If several regular expressions match a prefix of the input, the
+``longest match'' rule applies: the regular expression that matches
+the longest prefix of the input is selected.  In case of tie, the
+regular expression that occurs earlier in the rule is selected.
+
+However, if lexer rules are introduced with the "shortest" keyword in
+place of the "parse" keyword, then the ``shortest match'' rule applies:
+the shortest prefix of the input is selected. In case of tie, the
+regular expression that occurs earlier in the rule is still selected.
+This feature is not intended for use in ordinary lexical analyzers, it
+may facilitate the use of "ocamllex" as a simple text processing tool.
+
+
+
+\subsection{Regular expressions}
+
+The regular expressions are in the style of "lex", with a more
+OCaml-like syntax.
+\begin{syntax}
+regexp:
+  \ldots
+\end{syntax}
+\begin{options}
+
+\item[@"'" regular-char || escape-sequence "'"@]
+A character constant, with the same syntax as OCaml character
+constants. Match the denoted character.
+
+\item["_"]
+(underscore) Match any character.
+
+\item[@"eof"@]
+Match the end of the lexer input.\\
+{\bf Note:} On some systems, with interactive input, an end-of-file
+may be followed by more characters.  However, "ocamllex" will not
+correctly handle regular expressions that contain "eof" followed by
+something else.
+
+\item[@'"' { string-character } '"'@]
+A string constant, with the same syntax as OCaml string
+constants. Match the corresponding sequence of characters.
+
+\item[@'[' character-set ']'@]
+Match any single character belonging to the given
+character set. Valid character sets are: single
+character constants @"'" @c@ "'"@; ranges of characters
+@"'" @c@_1 "'" "-" "'" @c@_2 "'"@ (all characters between $c_1$ and $c_2$,
+inclusive); and the union of two or more character sets, denoted by
+concatenation.
+
+\item[@'[' '^' character-set ']'@]
+Match any single character not belonging to the given character set.
+
+
+\item[@regexp_1 '#' regexp_2@]
+(difference of character sets)
+Regular expressions @regexp_1@ and @regexp_2@ must be character sets
+defined with @'['\ldots ']'@ (or a a single character expression or
+underscore "_").
+Match the difference of the two specified character sets.
+
+
+\item[@regexp '*'@]
+(repetition) Match the concatenation of zero or more
+strings that match @regexp@.
+
+\item[@regexp '+'@]
+(strict repetition) Match the concatenation of one or more
+strings that match @regexp@.
+
+\item[@regexp '?'@]
+(option) Match the empty string, or a string matching @regexp@.
+
+\item[@regexp_1 '|' regexp_2@]
+(alternative) Match any string that matches @regexp_1@ or @regexp_2@
+
+\item[@regexp_1 regexp_2@]
+(concatenation) Match the concatenation of two strings, the first
+matching @regexp_1@, the second matching @regexp_2@.
+
+\item[@'(' regexp ')'@]
+Match the same strings as @regexp@.
+
+\item[@ident@]
+Reference the regular expression bound to @ident@ by an earlier
+@"let" ident "=" regexp@ definition.
+
+\item[@regexp 'as' ident@]
+Bind the substring matched by @regexp@ to identifier @ident@.
+\end{options}
+
+Concerning the precedences of operators, "#" has the highest precedence,
+followed by "*", "+"  and "?",
+then concatenation, then "|" (alternation), then "as".
+
+\subsection{Actions}
+
+The actions are arbitrary OCaml expressions. They are evaluated in
+a context where the identifiers defined by using the "as" construct
+are bound to subparts of the matched string.
+Additionally, "lexbuf" is bound to the current lexer
+buffer. Some typical uses for "lexbuf", in conjunction with the
+operations on lexer buffers provided by the "Lexing" standard library
+module, are listed below.
+
+\begin{options}
+\item["Lexing.lexeme lexbuf"]
+Return the matched string.
+
+\item["Lexing.lexeme_char lexbuf "$n$]
+Return the $n\th$
+character in the matched string. The first character corresponds to $n = 0$.
+
+\item["Lexing.lexeme_start lexbuf"]
+Return the absolute position in the input text of the beginning of the
+matched string (i.e. the offset of the first character of the matched
+string). The first character read from the input text has offset 0.
+
+\item["Lexing.lexeme_end lexbuf"]
+Return the absolute position in the input text of the end of the
+matched string (i.e. the offset of the first character after the
+matched string). The first character read from the input text has
+offset 0.
+
+\newcommand{\sub}[1]{$_{#1}$}%
+\item[\var{entrypoint} {[\var{exp\sub{1}}\ldots{} \var{exp\sub{n}}]} "lexbuf"]
+(Where \var{entrypoint} is the name of another entry point in the same
+lexer definition.) Recursively call the lexer on the given entry point.
+Notice that "lexbuf" is the last argument.
+Useful for lexing nested comments, for example.
+
+\end{options}
+
+\subsection{Variables in regular expressions}
+The "as" construct is similar to ``\emph{groups}'' as provided by
+numerous regular expression packages.
+The type of these variables can be "string", "char", "string option"
+or "char option".
+
+We first consider the case of linear patterns, that is the case when
+all "as" bound variables are distinct.
+In @regexp 'as' ident@, the type of @ident@ normally is "string" (or
+"string option") except
+when @regexp@ is a character constant, an underscore, a string
+constant of length one, a character set specification, or an
+alternation of those. Then, the type of @ident@ is "char" (or "char
+option").
+Option types are introduced when overall rule matching does not
+imply matching of the bound sub-pattern. This is in particular the
+case of @'(' regexp 'as' ident ')' '?'@ and of
+@regexp_1 '|' '(' regexp_2 'as' ident ')'@.
+
+There is no linearity restriction over "as" bound variables.
+When a variable is bound more than once, the previous rules are to be
+extended as follows:
+\begin{itemize}
+\item A variable is a "char" variable when all its occurrences bind
+"char" occurrences in the previous sense.
+\item A variable is an "option" variable when the overall expression
+can be matched without binding this variable.
+\end{itemize}
+For instance, in
+"('a' as x) | ( 'a' (_ as x) )" the variable "x"  is of type
+"char", whereas in
+"(\"ab\" as x) | ( 'a' (_ as x) ? )" the variable "x"  is of type
+"string option".
+
+
+In some cases, a successful match may not yield a unique set of bindings.
+For instance the matching of \verb+aba+ by the regular expression
+"(('a'|\"ab\") as x) ((\"ba\"|'a') as y)" may result in binding
+either
+\verb+x+ to \verb+"ab"+ and \verb+y+ to \verb+"a"+, or
+\verb+x+ to \verb+"a"+ and \verb+y+ to \verb+"ba"+.
+The automata produced "ocamllex" on such ambiguous regular
+expressions will select one of the possible resulting sets of
+bindings.
+The selected set of bindings is purposely left unspecified.
+
+\subsection{Refill handlers}
+\label{ss:refill-handlers}
+
+By default, when ocamllex reaches the end of its lexing buffer, it
+will silently call the "refill_buff" function of "lexbuf" structure
+and continue lexing. It is sometimes useful to be able to take control
+of refilling action; typically, if you use a library for asynchronous
+computation, you may want to wrap the refilling action in a delaying
+function to avoid blocking synchronous operations.
+
+Since OCaml 4.02, it is possible to specify a \var{refill-handler},
+a function that will be called when refill happens. It is passed the
+continuation of the lexing, on which it has total control. The OCaml
+expression used as refill action should have a type that is an
+instance of
+\begin{verbatim}
+   (Lexing.lexbuf -> 'a) -> Lexing.lexbuf -> 'a
+\end{verbatim}
+where the first argument is the continuation which captures the
+processing ocamllex would usually perform (refilling the buffer, then
+calling the lexing function again), and the result type that
+instantiates ['a] should unify with the result type of all lexing
+rules.
+
+As an example, consider the following lexer that is parametrized over
+an arbitrary monad:
+\begin{verbatim}
+{
+type token = EOL | INT of int | PLUS
+
+module Make (M : sig
+               type 'a t
+               val return: 'a -> 'a t
+               val bind: 'a t -> ('a -> 'b t) -> 'b t
+               val fail : string -> 'a t
+
+               (* Set up lexbuf *)
+               val on_refill : Lexing.lexbuf -> unit t
+             end)
+= struct
+
+let refill_handler k lexbuf =
+    M.bind (M.on_refill lexbuf) (fun () -> k lexbuf)
+
+}
+
+refill {refill_handler}
+
+rule token = parse
+| [' ' '\t']
+    { token lexbuf }
+| '\n'
+    { M.return EOL }
+| ['0'-'9']+ as i
+    { M.return (INT (int_of_string i)) }
+| '+'
+    { M.return PLUS }
+| _
+    { M.fail "unexpected character" }
+{
+end
+}
+\end{verbatim}
+
+\subsection{Reserved identifiers}
+
+All identifiers starting with "__ocaml_lex" are reserved for use by
+"ocamllex"; do not use any such identifier in your programs.
+
+
+\section{Overview of \texttt{ocamlyacc}}
+
+The "ocamlyacc" command produces a parser from a context-free grammar
+specification with attached semantic actions, in the style of "yacc".
+Assuming the input file is \var{grammar}".mly", executing
+\begin{alltt}
+        ocamlyacc \var{options} \var{grammar}.mly
+\end{alltt}
+produces OCaml code for a parser in the file \var{grammar}".ml",
+and its interface in file \var{grammar}".mli".
+
+The generated module defines one parsing function per entry point in
+the grammar. These functions have the same names as the entry points.
+Parsing functions take as arguments a lexical analyzer (a function
+from lexer buffers to tokens) and a lexer buffer, and return the
+semantic attribute of the corresponding entry point. Lexical analyzer
+functions are usually generated from a lexer specification by the
+"ocamllex" program. Lexer buffers are an abstract data type
+implemented in the standard library module "Lexing". Tokens are values from
+the concrete type "token", defined in the interface file
+\var{grammar}".mli" produced by "ocamlyacc".
+
+\section{Syntax of grammar definitions}
+
+Grammar definitions have the following format:
+\begin{alltt}
+\%\{
+  \var{header}
+\%\}
+  \var{declarations}
+\%\%
+  \var{rules}
+\%\%
+  \var{trailer}
+\end{alltt}
+
+Comments are enclosed between \verb|/*| and \verb|*/| (as in C) in the
+``declarations'' and ``rules'' sections, and between \verb|(*| and
+\verb|*)| (as in OCaml) in the ``header'' and ``trailer'' sections.
+
+\subsection{Header and trailer}
+
+The header and the trailer sections are OCaml code that is copied
+as is into file \var{grammar}".ml". Both sections are optional. The header
+goes at the beginning of the output file; it usually contains
+"open" directives and auxiliary functions required by the semantic
+actions of the rules. The trailer goes at the end of the output file.
+
+\subsection{Declarations}
+
+Declarations are given one per line. They all start with a \verb"%" sign.
+
+\begin{options}
+
+\item[@"%token" constr \ldots constr@]
+Declare the given symbols @constr \ldots constr@
+as tokens (terminal symbols).  These symbols
+are added as constant constructors for the "token" concrete type.
+
+\item[@"%token" "<" typexpr ">" constr \ldots constr@]
+Declare the given symbols @constr \ldots constr@ as tokens with an
+attached attribute of the
+given type. These symbols are added as constructors with arguments of
+the given type for the "token" concrete type. The @typexpr@ part is
+an arbitrary OCaml type expression, except that all type
+constructor names must be fully qualified (e.g. "Modname.typename")
+for all types except standard built-in types, even if the proper
+\verb|open| directives (e.g. \verb|open Modname|) were given in the
+header section. That's because the header is copied only to the ".ml"
+output file, but not to the ".mli" output file, while the @typexpr@ part
+of a \verb"%token" declaration is copied to both.
+
+\item[@"%start" symbol \ldots symbol@]
+Declare the given symbols as entry points for the grammar. For each
+entry point, a parsing function with the same name is defined in the
+output module. Non-terminals that are not declared as entry points
+have no such parsing function. Start symbols must be given a type with
+the \verb|%type| directive below.
+
+\item[@"%type" "<" typexpr ">" symbol \ldots symbol@]
+Specify the type of the semantic attributes for the given symbols.
+This is mandatory for start symbols only. Other nonterminal symbols
+need not be given types by hand: these types will be inferred when
+running the output files through the OCaml compiler (unless the
+\verb"-s" option is in effect). The @typexpr@ part is an arbitrary OCaml
+type expression, except that all type constructor names must be
+fully qualified, as explained above for "%token".
+
+\item[@"%left" symbol \ldots symbol@]
+\item[@"%right" symbol \ldots symbol@]
+\item[@"%nonassoc" symbol \ldots symbol@]
+
+Associate precedences and associativities to the given symbols. All
+symbols on the same line are given the same precedence. They have
+higher precedence than symbols declared before in a \verb"%left",
+\verb"%right" or \verb"%nonassoc" line. They have lower precedence
+than symbols declared after in a \verb"%left", \verb"%right" or
+\verb"%nonassoc" line. The symbols are declared to associate to the
+left (\verb"%left"), to the right (\verb"%right"), or to be
+non-associative (\verb"%nonassoc"). The symbols are usually tokens.
+They can also be dummy nonterminals, for use with the \verb"%prec"
+directive inside the rules.
+
+The precedence declarations are used in the following way to
+resolve reduce/reduce and shift/reduce conflicts:
+\begin{itemize}
+\item Tokens and rules have precedences.  By default, the precedence
+  of a rule is the precedence of its rightmost terminal.  You
+  can override this default by using the @"%prec"@ directive in the rule.
+\item A reduce/reduce conflict
+  is resolved in favor of the first rule (in the order given by the
+  source file), and "ocamlyacc" outputs a warning.
+\item A shift/reduce conflict
+  is resolved by comparing the precedence of the rule to be
+  reduced with the precedence of the token to be shifted.  If the
+  precedence of the rule is higher, then the rule will be reduced;
+  if the precedence of the token is higher, then the token will
+  be shifted.
+\item A shift/reduce conflict between a rule and a token with the
+  same precedence will be resolved using the associativity: if the
+  token is left-associative, then the parser will reduce; if the
+  token is right-associative, then the parser will shift.  If the
+  token is non-associative, then the parser will declare a syntax
+  error.
+\item When a shift/reduce conflict cannot be resolved using the above
+  method, then "ocamlyacc" will output a warning and the parser will
+  always shift.
+\end{itemize}
+
+\end{options}
+
+\subsection{Rules}
+
+The syntax for rules is as usual:
+\begin{alltt}
+\var{nonterminal} :
+    \var{symbol} \ldots \var{symbol} \{ \var{semantic-action} \}
+  | \ldots
+  | \var{symbol} \ldots \var{symbol} \{ \var{semantic-action} \}
+;
+\end{alltt}
+%
+Rules can also contain the \verb"%prec "{\it symbol} directive in the
+right-hand side part, to override the default precedence and
+associativity of the rule with the precedence and associativity of the
+given symbol.
+
+Semantic actions are arbitrary OCaml expressions, that
+are evaluated to produce the semantic attribute attached to
+the defined nonterminal. The semantic actions can access the
+semantic attributes of the symbols in the right-hand side of
+the rule with the \verb"$" notation: \verb"$1" is the attribute for the
+first (leftmost) symbol, \verb"$2" is the attribute for the second
+symbol, etc.
+
+The rules may contain the special symbol "error" to indicate
+resynchronization points, as in "yacc".
+
+Actions occurring in the middle of rules are not supported.
+
+Nonterminal symbols are like regular OCaml symbols, except that they
+cannot end with "'" (single quote).
+
+\subsection{Error handling}
+
+Error recovery is supported as follows: when the parser reaches an
+error state (no grammar rules can apply), it calls a function named
+"parse_error" with the string "\"syntax error\"" as argument. The default
+"parse_error" function does nothing and returns, thus initiating error
+recovery (see below). The user can define a customized "parse_error"
+function in the header section of the grammar file.
+
+The parser also enters error recovery mode if one of the grammar
+actions raises the "Parsing.Parse_error" exception.
+
+In error recovery mode, the parser discards states from the
+stack until it reaches a place where the error token can be shifted.
+It then discards tokens from the input until it finds three successive
+tokens that can be accepted, and starts processing with the first of
+these.  If no state can be uncovered where the error token can be
+shifted, then the parser aborts by raising the "Parsing.Parse_error"
+exception.
+
+Refer to documentation on "yacc" for more details and guidance in how
+to use error recovery.
+
+\section{Options}
+
+The "ocamlyacc" command recognizes the following options:
+
+\begin{options}
+
+\item["-b"{\it prefix}]
+Name the output files {\it prefix}".ml", {\it prefix}".mli",
+{\it prefix}".output", instead of the default naming convention.
+
+\item["-q"]
+This option has no effect.
+
+\item["-v"]
+Generate a description of the parsing tables and a report on conflicts
+resulting from ambiguities in the grammar. The description is put in
+file \var{grammar}".output".
+
+\item["-version"]
+Print version string and exit.
+
+\item["-vnum"]
+Print short version number and exit.
+
+\item["-"]
+Read the grammar specification from standard input.  The default
+output file names are "stdin.ml" and "stdin.mli".
+
+\item["--" \var{file}]
+Process \var{file} as the grammar specification, even if its name
+starts with a dash (-) character.  This option must be the last on the
+command line.
+
+\end{options}
+
+At run-time, the "ocamlyacc"-generated parser can be debugged by
+setting the "p" option in the "OCAMLRUNPARAM" environment variable
+(see section~\ref{ocamlrun-options}).  This causes the pushdown
+automaton executing the parser to print a trace of its action (tokens
+shifted, rules reduced, etc).  The trace mentions rule numbers and
+state numbers that can be interpreted by looking at the file
+\var{grammar}".output" generated by "ocamlyacc -v".
+
+\section{A complete example}
+
+The all-time favorite: a desk calculator. This program reads
+arithmetic expressions on standard input, one per line, and prints
+their values. Here is the grammar definition:
+\begin{verbatim}
+        /* File parser.mly */
+        %token  INT
+        %token PLUS MINUS TIMES DIV
+        %token LPAREN RPAREN
+        %token EOL
+        %left PLUS MINUS        /* lowest precedence */
+        %left TIMES DIV         /* medium precedence */
+        %nonassoc UMINUS        /* highest precedence */
+        %start main             /* the entry point */
+        %type  main
+        %%
+        main:
+            expr EOL                { $1 }
+        ;
+        expr:
+            INT                     { $1 }
+          | LPAREN expr RPAREN      { $2 }
+          | expr PLUS expr          { $1 + $3 }
+          | expr MINUS expr         { $1 - $3 }
+          | expr TIMES expr         { $1 * $3 }
+          | expr DIV expr           { $1 / $3 }
+          | MINUS expr %prec UMINUS { - $2 }
+        ;
+\end{verbatim}
+Here is the definition for the corresponding lexer:
+\begin{verbatim}
+        (* File lexer.mll *)
+        {
+        open Parser        (* The type token is defined in parser.mli *)
+        exception Eof
+        }
+        rule token = parse
+            [' ' '\t']     { token lexbuf }     (* skip blanks *)
+          | ['\n' ]        { EOL }
+          | ['0'-'9']+ as lxm { INT(int_of_string lxm) }
+          | '+'            { PLUS }
+          | '-'            { MINUS }
+          | '*'            { TIMES }
+          | '/'            { DIV }
+          | '('            { LPAREN }
+          | ')'            { RPAREN }
+          | eof            { raise Eof }
+\end{verbatim}
+Here is the main program, that combines the parser with the lexer:
+\begin{verbatim}
+        (* File calc.ml *)
+        let _ =
+          try
+            let lexbuf = Lexing.from_channel stdin in
+            while true do
+              let result = Parser.main Lexer.token lexbuf in
+                print_int result; print_newline(); flush stdout
+            done
+          with Lexer.Eof ->
+            exit 0
+\end{verbatim}
+To compile everything, execute:
+\begin{verbatim}
+        ocamllex lexer.mll       # generates lexer.ml
+        ocamlyacc parser.mly     # generates parser.ml and parser.mli
+        ocamlc -c parser.mli
+        ocamlc -c lexer.ml
+        ocamlc -c parser.ml
+        ocamlc -c calc.ml
+        ocamlc -o calc lexer.cmo parser.cmo calc.cmo
+\end{verbatim}
+
+\section{Common errors}
+
+\begin{options}
+
+\item[ocamllex: transition table overflow, automaton is too big]
+
+The deterministic automata generated by "ocamllex" are limited to at
+most 32767 transitions.  The message above indicates that your lexer
+definition is too complex and overflows this limit.  This is commonly
+caused by lexer definitions that have separate rules for each of the
+alphabetic keywords of the language, as in the following example.
+\begin{verbatim}
+rule token = parse
+  "keyword1"   { KWD1 }
+| "keyword2"   { KWD2 }
+| ...
+| "keyword100" { KWD100 }
+| ['A'-'Z' 'a'-'z'] ['A'-'Z' 'a'-'z' '0'-'9' '_'] * as id
+               { IDENT id}
+\end{verbatim}
+To keep the generated automata small, rewrite those definitions with
+only one general ``identifier'' rule, followed by a hashtable lookup
+to separate keywords from identifiers:
+\begin{verbatim}
+{ let keyword_table = Hashtbl.create 53
+  let _ =
+    List.iter (fun (kwd, tok) -> Hashtbl.add keyword_table kwd tok)
+              [ "keyword1", KWD1;
+                "keyword2", KWD2; ...
+                "keyword100", KWD100 ]
+}
+rule token = parse
+  ['A'-'Z' 'a'-'z'] ['A'-'Z' 'a'-'z' '0'-'9' '_'] * as id
+               { try
+                   Hashtbl.find keyword_table id
+                 with Not_found ->
+                   IDENT id }
+\end{verbatim}
+
+\item[ocamllex: Position memory overflow, too many bindings]
+The deterministic automata generated by "ocamllex" maintain a table of
+positions inside the scanned lexer buffer. The size of this table is
+limited to at most 255 cells. This error should not show up in normal
+situations.
+
+\end{options}
diff --git a/manual/manual/cmds/native.etex b/manual/manual/cmds/native.etex
new file mode 100644
index 0000000000..4291a338b5
--- /dev/null
+++ b/manual/manual/cmds/native.etex
@@ -0,0 +1,639 @@
+\chapter{Native-code compilation (ocamlopt)} \label{c:nativecomp}
+\pdfchapter{Native-code compilation (ocamlopt)}
+%HEVEA\cutname{native.html}
+
+This chapter describes the OCaml high-performance
+native-code compiler "ocamlopt", which compiles OCaml source files to
+native code object files and link these object files to produce
+standalone executables.
+
+The native-code compiler is only available on certain platforms.
+It produces code that runs faster than the bytecode produced by
+"ocamlc", at the cost of increased compilation time and executable code
+size. Compatibility with the bytecode compiler is extremely high: the
+same source code should run identically when compiled with "ocamlc" and
+"ocamlopt".
+
+It is not possible to mix native-code object files produced by "ocamlopt"
+with bytecode object files produced by "ocamlc": a program must be
+compiled entirely with "ocamlopt" or entirely with "ocamlc". Native-code
+object files produced by "ocamlopt" cannot be loaded in the toplevel
+system "ocaml".
+
+\section{Overview of the compiler}
+
+The "ocamlopt" command has a command-line interface very close to that
+of "ocamlc". It accepts the same types of arguments, and processes them
+sequentially, after all options have been processed:
+
+\begin{itemize}
+\item
+Arguments ending in ".mli" are taken to be source files for
+compilation unit interfaces. Interfaces specify the names exported by
+compilation units: they declare value names with their types, define
+public data types, declare abstract data types, and so on. From the
+file \var{x}".mli", the "ocamlopt" compiler produces a compiled interface
+in the file \var{x}".cmi". The interface produced is identical to that
+produced by the bytecode compiler "ocamlc".
+
+\item
+Arguments ending in ".ml" are taken to be source files for compilation
+unit implementations. Implementations provide definitions for the
+names exported by the unit, and also contain expressions to be
+evaluated for their side-effects.  From the file \var{x}".ml", the "ocamlopt"
+compiler produces two files: \var{x}".o", containing native object code,
+and \var{x}".cmx", containing extra information for linking and
+optimization of the clients of the unit. The compiled implementation
+should always be referred to under the name \var{x}".cmx" (when given
+a ".o" or ".obj" file, "ocamlopt" assumes that it contains code compiled from C,
+not from OCaml).
+
+The implementation is checked against the interface file \var{x}".mli"
+(if it exists) as described in the manual for "ocamlc"
+(chapter~\ref{c:camlc}).
+
+\item
+Arguments ending in ".cmx" are taken to be compiled object code.  These
+files are linked together, along with the object files obtained
+by compiling ".ml" arguments (if any), and the OCaml standard
+library, to produce a native-code executable program. The order in
+which ".cmx" and ".ml" arguments are presented on the command line is
+relevant: compilation units are initialized in that order at
+run-time, and it is a link-time error to use a component of a unit
+before having initialized it. Hence, a given \var{x}".cmx" file must come
+before all ".cmx" files that refer to the unit \var{x}.
+
+\item
+Arguments ending in ".cmxa" are taken to be libraries of object code.
+Such a library packs in two files (\var{lib}".cmxa" and \var{lib}".a"/".lib")
+a set of object files (".cmx" and ".o"/".obj" files). Libraries are build with
+"ocamlopt -a" (see the description of the "-a" option below). The object
+files contained in the library are linked as regular ".cmx" files (see
+above), in the order specified when the library was built. The only
+difference is that if an object file contained in a library is not
+referenced anywhere in the program, then it is not linked in.
+
+\item
+Arguments ending in ".c" are passed to the C compiler, which generates
+a ".o"/".obj" object file. This object file is linked with the program.
+
+\item
+Arguments ending in ".o", ".a" or ".so" (".obj", ".lib" and ".dll"
+under Windows) are assumed to be C object files and
+libraries. They are linked with the program.
+
+\end{itemize}
+
+The output of the linking phase is a regular Unix or Windows
+executable file. It does not need "ocamlrun" to run.
+
+\section{Options}
+
+The following command-line options are recognized by "ocamlopt".
+The options "-pack", "-a", "-shared", "-c" and "-output-obj" are mutually
+exclusive.
+
+\begin{options}
+
+\item["-a"]
+Build a library (".cmxa" and ".a"/".lib" files) with the object files
+(".cmx" and ".o"/".obj" files) given on the command line, instead of
+linking them into an executable file. The name of the library must be
+set with the "-o" option.
+
+If "-cclib" or "-ccopt" options are passed on the command
+line, these options are stored in the resulting ".cmxa" library.  Then,
+linking with this library automatically adds back the
+"-cclib" and "-ccopt" options as if they had been provided on the
+command line, unless the "-noautolink" option is given.
+
+\item["-absname"]
+Force error messages to show absolute paths for file names.
+
+\item["-annot"]
+Dump detailed information about the compilation (types, bindings,
+tail-calls, etc).  The information for file \var{src}".ml"
+is put into file \var{src}".annot".  In case of a type error, dump
+all the information inferred by the type-checker before the error.
+The \var{src}".annot" file can be used with the emacs commands given in
+"emacs/caml-types.el" to display types and other annotations
+interactively.
+
+\item["-bin-annot"]
+Dump detailed information about the compilation (types, bindings,
+tail-calls, etc) in binary format. The information for file \var{src}".ml"
+is put into file \var{src}".cmt".  In case of a type error, dump
+all the information inferred by the type-checker before the error.
+The "*.cmt" files produced by "-bin-annot" contain more information
+and are much more compact than the files produced by "-annot".
+
+\item["-c"]
+Compile only. Suppress the linking phase of the
+compilation. Source code files are turned into compiled files, but no
+executable file is produced. This option is useful to
+compile modules separately.
+
+\item["-cc" \var{ccomp}]
+Use \var{ccomp} as the C linker called to build the final executable
+and as the C compiler for compiling ".c" source files.
+
+\item["-cclib" "-l"\var{libname}]
+Pass the "-l"\var{libname} option to the linker. This causes the given
+C library to be linked with the program.
+
+\item["-ccopt" \var{option}]
+Pass the given option to the C compiler and linker. For instance,
+"-ccopt -L"\var{dir} causes the C linker to search for C libraries in
+directory \var{dir}.
+
+\item["-compact"]
+Optimize the produced code for space rather than for time. This
+results in slightly smaller but slightly slower programs. The default is to
+optimize for speed.
+
+\item["-config"]
+Print the version number of "ocamlopt" and a detailed summary of its
+configuration, then exit.
+
+\item["-for-pack" \var{module-path}]
+Generate an object file (".cmx" and ".o"/".obj" files) that can later be
+included
+as a sub-module (with the given access path) of a compilation unit
+constructed with "-pack".  For instance, "ocamlopt -for-pack P -c A.ml"
+will generate "a.cmx" and "a.o" files that can later be used with
+"ocamlopt -pack -o P.cmx a.cmx".
+
+\item["-g"]
+Add debugging information while compiling and linking. This option is
+required in order to produce stack backtraces when
+the program terminates on an uncaught exception (see
+section~\ref{ocamlrun-options}).
+
+\item["-i"]
+Cause the compiler to print all defined names (with their inferred
+types or their definitions) when compiling an implementation (".ml"
+file).  No compiled files (".cmo" and ".cmi" files) are produced.
+This can be useful to check the types inferred by the
+compiler. Also, since the output follows the syntax of interfaces, it
+can help in writing an explicit interface (".mli" file) for a file:
+just redirect the standard output of the compiler to a ".mli" file,
+and edit that file to remove all declarations of unexported names.
+
+\item["-I" \var{directory}]
+Add the given directory to the list of directories searched for
+compiled interface files (".cmi"), compiled object code files
+(".cmx"), and libraries (".cmxa"). By default, the current directory
+is searched first, then the standard library directory. Directories
+added with "-I" are searched after the current directory, in the order
+in which they were given on the command line, but before the standard
+library directory. See also option "-nostdlib".
+
+If the given directory starts with "+", it is taken relative to the
+standard library directory.  For instance, "-I +labltk" adds the
+subdirectory "labltk" of the standard library to the search path.
+
+\item["-impl" \var{filename}]
+Compile the file \var{filename} as an implementation file, even if its
+extension is not ".ml".
+
+\item["-inline" \var{n}]
+Set aggressiveness of inlining to \var{n}, where \var{n} is a positive
+integer. Specifying "-inline 0" prevents all functions from being
+inlined, except those whose body is smaller than the call site. Thus,
+inlining causes no expansion in code size. The default aggressiveness,
+"-inline 1", allows slightly larger functions to be inlined, resulting
+in a slight expansion in code size. Higher values for the "-inline"
+option cause larger and larger functions to become candidate for
+inlining, but can result in a serious increase in code size.
+
+\item["-intf" \var{filename}]
+Compile the file \var{filename} as an interface file, even if its
+extension is not ".mli".
+
+\item["-intf-suffix" \var{string}]
+Recognize file names ending with \var{string} as interface files
+(instead of the default ".mli").
+
+\item["-labels"]
+Labels are not ignored in types, labels may be used in applications,
+and labelled parameters can be given in any order.  This is the default.
+
+\item["-linkall"]
+Force all modules contained in libraries to be linked in. If this
+flag is not given, unreferenced modules are not linked in. When
+building a library ("-a" flag), setting the "-linkall" flag forces all
+subsequent links of programs involving that library to link all the
+modules contained in the library.
+
+\item["-no-app-funct"]
+Deactivates the applicative behaviour of functors. With this option,
+each functor application generates new types in its result and
+applying the same functor twice to the same argument yields two
+incompatible structures.
+
+\item["-noassert"]
+Do not compile assertion checks.  Note that the special form
+"assert false" is always compiled because it is typed specially.
+This flag has no effect when linking already-compiled files.
+
+\item["-noautolink"]
+When linking ".cmxa" libraries, ignore "-cclib" and "-ccopt"
+options potentially contained in the libraries (if these options were
+given when building the libraries).  This can be useful if a library
+contains incorrect specifications of C libraries or C options; in this
+case, during linking, set "-noautolink" and pass the correct C
+libraries and options on the command line.
+
+\item["-nodynlink"]
+Allow the compiler to use some optimizations that are valid only for code
+that is never dynlinked.
+
+\item["-nolabels"]
+Ignore non-optional labels in types. Labels cannot be used in
+applications, and parameter order becomes strict.
+
+\item["-nostdlib"]
+Do not automatically add the standard library directory the list of
+directories searched for compiled interface files (".cmi"), compiled
+object code files (".cmx"), and libraries (".cmxa"). See also option
+"-I".
+
+\item["-o" \var{exec-file}]
+Specify the name of the output file produced by the linker. The
+default output name is "a.out" under Unix and "camlprog.exe" under
+Windows. If the "-a" option is given, specify the name of the library
+produced.  If the "-pack" option is given, specify the name of the
+packed object file produced.  If the "-output-obj" option is given,
+specify the name of the output file produced. If the "-shared" option
+is given, specify the name of plugin file produced.
+
+\item["-output-obj"]
+Cause the linker to produce a C object file instead of an executable
+file. This is useful to wrap OCaml code as a C library,
+callable from any C program. See chapter~\ref{c:intf-c},
+section~\ref{s:embedded-code}. The name of the output object file
+must be set with the "-o" option.
+This option can also be used to produce a compiled shared/dynamic
+library (".so" extension, ".dll" under Windows).
+
+\item["-p"]
+Generate extra code to write profile information when the program is
+executed.  The profile information can then be examined with the
+analysis program "gprof".  (See chapter~\ref{c:profiler} for more
+information on profiling.)  The "-p" option must be given both at
+compile-time and at link-time.  Linking object files not compiled with
+"-p" is possible, but results in less precise profiling.
+
+\begin{unix} See the Unix manual page for "gprof(1)" for more
+information about the profiles.
+
+Full support for "gprof" is only available for certain platforms
+(currently: Intel x86 32 and 64 bits under Linux, BSD and MacOS X).
+On other platforms, the "-p" option will result in a less precise
+profile (no call graph information, only a time profile).
+\end{unix}
+
+\begin{windows}
+The "-p" option does not work under Windows.
+\end{windows}
+
+\item["-pack"]
+Build an object file (".cmx" and ".o"/".obj" files) and its associated compiled
+interface (".cmi") that combines the ".cmx" object
+files given on the command line, making them appear as sub-modules of
+the output ".cmx" file.  The name of the output ".cmx" file must be
+given with the "-o" option.  For instance,
+\begin{verbatim}
+        ocamlopt -pack -o P.cmx A.cmx B.cmx C.cmx
+\end{verbatim}
+generates compiled files "P.cmx", "P.o" and "P.cmi" describing a
+compilation unit having three sub-modules "A", "B" and "C",
+corresponding to the contents of the object files "A.cmx", "B.cmx" and
+"C.cmx".  These contents can be referenced as "P.A", "P.B" and "P.C"
+in the remainder of the program.
+
+The ".cmx" object files being combined must have been compiled with
+the appropriate "-for-pack" option.  In the example above,
+"A.cmx", "B.cmx" and "C.cmx" must have been compiled with
+"ocamlopt -for-pack P".
+
+Multiple levels of packing can be achieved by combining "-pack" with
+"-for-pack".  Consider the following example:
+\begin{verbatim}
+        ocamlopt -for-pack P.Q -c A.ml
+        ocamlopt -pack -o Q.cmx -for-pack P A.cmx
+        ocamlopt -for-pack P -c B.ml
+        ocamlopt -pack -o P.cmx Q.cmx B.cmx
+\end{verbatim}
+The resulting "P.cmx" object file has sub-modules "P.Q", "P.Q.A"
+and "P.B".
+
+\item["-plugin" \var{plugin}]
+Dynamically load the code of the given \var{plugin}
+(a ".cmo", ".cma" or ".cmxs" file) in the compiler. \var{plugin} must exist in
+the same kind of code as the compiler ("ocamlopt.byte" must load bytecode
+plugins, while "ocamlopt.opt" must load native code plugins), and
+extension adaptation is done automatically for ".cma" files (to ".cmxs" files
+if the compiler is compiled in native code).
+
+\item["-pp" \var{command}]
+Cause the compiler to call the given \var{command} as a preprocessor
+for each source file. The output of \var{command} is redirected to
+an intermediate file, which is compiled. If there are no compilation
+errors, the intermediate file is deleted afterwards.
+
+\item["-ppx" \var{command}]
+After parsing, pipe the abstract syntax tree through the preprocessor
+\var{command}. The module "Ast_mapper", described in
+chapter~\ref{Ast-underscoremapper}, implements the external interface
+of a preprocessor.
+
+\item["-principal"]
+Check information path during type-checking, to make sure that all
+types are derived in a principal way. All programs accepted in
+"-principal" mode are also accepted in default mode with equivalent
+types, but different binary signatures.
+
+\item["-rectypes"]
+Allow arbitrary recursive types during type-checking.  By default,
+only recursive types where the recursion goes through an object type
+are supported. Note that once you have created an interface using this
+flag, you must use it again for all dependencies.
+
+\item["-runtime-variant" \var{suffix}]
+Add the \var{suffix} string to the name of the runtime library used by
+the program.  Currently, only one such suffix is supported: "d", and
+only if the OCaml compiler was configured with option
+"-with-debug-runtime".  This suffix gives the debug version of the
+runtime, which is useful for debugging pointer problems in low-level
+code such as C stubs.
+
+\item["-S"]
+Keep the assembly code produced during the compilation. The assembly
+code for the source file \var{x}".ml" is saved in the file \var{x}".s".
+
+\item["-shared"]
+Build a plugin (usually ".cmxs") that can be dynamically loaded with
+the "Dynlink" module. The name of the plugin must be
+set with the "-o" option. A plugin can include a number of OCaml
+modules and libraries, and extra native objects (".o", ".obj", ".a",
+".lib" files). Building native plugins is only supported for some
+operating system. Under some systems (currently,
+only Linux AMD 64), all the OCaml code linked in a plugin must have
+been compiled without the "-nodynlink" flag. Some constraints might also
+apply to the way the extra native objects have been compiled (under
+Linux AMD 64, they must contain only position-independent code).
+
+\item["-safe-string"]
+Enforce the separation between types "string" and "bytes",
+thereby making strings read-only. This will become the default in
+a future version of OCaml.
+
+\item["-short-paths"]
+When a type is visible under several module-paths, use the shortest
+one when printing the type's name in inferred interfaces and error and
+warning messages. Identifier names starting with an underscore "_" or
+containing double underscores "__" incur a penalty of $+10$ when computing
+their length.
+
+\item["-strict-sequence"]
+Force the left-hand part of each sequence to have type unit.
+
+\item["-strict-formats"]
+Reject invalid formats that were accepted in legacy format
+implementations. You should use this flag to detect and fix such
+invalid formats, as they will be rejected by future OCaml versions.
+
+\item["-thread"]
+Compile or link multithreaded programs, in combination with the
+system "threads" library described in chapter~\ref{c:threads}.
+
+\item["-unboxed-types"]
+When a type is unboxable (i.e. a record with a single argument or a
+concrete datatype with a single constructor of one argument) it will
+be unboxed unless annotated with "[@@ocaml.boxed]".
+
+\item["-no-unboxed-types"]
+When a type is unboxable  it will be boxed unless annotated with
+"[@@ocaml.unboxed]". This is the default.
+
+\item["-unsafe"]
+Turn bound checking off for array and string accesses (the "v.(i)" and
+"s.[i]" constructs). Programs compiled with "-unsafe" are therefore
+faster, but unsafe: anything can happen if the program accesses an
+array or string outside of its bounds.  Additionally, turn off the
+check for zero divisor in integer division and modulus operations.
+With "-unsafe", an integer division (or modulus) by zero can halt the
+program or continue with an unspecified result instead of raising a
+"Division_by_zero" exception.
+
+\item["-unsafe-string"]
+Identify the types "string" and "bytes",
+thereby making strings writable. For reasons of backward compatibility,
+this is the default setting for the moment, but this will change in a future
+version of OCaml.
+
+\item["-v"]
+Print the version number of the compiler and the location of the
+standard library directory, then exit.
+
+\item["-verbose"]
+Print all external commands before they are executed, in particular
+invocations of the assembler, C compiler, and linker.
+
+\item["-version" or "-vnum"]
+Print the version number of the compiler in short form (e.g. "3.11.0"),
+then exit.
+
+\item["-w" \var{warning-list}]
+Enable, disable, or mark as fatal the warnings specified by the argument
+\var{warning-list}.
+Each warning can be {\em enabled} or {\em disabled}, and each warning
+can be {\em fatal} or {\em non-fatal}.
+If a warning is disabled, it isn't displayed and doesn't affect
+compilation in any way (even if it is fatal).  If a warning is
+enabled, it is displayed normally by the compiler whenever the source
+code triggers it.  If it is enabled and fatal, the compiler will also
+stop with an error after displaying it.
+
+The \var{warning-list} argument is a sequence of warning specifiers,
+with no separators between them.  A warning specifier is one of the
+following:
+
+\begin{options}
+\item["+"\var{num}] Enable warning number \var{num}.
+\item["-"\var{num}] Disable warning number \var{num}.
+\item["@"\var{num}] Enable and mark as fatal warning number \var{num}.
+\item["+"\var{num1}..\var{num2}] Enable warnings in the given range.
+\item["-"\var{num1}..\var{num2}] Disable warnings in the given range.
+\item["@"\var{num1}..\var{num2}] Enable and mark as fatal warnings in
+the given range.
+\item["+"\var{letter}] Enable the set of warnings corresponding to
+\var{letter}. The letter may be uppercase or lowercase.
+\item["-"\var{letter}] Disable the set of warnings corresponding to
+\var{letter}. The letter may be uppercase or lowercase.
+\item["@"\var{letter}] Enable and mark as fatal the set of warnings
+corresponding to \var{letter}. The letter may be uppercase or
+lowercase.
+\item[\var{uppercase-letter}] Enable the set of warnings corresponding
+to \var{uppercase-letter}.
+\item[\var{lowercase-letter}] Disable the set of warnings corresponding
+to \var{lowercase-letter}.
+\end{options}
+
+Warning numbers and letters which are out of the range of warnings
+that are currently defined are ignored. The warning are as follows.
+\begin{options}
+\input{warnings-help.tex}
+\end{options}
+
+The default setting is "-w +a-4-6-7-9-27-29-32..39-41..42-44-45-48-50".
+It is displayed by "ocamlopt -help".
+Note that warnings 5 and 10 are not always triggered, depending on
+the internals of the type checker.
+
+\item["-warn-error" \var{warning-list}]
+Mark as fatal the warnings specified in the argument \var{warning-list}.
+The compiler will stop with an error when one of these warnings is
+emitted. The \var{warning-list} has the same meaning as for
+the "-w" option: a "+" sign (or an uppercase letter) marks the
+corresponding warnings as fatal, a "-"
+sign (or a lowercase letter) turns them back into non-fatal warnings,
+and a "@" sign both enables and marks as fatal the corresponding
+warnings.
+
+Note: it is not recommended to use warning sets (i.e. letters) as
+arguments to "-warn-error"
+in production code, because this can break your build when future versions
+of OCaml add some new warnings.
+
+The default setting is "-warn-error -a+31" (only warning 31 is fatal).
+
+\item["-warn-help"]
+Show the description of all available warning numbers.
+
+\item["-where"]
+Print the location of the standard library, then exit.
+
+\item["-" \var{file}]
+Process \var{file} as a file name, even if it starts with a dash (-)
+character.
+
+\item["-help" or "--help"]
+Display a short usage summary and exit.
+%
+\end{options}
+
+\paragraph{Options for the IA32 architecture}
+The IA32 code generator (Intel Pentium, AMD Athlon) supports the
+following additional option:
+
+\begin{options}
+\item["-ffast-math"] Use the IA32 instructions to compute
+trigonometric and exponential functions, instead of calling the
+corresponding library routines.  The functions affected are:
+"atan", "atan2", "cos", "log", "log10", "sin", "sqrt" and "tan".
+The resulting code runs faster, but the range of supported arguments
+and the precision of the result can be reduced.  In particular,
+trigonometric operations "cos", "sin", "tan" have their range reduced to
+$[-2^{64}, 2^{64}]$.
+\end{options}
+
+\paragraph{Options for the AMD64 architecture}
+The AMD64 code generator (64-bit versions of Intel Pentium and AMD
+Athlon) supports the following additional options:
+
+\begin{options}
+\item["-fPIC"] Generate position-independent machine code.  This is
+the default.
+\item["-fno-PIC"] Generate position-dependent machine code.
+\end{options}
+
+\paragraph{Options for the Sparc architecture}
+The Sparc code generator supports the following additional options:
+\begin{options}
+\item["-march=v8"] Generate SPARC version 8 code.
+\item["-march=v9"] Generate SPARC version 9 code.
+\end{options}
+The default is to generate code for SPARC version 7, which runs on all
+SPARC processors.
+
+\paragraph{Contextual control of command-line options}
+
+The compiler command line can be modified ``from the outside''
+with the following mechanisms. These are experimental
+and subject to change. They should be used only for experimental and
+development work, not in released packages.
+
+\begin{options}
+\item["OCAMLPARAM" \rm(environment variable)]
+Arguments that will be inserted before or after the arguments from the
+command line.
+\item["ocaml_compiler_internal_params" \rm(file in the stdlib directory)]
+A mapping of file names to lists of arguments that
+will be added to the command line (and "OCAMLPARAM") arguments.
+\item["OCAML_FLEXLINK" \rm(environment variable)]
+Alternative executable to use on native
+Windows for "flexlink" instead of the
+configured value. Primarily used for bootstrapping.
+\end{options}
+
+\section{Common errors}
+
+The error messages are almost identical to those of "ocamlc".
+See section~\ref{s:comp-errors}.
+
+\section{Running executables produced by ocamlopt}
+
+Executables generated by "ocamlopt" are native, stand-alone executable
+files that can be invoked directly.  They do
+not depend on the "ocamlrun" bytecode runtime system nor on
+dynamically-loaded C/OCaml stub libraries.
+
+During execution of an "ocamlopt"-generated executable,
+the following environment variables are also consulted:
+\begin{options}
+\item["OCAMLRUNPARAM"]  Same usage as in "ocamlrun"
+  (see section~\ref{ocamlrun-options}), except that option "l"
+  is ignored (the operating system's stack size limit
+  is used instead).
+\item["CAMLRUNPARAM"]  If "OCAMLRUNPARAM" is not found in the
+  environment, then "CAMLRUNPARAM" will be used instead.  If
+  "CAMLRUNPARAM" is not found, then the default values will be used.
+\end{options}
+
+\section{Compatibility with the bytecode compiler}
+\label{s:compat-native-bytecode}
+
+This section lists the known incompatibilities between the bytecode
+compiler and the native-code compiler. Except on those points, the two
+compilers should generate code that behave identically.
+
+\begin{itemize}
+
+\item Signals are detected only when the program performs an
+allocation in the heap. That is, if a signal is delivered while in a
+piece of code that does not allocate, its handler will not be called
+until the next heap allocation.
+
+\item Stack overflow, typically caused by excessively deep recursion,
+is handled in one of the following ways, depending on the
+platform used:
+\begin{itemize}
+\item By raising a "Stack_overflow" exception, like the bytecode
+  compiler does.  (IA32/Linux, AMD64/Linux, PowerPC/MacOSX, MS Windows
+  32-bit ports).
+\item By aborting the program on a ``segmentation fault'' signal.
+(All other Unix systems.)
+\item By terminating the program silently.
+(MS Windows 64 bits).
+\end{itemize}
+
+\item On IA32 processors only (Intel and AMD x86 processors in 32-bit
+mode), some intermediate results in floating-point computations are
+kept in extended precision rather than being rounded to double
+precision like the bytecode compiler always does.  Floating-point
+results can therefore differ slightly between bytecode and native code.
+
+\end{itemize}
+
diff --git a/manual/manual/cmds/ocamlbuild.etex b/manual/manual/cmds/ocamlbuild.etex
new file mode 100644
index 0000000000..9a55b48aae
--- /dev/null
+++ b/manual/manual/cmds/ocamlbuild.etex
@@ -0,0 +1,6 @@
+\chapter{The ocamlbuild compilation manager} \label{c:ocamlbuild}
+\pdfchapter{The ocamlbuild compilation manager}
+
+Since OCaml version 4.03, the ocamlbuild compilation manager is
+distributed separately from the OCaml compiler. The project is now
+hosted at \url{https://github.com/ocaml/ocamlbuild/}.
diff --git a/manual/manual/cmds/ocamldoc.etex b/manual/manual/cmds/ocamldoc.etex
new file mode 100644
index 0000000000..d1ab0f6364
--- /dev/null
+++ b/manual/manual/cmds/ocamldoc.etex
@@ -0,0 +1,1132 @@
+\chapter{The documentation generator (ocamldoc)} \label{c:ocamldoc}
+\pdfchapter{The documentation generator (ocamldoc)}
+%HEVEA\cutname{ocamldoc.html}
+
+This chapter describes OCamldoc, a tool that generates documentation from
+special comments embedded in source files.  The comments used by OCamldoc
+are of the form "(**"\ldots"*)" and follow the format described
+in section \ref{s:ocamldoc-comments}.
+
+OCamldoc can produce documentation in various formats: HTML, \LaTeX ,
+TeXinfo, Unix man pages, and "dot" dependency graphs.  Moreover,
+users can add their own custom generators, as explained in
+section \ref{s:ocamldoc-custom-generators}.
+
+In this chapter, we use the word {\em element} to refer to any of the
+following parts of an OCaml source file: a type declaration, a value,
+a module, an exception, a module type, a type constructor, a record
+field, a class, a class type, a class method, a class value or a class
+inheritance clause.
+
+\section{Usage} \label{s:ocamldoc-usage}
+
+\subsection{Invocation}
+
+OCamldoc is invoked via the command "ocamldoc", as follows:
+\begin{alltt}
+        ocamldoc \var{options} \var{sourcefiles}
+\end{alltt}
+
+\subsubsection*{Options for choosing the output format}
+
+The following options determine the format for the generated
+documentation.
+
+\begin{options}
+\item["-html"]
+Generate documentation in HTML default format. The generated HTML pages
+are stored in the current directory, or in the directory specified
+with the {\bf\tt -d} option.   You can customize the style of the
+generated pages by editing the generated "style.css" file, or by providing
+your own style sheet using option "-css-style".
+The file "style.css" is not generated if it already exists or if -css-style is used.
+
+\item["-latex"]
+Generate documentation in \LaTeX\ default format.  The generated
+\LaTeX\ document is saved in file "ocamldoc.out", or in the file
+specified with the {\bf\tt -o} option.  The document uses the style file
+"ocamldoc.sty". This file is generated when using the "-latex" option,
+if it does not already exist.
+You can change this file to  customize the style of your \LaTeX\ documentation.
+
+\item["-texi"]
+Generate documentation in TeXinfo default format.  The generated
+\LaTeX\ document is saved in file "ocamldoc.out", or in the file
+specified with the {\bf\tt -o} option.
+
+\item["-man"]
+Generate documentation as a set of Unix "man" pages.  The generated pages
+are stored in the current directory, or in the directory specified
+with the {\bf\tt -d} option.
+
+\item["-dot"]
+Generate a dependency graph for the toplevel modules, in a format suitable
+for displaying and processing by "dot". The "dot" tool is available from
+\url{http://www.research.att.com/sw/tools/graphviz/}.
+The textual representation of the graph is written to the file
+"ocamldoc.out", or to the file specified with the {\bf\tt -o} option.
+Use "dot ocamldoc.out" to display it.
+
+\item["-g" \var{file.cm[o,a,xs]}]
+Dynamically load the given file, which defines a custom documentation
+generator.  See section \ref{s:ocamldoc-compilation-and-usage}.  This
+option is supported by the "ocamldoc" command (to load ".cmo" and ".cma" files)
+and by its native-code version "ocamldoc.opt" (to load ".cmxs" files).
+If the given file is a simple one and does not exist in
+the current directory, then ocamldoc looks for it in the custom
+generators default directory, and in the directories specified with
+optional "-i" options.
+
+\item["-customdir"]
+Display the custom generators default directory.
+
+\item["-i" \var{directory}]
+Add the given directory to the path where to look for custom generators.
+
+\end{options}
+
+\subsubsection*{General options}
+
+\begin{options}
+
+\item["-d" \var{dir}]
+Generate files in directory \var{dir}, rather than the current directory.
+
+\item["-dump" \var{file}]
+Dump collected information into \var{file}.  This information can be
+read with the "-load" option in a subsequent invocation of "ocamldoc".
+
+\item["-hide" \var{modules}]
+Hide the given complete module names in the generated documentation.
+\var{modules} is a list of complete module names separated
+ by '","', without blanks.  For instance: "Pervasives,M2.M3".
+
+\item["-inv-merge-ml-mli"]
+Reverse the precedence of implementations and interfaces when merging.
+All elements
+in implementation files are kept, and the {\bf\tt -m} option
+indicates which parts of the comments in interface files are merged
+with the comments in implementation files.
+
+\item["-keep-code"]
+Always keep the source code for values, methods and instance variables,
+when available.
+The source code is always kept when a ".ml"
+file is given, but is by default discarded when a ".mli" is given.
+This option keeps the source code in all cases.
+
+\item["-load" \var{file}]
+Load information from \var{file}, which has been produced by
+"ocamldoc -dump".  Several "-load" options can be given.
+
+\item["-m" \var{flags}]
+Specify merge options between interfaces and implementations.
+(see section \ref{s:ocamldoc-merge} for details).
+\var{flags} can be one or several of the following characters:
+\begin{options}
+        \item["d"] merge description
+        \item["a"] merge "\@author"
+        \item["v"] merge "\@version"
+        \item["l"] merge "\@see"
+        \item["s"] merge "\@since"
+        \item["b"] merge "\@before"
+        \item["o"] merge "\@deprecated"
+        \item["p"] merge "\@param"
+        \item["e"] merge "\@raise"
+        \item["r"] merge "\@return"
+        \item["A"] merge everything
+\end{options}
+
+\item["-no-custom-tags"]
+Do not allow custom \@-tags (see section \ref{s:ocamldoc-tags}).
+
+\item["-no-stop"]
+Keep elements placed after/between the "(**/**)" special comment(s)
+(see section \ref{s:ocamldoc-comments}).
+
+\item["-o" \var{file}]
+Output the generated documentation to \var{file} instead of "ocamldoc.out".
+This option is meaningful only in conjunction with the
+{\bf\tt -latex}, {\bf\tt -texi}, or {\bf\tt -dot} options.
+
+\item["-pp" \var{command}]
+Pipe sources through preprocessor \var{command}.
+
+\item["-impl" \var{filename}]
+Process the file \var{filename} as an implementation file, even if its
+extension is not ".ml".
+
+\item["-intf" \var{filename}]
+Process the file \var{filename} as an interface file, even if its
+extension is not ".mli".
+
+\item["-text" \var{filename}]
+Process the file \var{filename} as a text file, even if its
+extension is not ".txt".
+
+\item["-sort"]
+Sort the list of top-level modules before generating the documentation.
+
+\item["-stars"]
+Remove blank characters until the first asterisk ('"*"') in each
+line of comments.
+
+\item["-t" \var{title}]
+Use \var{title} as the title for the generated documentation.
+
+\item["-intro" \var{file}]
+Use content of \var{file} as ocamldoc text to use as introduction (HTML,
+\LaTeX{} and TeXinfo only).
+For HTML, the file is used to create the whole "index.html" file.
+
+\item["-v"]
+Verbose mode. Display progress information.
+
+\item["-version"]
+Print version string and exit.
+
+\item["-vnum"]
+Print short version number and exit.
+
+\item["-warn-error"]
+Treat Ocamldoc warnings as errors.
+
+\item["-hide-warnings"]
+Do not print OCamldoc warnings.
+
+\item["-help" or "--help"]
+Display a short usage summary and exit.
+%
+\end{options}
+
+\subsubsection*{Type-checking options}
+
+OCamldoc calls the OCaml type-checker to obtain type
+information.  The following options impact the type-checking phase.
+They have the same meaning as for the "ocamlc" and "ocamlopt" commands.
+
+\begin{options}
+
+\item["-I" \var{directory}]
+Add \var{directory} to the list of directories search for compiled
+interface files (".cmi" files).
+
+\item["-nolabels"]
+Ignore non-optional labels in types.
+
+\item["-rectypes"]
+Allow arbitrary recursive types.  (See the "-rectypes" option to "ocamlc".)
+
+\end{options}
+
+\subsubsection*{Options for generating HTML pages}
+
+The following options apply in conjunction with the "-html" option:
+
+\begin{options}
+\item["-all-params"]
+Display the complete list of parameters for functions and methods.
+
+\item["-charset" \var{charset}]
+Add information about character encoding being \var{charset}
+(default is iso-8859-1).
+
+\item["-colorize-code"]
+Colorize the OCaml code enclosed in "[ ]" and "{[ ]}", using colors
+to emphasize keywords, etc.  If the code fragments are not
+syntactically correct, no color is added.
+
+\item["-css-style" \var{filename}]
+Use \var{filename} as the Cascading Style Sheet file.
+
+\item["-index-only"]
+Generate only index files.
+
+\item["-short-functors"]
+Use a short form to display functors:
+\begin{alltt}
+module M : functor (A:Module) -> functor (B:Module2) -> sig .. end
+\end{alltt}
+is displayed as:
+\begin{alltt}
+module M (A:Module) (B:Module2) : sig .. end
+\end{alltt}
+
+\end{options}
+
+\subsubsection*{Options for generating \LaTeX\ files}
+
+The following options apply in conjunction with the "-latex" option:
+
+\begin{options}
+\item["-latex-value-prefix" \var{prefix}]
+Give a prefix to use for the labels of the values in the generated
+\LaTeX\ document.
+The default prefix is the empty string. You can also use the options
+{\tt -latex-type-prefix}, {\tt -latex-exception-prefix},
+{\tt -latex-module-prefix},
+{\tt -latex-module-type-prefix}, {\tt -latex-class-prefix},
+{\tt -latex-class-type-prefix},
+{\tt -latex-attribute-prefix} and {\tt -latex-method-prefix}.
+
+These options are useful when you have, for example, a type and a value with
+ the same name. If you do not specify prefixes, \LaTeX\ will complain about
+multiply defined labels.
+
+\item["-latextitle" \var{n,style}]
+Associate style number \var{n} to the given \LaTeX\ sectioning command
+\var{style}, e.g. "section" or "subsection".  (\LaTeX\ only.)  This is
+useful when including the generated document in another \LaTeX\ document,
+at a given sectioning level.  The default association is 1 for "section",
+2 for "subsection", 3 for "subsubsection", 4 for "paragraph" and 5 for
+"subparagraph".
+
+\item["-noheader"]
+Suppress header in generated documentation.
+
+\item["-notoc"]
+Do not generate a table of contents.
+
+\item["-notrailer"]
+Suppress trailer in generated documentation.
+
+\item["-sepfiles"]
+Generate one ".tex" file per toplevel module, instead of the global
+"ocamldoc.out" file.
+\end{options}
+
+\subsubsection*{Options for generating TeXinfo files}
+
+The following options apply in conjunction with the "-texi" option:
+
+\begin{options}
+\item["-esc8"]
+Escape accented characters in Info files.
+
+\item["-info-entry"]
+Specify Info directory entry.
+
+\item["-info-section"]
+Specify section of Info directory.
+
+\item["-noheader"]
+Suppress header in generated documentation.
+
+\item["-noindex"]
+Do not build index for Info files.
+
+\item["-notrailer"]
+Suppress trailer in generated documentation.
+\end{options}
+
+\subsubsection*{Options for generating "dot" graphs}
+
+The following options apply in conjunction with the "-dot" option:
+
+\begin{options}
+\item["-dot-colors" \var{colors}]
+Specify the colors to use in the generated "dot" code.
+When generating module dependencies, "ocamldoc" uses different colors
+for modules, depending on the directories in which they reside.
+When generating types dependencies, "ocamldoc" uses different colors
+for types, depending on the modules in which they are defined.
+\var{colors} is a list of color names separated by '","', as
+in "Red,Blue,Green". The available colors are the ones supported by
+the "dot" tool.
+
+\item["-dot-include-all"]
+Include all modules in the "dot" output, not only modules given
+on the command line or loaded with the {\bf\tt -load} option.
+
+\item["-dot-reduce"]
+Perform a transitive reduction of the dependency graph before
+outputting the "dot" code. This can be useful if there are
+a lot of transitive dependencies that clutter the graph.
+
+\item["-dot-types"]
+Output "dot" code describing the type dependency graph instead of
+the module dependency graph.
+\end{options}
+
+\subsubsection*{Options for generating man files}
+
+The following options apply in conjunction with the "-man" option:
+
+\begin{options}
+\item["-man-mini"]
+Generate man pages only for modules, module types, classes and class
+types, instead of pages for all elements.
+
+\item["-man-suffix" \var{suffix}]
+Set the suffix used for generated man filenames. Default is '"3o"',
+as in "List.3o".
+
+\item["-man-section" \var{section}]
+Set the section number used for generated man filenames. Default is '"3"'.
+
+\end{options}
+
+\subsection{Merging of module information}
+\label{s:ocamldoc-merge}
+
+Information on a module can be extracted either from the ".mli" or ".ml"
+file, or both, depending on the files given on the command line.
+When both ".mli" and ".ml" files are given for the same module,
+information extracted from these files is merged according to the
+following rules:
+\begin{itemize}
+\item Only elements (values, types, classes, ...) declared in the ".mli"
+file are kept.  In other terms, definitions from the ".ml" file that are
+not exported in the ".mli" file are not documented.
+\item Descriptions of elements and descriptions in \@-tags are handled
+as follows.  If a description for the same element or in the same
+\@-tag of the same element is present in both files, then the
+description of the ".ml" file is concatenated to the one in the ".mli" file,
+if the corresponding "-m" flag is given on the command line.
+If a description is present in the ".ml" file and not in the
+".mli" file, the ".ml" description is kept.
+In either case, all the information given in the ".mli" file is kept.
+\end{itemize}
+
+\subsection{Coding rules}
+\label{s:ocamldoc-rules}
+The following rules must be respected in order to avoid name clashes
+resulting in cross-reference errors:
+\begin{itemize}
+\item In a module, there must not be two modules, two module types or
+  a module and a module type with the same name.
+  In the default HTML generator, modules "ab" and "AB" will be printed
+  to the same file on case insensitive file systems.
+\item In a module, there must not be two classes, two class types or
+  a class and a class type with the same name.
+\item In a module, there must not be two values, two types, or two
+  exceptions with the same name.
+\item Values defined in tuple, as in "let (x,y,z) = (1,2,3)"
+are not kept by OCamldoc.
+\item Avoid the following construction:
+\begin{verbatim}
+open Foo (* which has a module Bar with a value x *)
+module Foo =
+  struct
+    module Bar =
+      struct
+        let x = 1
+      end
+  end
+  let dummy = Bar.x
+\end{verbatim}
+In this case, OCamldoc will associate "Bar.x" to the "x" of module
+"Foo" defined just above, instead of to the "Bar.x" defined in the
+opened module "Foo".
+\end{itemize}
+
+\section{Syntax of documentation comments}
+\label{s:ocamldoc-comments}
+
+Comments containing documentation material are called {\em special
+comments} and are written between "(**" and "*)". Special comments
+must start exactly with "(**".  Comments beginning with "(" and more
+than two "*" are ignored.
+
+\subsection{Placement of documentation comments}
+OCamldoc can associate comments to some elements of the language
+encountered in the source files.  The association is made according to
+the locations of comments with respect to the language elements.  The
+locations of comments in ".mli" and ".ml" files are different.
+
+%%%%%%%%%%%%%
+\subsubsection{Comments in ".mli" files}
+A special comment is associated to an element if it is placed before or
+after the element.\\
+A special comment before an element is associated to this element if~:
+\begin{itemize}
+\item There is no blank line or another special comment between the special
+comment and the element. However, a regular comment can occur between
+the special comment and the element.
+\item The special comment is not already associated to the previous element.
+\item The special comment is not the first one of a toplevel module.
+\end{itemize}
+
+A special comment after an element is associated to this element if
+there is no blank line or comment between the special comment and the
+element.
+
+There are two exceptions: for constructors and record fields in
+type definitions, the associated comment can only be placed after the
+constructor or field definition, without blank lines or other comments
+between them. The special comment for a constructor
+with another constructor following must be placed before the '"|"'
+character separating the two constructors.
+
+The following sample interface file "foo.mli" illustrates the
+placement rules for comments in ".mli" files.
+
+\begin{verbatim}
+(** The first special comment of the file is the comment associated
+    with the whole module.*)
+
+
+(** Special comments can be placed between elements and are kept
+    by the OCamldoc tool, but are not associated to any element.
+    @-tags in these comments are ignored.*)
+
+(*******************************************************************)
+(** Comments like the one above, with more than two asterisks,
+    are ignored. *)
+
+(** The comment for function f. *)
+val f : int -> int -> int
+(** The continuation of the comment for function f. *)
+
+(** Comment for exception My_exception, even with a simple comment
+    between the special comment and the exception.*)
+(* Hello, I'm a simple comment :-) *)
+exception My_exception of (int -> int) * int
+
+(** Comment for type weather  *)
+type weather =
+| Rain of int (** The comment for constructor Rain *)
+| Sun (** The comment for constructor Sun *)
+
+(** Comment for type weather2  *)
+type weather2 =
+| Rain of int (** The comment for constructor Rain *)
+| Sun (** The comment for constructor Sun *)
+(** I can continue the comment for type weather2 here
+  because there is already a comment associated to the last constructor.*)
+
+(** The comment for type my_record *)
+type my_record = {
+    val foo : int ;    (** Comment for field foo *)
+    val bar : string ; (** Comment for field bar *)
+  }
+  (** Continuation of comment for type my_record *)
+
+(** Comment for foo *)
+val foo : string
+(** This comment is associated to foo and not to bar. *)
+val bar : string
+(** This comment is associated to bar. *)
+
+(** The comment for class my_class *)
+class my_class :
+  object
+    (** A comment to describe inheritance from cl *)
+    inherit cl
+
+    (** The comment for attribute tutu *)
+    val mutable tutu : string
+
+    (** The comment for attribute toto. *)
+    val toto : int
+
+    (** This comment is not attached to titi since
+        there is a blank line before titi, but is kept
+        as a comment in the class. *)
+
+    val titi : string
+
+    (** Comment for method toto *)
+    method toto : string
+
+    (** Comment for method m *)
+    method m : float -> int
+  end
+
+(** The comment for the class type my_class_type *)
+class type my_class_type =
+  object
+    (** The comment for variable x. *)
+    val mutable x : int
+
+    (** The commend for method m. *)
+    method m : int -> int
+end
+
+(** The comment for module Foo *)
+module Foo =
+  struct
+    (** The comment for x *)
+    val x : int
+
+    (** A special comment that is kept but not associated to any element *)
+  end
+
+(** The comment for module type my_module_type. *)
+module type my_module_type =
+  sig
+    (** The comment for value x. *)
+    val x : int
+
+    (** The comment for module M. *)
+    module M =
+      struct
+        (** The comment for value y. *)
+        val y : int
+
+        (* ... *)
+      end
+
+  end
+
+\end{verbatim}
+
+%%%%%%%%%%%%%
+\subsubsection{Comments in {\tt .ml} files}
+
+A special comment is associated to an element if it is placed before
+the element and there is no blank line between the comment and the
+element. Meanwhile, there can be a simple comment between the special
+comment and the element. There are two exceptions, for
+constructors and record fields in type definitions, whose associated
+comment must be placed after the constructor or field definition,
+without blank line between them. The special comment for a constructor
+with another constructor following must be placed before the '"|"'
+character separating the two constructors.
+
+The following example of file "toto.ml" shows where to place comments
+in a ".ml" file.
+
+\begin{verbatim}
+(** The first special comment of the file is the comment associated
+    to the whole module. *)
+
+(** The comment for function f *)
+let f x y = x + y
+
+(** This comment is not attached to any element since there is another
+    special comment just before the next element. *)
+
+(** Comment for exception My_exception, even with a simple comment
+    between the special comment and the exception.*)
+(* A simple comment. *)
+exception My_exception of (int -> int) * int
+
+(** Comment for type weather  *)
+type weather =
+| Rain of int (** The comment for constructor Rain *)
+| Sun (** The comment for constructor Sun *)
+
+(** The comment for type my_record *)
+type my_record = {
+    val foo : int ;    (** Comment for field foo *)
+    val bar : string ; (** Comment for field bar *)
+  }
+
+(** The comment for class my_class *)
+class my_class =
+    object
+      (** A comment to describe inheritance from cl *)
+      inherit cl
+
+      (** The comment for the instance variable tutu *)
+      val mutable tutu = "tutu"
+      (** The comment for toto *)
+      val toto = 1
+      val titi = "titi"
+      (** Comment for method toto *)
+      method toto = tutu ^ "!"
+      (** Comment for method m *)
+      method m (f : float) = 1
+    end
+
+(** The comment for class type my_class_type *)
+class type my_class_type =
+  object
+    (** The comment for the instance variable x. *)
+    val mutable x : int
+    (** The commend for method m. *)
+    method m : int -> int
+  end
+
+(** The comment for module Foo *)
+module Foo =
+  struct
+    (** The comment for x *)
+    val x : int
+    (** A special comment in the class, but not associated to any element. *)
+  end
+
+(** The comment for module type my_module_type. *)
+module type my_module_type =
+  sig
+    (* Comment for value x. *)
+    val x : int
+    (* ... *)
+  end
+\end{verbatim}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{The Stop special comment}
+The special comment "(**/**)" tells OCamldoc to discard
+elements placed after this comment, up to the end of the current
+class, class type,  module or module type, or up to the next stop comment.
+For instance:
+\begin{verbatim}
+class type foo =
+  object
+    (** comment for method m *)
+    method m : string
+
+    (**/**)
+
+    (** This method won't appear in the documentation *)
+    method bar : int
+  end
+
+(** This value appears in the documentation, since the Stop special comment
+    in the class does not affect the parent module of the class.*)
+val foo : string
+
+(**/**)
+(** The value bar does not appear in the documentation.*)
+val bar : string
+(**/**)
+
+(** The type t appears since in the documentation since the previous stop comment
+toggled off the "no documentation mode". *)
+type t = string
+\end{verbatim}
+
+The {\bf\tt -no-stop} option to "ocamldoc" causes the Stop special
+comments to be ignored.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Syntax of documentation comments}
+
+The inside of documentation comments "(**"\ldots"*)" consists of
+free-form text with optional formatting annotations, followed by
+optional {\em tags} giving more specific information about parameters,
+version, authors, \ldots\ The tags are distinguished by a leading "\@"
+character.  Thus, a documentation comment has the following shape:
+\begin{verbatim}
+(** The comment begins with a description, which is text formatted
+   according to the rules described in the next section.
+   The description continues until the first non-escaped '@' character.
+   @author Mr Smith
+   @param x description for parameter x
+*)
+\end{verbatim}
+Some elements support only a subset of all \@-tags.  Tags that are not
+relevant to the documented element are simply ignored.  For instance,
+all tags are ignored when documenting type constructors, record
+fields, and class inheritance clauses.  Similarly, a "\@param" tag on a
+class instance variable is ignored.
+
+At last, "(**)" is the empty documentation comment.
+
+%%%%%%%%%%%%%
+
+% enable section numbering for subsubsections (PR#6189, item 3)
+\setcounter{secnumdepth}{3}
+
+\subsection{Text formatting}
+
+Here is the BNF grammar for the simple markup language used to format
+text descriptions.
+
+\newpage
+
+\begin{syntax}
+text: {{text-element}}
+;
+\end{syntax}
+
+\noindent
+\begin{syntaxleft}
+\nonterm{text-element}\is{}
+\end{syntaxleft}
+
+\begin{tabular}{rlp{10cm}}
+@||@&@ '{' {{ "0" \ldots "9" }} text '}' @ & format @text@ as a section header;
+  the integer following "{" indicates the sectioning level. \\
+@||@&@ '{' {{ "0" \ldots "9" }} ':' @ \nt{label} @ text '}' @ &
+  same, but also associate the name \nt{label} to the current point.
+  This point can be referenced by its fully-qualified label in a
+  "{!" command, just like any other element. \\
+@||@&@ '{b' text '}' @ & set @text@ in bold. \\
+@||@&@ '{i' text '}' @ & set @text@ in italic. \\
+@||@&@ '{e' text '}' @ & emphasize @text@. \\
+@||@&@ '{C' text '}' @ & center @text@. \\
+@||@&@ '{L' text '}' @ & left align @text@. \\
+@||@&@ '{R' text '}' @ & right align @text@. \\
+@||@&@ '{ul' list '}' @ & build a list. \\
+@||@&@ '{ol' list '}' @ & build an enumerated list. \\
+@||@&@ '{{:' string '}' text '}' @ & put a link to the given address
+(given as @string@) on the given @text@. \\
+@||@&@ '[' string ']' @ & set the given @string@ in source code style. \\
+@||@&@ '{[' string ']}' @ & set the given @string@ in preformatted
+				source code style.\\
+@||@&@ '{v' string 'v}' @ & set the given @string@ in verbatim style. \\
+@||@&@ '{%' string '%}' @ & target-specific content
+        (\LaTeX\ code by default, see details
+        in \ref{sss:target-specific-syntax}) \\
+@||@&@ '{!' string '}' @ & insert a cross-reference to an element
+        (see section \ref{sss:crossref} for the syntax of cross-references).\\
+@||@&@ '{!modules:' string string ... '}' @ & insert an index table
+for the given module names. Used in HTML only.\\
+@||@&@ '{!indexlist}' @ & insert a table of links to the various indexes
+(types, values, modules, ...). Used in HTML only.\\
+@||@&@ '{^' text '}' @ & set text in superscript.\\
+@||@&@ '{_' text '}' @ & set text in subscript.\\
+@||@& \nt{escaped-string} & typeset the given string as is;
+special characters ('"{"', '"}"', '"["', '"]"' and '"\@"')
+must be	escaped by a '"\\"'\\
+@||@& \nt{blank-line} & force a new line.
+\end{tabular} \\
+
+\subsubsection{List formatting}
+
+\begin{syntax}
+list:
+| {{ '{-' text '}' }}
+| {{ '{li' text '}' }}
+\end{syntax}
+
+A shortcut syntax exists for lists and enumerated lists:
+\begin{verbatim}
+(** Here is a {b list}
+- item 1
+- item 2
+- item 3
+
+The list is ended by the blank line.*)
+\end{verbatim}
+is equivalent to:
+\begin{verbatim}
+(** Here is a {b list}
+{ul {- item 1}
+{- item 2}
+{- item 3}}
+The list is ended by the blank line.*)
+\end{verbatim}
+
+The same shortcut is available for enumerated lists, using '"+"'
+instead of '"-"'.
+Note that only one list can be defined by this shortcut in nested lists.
+
+\subsubsection{Cross-reference formatting}
+\label{sss:crossref}
+
+Cross-references are fully qualified element names, as in the example
+"{!Foo.Bar.t}". This is an ambiguous reference as it may designate
+a type name, a value name, a class name, etc. It is possible to make
+explicit the intended syntactic class, using "{!type:Foo.Bar.t}" to
+designate a type, and "{!val:Foo.Bar.t}" a value of the same name.
+
+The list of possible syntactic class is as follows:
+\begin{center}
+\begin{tabular}{rl}
+\multicolumn{1}{c}{"tag"} & \multicolumn{1}{c}{syntactic class}\\ \hline
+"module:" & module \\
+"modtype:" & module type \\
+"class:" & class \\
+"classtype:" & class type \\
+"val:" & value \\
+"type:" & type \\
+"exception:" & exception \\
+"attribute:" & attribute \\
+"method:" & class method \\
+"section:" & ocamldoc section \\
+"const:" & variant constructor \\
+"recfield:" & record field
+\end{tabular}
+\end{center}
+
+In the case of variant constructors or record field, the constructor
+or field name should be preceded by the name of the correspond type --
+to avoid the ambiguity of several types having the same constructor
+names. For example, the constructor "Node" of the type "tree" will be
+referenced as "{!tree.Node}" or "{!const:tree.Node}", or possibly
+"{!Mod1.Mod2.tree.Node}" from outside the module.
+
+\subsubsection{First sentence}
+
+In the description of a value, type, exception, module, module type, class
+or class type, the {\em first sentence} is sometimes used in indexes, or
+when just a part of the description is needed. The first sentence
+is composed of the first characters of the description, until
+\begin{itemize}
+\item the first dot followed by a blank, or
+\item the first blank line
+\end{itemize}
+outside of the following text formatting :
+@ '{ul' list '}' @,
+@ '{ol' list '}' @,
+@ '[' string ']' @,
+@ '{[' string ']}' @,
+@ '{v' string 'v}' @,
+@ '{%' string '%}' @,
+@ '{!' string '}' @,
+@ '{^' text '}' @,
+@ '{_' text '}' @.
+
+\subsubsection{Target-specific formatting}
+\label{sss:target-specific-syntax}
+
+The content inside "{%foo: ... %}" is target-specific and will only be
+interpreted by the backend "foo", and ignored by the others. The
+backends of the distribution are "latex", "html", "texi" and "man". If
+no target is specified (syntax "{% ... %}"), "latex" is chosen by
+default. Custom generators may support their own target prefix.
+
+\subsubsection{Recognized HTML tags}
+The HTML tags  "..",
+"..",
+"..",
+"
    ..
", +"
    ..
", +"
  • ..
  • ", +"
    ..
    " and +".." can be used instead of, respectively, +@ '{b ..}' @, +@ '[..]' @, +@ '{i ..}' @, +@ '{ul ..}' @, +@ '{ol ..}' @, +@ '{li ..}' @, +@ '{C ..}' @ and +"{[0-9] ..}". + +%disable section numbering for subsubsections +\setcounter{secnumdepth}{2} + +%%%%%%%%%%%%% +\subsection{Documentation tags (\@-tags)} +\label{s:ocamldoc-tags} + +\subsubsection{Predefined tags} +The following table gives the list of predefined \@-tags, with their +syntax and meaning.\\ + +\begin{tabular}{|p{5cm}|p{10cm}|}\hline +@ "@author" string @ & The author of the element. One author per +"\@author" tag. +There may be several "\@author" tags for the same element. \\ \hline + +@ "@deprecated" text @ & The @text@ should describe when the element was +deprecated, what to use as a replacement, and possibly the reason +for deprecation. \\ \hline + +@ "@param" id text @ & Associate the given description (@text@) to the +given parameter name @id@. This tag is used for functions, +methods, classes and functors. \\ \hline + +@ "@raise" Exc text @ & Explain that the element may raise + the exception @Exc@. \\ \hline + +@ "@return" text @ & Describe the return value and + its possible values. This tag is used for functions + and methods. \\ \hline + +@ "@see" '<' URL '>' text @ & Add a reference to the @URL@ +with the given @text@ as comment. \\ \hline + +@ "@see" "'"@\nt{filename}@"'" text @ & Add a reference to the given file name +(written between single quotes), with the given @text@ as comment. \\ \hline + +@ "@see" '"'@\nt{document-name}@'"' text @ & Add a reference to the given +document name (written between double quotes), with the given @text@ +as comment. \\ \hline + +@ "@since" string @ & Indicate when the element was introduced. \\ \hline + +@ "@before" @ \nt{version} @ text @ & Associate the given description (@text@) +to the given \nt{version} in order to document compatibility issues. \\ \hline + +@ "@version" string @ & The version number for the element. \\ \hline +\end{tabular} + +\subsubsection{Custom tags} +\label{s:ocamldoc-custom-tags} +You can use custom tags in the documentation comments, but they will +have no effect if the generator used does not handle them. To use a +custom tag, for example "foo", just put "\@foo" with some text in your +comment, as in: +\begin{verbatim} +(** My comment to show you a custom tag. +@foo this is the text argument to the [foo] custom tag. +*) +\end{verbatim} + +To handle custom tags, you need to define a custom generator, +as explained in section \ref{s:ocamldoc-handling-custom-tags}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Custom generators} +\label{s:ocamldoc-custom-generators} + +OCamldoc operates in two steps: +\begin{enumerate} +\item analysis of the source files; +\item generation of documentation, through a documentation generator, + which is an object of class "Odoc_args.class_generator". +\end{enumerate} +Users can provide their own documentation generator to be used during +step 2 instead of the default generators. +All the information retrieved during the analysis step is available through +the "Odoc_info" module, which gives access to all the types and functions + representing the elements found in the given modules, with their associated +description. + +The files you can use to define custom generators are installed in the +"ocamldoc" sub-directory of the OCaml standard library. + +%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{The generator modules} +The type of a generator module depends on the kind of generated documentation. +Here is the list of generator module types, with the name of the generator +class in the module~: +\begin{itemize} +\item for HTML~: "Odoc_html.Html_generator" (class "html"), +\item for \LaTeX~: "Odoc_latex.Latex_generator" (class "latex"), +\item for TeXinfo~: "Odoc_texi.Texi_generator" (class "texi"), +\item for man pages~: "Odoc_man.Man_generator" (class "man"), +\item for graphviz (dot)~: "Odoc_dot.Dot_generator" (class "dot"), +\item for other kinds~: "Odoc_gen.Base" (class "generator"). +\end{itemize} +That is, to define a new generator, one must implement a module with +the expected signature, and with the given generator class, providing +the "generate" method as entry point to make the generator generates +documentation for a given list of modules~: + +\begin{verbatim} + method generate : Odoc_info.Module.t_module list -> unit +\end{verbatim} + +\noindent{}This method will be called with the list of analysed and possibly +merged "Odoc_info.t_module" structures. + +It is recommended to inherit from the current generator of the same +kind as the one you want to define. Doing so, it is possible to +load various custom generators to combine improvements brought by each one. + +This is done using first class modules (see chapter \ref{s-first-class-modules}). + +The easiest way to define a custom generator is the following this example, +here extending the current HTML generator. We don't have to know if this is +the original HTML generator defined in ocamldoc or if it has been extended +already by a previously loaded custom generator~: + +\begin{verbatim} +module Generator (G : Odoc_html.Html_generator) = +struct + class html = + object(self) + inherit G.html as html + (* ... *) + + method generate module_list = + (* ... *) + () + + (* ... *) + end +end;; + +let _ = Odoc_args.extend_html_generator (module Generator : Odoc_gen.Html_functor);; +\end{verbatim} + +To know which methods to override and/or which methods are available, +have a look at the different base implementations, depending on the +kind of generator you are extending~: +\begin{itemize} +\item for HTML~: \href{http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/version/\ocamlversion/ocamldoc/odoc_html.ml?view=markup}{"odoc_html.ml"}, +\item for \LaTeX~: \href{http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/version/\ocamlversion/ocamldoc/odoc_latex.ml?view=markup}{"odoc_latex.ml"}, +\item for TeXinfo~: \href{http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/version/\ocamlversion/ocamldoc/odoc_texi.ml?view=markup}{"odoc_texi.ml"}, +\item for man pages~: \href{http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/version/\ocamlversion/ocamldoc/odoc_man.ml?view=markup}{"odoc_man.ml"}, +\item for graphviz (dot)~: \href{http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/version/\ocamlversion/ocamldoc/odoc_dot.ml?view=markup}{"odoc_dot.ml"}. +\end{itemize} + +%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Handling custom tags} +\label{s:ocamldoc-handling-custom-tags} + +Making a custom generator handle custom tags (see +\ref{s:ocamldoc-custom-tags}) is very simple. + +\subsubsection*{For HTML} +Here is how to develop a HTML generator handling your custom tags. + +The class "Odoc_html.Generator.html" inherits +from the class "Odoc_html.info", containing a field "tag_functions" which is a +list pairs composed of a custom tag (e.g. "\"foo\"") and a function taking +a "text" and returning HTML code (of type "string"). +To handle a new tag "bar", extend the current HTML generator + and complete the "tag_functions" field: +\begin{verbatim} +module Generator (G : Odoc_html.Html_generator) = +struct + class html = + object(self) + inherit G.html + + (** Return HTML code for the given text of a bar tag. *) + method html_of_bar t = (* your code here *) + + initializer + tag_functions <- ("bar", self#html_of_bar) :: tag_functions + end +end +let _ = Odoc_args.extend_html_generator (module Generator : Odoc_gen.Html_functor);; +\end{verbatim} + +Another method of the class "Odoc_html.info" will look for the +function associated to a custom tag and apply it to the text given to +the tag. If no function is associated to a custom tag, then the method +prints a warning message on "stderr". + +\subsubsection{For other generators} +You can act the same way for other kinds of generators. + +%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Adding command line options} +The command line analysis is performed after loading the module containing the +documentation generator, thus allowing command line options to be added to the + list of existing ones. Adding an option can be done with the function +\begin{verbatim} + Odoc_args.add_option : string * Arg.spec * string -> unit +\end{verbatim} +\noindent{}Note: Existing command line options can be redefined using +this function. + +%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Compilation and usage} +\label{s:ocamldoc-compilation-and-usage} + +%%%%%%%%%%%%%% +\subsubsection{Defining a custom generator class in one file} +Let "custom.ml" be the file defining a new generator class. +Compilation of "custom.ml" can be performed by the following command~: +\begin{alltt} + ocamlc -I +ocamldoc -c custom.ml +\end{alltt} +\noindent{}The file "custom.cmo" is created and can be used this way~: +\begin{alltt} + ocamldoc -g custom.cmo \var{other-options} \var{source-files} +\end{alltt} +\noindent{}Options selecting a built-in generator to "ocamldoc", such as +"-html", have no effect if a custom generator of the same kind is provided using +"-g". If the kinds do not match, the selected built-in generator is used and the +custom one is ignored. + +%%%%%%%%%%%%%% +\subsubsection{Defining a custom generator class in several files} +It is possible to define a generator class in several modules, which +are defined in several files \var{\nth{file}{1}}".ml"["i"], +\var{\nth{file}{2}}".ml"["i"], ..., \var{\nth{file}{n}}".ml"["i"]. A ".cma" +library file must be created, including all these files. + +The following commands create the "custom.cma" file from files +\var{\nth{file}{1}}".ml"["i"], ..., \var{\nth{file}{n}}".ml"["i"]~: +\begin{alltt} +ocamlc -I +ocamldoc -c \var{\nth{file}{1}}.ml\textrm{[}i\textrm{]} +ocamlc -I +ocamldoc -c \var{\nth{file}{2}}.ml\textrm{[}i\textrm{]} +... +ocamlc -I +ocamldoc -c \var{\nth{file}{n}}.ml\textrm{[}i\textrm{]} +ocamlc -o custom.cma -a \var{\nth{file}{1}}.cmo \var{\nth{file}{2}}.cmo ... \var{\nth{file}{n}}.cmo +\end{alltt} +\noindent{}Then, the following command uses "custom.cma" as custom generator: +\begin{alltt} + ocamldoc -g custom.cma \var{other-options} \var{source-files} +\end{alltt} diff --git a/manual/manual/cmds/profil.etex b/manual/manual/cmds/profil.etex new file mode 100644 index 0000000000..0e7c7c2bd3 --- /dev/null +++ b/manual/manual/cmds/profil.etex @@ -0,0 +1,170 @@ +\chapter{Profiling (ocamlprof)} \label{c:profiler} +\pdfchapter{Profiling (ocamlprof)} +%HEVEA\cutname{profil.html} + +This chapter describes how the execution of OCaml +programs can be profiled, by recording how many times functions are +called, branches of conditionals are taken, \ldots + +\section{Compiling for profiling} + +Before profiling an execution, the program must be compiled in +profiling mode, using the "ocamlcp" front-end to the "ocamlc" compiler +(see chapter~\ref{c:camlc}) or the "ocamloptp" front-end to the +"ocamlopt" compiler (see chapter~\ref{c:nativecomp}). When compiling +modules separately, "ocamlcp" or "ocamloptp" must be used when +compiling the modules (production of ".cmo" or ".cmx" files), and can +also be used (though this is not strictly necessary) when linking them +together. + +\paragraph{Note} If a module (".ml" file) doesn't have a corresponding +interface (".mli" file), then compiling it with "ocamlcp" will produce +object files (".cmi" and ".cmo") that are not compatible with the ones +produced by "ocamlc", which may lead to problems (if the ".cmi" or +".cmo" is still around) when switching between profiling and +non-profiling compilations. To avoid this problem, you should always +have a ".mli" file for each ".ml" file. The same problem exists with +"ocamloptp". + +\paragraph{Note} To make sure your programs can be compiled in +profiling mode, avoid using any identifier that begins with +"__ocaml_prof". + +The amount of profiling information can be controlled through the "-P" +option to "ocamlcp" or "ocamloptp", followed by one or several letters +indicating which parts of the program should be profiled: + +%% description des options +\begin{options} +\item["a"] all options +\item["f"] function calls : a count point is set at the beginning of +each function body +\item["i"] {\bf if \ldots then \ldots else \ldots} : count points are set in +both {\bf then} branch and {\bf else} branch +\item["l"] {\bf while, for} loops: a count point is set at the beginning of +the loop body +\item["m"] {\bf match} branches: a count point is set at the beginning of the +body of each branch +\item["t"] {\bf try \ldots with \ldots} branches: a count point is set at the +beginning of the body of each branch +\end{options} + +For instance, compiling with "ocamlcp -P film" profiles function calls, +if\ldots then\ldots else\ldots, loops and pattern matching. + +Calling "ocamlcp" or "ocamloptp" without the "-P" option defaults to +"-P fm", meaning that only function calls and pattern matching are +profiled. + +\paragraph{Note} For compatibility with previous releases, "ocamlcp" +also accepts the "-p" option, with the same arguments and behaviour as +"-P". + +The "ocamlcp" and "ocamloptp" commands also accept all the options of +the corresponding "ocamlc" or "ocamlopt" compiler, except the "-pp" +(preprocessing) option. + + +\section{Profiling an execution} + +Running an executable that has been compiled with "ocamlcp" or +"ocamloptp" records the execution counts for the specified parts of +the program and saves them in a file called "ocamlprof.dump" in the +current directory. + +If the environment variable "OCAMLPROF_DUMP" is set when the program +exits, its value is used as the file name instead of "ocamlprof.dump". + +The dump file is written only if the program terminates +normally (by calling "exit" or by falling through). It is not written +if the program terminates with an uncaught exception. + +If a compatible dump file already exists in the current directory, then the +profiling information is accumulated in this dump file. This allows, for +instance, the profiling of several executions of a program on +different inputs. Note that dump files produced by byte-code +executables (compiled with "ocamlcp") are compatible with the dump +files produced by native executables (compiled with "ocamloptp"). + +\section{Printing profiling information} + +The "ocamlprof" command produces a source listing of the program modules +where execution counts have been inserted as comments. For instance, +\begin{verbatim} + ocamlprof foo.ml +\end{verbatim} +prints the source code for the "foo" module, with comments indicating +how many times the functions in this module have been called. Naturally, +this information is accurate only if the source file has not been modified +after it was compiled. + +The following options are recognized by "ocamlprof": + +\begin{options} + +\item["-f" \var{dumpfile}] +Specifies an alternate dump file of profiling information to be read. + +\item["-F" \var{string}] +Specifies an additional string to be output with profiling information. +By default, "ocamlprof" will annotate programs with comments of the form +{\tt (* \var{n} *)} where \var{n} is the counter value for a profiling +point. With option {\tt -F \var{s}}, the annotation will be +{\tt (* \var{s}\var{n} *)}. + +\item["-impl" \var{filename}] +Process the file \var{filename} as an implementation file, even if its +extension is not ".ml". + +\item["-intf" \var{filename}] +Process the file \var{filename} as an interface file, even if its +extension is not ".mli". + +\item["-version"] +Print version string and exit. + +\item["-vnum"] +Print short version number and exit. + +\item["-help" or "--help"] +Display a short usage summary and exit. +% +\end{options} + +\section{Time profiling} + +Profiling with "ocamlprof" only records execution counts, not the actual +time spent within each function. There is currently no way to perform +time profiling on bytecode programs generated by "ocamlc". + +Native-code programs generated by "ocamlopt" can be profiled for time +and execution counts using the "-p" option and the standard Unix +profiler "gprof". Just add the "-p" option when compiling and linking +the program: +\begin{alltt} + ocamlopt -o myprog -p \var{other-options} \var{files} + ./myprog + gprof myprog +\end{alltt} +OCaml function names in the output of "gprof" have the following format: +\begin{alltt} + \var{Module-name}_\var{function-name}_\var{unique-number} +\end{alltt} +Other functions shown are either parts of the OCaml run-time system or +external C functions linked with the program. + +The output of "gprof" is described in the Unix manual page for +"gprof(1)". It generally consists of two parts: a ``flat'' profile +showing the time spent in each function and the number of invocation +of each function, and a ``hierarchical'' profile based on the call +graph. Currently, only the Intel x86 ports of "ocamlopt" under +Linux, BSD and MacOS X support the two profiles. On other platforms, +"gprof" will report only the ``flat'' profile with just time +information. When reading the output of "gprof", keep in mind that +the accumulated times computed by "gprof" are based on heuristics and +may not be exact. + +\paragraph{Note} The "ocamloptp" command also accepts the "-p" +option. In that case, both kinds of profiling are performed by the +program, and you can display the results with the "gprof" and "ocamlprof" +commands, respectively. diff --git a/manual/manual/cmds/runtime.etex b/manual/manual/cmds/runtime.etex new file mode 100644 index 0000000000..59c3cc7f3e --- /dev/null +++ b/manual/manual/cmds/runtime.etex @@ -0,0 +1,277 @@ +\chapter{The runtime system (ocamlrun)} \label{c:runtime} +\pdfchapter{The runtime system (ocamlrun)} +%HEVEA\cutname{runtime.html} + +The "ocamlrun" command executes bytecode files produced by the +linking phase of the "ocamlc" command. + +\section{Overview} + +The "ocamlrun" command comprises three main parts: the bytecode +interpreter, that actually executes bytecode files; the memory +allocator and garbage collector; and a set of C functions that +implement primitive operations such as input/output. + +The usage for "ocamlrun" is: +\begin{alltt} + ocamlrun \var{options} \var{bytecode-executable} \nth{arg}{1} ... \nth{arg}{n} +\end{alltt} +The first non-option argument is taken to be the name of the file +containing the executable bytecode. (That file is searched in the +executable path as well as in the current directory.) The remaining +arguments are passed to the OCaml program, in the string array +"Sys.argv". Element 0 of this array is the name of the +bytecode executable file; elements 1 to \var{n} are the remaining +arguments \nth{arg}{1} to \nth{arg}{n}. + +As mentioned in chapter~\ref{c:camlc}, the bytecode executable files +produced by the "ocamlc" command are self-executable, and manage to +launch the "ocamlrun" command on themselves automatically. That is, +assuming "a.out" is a bytecode executable file, +\begin{alltt} + a.out \nth{arg}{1} ... \nth{arg}{n} +\end{alltt} +works exactly as +\begin{alltt} + ocamlrun a.out \nth{arg}{1} ... \nth{arg}{n} +\end{alltt} +Notice that it is not possible to pass options to "ocamlrun" when +invoking "a.out" directly. + +\begin{windows} +Under several versions of Windows, bytecode executable files are +self-executable only if their name ends in ".exe". It is recommended +to always give ".exe" names to bytecode executables, e.g. compile +with "ocamlc -o myprog.exe ..." rather than "ocamlc -o myprog ...". +\end{windows} + +\section{Options} \label{ocamlrun-options} + +The following command-line options are recognized by "ocamlrun". + +\begin{options} + +\item["-b"] +When the program aborts due to an uncaught exception, print a detailed +``back trace'' of the execution, showing where the exception was +raised and which function calls were outstanding at this point. The +back trace is printed only if the bytecode executable contains +debugging information, i.e. was compiled and linked with the "-g" +option to "ocamlc" set. This is equivalent to setting the "b" flag +in the "OCAMLRUNPARAM" environment variable (see below). +\item["-I" \var{dir}] +Search the directory \var{dir} for dynamically-loaded libraries, +in addition to the standard search path (see +section~\ref{s-ocamlrun-dllpath}). +\item["-p"] +Print the names of the primitives known to this version of +"ocamlrun" and exit. +\item["-v"] +Direct the memory manager to print some progress messages on +standard error. This is equivalent to setting "v=63" in the +"OCAMLRUNPARAM" environment variable (see below). +\item["-version"] +Print version string and exit. +\item["-vnum"] +Print short version number and exit. + +\end{options} + +\noindent +The following environment variables are also consulted: + +\begin{options} +\item["CAML_LD_LIBRARY_PATH"] Additional directories to search for + dynamically-loaded libraries (see section~\ref{s-ocamlrun-dllpath}). + +\item["OCAMLLIB"] The directory containing the OCaml standard + library. (If "OCAMLLIB" is not set, "CAMLLIB" will be used instead.) + Used to locate the "ld.conf" configuration file for + dynamic loading (see section~\ref{s-ocamlrun-dllpath}). If not set, + default to the library directory specified when compiling OCaml. + +\item["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 separated + by commas. + A parameter specification is an option letter followed by an "=" + sign, a decimal number (or an hexadecimal number prefixed by "0x"), + and an optional multiplier. The options are documented below; + the last six correspond to the fields of the + "control" record documented in +\ifouthtml + \ahref{libref/Gc.html}{Module \texttt{Gc}}. +\else + section~\ref{Gc}. +\fi + \begin{options} + \item[b] (backtrace) Trigger the printing of a stack backtrace + when an uncaught exception aborts the program. + This option takes no argument. + \item[p] (parser trace) Turn on debugging support for + "ocamlyacc"-generated parsers. When this option is on, + the pushdown automaton that executes the parsers prints a + trace of its actions. This option takes no argument. + \item[R] (randomize) Turn on randomization of all hash tables by default + (see +\ifouthtml + \ahref{libref/Hashtbl.html}{Module \texttt{Hashtbl}}). +\else + section~\ref{Hashtbl}). +\fi + This option takes no argument. + \item[h] The initial size of the major heap (in words). + \item[a] ("allocation_policy") The policy used for allocating in the + OCaml heap. Possible values are 0 for the next-fit policy, and 1 + for the first-fit policy. Next-fit is usually faster, but first-fit + is better for avoiding fragmentation and the associated heap + compactions. + \item[s] ("minor_heap_size") Size of the minor heap. (in words) + \item[i] ("major_heap_increment") Default size increment for the + major heap. (in words) + \item[o] ("space_overhead") The major GC speed setting. + \item[O] ("max_overhead") The heap compaction trigger setting. + \item[l] ("stack_limit") The limit (in words) of the stack size. + \item[v] ("verbose") What GC messages to print to stderr. This + is a sum of values selected from the following: + \begin{options} + \item[1 (= 0x001)] Start of major GC cycle. + \item[2 (= 0x002)] Minor collection and major GC slice. + \item[4 (= 0x004)] Growing and shrinking of the heap. + \item[8 (= 0x008)] Resizing of stacks and memory manager tables. + \item[16 (= 0x010)] Heap compaction. + \item[32 (= 0x020)] Change of GC parameters. + \item[64 (= 0x040)] Computation of major GC slice size. + \item[128 (= 0x080)] Calling of finalization functions + \item[256 (= 0x100)] Startup messages (loading the bytecode + executable file, resolving shared libraries). + \item[512 (= 0x200)] Computation of compaction-triggering condition. + \item[1024 (= 0x400)] Output GC statistics at program exit. + \end{options} + \end{options} + The multiplier is "k", "M", or "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 +\begin{verbatim} + export OCAMLRUNPARAM='b,s=256k,v=0x015' +\end{verbatim} + tells a subsequent "ocamlrun" to print backtraces for uncaught exceptions, + set its initial minor heap size to 1~megabyte and + print a message at the start of each major GC cycle, when the heap + size changes, and when compaction is triggered. + +\item["CAMLRUNPARAM"] If "OCAMLRUNPARAM" is not found in the + environment, then "CAMLRUNPARAM" will be used instead. If + "CAMLRUNPARAM" is also not found, then the default values will be used. + +\item["PATH"] List of directories searched to find the bytecode +executable file. +\end{options} + +\section{Dynamic loading of shared libraries} \label{s-ocamlrun-dllpath} + +On platforms that support dynamic loading, "ocamlrun" can link +dynamically with C shared libraries (DLLs) providing additional C primitives +beyond those provided by the standard runtime system. The names for +these libraries are provided at link time as described in +section~\ref{dynlink-c-code}), and recorded in the bytecode executable +file; "ocamlrun", then, locates these libraries and resolves references +to their primitives when the bytecode executable program starts. + +The "ocamlrun" command searches shared libraries in the following +directories, in the order indicated: +\begin{enumerate} +\item Directories specified on the "ocamlrun" command line with the +"-I" option. +\item Directories specified in the "CAML_LD_LIBRARY_PATH" environment +variable. +\item Directories specified at link-time via the "-dllpath" option to +"ocamlc". (These directories are recorded in the bytecode executable +file.) +\item Directories specified in the file "ld.conf". This file resides +in the OCaml standard library directory, and lists directory +names (one per line) to be searched. Typically, it contains only one +line naming the "stublibs" subdirectory of the OCaml standard +library directory. Users can add there the names of other directories +containing frequently-used shared libraries; however, for consistency +of installation, we recommend that shared libraries are installed +directly in the system "stublibs" directory, rather than adding lines +to the "ld.conf" file. +\item Default directories searched by the system dynamic loader. +Under Unix, these generally include "/lib" and "/usr/lib", plus the +directories listed in the file "/etc/ld.so.conf" and the environment +variable "LD_LIBRARY_PATH". Under Windows, these include the Windows +system directories, plus the directories listed in the "PATH" +environment variable. +\end{enumerate} + +\section{Common errors} + +This section describes and explains the most frequently encountered +error messages. + +\begin{options} + +\item[{\it filename}": no such file or directory"] +If {\it filename} is the name of a self-executable bytecode file, this +means that either that file does not exist, or that it failed to run +the "ocamlrun" bytecode interpreter on itself. The second possibility +indicates that OCaml has not been properly installed on your +system. + +\item["Cannot exec ocamlrun"] +(When launching a self-executable bytecode file.) The "ocamlrun" + could not be found in the executable path. Check that OCaml + has been properly installed on your system. + +\item["Cannot find the bytecode file"] +The file that "ocamlrun" is trying to execute (e.g. the file given as +first non-option argument to "ocamlrun") either does not exist, or is +not a valid executable bytecode file. + +\item["Truncated bytecode file"] +The file that "ocamlrun" is trying to execute is not a valid executable +bytecode file. Probably it has been truncated or mangled since +created. Erase and rebuild it. + +\item["Uncaught exception"] +The program being executed contains a ``stray'' exception. That is, +it raises an exception at some point, and this exception is never +caught. This causes immediate termination of the program. The name of +the exception is printed, along with its string, byte sequence, and +integer arguments +(arguments of more complex types are not correctly printed). +To locate the context of the uncaught exception, compile the program +with the "-g" option and either run it again under the "ocamldebug" +debugger (see chapter~\ref{c:debugger}), or run it with "ocamlrun -b" +or with the "OCAMLRUNPARAM" environment variable set to "b=1". + +\item["Out of memory"] +The program being executed requires more memory than available. Either +the program builds excessively large data structures; or the program +contains too many nested function calls, and the stack overflows. In +some cases, your program is perfectly correct, it just requires more +memory than your machine provides. In other cases, the ``out of +memory'' message reveals an error in your program: non-terminating +recursive function, allocation of an excessively large array, +string or byte sequence, attempts to build an infinite list or other +data structure, \ldots + +To help you diagnose this error, run your program with the "-v" option +to "ocamlrun", or with the "OCAMLRUNPARAM" environment variable set to +"v=63". If it displays lots of ``"Growing stack"\ldots'' +messages, this is probably a looping recursive function. If it +displays lots of ``"Growing heap"\ldots'' messages, with the heap size +growing slowly, this is probably an attempt to construct a data +structure with too many (infinitely many?) cells. If it displays few +``"Growing heap"\ldots'' messages, but with a huge increment in the +heap size, this is probably an attempt to build an excessively large +array, string or byte sequence. + +\end{options} diff --git a/manual/manual/cmds/spacetime.etex b/manual/manual/cmds/spacetime.etex new file mode 100644 index 0000000000..7abc709520 --- /dev/null +++ b/manual/manual/cmds/spacetime.etex @@ -0,0 +1,126 @@ +\chapter{Memory profiling with Spacetime} +\pdfchapterfold{-9}{Memory profiling with Spacetime} +%HEVEA\cutname{spacetime.html} + +\section{Overview} + +Spacetime is the name given to functionality within the OCaml compiler that +provides for accurate profiling of the memory behaviour of a program. +Using Spacetime it is possible to determine the source of memory leaks +and excess memory allocation quickly and easily. Excess allocation slows +programs down both by imposing a higher load on the garbage collector and +reducing the cache locality of the program's code. Spacetime provides +full backtraces for every allocation that occurred on the OCaml heap +during the lifetime of the program including those in C stubs. + +Spacetime only analyses the memory behaviour of a program with respect to +the OCaml heap allocators and garbage collector. It does not analyse +allocation on the C heap. Spacetime does not affect the memory behaviour +of a program being profiled with the exception of any change caused by the +overhead of profiling (see section\ \ref{runtimeoverhead})---for example +the program running slower might cause it to allocate less memory in total. + +Spacetime is currently only available for x86-64 targets and has only been +tested on Linux systems (although it is expected to work on most modern +Unix-like systems and provision has been made for running under +Windows). It is expected that the set of supported platforms will +be extended in the future. + +\section{How to use it} + +\subsection{Building} + +To use Spacetime it is necessary to use an OCaml compiler that was +configured with the {\tt -spacetime} option. It is not possible to select +Spacetime on a per-source-file basis or for a subset of files in a project; +all files involved in the executable being profiled must be built with the +Spacetime compiler. Only native code compilation is supported (not +bytecode). + +If the {\tt libunwind} library is not available on the system then it will +not be possible for Spacetime to profile allocations occurring within +C stubs. If the {\tt libunwind} library is available but in an unusual +location then that location may be specified to the {\tt configure} script +using the {\tt -libunwinddir} option (or alternatively, using separate +{\tt -libunwindinclude} and {\tt -libunwindlib} options). + +OPAM switches will be provided for Spacetime-configured compilers. + +Once the appropriate compiler has been selected the program should be +built as normal (ensuring that all files are built with the Spacetime +compiler---there is currently no protection to ensure this is the case, but +it is essential). For many uses it will not be necessary to change the +code of the program to use the profiler. + +Spacetime-configured compilers run slower and occupy more memory than their +counterparts. It is hoped this will be fixed in the future as part of +improved cross compilation support. + +\subsection{Running} + +Programs built with Spacetime instrumentation have a dependency on +the {\tt libunwind} library unless that was unavailable at configure time or +the {\tt -disable-libunwind} option was specified +(see section\ \ref{runtimeoverhead}). + +Setting the {\tt OCAML\_SPACETIME\_INTERVAL} environment variable to an +integer representing a number of milliseconds before running a program built +with Spacetime will cause memory profiling to be in operation when the +program is started. The contents of the OCaml heap will be sampled each +time the number of milliseconds that the program has spent executing since the +last sample exceeds the given number. (Note that the time base is combined +user plus system time---{\em not} wall clock time. This peculiarity may be +changed in future.) + +The program being profiled must exit normally or be caused to exit using +the {\tt SIGINT} signal (e.g. by pressing Ctrl+C). When the program exits +files will be written in the directory that was the working directory when +the program was started. One Spacetime file will be written for each +process that was involved, indexed by process ID; there will normally only +be one such. The Spacetime files may be substantial. The directory to which +they are written may be overridden by setting +the {\tt OCAML\_SPACETIME\_SNAPSHOT\_DIR} environment variable before the +program is started. + +Instead of using the automatic snapshot facility described above it is also +possible to manually control Spacetime profiling. (The environment variables +{\tt OCAML\_SPACETIME\_INTERVAL} and {\tt OCAML\_SPACETIME\_SNAPSHOT\_DIR} +are then not relevant.) Full documentation as regards this method of profiling +is provided in the standard library documentation (section\ \ref{c:stdlib}) +for the {\tt Spacetime} module. + +\subsection{Analysis} + +The compiler distribution does not itself provide the facility for analysing +Spacetime output files; this is left to external tools. The first such tool +will appear in OPAM as a package called {\tt prof_spacetime}. That tool will +provide interactive graphical and terminal-based visualisation of +the results of profiling. + +\section{Runtime overhead}\label{runtimeoverhead} + +The runtime overhead imposed by Spacetime varies considerably depending on +the particular program being profiled. The overhead may be as low as +ten percent---but more usually programs should be expected to run at perhaps +a third or quarter of their normal speed. It is expected that this overhead +will be reduced in future versions of the compiler. + +Execution speed of instrumented programs may be increased by using a compiler +configured with the {\tt -disable-libunwind} option. This prevents collection +of profiling information from C stubs. + +Programs running with Spacetime instrumentation consume significantly more +memory than their non-instrumented counterparts. It is expected that this +memory overhead will also be reduced in the future. + +\section{For developers} + +The compiler distribution provides an ``{\tt otherlibs}'' library called +{\tt raw\_spacetime\_lib} for decoding Spacetime files. This library +provides facilities to read not only memory profiling information but also +the full dynamic call graph of the profiled program which is written into +Spacetime output files. + +A library package {\tt spacetime\_lib} will be provided in OPAM +to provide an interface for decoding profiling information at a higher +level than that provided by {\tt raw\_spacetime\_lib}. diff --git a/manual/manual/cmds/top.etex b/manual/manual/cmds/top.etex new file mode 100644 index 0000000000..3b6a018930 --- /dev/null +++ b/manual/manual/cmds/top.etex @@ -0,0 +1,565 @@ +\chapter{The toplevel system (ocaml)} \label{c:camllight} +\pdfchapter{The toplevel system (ocaml)} +%HEVEA\cutname{toplevel.html} + +This chapter describes the toplevel system for OCaml, that permits +interactive use of the OCaml system +through a read-eval-print loop. In this mode, the system repeatedly +reads OCaml phrases from the input, then typechecks, compile and +evaluate them, then prints the inferred type and result value, if +any. The system prints a "#" (sharp) prompt before reading each +phrase. + +Input to the toplevel can span several lines. It is terminated by @";;"@ (a +double-semicolon). The toplevel input consists in one or several +toplevel phrases, with the following syntax: + +\begin{syntax} +toplevel-input: + {{ definition }} ';;' + | expr ';;' + | '#' ident [ directive-argument ] ';;' +; +directive-argument: + string-literal + | integer-literal + | value-path + | 'true' || 'false' +\end{syntax} + +A phrase can consist of a definition, like those found in +implementations of compilation units or in @'struct' \ldots 'end'@ +module expressions. The definition can bind value names, type names, +an exception, a module name, or a module type name. The toplevel +system performs the bindings, then prints the types and values (if +any) for the names thus defined. + +A phrase may also consist in a value expression +(section~\ref{s:value-expr}). It is simply evaluated +without performing any bindings, and its value is +printed. + +Finally, a phrase can also consist in a toplevel directive, +starting with @"#"@ (the sharp sign). These directives control the +behavior of the toplevel; they are listed below in +section~\ref{s:toplevel-directives}. + +\begin{unix} +The toplevel system is started by the command "ocaml", as follows: +\begin{alltt} + ocaml \var{options} \var{objects} # interactive mode + ocaml \var{options} \var{objects} \var{scriptfile} # script mode +\end{alltt} +\var{options} are described below. +\var{objects} are filenames ending in ".cmo" or ".cma"; they are +loaded into the interpreter immediately after \var{options} are set. +\var{scriptfile} is any file name not ending in ".cmo" or ".cma". + +If no \var{scriptfile} is given on the command line, the toplevel system +enters interactive mode: phrases are read on standard input, results +are printed on standard output, errors on standard error. End-of-file +on standard input terminates "ocaml" (see also the "#quit" directive +in section~\ref{s:toplevel-directives}). + +On start-up (before the first phrase is read), if the file +".ocamlinit" exists in the current directory, +its contents are read as a sequence of OCaml phrases +and executed as per the "#use" directive +described in section~\ref{s:toplevel-directives}. +The evaluation outcode for each phrase are not displayed. +If the current directory does not contain an ".ocamlinit" file, but +the user's home directory (environment variable "HOME") does, the +latter is read and executed as described below. + +The toplevel system does not perform line editing, but it can +easily be used in conjunction with an external line editor such as +"ledit", "ocaml2" or "rlwrap" +\begin{latexonly} +(see the Caml Hump "http://caml.inria.fr/humps/index_framed_caml.html"). +\end{latexonly} +\begin{htmlonly} +(see the +\ahref{http://caml.inria.fr/humps/index\_framed\_caml.html}{Caml Hump}). +\end{htmlonly} +Another option is to use "ocaml" under Gnu Emacs, which gives the +full editing power of Emacs (command "run-caml" from library "inf-caml"). + +At any point, the parsing, compilation or evaluation of the current +phrase can be interrupted by pressing "ctrl-C" (or, more precisely, +by sending the "INTR" signal to the "ocaml" process). The toplevel +then immediately returns to the "#" prompt. + +If \var{scriptfile} is given on the command-line to "ocaml", the toplevel +system enters script mode: the contents of the file are read as a +sequence of OCaml phrases and executed, as per the "#use" +directive (section~\ref{s:toplevel-directives}). The outcome of the +evaluation is not printed. On reaching the end of file, the "ocaml" +command exits immediately. No commands are read from standard input. +"Sys.argv" is transformed, ignoring all OCaml parameters, and +starting with the script file name in "Sys.argv.(0)". + +In script mode, the first line of the script is ignored if it starts +with "#!". Thus, it should be possible to make the script +itself executable and put as first line "#!/usr/local/bin/ocaml", +thus calling the toplevel system automatically when the script is +run. However, "ocaml" itself is a "#!" script on most installations +of OCaml, and Unix kernels usually do not handle nested "#!" +scripts. A better solution is to put the following as the first line +of the script: +\begin{verbatim} + #!/usr/local/bin/ocamlrun /usr/local/bin/ocaml +\end{verbatim} + +\end{unix} + +\begin{windows} +In addition to the text-only command "ocaml.exe", which works exactly +as under Unix (see above), a graphical user interface for the +toplevel is available under the name "ocamlwin.exe". It should be +launched from the Windows file manager or program manager. +This interface provides a text window in which commands can be entered +and edited, and the toplevel responses are printed. +\end{windows} + +\section{Options} \label{s:toplevel-options} + +The following command-line options are recognized by the "ocaml" command. + +\begin{options} + +\item["-absname"] +Force error messages to show absolute paths for file names. + +\item["-I" \var{directory}] +Add the given directory to the list of directories searched for +source and compiled files. By default, the current directory is +searched first, then the standard library directory. Directories added +with "-I" are searched after the current directory, in the order in +which they were given on the command line, but before the standard +library directory. + +If the given directory starts with "+", it is taken relative to the +standard library directory. For instance, "-I +labltk" adds the +subdirectory "labltk" of the standard library to the search path. + +Directories can also be added to the list once +the toplevel is running with the "#directory" directive +(section~\ref{s:toplevel-directives}). + +\item["-init" \var{file}] +Load the given file instead of the default initialization file. +The default file is ".ocamlinit" in the current directory if it +exists, otherwise ".ocamlinit" in the user's home directory. + +\item["-labels"] +Labels are not ignored in types, labels may be used in applications, +and labelled parameters can be given in any order. This is the default. + +\item["-no-app-funct"] +Deactivates the applicative behaviour of functors. With this option, +each functor application generates new types in its result and +applying the same functor twice to the same argument yields two +incompatible structures. + +\item["-noassert"] +Do not compile assertion checks. Note that the special form +"assert false" is always compiled because it is typed specially. + +\item["-nolabels"] +Ignore non-optional labels in types. Labels cannot be used in +applications, and parameter order becomes strict. + +\item["-noprompt"] +Do not display any prompt when waiting for input. + +\item["-nopromptcont"] +Do not display the secondary prompt when waiting for continuation +lines in multi-line inputs. This should be used e.g. when running +"ocaml" in an "emacs" window. + +\item["-nostdlib"] +Do not include the standard library directory in the list of +directories searched for source and compiled files. + +\item["-ppx" \var{command}] +After parsing, pipe the abstract syntax tree through the preprocessor +\var{command}. The module "Ast_mapper", described in +chapter~\ref{Ast-underscoremapper}, implements the external interface +of a preprocessor. + +\item["-principal"] +Check information paths during type-checking, to make sure that all +types are derived in a principal way. When using labelled arguments +and/or polymorphic methods, this flag is required to ensure future +versions of the compiler will be able to infer types correctly, even +if internal algorithms change. +All programs accepted in "-principal" mode are also accepted in the +default mode with equivalent types, but different binary signatures, +and this may slow down type checking; yet it is a good idea to +use it once before publishing source code. + +\item["-rectypes"] +Allow arbitrary recursive types during type-checking. By default, +only recursive types where the recursion goes through an object type +are supported. + +\item["-safe-string"] +Enforce the separation between types "string" and "bytes", +thereby making strings read-only. This will become the default in +a future version of OCaml. + +\item["-short-paths"] +When a type is visible under several module-paths, use the shortest +one when printing the type's name in inferred interfaces and error and +warning messages. Identifier names starting with an underscore "_" or +containing double underscores "__" incur a penalty of $+10$ when computing +their length. + +\item["-stdin"] +Read the standard input as a script file rather than starting an +interactive session. + +\item["-strict-sequence"] +Force the left-hand part of each sequence to have type unit. + +\item["-strict-formats"] +Reject invalid formats that were accepted in legacy format +implementations. You should use this flag to detect and fix such +invalid formats, as they will be rejected by future OCaml versions. + +\item["-unsafe"] +See the corresponding option for "ocamlc", chapter~\ref{c:camlc}. +Turn bound checking off on array and string accesses (the "v.(i)" and +"s.[i]" constructs). Programs compiled with "-unsafe" are therefore +slightly faster, but unsafe: anything can happen if the program +accesses an array or string outside of its bounds. + +\item["-unsafe-string"] +Identify the types "string" and "bytes", +thereby making strings writable. For reasons of backward compatibility, +this is the default setting for the moment, but this will change in a future +version of OCaml. + +\item["-version"] +Print version string and exit. + +\item["-vnum"] +Print short version number and exit. + +\item["-no-version"] +Do not print the version banner at startup. + +\item["-w" \var{warning-list}] +Enable or disable warnings according to the argument \var{warning-list}. +See section~\ref{s:comp-options} for the syntax of the argument. + +\item["-warn-error" \var{warning-list}] +Mark as fatal the warnings enabled by the argument \var{warning-list}. +See section~\ref{s:comp-options} for the syntax of the argument. + +\item["-warn-help"] +Show the description of all available warning numbers. + +\item["-" \var{file}] +Use \var{file} as a script file name, even when it starts with a +hyphen (-). + +\item["-help" or "--help"] +Display a short usage summary and exit. +% +\end{options} + +\begin{unix} +The following environment variables are also consulted: +\begin{options} +\item["LC_CTYPE"] If set to "iso_8859_1", accented characters (from the +ISO Latin-1 character set) in string and character literals are +printed as is; otherwise, they are printed as decimal escape sequences +("\\"\var{ddd}). + +\item["TERM"] When printing error messages, the toplevel system +attempts to underline visually the location of the error. It +consults the "TERM" variable to determines the type of output terminal +and look up its capabilities in the terminal database. + +\item["HOME"] Directory where the ".ocamlinit" file is searched. +\end{options} +\end{unix} + +\section{Toplevel directives} +\label{s:toplevel-directives} + +The following directives control the toplevel behavior, load files in +memory, and trace program execution. + +{\bf Note:} all directives start with a "#" (sharp) symbol. This "#" +must be typed before the directive, and must not be confused with the +"#" prompt displayed by the interactive loop. For instance, +typing "#quit;;" will exit the toplevel loop, but typing "quit;;" +will result in an ``unbound value "quit"'' error. + +% +% Remark: this list of options should be kept synchronized with the documentation +% in toplevel/topdirs.ml. +% +\begin{options} +\item[General] + \begin{options} + \item["#help;;"] + Prints a list of all available directives, with corresponding argument type + if appropriate. + \item["#quit;;"] + Exit the toplevel loop and terminate the "ocaml" command. + \end{options} + +\item[Loading codes] + \begin{options} + + \item["#cd \""\var{dir-name}"\";;"] + Change the current working directory. + + \item["#directory \""\var{dir-name}"\";;"] + Add the given directory to the list of directories searched for + source and compiled files. + + \item["#remove_directory \""\var{dir-name}"\";;"] + Remove the given directory from the list of directories searched for + source and compiled files. Do nothing if the list does not contain + the given directory. + + \item["#load \""\var{file-name}"\";;"] + Load in memory a bytecode object file (".cmo" file) or library file + (".cma" file) produced by the batch compiler "ocamlc". + + \item["#load_rec \""\var{file-name}"\";;"] + Load in memory a bytecode object file (".cmo" file) or library file + (".cma" file) produced by the batch compiler "ocamlc". + When loading an object file that depends on other modules + which have not been loaded yet, the .cmo files for these modules + are searched and loaded as well, recursively. The loading order + is not specified. + + \item["#use \""\var{file-name}"\";;"] + Read, compile and execute source phrases from the given file. + This is textual inclusion: phrases are processed just as if + they were typed on standard input. The reading of the file stops at + the first error encountered. + + \item["#mod_use \""\var{file-name}"\";;"] + Similar to "#use" but also wrap the code into a top-level module of the + same name as capitalized file name without extensions, following + semantics of the compiler. + \end{options} + +\item[Environment queries] + \begin{options} + \item["#show_class "\var{class-path}";;"]\vspace{-4.7ex} + \item["#show_class_type "\var{class-path}";;"]\vspace{-4.7ex} + \item["#show_exception "\var{ident}";;"]\vspace{-4.7ex} + \item["#show_module "\var{module-path}";;"]\vspace{-4.7ex} + \item["#show_module_type "\var{modtype-path}";;"]\vspace{-4.7ex} + \item["#show_type "\var{typeconstr}";;"]\vspace{-4.7ex} + \item["#show_val "\var{value-path}";;"] + Print the signature of the corresponding component. + + \item["#show "\var{ident}";;"] + Print the signatures of components with name \var{ident} in all the + above categories. + \end{options} + +\item[Pretty-printing] + \begin{options} + + \item["#install_printer "\var{printer-name}";;"] + This directive registers the function named \var{printer-name} (a + value path) as a printer for values whose types match the argument + type of the function. That is, the toplevel loop will call + \var{printer-name} when it has such a value to print. + + The printing function \var{printer-name} should have type + @"Format.formatter" "->" @t@ "->" "unit"@, where @@t@@ is the + type for the values to be printed, and should output its textual + representation for the value of type @@t@@ on the given formatter, + using the functions provided by the "Format" library. For backward + compatibility, \var{printer-name} can also have type + @@t@ "->" "unit"@ and should then output on the standard + formatter, but this usage is deprecated. + + \item["#print_depth "\var{n}";;"] + Limit the printing of values to a maximal depth of \var{n}. + The parts of values whose depth exceeds \var{n} are printed as "..." + (ellipsis). + + \item["#print_length "\var{n}";;"] + Limit the number of value nodes printed to at most \var{n}. + Remaining parts of values are printed as "..." (ellipsis). + + \item["#remove_printer "\var{printer-name}";;"] + Remove the named function from the table of toplevel printers. +\end{options} + +\item[Tracing] + \begin{options} + \item["#trace "\var{function-name}";;"] + After executing this directive, all calls to the function named + \var{function-name} will be ``traced''. That is, the argument and the + result are displayed for each call, as well as the exceptions escaping + out of the function, raised either by the function itself or by + another function it calls. If the function is curried, each argument + is printed as it is passed to the function. + + \item["#untrace "\var{function-name}";;"] + Stop tracing the given function. + + \item["#untrace_all;;"] + Stop tracing all functions traced so far. + \end{options} + +\item[Compiler options] + \begin{options} + \item["#labels "\var{bool}";;"] + Ignore labels in function types if argument is "false", or switch back + to default behaviour (commuting style) if argument is "true". + + \item["#ppx \""\var{file-name}"\";;"] + After parsing, pipe the abstract syntax tree through the preprocessor + command. + + \item["#principal "\var{bool}";;"] + If the argument is "true", check information paths during + type-checking, to make sure that all types are derived in a principal + way. If the argument is "false", do not check information paths. + + \item["#rectypes;;"] + Allow arbitrary recursive types during type-checking. Note: once + enabled, this option cannot be disabled because that would lead to + unsoundness of the type system. + + \item["#warn_error \""\var{warning-list}"\";;"] + Treat as errors the warnings enabled by the argument and as normal + warnings the warnings disabled by the argument. + + \item["#warnings \""\var{warning-list}"\";;"] + Enable or disable warnings according to the argument. + + \end{options} + +\end{options} + +\section{The toplevel and the module system} \label{s:toplevel-modules} + +Toplevel phrases can refer to identifiers defined in compilation units +with the same mechanisms as for separately compiled units: either by +using qualified names ("Modulename.localname"), or by using +the "open" construct and unqualified names (see section~\ref{s:names}). + +However, before referencing another compilation unit, an +implementation of that unit must be present in memory. +At start-up, the toplevel system contains implementations for all the +modules in the the standard library. Implementations for user modules +can be entered with the "#load" directive described above. Referencing +a unit for which no implementation has been provided +results in the error "Reference to undefined global `...'". + +Note that entering "open "\var{Mod} merely accesses the compiled +interface (".cmi" file) for \var{Mod}, but does not load the +implementation of \var{Mod}, and does not cause any error if no +implementation of \var{Mod} has been loaded. The error +``reference to undefined global \var{Mod}'' will occur only when +executing a value or module definition that refers to \var{Mod}. + +\section{Common errors} + +This section describes and explains the most frequently encountered +error messages. + +\begin{options} + +\item[Cannot find file \var{filename}] +The named file could not be found in the current directory, nor in the +directories of the search path. + +If \var{filename} has the format \var{mod}".cmi", this +means you have referenced the compilation unit \var{mod}, but its +compiled interface could not be found. Fix: compile \var{mod}".mli" or +\var{mod}".ml" first, to create the compiled interface \var{mod}".cmi". + +If \var{filename} has the format \var{mod}".cmo", this +means you are trying to load with "#load" a bytecode object file that +does not exist yet. Fix: compile \var{mod}".ml" first. + +If your program spans several directories, this error can also appear +because you haven't specified the directories to look into. Fix: use +the "#directory" directive to add the correct directories to the +search path. + +\item[This expression has type \nth{t}{1}, but is used with type \nth{t}{2}] +See section~\ref{s:comp-errors}. + +\item[Reference to undefined global \var{mod}] +You have neglected to load in memory an implementation for a module +with "#load". See section~\ref{s:toplevel-modules} above. + +\end{options} + +\section{Building custom toplevel systems: \texttt{ocamlmktop}} + +The "ocamlmktop" command builds OCaml toplevels that +contain user code preloaded at start-up. + +The "ocamlmktop" command takes as argument a set of ".cmo" and ".cma" +files, and links them with the object files that implement the OCaml toplevel. +The typical use is: +\begin{verbatim} + ocamlmktop -o mytoplevel foo.cmo bar.cmo gee.cmo +\end{verbatim} +This creates the bytecode file "mytoplevel", containing the OCaml toplevel +system, plus the code from the three ".cmo" +files. This toplevel is directly executable and is started by: +\begin{verbatim} + ./mytoplevel +\end{verbatim} +This enters a regular toplevel loop, except that the code from +"foo.cmo", "bar.cmo" and "gee.cmo" is already loaded in memory, just as +if you had typed: +\begin{verbatim} + #load "foo.cmo";; + #load "bar.cmo";; + #load "gee.cmo";; +\end{verbatim} +on entrance to the toplevel. The modules "Foo", "Bar" and "Gee" are +not opened, though; you still have to do +\begin{verbatim} + open Foo;; +\end{verbatim} +yourself, if this is what you wish. + +\section{Options} + +The following command-line options are recognized by "ocamlmktop". + +\begin{options} + +\item["-cclib" \var{libname}] +Pass the "-l"\var{libname} option to the C linker when linking in +``custom runtime'' mode. See the corresponding option for +"ocamlc", in chapter~\ref{c:camlc}. + +\item["-ccopt" \var{option}] +Pass the given option to the C compiler and linker, when linking in +``custom runtime'' mode. See the corresponding option for +"ocamlc", in chapter~\ref{c:camlc}. + +\item["-custom"] +Link in ``custom runtime'' mode. See the corresponding option for +"ocamlc", in chapter~\ref{c:camlc}. + +\item["-I" \var{directory}] +Add the given directory to the list of directories searched for +compiled object code files (".cmo" and ".cma"). + +\item["-o" \var{exec-file}] +Specify the name of the toplevel file produced by the linker. +The default is "a.out". + +\end{options} diff --git a/manual/manual/foreword.etex b/manual/manual/foreword.etex new file mode 100644 index 0000000000..2529a86cb8 --- /dev/null +++ b/manual/manual/foreword.etex @@ -0,0 +1,81 @@ +\chapter*{Foreword} +\markboth{Foreword}{} +%HEVEA\cutname{foreword.html} + +This manual documents the release \ocamlversion\ of the OCaml +system. It is organized as follows. +\begin{itemize} +\item Part~\ref{p:tutorials}, ``An introduction to OCaml'', +gives an overview of the language. +\item Part~\ref{p:refman}, ``The OCaml language'', is the +reference description of the language. +\item Part~\ref{p:commands}, ``The OCaml tools'', documents +the compilers, toplevel system, and programming utilities. +\item Part~\ref{p:library}, ``The OCaml library'', describes the +modules provided in the standard library. +\begin{latexonly} +\item Part~\ref{p:appendix}, ``Appendix'', contains an +index of all identifiers defined in the standard library, and an +index of keywords. +\end{latexonly} +\end{itemize} + +\section*{Conventions} + +OCaml runs on several operating systems. The parts of +this manual that are specific to one operating system are presented as +shown below: + +\begin{unix} This is material specific to the Unix family of operating +systems, including Linux and \hbox{MacOS~X}. +\end{unix} + +\begin{windows} This is material specific to Microsoft Windows (2000, + XP, Vista, Seven). +\end{windows} + +\section*{License} + +The OCaml system is copyright \copyright\ 1996--\number\year\ +Institut National de Recherche en Informatique et en +Automatique (INRIA). +INRIA holds all ownership rights to the OCaml system. + +The OCaml system is open source and can be freely +redistributed. See the file "LICENSE" in the distribution for +licensing information. + +The present documentation is copyright \copyright\ \number\year\ +Institut National de Recherche en Informatique et en +Automatique (INRIA). The OCaml documentation and user's +manual may be reproduced and distributed in whole or +in part, subject to the following conditions: +\begin{itemize} +\item The copyright notice above and this permission notice must be +preserved complete on all complete or partial copies. +\item Any translation or derivative work of the OCaml +documentation and user's manual must be approved by the authors in +writing before distribution. +\item If you distribute the OCaml +documentation and user's manual in part, instructions for obtaining +the complete version of this manual must be included, and a +means for obtaining a complete version provided. +\item Small portions may be reproduced as illustrations for reviews or +quotes in other works without this permission notice if proper +citation is given. +\end{itemize} + +\section*{Availability} + +\begin{latexonly} +The complete OCaml distribution can be accessed via the Web +site \url{http://caml.inria.fr/}. This Web site contains a lot of +additional information on OCaml. +\end{latexonly} + +\begin{htmlonly} +The complete OCaml distribution can be accessed via the +\href{http://caml.inria.fr/}{Caml Web site}. +The \href{http://caml.inria.fr/}{Caml Web site} +contains a lot of additional information on OCaml. +\end{htmlonly} diff --git a/manual/manual/htmlman/.gitignore b/manual/manual/htmlman/.gitignore new file mode 100644 index 0000000000..3cecdc2c40 --- /dev/null +++ b/manual/manual/htmlman/.gitignore @@ -0,0 +1,8 @@ +*.html +*.haux +*.hind +libref +manual.hmanual +manual.hmanual.kwd +manual.css +*.htoc diff --git a/manual/manual/htmlman/contents_motif.gif b/manual/manual/htmlman/contents_motif.gif new file mode 100644 index 0000000000..5d3d016702 Binary files /dev/null and b/manual/manual/htmlman/contents_motif.gif differ diff --git a/manual/manual/htmlman/libgraph.gif b/manual/manual/htmlman/libgraph.gif new file mode 100644 index 0000000000..b385985b13 Binary files /dev/null and b/manual/manual/htmlman/libgraph.gif differ diff --git a/manual/manual/htmlman/next_motif.gif b/manual/manual/htmlman/next_motif.gif new file mode 100644 index 0000000000..3f84bacfb2 Binary files /dev/null and b/manual/manual/htmlman/next_motif.gif differ diff --git a/manual/manual/htmlman/previous_motif.gif b/manual/manual/htmlman/previous_motif.gif new file mode 100644 index 0000000000..8c8a3e6430 Binary files /dev/null and b/manual/manual/htmlman/previous_motif.gif differ diff --git a/manual/manual/index.tex b/manual/manual/index.tex new file mode 100644 index 0000000000..aff78b9fb4 --- /dev/null +++ b/manual/manual/index.tex @@ -0,0 +1,20 @@ +\ifouthtml +\begin{rawhtml} + +\end{rawhtml} +\else +\chapter*{Index to the library} +\markright{Index to the library} +\addcontentsline{toc}{chapter}{Index to the library} +\myprintindex{\jobname.ind} +\fi +\chapter*{Index of keywords} +\markright{Index of keywords} +\addcontentsline{toc}{chapter}{Index of keywords} +\myprintindex{\jobname.kwd.ind} diff --git a/manual/manual/infoman/.gitignore b/manual/manual/infoman/.gitignore new file mode 100644 index 0000000000..916af019f2 --- /dev/null +++ b/manual/manual/infoman/.gitignore @@ -0,0 +1,5 @@ +*.haux +*.hind +*.info*.gz +*.info.body* +ocaml.hocaml.kwd diff --git a/manual/manual/labltk.tex b/manual/manual/labltk.tex new file mode 100644 index 0000000000..944acb3daf --- /dev/null +++ b/manual/manual/labltk.tex @@ -0,0 +1,42 @@ +\documentclass[11pt]{book} +\usepackage[latin1]{inputenc} +%HEVEA\@def@charset{US-ASCII}% +\usepackage{alltt} +\usepackage{fullpage} +\usepackage{syntaxdef} +\usepackage{multind} +\usepackage{html} +\usepackage{textcomp} +\usepackage{caml-sl} +\usepackage{ocamldoc} +\usepackage{xspace} +\newif\ifplaintext +\plaintextfalse +%\newif\ifpdf +%\pdffalse +\input{macros.tex} + +\usepackage{hyperref} +%\makeatletter \def\@wrindex#1#2{\xdef \@indexfile{\csname #1@idxfile\endcsname}\@@wrindex#2||\\}\makeatother +\def\th{^{\hbox{\scriptsize th}}} + +\raggedbottom +\input{version.tex} + +\begin{document} +\thispagestyle{empty} +\begin{center} +~\vfill +\Huge The LablTk library + release 8.06.0 \\ + and \\ + The OCamlBrowser library explorer \\[1cm] +\large Jacques Garrigue, Jun Furuse \\ + \today \\ +\vfill +\end{center} +\setcounter{page}{1} + +\input{library/liblabltk.tex} +\input{cmds/browser.tex} +\end{document} diff --git a/manual/manual/library/.cvsignore b/manual/manual/library/.cvsignore new file mode 100644 index 0000000000..8955ee047a --- /dev/null +++ b/manual/manual/library/.cvsignore @@ -0,0 +1,5 @@ +*.tex +*.htex +arithstatus.mli +ocamldoc.out +ocamldoc.sty diff --git a/manual/manual/library/.gitignore b/manual/manual/library/.gitignore new file mode 100644 index 0000000000..8955ee047a --- /dev/null +++ b/manual/manual/library/.gitignore @@ -0,0 +1,5 @@ +*.tex +*.htex +arithstatus.mli +ocamldoc.out +ocamldoc.sty diff --git a/manual/manual/library/Makefile b/manual/manual/library/Makefile new file mode 100644 index 0000000000..4ac87d9e6f --- /dev/null +++ b/manual/manual/library/Makefile @@ -0,0 +1,104 @@ +CORE_INTF=Pervasives.tex + +STDLIB_INTF=Arg.tex Array.tex ArrayLabels.tex Char.tex Complex.tex \ + Digest.tex Filename.tex Format.tex \ + Gc.tex Genlex.tex Hashtbl.tex Int32.tex Int64.tex \ + Lazy.tex Lexing.tex List.tex ListLabels.tex Map.tex Marshal.tex \ + MoreLabels.tex Nativeint.tex Obj.tex Oo.tex \ + Parsing.tex Printexc.tex Printf.tex Queue.tex Random.tex Scanf.tex \ + Set.tex Sort.tex Stack.tex Stream.tex String.tex StringLabels.tex Sys.tex \ + Weak.tex Callback.tex Buffer.tex StdLabels.tex \ + Bytes.tex BytesLabels.tex Spacetime.tex + +COMPILER_LIBS_INTF=Asthelper.tex Astmapper.tex Asttypes.tex \ + Lexer.tex Location.tex Longident.tex Parse.tex Pprintast.tex Printast.tex + +OTHERLIB_INTF=Unix.tex UnixLabels.tex Str.tex \ + Num.tex Arithstatus.tex Bigint.tex \ + Graphics.tex GraphicsX11.tex \ + Thread.tex Mutex.tex Condition.tex Event.tex ThreadUnix.tex \ + Dynlink.tex Bigarray.tex + + +INTF=$(CORE_INTF) $(STDLIB_INTF) $(COMPILER_LIBS_INTF) $(OTHERLIB_INTF) + +MLIS=$(CSLDIR)/stdlib/*.mli \ + $(CSLDIR)/utils/*.mli \ + $(CSLDIR)/parsing/*.mli \ + $(CSLDIR)/otherlibs/bigarray/bigarray.mli \ + $(CSLDIR)/otherlibs/dynlink/dynlink.mli \ + $(CSLDIR)/otherlibs/graph/graphics.mli \ + $(CSLDIR)/otherlibs/graph/graphicsX11.mli \ + $(CSLDIR)/otherlibs/num/num.mli \ + $(CSLDIR)/otherlibs/num/arith_status.mli \ + $(CSLDIR)/otherlibs/num/big_int.mli \ + $(CSLDIR)/otherlibs/str/*.mli \ + $(CSLDIR)/otherlibs/systhreads/*.mli \ + $(CSLDIR)/otherlibs/unix/*.mli + +BLURB=core.tex builtin.tex stdlib.tex compilerlibs.tex \ + libunix.tex libstr.tex libnum.tex libgraph.tex \ + libthreads.tex libdynlink.tex libbigarray.tex + +FILES=$(BLURB) $(INTF) + +FORMAT=../../tools/format-intf +TEXQUOTE=../../tools/texquote2 + +CSLDIR=$(RELEASEDIR) + +VPATH=.:$(CSLDIR)/stdlib:$(CSLDIR)/parsing:$(CSLDIR)/otherlibs/unix:$(CSLDIR)/otherlibs/str:$(CSLDIR)/otherlibs/num:$(CSLDIR)/otherlibs/graph:$(CSLDIR)/otherlibs/threads:$(CSLDIR)/otherlibs/dynlink:$(CSLDIR)/otherlibs/bigarray + +all: libs + ./check-stdlib-modules $(CSLDIR) + +libs: $(FILES) + +$(INTF): $(MLIS) + $(CSLDIR)/byterun/ocamlrun $(CSLDIR)/ocamldoc/ocamldoc -latex \ + -I $(CSLDIR)/utils \ + -I $(CSLDIR)/stdlib \ + -I $(CSLDIR)/parsing \ + -I $(CSLDIR)/otherlibs/bigarray \ + -I $(CSLDIR)/otherlibs/dynlink \ + -I $(CSLDIR)/otherlibs/graph \ + -I $(CSLDIR)/otherlibs/num \ + -I $(CSLDIR)/otherlibs/str \ + -I $(CSLDIR)/otherlibs/systhreads \ + -I $(CSLDIR)/otherlibs/unix \ + $(MLIS) \ + -sepfiles \ + -latextitle "6,subsection*" \ + -latextitle "7,subsubsection*" \ + -latex-type-prefix "TYP" \ + -latex-module-prefix "" \ + -latex-module-type-prefix "" \ + -latex-value-prefix "" + mv -f Arith_status.tex Arithstatus.tex + mv -f Big_int.tex Bigint.tex + mv -f Ast_helper.tex Asthelper.tex + mv -f Ast_mapper.tex Astmapper.tex + +Tk.tex: tk.mli + $(CSLDIR)/byterun/ocamlrun $(CSLDIR)/ocamldoc/ocamldoc -latex \ + -I +labltk tk.mli \ + -sepfiles \ + -latextitle "6,subsection*" \ + -latextitle "7,subsubsection*" \ + -latex-type-prefix "TYP" \ + -latex-module-prefix "" \ + -latex-module-type-prefix "" \ + -latex-value-prefix "" + +clean: + rm -f $(FILES) + + +.SUFFIXES: +.SUFFIXES: .tex .etex .mli + +.etex.tex: $(TEXQUOTE) + $(TEXQUOTE) < $*.etex > $*.tex + +.mli.tex: $(FORMAT) + $(FORMAT) $< > $*.tex < $< diff --git a/manual/manual/library/builtin.etex b/manual/manual/library/builtin.etex new file mode 100644 index 0000000000..404f5608fb --- /dev/null +++ b/manual/manual/library/builtin.etex @@ -0,0 +1,281 @@ +\section{Built-in types and predefined exceptions} + +The following built-in types and predefined exceptions are always +defined in the +compilation environment, but are not part of any module. As a +consequence, they can only be referred by their short names. + +%\vspace{0.1cm} +\subsection*{Built-in types} +%\vspace{0.1cm} + +\begin{ocamldoccode} + type int +\end{ocamldoccode} +\index{int@\verb`int`} +\begin{ocamldocdescription} + The type of integer numbers. +\end{ocamldocdescription} + +\begin{ocamldoccode} + type char +\end{ocamldoccode} +\index{char@\verb`char`} +\begin{ocamldocdescription} + The type of characters. +\end{ocamldocdescription} + +\begin{ocamldoccode} + type bytes +\end{ocamldoccode} +\index{bytes@\verb`bytes`} +\begin{ocamldocdescription} + The type of (writable) byte sequences. +\end{ocamldocdescription} + +\begin{ocamldoccode} + type string +\end{ocamldoccode} +\index{string@\verb`string`} +\begin{ocamldocdescription} + The type of (read-only) character strings. +\end{ocamldocdescription} + +\begin{ocamldoccode} + type float +\end{ocamldoccode} +\index{float@\verb`float`} +\begin{ocamldocdescription} + The type of floating-point numbers. +\end{ocamldocdescription} + +\begin{ocamldoccode} + type bool = false | true +\end{ocamldoccode} +\index{bool@\verb`bool`} +\begin{ocamldocdescription} + The type of booleans (truth values). +\end{ocamldocdescription} + +\begin{ocamldoccode} + type unit = () +\end{ocamldoccode} +\index{unit@\verb`unit`} +\begin{ocamldocdescription} + The type of the unit value. +\end{ocamldocdescription} + +\begin{ocamldoccode} + type exn +\end{ocamldoccode} +\index{exn@\verb`exn`} +\begin{ocamldocdescription} + The type of exception values. +\end{ocamldocdescription} + +\begin{ocamldoccode} + type 'a array +\end{ocamldoccode} +\index{array@\verb`array`} +\begin{ocamldocdescription} + The type of arrays whose elements have type "'a". +\end{ocamldocdescription} + +\begin{ocamldoccode} + type 'a list = [] | :: of 'a * 'a list +\end{ocamldoccode} +\index{list@\verb`list`} +\begin{ocamldocdescription} + The type of lists whose elements have type "'a". +\end{ocamldocdescription} + +\begin{ocamldoccode} +type 'a option = None | Some of 'a +\end{ocamldoccode} +\index{option@\verb`option`} +\begin{ocamldocdescription} + The type of optional values of type "'a". +\end{ocamldocdescription} + +\begin{ocamldoccode} +type int32 +\end{ocamldoccode} +\index{int32@\verb`int32`} +\begin{ocamldocdescription} + The type of signed 32-bit integers. + See the "Int32"[\moduleref{Int32}] module. +\end{ocamldocdescription} + +\begin{ocamldoccode} +type int64 +\end{ocamldoccode} +\index{int64@\verb`int64`} +\begin{ocamldocdescription} + The type of signed 64-bit integers. + See the "Int64"[\moduleref{Int64}] module. +\end{ocamldocdescription} + +\begin{ocamldoccode} +type nativeint +\end{ocamldoccode} +\index{nativeint@\verb`nativeint`} +\begin{ocamldocdescription} + The type of signed, platform-native integers (32 bits on 32-bit + processors, 64 bits on 64-bit processors). + See the "Nativeint"[\moduleref{Nativeint}] module. +\end{ocamldocdescription} + +\begin{ocamldoccode} +type ('a, 'b, 'c, 'd, 'e, 'f) format6 +\end{ocamldoccode} +\index{format4@\verb`format4`} +\begin{ocamldocdescription} + The type of format strings. "'a" is the type of the parameters of + the format, "'f" is the result type for the "printf"-style + functions, "'b" is the type of the first argument given to "%a" and + "%t" printing functions (see module "Printf"[\moduleref{Printf}]), + "'c" is the result type of these functions, and also the type of the + argument transmitted to the first argument of "kprintf"-style + functions, "'d" is the result type for the "scanf"-style functions + (see module "Scanf"[\moduleref{Scanf}]), + and "'e" is the type of the receiver function for the "scanf"-style + functions. +\end{ocamldocdescription} + +\begin{ocamldoccode} +type 'a lazy_t +\end{ocamldoccode} +\index{lazyt@\verb`lazy_t`} +\begin{ocamldocdescription} + This type is used to implement the "Lazy"[\moduleref{Lazy}] module. + It should not be used directly. +\end{ocamldocdescription} + +%\vspace{0.1cm} +\subsection*{Predefined exceptions} +%\vspace{0.1cm} + +\begin{ocamldoccode} +exception Match_failure of (string * int * int) +\end{ocamldoccode} +\index{Matchfailure@\verb`Match_failure`} +\begin{ocamldocdescription} + Exception raised when none of the cases of a pattern-matching + apply. The arguments are the location of the "match" keyword + in the source code (file name, line number, column number). +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Assert_failure of (string * int * int) +\end{ocamldoccode} +\index{Assertfailure@\verb`Assert_failure`} +\begin{ocamldocdescription} + Exception raised when an assertion fails. The arguments are + the location of the "assert" keyword in the source code + (file name, line number, column number). +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Invalid_argument of string +\end{ocamldoccode} +\index{Invalidargument@\verb`Invalid_argument`} +\begin{ocamldocdescription} + Exception raised by library functions to signal that the given + arguments do not make sense. The string gives some information + to the programmer. As a general rule, this exception should not + be caught, it denotes a programming error and the code should be + modified not to trigger it. +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Failure of string +\end{ocamldoccode} +\index{Failure@\verb`Failure`} +\begin{ocamldocdescription} + Exception raised by library functions to signal that they are + undefined on the given arguments. The string is meant to give some + information to the programmer; you must \emph{not} pattern match on + the string literal because it may change in future versions (use + \verb`Failure _` instead). +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Not_found +\end{ocamldoccode} +\index{Notfound@\verb`Not_found`} +\begin{ocamldocdescription} + Exception raised by search functions when the desired object + could not be found. +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Out_of_memory +\end{ocamldoccode} +\index{Outofmemory@\verb`Out_of_memory`} +\begin{ocamldocdescription} + Exception raised by the garbage collector + when there is insufficient memory to complete the computation. +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Stack_overflow +\end{ocamldoccode} +\index{Stackoverflow@\verb`Stack_overflow`} +\begin{ocamldocdescription} + Exception raised by the bytecode interpreter when the evaluation + stack reaches its maximal size. This often indicates infinite + or excessively deep recursion in the user's program. + (Not fully implemented by the native-code compiler; + see section~\ref{s:compat-native-bytecode}.) +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Sys_error of string +\end{ocamldoccode} +\index{Syserror@\verb`Sys_error`} +\begin{ocamldocdescription} + Exception raised by the input/output functions to report an + operating system error. The string is meant to give some + information to the programmer; you must \emph{not} pattern match on + the string literal because it may change in future versions (use + \verb`Sys_error _` instead). +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception End_of_file +\end{ocamldoccode} +\index{Endoffile@\verb`End_of_file`} +\begin{ocamldocdescription} + Exception raised by input functions to signal that the + end of file has been reached. +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Division_by_zero +\end{ocamldoccode} +\index{Divisionbyzero@\verb`Division_by_zero`} +\begin{ocamldocdescription} + Exception raised by integer division and remainder operations + when their second argument is zero. +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Sys_blocked_io +\end{ocamldoccode} +\index{Sysblockedio@\verb`Sys_blocked_io`} +\begin{ocamldocdescription} + A special case of "Sys_error" raised when no I/O is possible + on a non-blocking I/O channel. +\end{ocamldocdescription} + +\begin{ocamldoccode} +exception Undefined_recursive_module of (string * int * int) +\end{ocamldoccode} +\index{Undefinedrecursivemodule@\verb`Undefined_recursive_module`} +\begin{ocamldocdescription} + Exception raised when an ill-founded recursive module definition + is evaluated. (See section~\ref{s-recursive-modules}.) + The arguments are the location of the definition in the source code + (file name, line number, column number). +\end{ocamldocdescription} + diff --git a/manual/manual/library/check-stdlib-modules b/manual/manual/library/check-stdlib-modules new file mode 100755 index 0000000000..4782ee4a15 --- /dev/null +++ b/manual/manual/library/check-stdlib-modules @@ -0,0 +1,23 @@ +#!/bin/sh + +TMPDIR="${TMPDIR:-/tmp}" + +(cd $1/stdlib; ls -1 *.mli) | sed -e 's/\.mli//' >$TMPDIR/stdlib-$$-files +cut -c 1 $TMPDIR/stdlib-$$-files | tr a-z A-Z >$TMPDIR/stdlib-$$-initials +cut -c 2- $TMPDIR/stdlib-$$-files \ +| paste -d '\0' $TMPDIR/stdlib-$$-initials - >$TMPDIR/stdlib-$$-modules + +exitcode=0 +for i in `cat $TMPDIR/stdlib-$$-modules`; do + case $i in + Camlinternal* | *Labels | Obj | Pervasives) continue;; + esac + grep -q -e '"'$i'" & p\.~\\pageref{'$i'} &' stdlib.etex || { + echo "Module $i is missing from stdlib.etex." >&2 + exitcode=2 + } +done + +rm -f $TMPDIR/stdlib-$$-* + +exit $exitcode diff --git a/manual/manual/library/compilerlibs.etex b/manual/manual/library/compilerlibs.etex new file mode 100644 index 0000000000..0666f18dbc --- /dev/null +++ b/manual/manual/library/compilerlibs.etex @@ -0,0 +1,58 @@ +\chapter{The compiler front-end} \label{c:parsinglib}\cutname{parsing.html} +\pdfchapterfold{-1}{The compiler front-end} + +This chapter describes the OCaml front-end, which declares the abstract +syntax tree used by the compiler, provides a way to parse, print +and pretty-print OCaml code, and ultimately allows to write abstract +syntax tree preprocessors invoked via the {\tt -ppx} flag (see chapters~\ref{c:camlc} +and~\ref{c:nativecomp}). + +It is important to note that the exported front-end interface follows the evolution of the OCaml language and implementation, and thus does not provide {\bf any} backwards compatibility guarantees. + +The front-end is a part of "compiler-libs" library. +Programs that use the "compiler-libs" library should be built as follows: +\begin{alltt} + ocamlfind ocamlc \var{other options} -package compiler-libs.common \var{other files} + ocamlfind ocamlopt \var{other options} -package compiler-libs.common \var{other files} +\end{alltt} +Use of the {\tt ocamlfind} utility is recommended. However, if this is not possible, an alternative method may be used: +\begin{alltt} + ocamlc \var{other options} -I +compiler-libs ocamlcommon.cma \var{other files} + ocamlopt \var{other options} -I +compiler-libs ocamlcommon.cmxa \var{other files} +\end{alltt} +For interactive use of the "compiler-libs" library, start "ocaml" and +type\\*"#load \"compiler-libs/ocamlcommon.cma\";;". + +% Some of the files below are commented out as the documentation is too poor +% or they are thought to be nonessential. + +\ifouthtml +\begin{links} +\item \ahref{libref/Ast\_helper.html}{Module \texttt{Ast_helper}: helper functions for AST construction} +\item \ahref{libref/Ast\_mapper.html}{Module \texttt{Ast_mapper}: -ppx rewriter interface} +\item \ahref{libref/Asttypes.html}{Module \texttt{Asttypes}: auxiliary types used by Parsetree} +% \item \ahref{libref/Lexer.html}{Module \texttt{Lexer}: OCaml syntax lexing} +\item \ahref{libref/Location.html}{Module \texttt{Location}: source code locations} +\item \ahref{libref/Longident.html}{Module \texttt{Longident}: long identifiers} +\item \ahref{libref/Parse.html}{Module \texttt{Parse}: OCaml syntax parsing} +\item \ahref{libref/Parsetree.html}{Module \texttt{Parsetree}: OCaml syntax tree} +\item \ahref{libref/Pprintast.html}{Module \texttt{Pprintast}: OCaml syntax printing} +% \item \ahref{libref/Printast.html}{Module \texttt{Printast}: AST printing} +\end{links} + +\else +% Ast_helper is excluded from the PDF and text manuals. +% It is over 20 pages long and does not have doc-comments. It is expected +% that Ast_helper will be only useful in the HTML manual (to look up signatures). +% \input{Asthelper.tex} +\input{Astmapper.tex} +\input{Asttypes.tex} +% \input{Lexer.tex} +\input{Location.tex} +\input{Longident.tex} +\input{Parse.tex} +\input{Parsetree.tex} +\input{Pprintast.tex} +% \input{Printast.tex} +\fi + diff --git a/manual/manual/library/core.etex b/manual/manual/library/core.etex new file mode 100644 index 0000000000..58297eab85 --- /dev/null +++ b/manual/manual/library/core.etex @@ -0,0 +1,36 @@ +\chapter{The core library} \label{c:corelib}\cutname{core.html} +\pdfchapterfold{-1}{The core library} + +This chapter describes the OCaml core library, which is + composed of declarations for built-in types and exceptions, plus +the module "Pervasives" that provides basic operations on these + built-in types. The "Pervasives" module is special in two +ways: +\begin{itemize} +\item It is automatically linked with the user's object code files by +the "ocamlc" command (chapter~\ref{c:camlc}). + +\item It is automatically ``opened'' when a compilation starts, or +when the toplevel system is launched. Hence, it is possible to use +unqualified identifiers to refer to the functions provided by the +"Pervasives" module, without adding a "open Pervasives" directive. +\end{itemize} + +\section*{Conventions} + +The declarations of the built-in types and the components of module +"Pervasives" are printed one by one in typewriter font, followed by a +short comment. All library modules and the components they provide are +indexed at the end of this report. + +\input{builtin.tex} + +\ifouthtml +\section{Module {\tt Pervasives}: the initially opened module} +\begin{links} +\item \ahref{libref/Pervasives.html}{Module \texttt{Pervasives}: the initially opened module} +\end{links} +\else +\input{Pervasives.tex} +\fi + diff --git a/manual/manual/library/libbigarray.etex b/manual/manual/library/libbigarray.etex new file mode 100644 index 0000000000..b0a0568765 --- /dev/null +++ b/manual/manual/library/libbigarray.etex @@ -0,0 +1,168 @@ +\chapter{The bigarray library} +\pdfchapterfold{-1}{The bigarray library} +%HEVEA\cutname{libbigarray.html} + +The "bigarray" library implements large, multi-dimensional, numerical +arrays. These arrays are called ``big arrays'' to distinguish them +from the standard OCaml arrays described in +\ifouthtml +\ahref{libref/Array.html}{Module \texttt{Array}}. +\else +section~\ref{Array}. +\fi +The main differences between ``big arrays'' and standard OCaml arrays +are as follows: +\begin{itemize} +\item Big arrays are not limited in size, unlike OCaml arrays +("float array" are limited to 2097151 elements on a 32-bit platform, +other "array" types to 4194303 elements). +\item Big arrays are multi-dimensional. Any number of dimensions +between 1 and 16 is supported. In contrast, OCaml arrays are +mono-dimensional and require encoding multi-dimensional arrays as +arrays of arrays. +\item Big arrays can only contain integers and floating-point +numbers, while OCaml arrays can contain arbitrary OCaml data types. +However, big arrays provide more space-efficient storage of integer +and floating-point elements, in particular because they support +``small'' types such as single-precision floats and 8 and 16-bit +integers, in addition to the standard OCaml types of double-precision +floats and 32 and 64-bit integers. +\item The memory layout of big arrays is entirely compatible with that +of arrays in C and Fortran, allowing large arrays to be passed back +and forth between OCaml code and C / Fortran code with no data copying +at all. +\item Big arrays support interesting high-level operations that normal +arrays do not provide efficiently, such as extracting sub-arrays and +``slicing'' a multi-dimensional array along certain dimensions, all +without any copying. +\end{itemize} +% +Programs that use the "bigarray" library must be linked as follows: +\begin{alltt} + ocamlc \var{other options} bigarray.cma \var{other files} + ocamlopt \var{other options} bigarray.cmxa \var{other files} +\end{alltt} +For interactive use of the "bigarray" library, do: +\begin{alltt} + ocamlmktop -o mytop bigarray.cma + ./mytop +\end{alltt} +or (if dynamic linking of C libraries is supported on your platform), +start "ocaml" and type "#load \"bigarray.cma\";;". + +\ifouthtml +\section{Module {\tt Bigarray}: large, multi-dimensional, numerical arrays} +\begin{links} +\item \ahref{libref/Bigarray.html}{Module \texttt{Bigarray}} +\end{links} + +\else +\input{Bigarray.tex} +\fi + +\section{Big arrays in the OCaml-C interface} + +C stub code that interface C or Fortran code with OCaml code, as +described in chapter~\ref{c:intf-c}, can exploit big arrays as +follows. + +\subsection{Include file} + +The include file "" must be included in the C stub +file. It declares the functions, constants and macros discussed +below. + +\subsection{Accessing an OCaml bigarray from C or Fortran} + +If \var{v} is a OCaml "value" representing a big array, the expression +"Caml_ba_data_val("\var{v}")" returns a pointer to the data part of the array. +This pointer is of type "void *" and can be cast to the appropriate C +type for the array (e.g. "double []", "char [][10]", etc). + +Various characteristics of the OCaml big array can be consulted from C +as follows: +\begin{tableau}{|l|l|}{C expression}{Returns} +\entree{"Caml_ba_array_val("\var{v}")->num_dims"}{number of dimensions} +\entree{"Caml_ba_array_val("\var{v}")->dim["\var{i}"]"}{\var{i}-th dimension} +\entree{"Caml_ba_array_val("\var{v}")->flags & BIGARRAY_KIND_MASK"}{kind of array elements} +\end{tableau} +The kind of array elements is one of the following constants: +\begin{tableau}{|l|l|}{Constant}{Element kind} +\entree{"CAML_BA_FLOAT32"}{32-bit single-precision floats} +\entree{"CAML_BA_FLOAT64"}{64-bit double-precision floats} +\entree{"CAML_BA_SINT8"}{8-bit signed integers} +\entree{"CAML_BA_UINT8"}{8-bit unsigned integers} +\entree{"CAML_BA_SINT16"}{16-bit signed integers} +\entree{"CAML_BA_UINT16"}{16-bit unsigned integers} +\entree{"CAML_BA_INT32"}{32-bit signed integers} +\entree{"CAML_BA_INT64"}{64-bit signed integers} +\entree{"CAML_BA_CAML_INT"}{31- or 63-bit signed integers} +\entree{"CAML_BA_NATIVE_INT"}{32- or 64-bit (platform-native) integers} +\end{tableau} +% +The following example shows the passing of a two-dimensional big array +to a C function and a Fortran function. +\begin{verbatim} + extern void my_c_function(double * data, int dimx, int dimy); + extern void my_fortran_function_(double * data, int * dimx, int * dimy); + + value caml_stub(value bigarray) + { + int dimx = Caml_ba_array_val(bigarray)->dim[0]; + int dimy = Caml_ba_array_val(bigarray)->dim[1]; + /* C passes scalar parameters by value */ + my_c_function(Caml_ba_data_val(bigarray), dimx, dimy); + /* Fortran passes all parameters by reference */ + my_fortran_function_(Caml_ba_data_val(bigarray), &dimx, &dimy); + return Val_unit; + } +\end{verbatim} + +\subsection{Wrapping a C or Fortran array as an OCaml big array} + +A pointer \var{p} to an already-allocated C or Fortran array can be +wrapped and returned to OCaml as a big array using the "caml_ba_alloc" +or "caml_ba_alloc_dims" functions. +\begin{itemize} +\item +"caml_ba_alloc("\var{kind} "|" \var{layout}, \var{numdims}, \var{p}, \var{dims}")" + +Return an OCaml big array wrapping the data pointed to by \var{p}. +\var{kind} is the kind of array elements (one of the "CAML_BA_" +kind constants above). \var{layout} is "CAML_BA_C_LAYOUT" for an +array with C layout and "CAML_BA_FORTRAN_LAYOUT" for an array with +Fortran layout. \var{numdims} is the number of dimensions in the +array. \var{dims} is an array of \var{numdims} long integers, giving +the sizes of the array in each dimension. + +\item +"caml_ba_alloc_dims("\var{kind} "|" \var{layout}, \var{numdims}, +\var{p}, "(long) "\nth{dim}{1}, "(long) "\nth{dim}{2}, \ldots, "(long) "\nth{dim}{numdims}")" + +Same as "caml_ba_alloc", but the sizes of the array in each dimension +are listed as extra arguments in the function call, rather than being +passed as an array. +\end{itemize} +% +The following example illustrates how statically-allocated C and +Fortran arrays can be made available to OCaml. +\begin{verbatim} + extern long my_c_array[100][200]; + extern float my_fortran_array_[300][400]; + + value caml_get_c_array(value unit) + { + long dims[2]; + dims[0] = 100; dims[1] = 200; + return caml_ba_alloc(CAML_BA_NATIVE_INT | CAML_BA_C_LAYOUT, + 2, my_c_array, dims); + } + + value caml_get_fortran_array(value unit) + { + return caml_ba_alloc_dims(CAML_BA_FLOAT32 | CAML_BA_FORTRAN_LAYOUT, + 2, my_fortran_array_, 300L, 400L); + } +\end{verbatim} + + diff --git a/manual/manual/library/libdynlink.etex b/manual/manual/library/libdynlink.etex new file mode 100644 index 0000000000..2d4d92d908 --- /dev/null +++ b/manual/manual/library/libdynlink.etex @@ -0,0 +1,29 @@ +\chapter{The dynlink library: dynamic loading and linking of object files} +\pdfchapterfold{-1}{The dynlink library: dynamic loading and linking of object files} +%HEVEA\cutname{libdynlink.html} + +The "dynlink" library supports type-safe dynamic loading and linking +of bytecode object files (".cmo" and ".cma" files) in a running +bytecode program, or of native plugins (usually ".cmxs" files) in a +running native program. Type safety is ensured by limiting the set of +modules from the running program that the loaded object file can +access, and checking that the running program and the loaded object +file have been compiled against the same interfaces for these modules. +In native code, there are also some compatibility checks on the +implementations (to avoid errors with cross-module optimizations); it +might be useful to hide ".cmx" files when building native plugins so +that they remain independent of the implementation of modules in the +main program. + +Programs that use the "dynlink" library simply need to link +"dynlink.cma" or "dynlink.cmxa" with their object files and other libraries. + +\ifouthtml +\begin{links} +\item \ahref{libref/Dynlink.html}{Module \texttt{Dynlink}: dynamic loading of bytecode object files} +\end{links} + +\else +\input{Dynlink.tex} +\fi + diff --git a/manual/manual/library/libgraph.etex b/manual/manual/library/libgraph.etex new file mode 100644 index 0000000000..28759f5ba1 --- /dev/null +++ b/manual/manual/library/libgraph.etex @@ -0,0 +1,100 @@ +\chapter{The graphics library} +\pdfchapterfold{-1}{The graphics library} +%HEVEA\cutname{libgraph.html} + +The "graphics" library provides a set of portable drawing primitives. +Drawing takes place +in a separate window that is created when "Graphics.open_graph" is called. + +\begin{unix} +This library is implemented under the X11 windows system. +Programs that use the "graphics" library must be linked as follows: +\begin{alltt} + ocamlc \var{other options} graphics.cma \var{other files} +\end{alltt} +For interactive use of the "graphics" library, do: +\begin{alltt} + ocamlmktop -o mytop graphics.cma + ./mytop +\end{alltt} +or (if dynamic linking of C libraries is supported on your platform), +start "ocaml" and type "#load \"graphics.cma\";;". + +Here are the graphics mode specifications supported by +"Graphics.open_graph" on +the X11 implementation of this library: +the argument to "Graphics.open_graph" has the format +"\""{\it display-name} {\it geometry\/}"\"", +where {\it display-name} is the name of the X-windows display to +connect to, and {\it geometry} is a standard X-windows geometry +specification. The two components are separated by a space. Either can +be omitted, or both. Examples: +\begin{options} +\item["Graphics.open_graph \"foo:0\""] +connects to the display "foo:0" and creates a window with the default geometry +\item["Graphics.open_graph \"foo:0 300x100+50-0\""] +connects to the display "foo:0" and creates a window 300 pixels wide +by 100 pixels tall, at location $(50,0)$ +\item["Graphics.open_graph \" 300x100+50-0\""] +connects to the default display and creates a window 300 pixels wide +by 100 pixels tall, at location $(50,0)$ +\item["Graphics.open_graph \"\""] +connects to the default display and creates a window with the default +geometry. +\end{options} +\end{unix} + +\begin{windows} +This library is available both for standalone compiled programs and +under the toplevel application "ocamlwin.exe". For the latter, this +library must be loaded in-core by typing +\begin{verbatim} + #load "graphics.cma";; +\end{verbatim} +\end{windows} + +The screen coordinates are interpreted as shown in the figure below. +Notice that the coordinate system used is the same as in mathematics: +$y$ increases from the bottom of the screen to the top of the screen, +and angles are measured counterclockwise (in degrees). +Drawing is clipped to the screen. +% +\begin{latexonly} +\begin{center} +\setlength{\unitlength}{0.5mm} +\begin{picture}(130,100)(-10,-10) +\thicklines +\put(-10,0){\vector(1,0){130}} +\put(125,0){\makebox(0,0)[l]{$x$}} +\put(0,-10){\vector(0,1){100}} +\put(0,95){\makebox(0,0){$y$}} +\thinlines +\put(100,80){\line(-1,0){105}} +\put(100,80){\line(0,-1){85}} +\put(95,75){\makebox(0,0)[tr]{Screen}} +\put(100,-10){\makebox(0,0){\tt size\_x()}} +\put(-10,80){\makebox(0,0)[r]{\tt size\_y()}} +\put(30,40){\makebox(4,4){\rule{2mm}{2mm}}} +\put(36,40){pixel at $(x,y)$} +\put(30,40){\line(-1,0){35}} +\put(30,-10){\makebox(0,0){$x$}} +\put(30,40){\line(0,-1){45}} +\put(-10,40){\makebox(0,0)[r]{$y$}} +\end{picture} +\end{center} +\end{latexonly} + +\begin{htmlonly} +\begin{center} +\imgsrc{libgraph.gif} +\end{center} +\end{htmlonly} +% + +\ifouthtml +\begin{links} +\item \ahref{libref/Graphics.html}{Module \texttt{Graphics}: machine-independent graphics primitives} +\end{links} +\else +\input{Graphics.tex} +\fi diff --git a/manual/manual/library/libgraph.fig b/manual/manual/library/libgraph.fig new file mode 100644 index 0000000000..55a6d1de33 --- /dev/null +++ b/manual/manual/library/libgraph.fig @@ -0,0 +1,29 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +2 1 0 1 0 7 0 0 -1 0.000 0 0 7 1 0 2 + 1 1 1.00 60.00 120.00 + 1050 3375 4575 3375 +2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 1200 3525 1200 825 +2 1 0 1 0 7 0 0 -1 0.000 0 0 7 0 0 3 + 1125 1200 3750 1200 3750 3450 +2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 3 + 1125 2400 2475 2400 2475 3450 +2 2 0 1 0 0 0 0 20 0.000 0 0 7 0 0 5 + 2475 2400 2550 2400 2550 2325 2475 2325 2475 2400 +4 0 0 0 0 0 12 0.0000 4 135 525 2325 1500 Screen\001 +4 0 0 0 0 0 12 0.0000 4 180 990 2175 2250 point at (x,y)\001 +4 0 0 0 0 0 12 0.0000 4 90 90 2400 3600 x\001 +4 0 0 0 0 0 12 0.0000 4 135 90 975 2475 y\001 +4 0 0 0 0 0 12 0.0000 4 180 450 1050 750 y axis\001 +4 0 0 0 0 14 12 0.0000 4 180 840 225 1200 size_y()\001 +4 0 0 0 0 14 12 0.0000 4 165 840 3375 3600 size_x()\001 +4 0 0 0 0 0 12 0.0000 4 135 450 4650 3375 x axis\001 diff --git a/manual/manual/library/libgraph.png b/manual/manual/library/libgraph.png new file mode 100644 index 0000000000..5841bfc805 Binary files /dev/null and b/manual/manual/library/libgraph.png differ diff --git a/manual/manual/library/liblabltk.etex b/manual/manual/library/liblabltk.etex new file mode 100644 index 0000000000..dcfaa6e8be --- /dev/null +++ b/manual/manual/library/liblabltk.etex @@ -0,0 +1,96 @@ +\chapter{The LablTk library: Tcl/Tk GUI interface} +\pdfchapterfold{-1}{The LablTk library: Tcl/Tk GUI interface} +%HEVEA\cutname{liblabltk.html} + +The "labltk" library provides access to the Tcl/Tk GUI from +OCaml programs. This interface is generated in an automated way, and +you should refer to Tcl/Tk books and man pages for detailed +information on the behavior of the numerous functions. We also suggest +to use "ocamlbrowser" to see the types of the various functions, that +are the best documentation for the library itself. + +\smallskip\noindent +Programs that use the "labltk" library must be linked as follows: +\begin{alltt} + ocamlc \var{other options} -I +labltk labltk.cma \var{other files} + ocamlopt \var{other options} -I +labltk labltk.cmxa \var{other files} +\end{alltt} + +\begin{unix} +The "labltk" library is available for any system with Tcl/Tk installed, +starting from Tcl/Tk 8.0 up to Tcl/Tk 8.6. Beware that some beta +versions may have compatibility problems. + +If the library was not compiled correctly, try to run again the +"configure" script with the option "-tkdefs" \var{switches}, +where \var{switches} is a list of C-style inclusion paths leading to +the right "tcl.h" and "tk.h", for instance +"\"-I/usr/local/include/tcl8.4 -I/usr/local/include/tk8.4\"". + +A script is installed, to make easier the use of the "labltk" +library as toplevel. +\begin{options} +\item["labltk"] +This is a toplevel including the "labltk" library, and the path is +already set as to allow the use of the various modules. It also +includes code for the Unix and Str libraries. You can use it +in place of "ocaml". +\end{options} +\end{unix} + +\begin{windows} +The "labltk" library has been precompiled for use with Tcl/Tk 8.5. +You must first have it installed on your system. +It can be downloaded from \\ +"http://www.activestate.com/products/ActiveTcl/". +After installing it, you must put the dynamically loaded libraries +"tcl85.dll" and "tk85.dll" (from the "bin" directory of the Tcl +installation) in a directory included in you path. + +No toplevel is available, but you can load the library from the +standard toplevel with the following commands. +\begin{quote} +\begin{verbatim} +# #directory "+labltk";; +# #load "labltk.cma";; +\end{verbatim} +\end{quote} +You can also load it directly from the command line. +\begin{quote} +\begin{verbatim} +C:\ocaml\bin> ocaml -I +labltk labltk.cma +\end{verbatim} +\end{quote} +\end{windows} + +The "labltk" library is composed of a large number of modules. +\begin{quote} +\begin{verbatim} +Bell Imagebitmap Place +Button Imagephoto Radiobutton +Canvas Label Scale +Checkbutton Listbox Scrollbar +Clipboard Menu Selection +Dialog Menubutton Text +Entry Message Tk +Focus Option Tkwait +Frame Optionmenu Toplevel +Grab Pack Winfo +Grid Palette Wm +\end{verbatim} +\end{quote} + +Giving a detailed account of each of these module would be impractical +here. We will just present some of the basic functions in the module +"Tk". Note that for most other modules information can be found in the +Tcl "man" page of their name. + +\ifouthtml +\begin{links} +\item \ahref{libref/Tk.html}{The \texttt{Tk} library: Basic functions and types for LablTk} +\end{links} + +\else +\input{Tk.tex} +\fi + diff --git a/manual/manual/library/libnum.etex b/manual/manual/library/libnum.etex new file mode 100644 index 0000000000..6c66f46031 --- /dev/null +++ b/manual/manual/library/libnum.etex @@ -0,0 +1,39 @@ +\chapter{The num library: arbitrary-precision rational arithmetic} +\pdfchapterfold{-3}{The num library: arbitrary-precision integer and rational arithmetic} +%HEVEA\cutname{libnum.html} + +The "num" library implements integer arithmetic and rational +arithmetic in arbitrary precision. + +More documentation on the functions provided in this library can be found +in {\em The CAML Numbers Reference Manual\/} by +Val�rie M�nissier-Morain, technical report 141, INRIA, july 1992 +(available electronically, +\url{http://hal.inria.fr/docs/00/07/00/27/PDF/RT-0141.pdf}). + +Programs that use the "num" library must be linked as follows: +\begin{alltt} + ocamlc \var{other options} nums.cma \var{other files} + ocamlopt \var{other options} nums.cmxa \var{other files} +\end{alltt} +For interactive use of the "nums" library, do: +\begin{alltt} + ocamlmktop -o mytop nums.cma + ./mytop +\end{alltt} +or (if dynamic linking of C libraries is supported on your platform), +start "ocaml" and type "#load \"nums.cma\";;". + +\ifouthtml +\begin{links} +\item \ahref{libref/Num.html}{Module \texttt{Num}: operation on arbitrary-precision numbers} +\item \ahref{libref/Big\_int.html}{Module \texttt{Big\_int}: operations on arbitrary-precision integers} +\item \ahref{libref/Arith\_status.html}{Module \texttt{Arith\_status}: flags that control rational arithmetic} +\end{links} +\else +\input{Num.tex} +\input{Bigint.tex} +\input{Arithstatus.tex} +\fi + + diff --git a/manual/manual/library/libstr.etex b/manual/manual/library/libstr.etex new file mode 100644 index 0000000000..a1939f8a31 --- /dev/null +++ b/manual/manual/library/libstr.etex @@ -0,0 +1,32 @@ +\chapter{The str library: regular expressions and string processing} +\pdfchapterfold{-1}{The str library: regular expressions and string processing} +%HEVEA\cutname{libstr.html} + +The "str" library provides high-level string processing functions, +some based on regular expressions. It is intended to support the kind +of file processing that is usually performed with scripting languages +such as "awk", "perl" or "sed". + +Programs that use the "str" library must be linked as follows: +\begin{alltt} + ocamlc \var{other options} str.cma \var{other files} + ocamlopt \var{other options} str.cmxa \var{other files} +\end{alltt} +For interactive use of the "str" library, do: +\begin{alltt} + ocamlmktop -o mytop str.cma + ./mytop +\end{alltt} +or (if dynamic linking of C libraries is supported on your platform), +start "ocaml" and type "#load \"str.cma\";;". + +\ifouthtml +\begin{links} +\item \ahref{libref/Str.html}{Module \texttt{Str}: regular expressions and string processing} +\end{links} + +\else +\input{Str.tex} +\fi + + diff --git a/manual/manual/library/libthreads.etex b/manual/manual/library/libthreads.etex new file mode 100644 index 0000000000..af23291d02 --- /dev/null +++ b/manual/manual/library/libthreads.etex @@ -0,0 +1,60 @@ +\chapter{The threads library} +\label{c:threads}\cutname{threads.html} +\pdfchapterfold{-5}{The threads library} +%HEVEA\cutname{libthreads.html} + +The "threads" library allows concurrent programming in OCaml. +It provides multiple threads of control (also called lightweight +processes) that execute concurrently in the same memory space. Threads +communicate by in-place modification of shared data structures, or by +sending and receiving data on communication channels. + +The "threads" library is implemented by time-sharing on a single +processor. It will not take advantage of multi-processor machines. +Using this library will therefore never make programs run +faster. However, many programs are easier to write when structured as +several communicating processes. + +Two implementations of the "threads" library are available, depending +on the capabilities of the operating system: +\begin{itemize} +\item System threads. This implementation builds on the OS-provided threads +facilities: POSIX 1003.1c threads for Unix, and Win32 threads for +Windows. When available, system threads support both bytecode and +native-code programs. +\item VM-level threads. This implementation performs time-sharing and +context switching at the level of the OCaml virtual machine (bytecode +interpreter). It is available on Unix systems, and supports only +bytecode programs. It cannot be used with native-code programs. +\end{itemize} +Programs that use system threads must be linked as follows: +\begin{alltt} + ocamlc -thread \var{other options} unix.cma threads.cma \var{other files} + ocamlopt -thread \var{other options} unix.cmxa threads.cmxa \var{other files} +\end{alltt} +Compilation units that use the "threads" library must also be compiled with +the "-thread" option (see chapter~\ref{c:camlc}). + +Programs that use VM-level threads must be compiled with the "-vmthread" +option to "ocamlc" (see chapter~\ref{c:camlc}), and be linked as follows: +\begin{alltt} + ocamlc -vmthread \var{other options} threads.cma \var{other files} +\end{alltt} +Compilation units that use "threads" library must also be compiled with +the "-vmthread" option (see chapter~\ref{c:camlc}). + +\ifouthtml +\begin{links} +\item \ahref{libref/Thread.html}{Module \texttt{Thread}: lightweight threads} +\item \ahref{libref/Mutex.html}{Module \texttt{Mutex}: locks for mutual exclusion} +\item \ahref{libref/Condition.html}{Module \texttt{Condition}: condition variables to synchronize between threads} +\item \ahref{libref/Event.html}{Module \texttt{Event}: first-class synchronous communication} +\item \ahref{libref/ThreadUnix.html}{Module \texttt{ThreadUnix}: thread-compatible system calls} +\end{links} +\else +\input{Thread.tex} +\input{Mutex.tex} +\input{Condition.tex} +\input{Event.tex} +\input{ThreadUnix.tex} +\fi diff --git a/manual/manual/library/libunix.etex b/manual/manual/library/libunix.etex new file mode 100644 index 0000000000..aa140fd0dc --- /dev/null +++ b/manual/manual/library/libunix.etex @@ -0,0 +1,94 @@ +\chapter{The unix library: Unix system calls} +\pdfchapterfold{-1}{The unix library: Unix system calls} +%HEVEA\cutname{libunix.html} + +The "unix" library makes many Unix +system calls and system-related library functions available to +OCaml programs. This chapter describes briefly the functions +provided. Refer to sections 2~and~3 of the Unix manual for more +details on the behavior of these functions. + +Not all functions are provided by all Unix variants. If some functions +are not available, they will raise "Invalid_arg" when called. + +Programs that use the "unix" library must be linked as follows: +\begin{alltt} + ocamlc \var{other options} unix.cma \var{other files} + ocamlopt \var{other options} unix.cmxa \var{other files} +\end{alltt} +For interactive use of the "unix" library, do: +\begin{alltt} + ocamlmktop -o mytop unix.cma + ./mytop +\end{alltt} +or (if dynamic linking of C libraries is supported on your platform), +start "ocaml" and type "#load \"unix.cma\";;". + +\begin{windows} +A fairly complete emulation of the Unix system calls is provided in +the Windows version of OCaml. The end of this chapter gives +more information on the functions that are not supported under Windows. +\end{windows} + +\ifouthtml +\begin{links} +\item \ahref{libref/Unix.html}{Module \texttt{Unix}: Unix system calls} +\item \ahref{libref/UnixLabels.html}{Module \texttt{UnixLabels}: Labeled + Unix system calls} +\end{links} +\else +\input{Unix.tex} + +\section{Module \texttt{UnixLabels}: labelized version of the interface} +\label{UnixLabels} +\index{UnixLabels (module)@\verb~UnixLabels~ (module)}% +\pdfsection{Module UnixLabels: labelized version of the interface} + +This module is identical to "Unix"~(\ref{Unix}), and only differs by +the addition of labels. You may see these labels directly by looking +at "unixLabels.mli", or by using the "ocamlbrowser" tool. +\fi + +\newpage +\begin{windows} +The Cygwin port of OCaml fully implements all functions from +the Unix module. The native Win32 ports implement a subset of them. +Below is a list of the functions that are not implemented, or only +partially implemented, by the Win32 ports. Functions not mentioned are +fully implemented and behave as described previously in this chapter. + +\begin{tableau}{|l|p{8cm}|}{Functions}{Comment} +\entree{"fork"}{not implemented, use "create_process" or threads} +\entree{"wait"}{not implemented, use "waitpid"} +\entree{"waitpid"}{can only wait for a given PID, not any child process} +\entree{"getppid"}{not implemented (meaningless under Windows)} +\entree{"nice"}{not implemented} +\entree{"truncate", "ftruncate"}{not implemented} +\entree{"link"}{implemented (since 3.02)} +\entree{"symlink", "readlink"}{implemented (since 4.03.0)} +\entree{"access"}{execute permission "X_OK" cannot be tested, + it just tests for read permission instead} +\entree{"fchmod"}{not implemented} +\entree{"chown", "fchown"}{not implemented (make no sense on a DOS +file system)} +\entree{"umask"}{not implemented} +\entree{"mkfifo"}{not implemented} +\entree{"kill"}{partially implemented (since 4.00.0): only the "sigkill" signal +is implemented} +\entree{"pause"}{not implemented (no inter-process signals in Windows)} +\entree{"alarm"}{not implemented} +\entree{"times"}{partially implemented, will not report timings for child +processes} +\entree{"getitimer", "setitimer"}{not implemented} +\entree{"getuid", "geteuid", "getgid", "getegid"}{always return 1} +\entree{"getgroups"}{always returns "[|1|]" (since 2.00)} +\entree{"setuid", "setgid", "setgroups"}{not implemented} +\entree{"getpwnam", "getpwuid"}{always raise "Not_found"} +\entree{"getgrnam", "getgrgid"}{always raise "Not_found"} +\entree{type "socket_domain"}{"PF_INET" is fully supported; +"PF_INET6" is fully supported (since 4.01.0); "PF_UNIX" is not supported } +\entree{"establish_server"}{not implemented; use threads} +\entree{terminal functions ("tc*")}{not implemented} +\end{tableau} + +\end{windows} diff --git a/manual/manual/library/stdlib.etex b/manual/manual/library/stdlib.etex new file mode 100644 index 0000000000..d8c4074470 --- /dev/null +++ b/manual/manual/library/stdlib.etex @@ -0,0 +1,186 @@ +\chapter{The standard library} \label{c:stdlib}\cutname{stdlib.html} +\pdfchapterfold{-32}{The standard library} + +This chapter describes the functions provided by the OCaml +standard library. The modules from the standard library are +automatically linked with the user's object code files by the "ocamlc" +command. Hence, these modules can be used in standalone programs without +having to add any ".cmo" file on the command line for the linking +phase. Similarly, in interactive use, these globals can be used in +toplevel phrases without having to load any ".cmo" file in memory. + +Unlike the "Pervasives" module from the core library, the modules from the +standard library are not automatically ``opened'' when a compilation +starts, or when the toplevel system is launched. Hence it is necessary +to use qualified identifiers to refer to the functions provided by these +modules, or to add "open" directives. + +\label{stdlib:top} + +\section*{Conventions} + +For easy reference, the modules are listed below in alphabetical order +of module names. +For each module, the declarations from its signature are printed +one by one in typewriter font, followed by a short comment. +All modules and the identifiers they export are indexed at the end of +this report. + +\begin{latexonly} +\section*{Overview} + +Here is a short listing, by theme, of the standard library modules. + +\subsubsection*{Data structures:} +\begin{tabular}{lll} +% Beware: these entries must be written in a very rigidly-defined +% format, or the check-stdlib-modules script will complain. +"String" & p.~\pageref{String} & string operations \\ +"Bytes" & p.~\pageref{Bytes} & operations on byte sequences\\ +"Array" & p.~\pageref{Array} & array operations \\ +"List" & p.~\pageref{List} & list operations \\ +"StdLabels" & p.~\pageref{StdLabels} & labelized versions of +the above 4 modules \\ +"Char" & p.~\pageref{Char} & character operations \\ +"Uchar" & p.~\pageref{Uchar} & Unicode characters \\ +"Sort" & p.~\pageref{Sort} & (deprecated) \\ +"Hashtbl" & p.~\pageref{Hashtbl} & hash tables and hash functions \\ +"Random" & p.~\pageref{Random} & pseudo-random number generator \\ +"Set" & p.~\pageref{Set} & sets over ordered types \\ +"Map" & p.~\pageref{Map} & association tables over ordered types \\ +"MoreLabels" & p.~\pageref{MoreLabels} & labelized versions of +"Hashtbl", "Set", and "Map" \\ +"Oo" & p.~\pageref{Oo} & useful functions on objects \\ +"Stack" & p.~\pageref{Stack} & last-in first-out stacks \\ +"Queue" & p.~\pageref{Queue} & first-in first-out queues \\ +"Buffer" & p.~\pageref{Buffer} & buffers that grow on demand \\ +"Lazy" & p.~\pageref{Lazy} & delayed evaluation \\ +"Weak" & p.~\pageref{Weak} & references that don't prevent objects +from being garbage-collected \\ +"Ephemeron" & p.~\pageref{Ephemeron} & ephemerons and weak hash tables +\end{tabular} +\subsubsection*{Arithmetic:} +\begin{tabular}{lll} +"Complex" & p.~\pageref{Complex} & Complex numbers \\ +"Int32" & p.~\pageref{Int32} & operations on 32-bit integers \\ +"Int64" & p.~\pageref{Int64} & operations on 64-bit integers \\ +"Nativeint" & p.~\pageref{Nativeint} & operations on platform-native +integers +\end{tabular} +\subsubsection{Input/output:} +\begin{tabular}{lll} +"Format" & p.~\pageref{Format} & pretty printing with automatic +indentation and line breaking \\ +"Marshal" & p.~\pageref{Marshal} & marshaling of data structures \\ +"Printf" & p.~\pageref{Printf} & formatting printing functions \\ +"Scanf" & p.~\pageref{Scanf} & formatted input functions \\ +"Digest" & p.~\pageref{Digest} & MD5 message digest \\ +\end{tabular} +\subsubsection{Parsing:} +\begin{tabular}{lll} +"Genlex" & p.~\pageref{Genlex} & a generic lexer over streams \\ +"Lexing" & p.~\pageref{Lexing} & the run-time library for lexers generated by "ocamllex" \\ +"Parsing" & p.~\pageref{Parsing} & the run-time library for parsers generated by "ocamlyacc" \\ +"Stream" & p.~\pageref{Stream} & basic functions over streams \\ +\end{tabular} +\subsubsection{System interface:} +\begin{tabular}{lll} +"Arg" & p.~\pageref{Arg} & parsing of command line arguments \\ +"Callback" & p.~\pageref{Callback} & registering OCaml functions to +be called from C \\ +"Filename" & p.~\pageref{Filename} & operations on file names \\ +"Gc" & p.~\pageref{Gc} & memory management control and statistics \\ +"Printexc" & p.~\pageref{Printexc} & a catch-all exception handler \\ +"Spacetime" & p.~\pageref{Spacetime} & memory profiler \\ +"Sys" & p.~\pageref{Sys} & system interface \\ +\end{tabular} +\end{latexonly} + +\ifouthtml +\begin{links} +\item \ahref{libref/Arg.html}{Module \texttt{Arg}: parsing of command line arguments} +\item \ahref{libref/Array.html}{Module \texttt{Array}: array operations} +\item \ahref{libref/ArrayLabels.html}{Module \texttt{ArrayLabels}: array operations (with labels)} +\item \ahref{libref/Buffer.html}{Module \texttt{Buffer}: extensible buffers} +\item \ahref{libref/Bytes.html}{Module \texttt{Bytes}: byte sequences} +\item \ahref{libref/Callback.html}{Module \texttt{Callback}: registering OCaml values with the C runtime} +\item \ahref{libref/Char.html}{Module \texttt{Char}: character operations} +\item \ahref{libref/Complex.html}{Module \texttt{Complex}: Complex numbers} +\item \ahref{libref/Digest.html}{Module \texttt{Digest}: MD5 message digest} +\item \ahref{libref/Ephemeron.html}{Module \texttt{Ephemeron}: Ephemerons and weak hash table} +\item \ahref{libref/Filename.html}{Module \texttt{Filename}: operations on file names} +\item \ahref{libref/Format.html}{Module \texttt{Format}: pretty printing} +\item \ahref{libref/Gc.html}{Module \texttt{Gc}: memory management control and statistics; finalized values} +\item \ahref{libref/Genlex.html}{Module \texttt{Genlex}: a generic lexical analyzer} +\item \ahref{libref/Hashtbl.html}{Module \texttt{Hashtbl}: hash tables and hash functions} +\item \ahref{libref/Int32.html}{Module \texttt{Int32}: 32-bit integers} +\item \ahref{libref/Int64.html}{Module \texttt{Int64}: 64-bit integers} +\item \ahref{libref/Lazy.html}{Module \texttt{Lazy}: deferred computations} +\item \ahref{libref/Lexing.html}{Module \texttt{Lexing}: the run-time library for lexers generated by \texttt{ocamllex}} +\item \ahref{libref/List.html}{Module \texttt{List}: list operations} +\item \ahref{libref/ListLabels.html}{Module \texttt{ListLabels}: list operations (with labels)} +\item \ahref{libref/Map.html}{Module \texttt{Map}: association tables over ordered types} +\item \ahref{libref/Marshal.html}{Module \texttt{Marshal}: marshaling of data structures} +\item \ahref{libref/MoreLabels.html}{Module \texttt{MoreLabels}: Include modules \texttt{Hashtbl}, \texttt{Map} and \texttt{Set} with labels} +\item \ahref{libref/Nativeint.html}{Module \texttt{Nativeint}: processor-native integers} +\item \ahref{libref/Oo.html}{Module \texttt{Oo}: object-oriented extension} +\item \ahref{libref/Parsing.html}{Module \texttt{Parsing}: the run-time library for parsers generated by \texttt{ocamlyacc}} +\item \ahref{libref/Printexc.html}{Module \texttt{Printexc}: facilities for printing exceptions} +\item \ahref{libref/Printf.html}{Module \texttt{Printf}: formatting printing functions} +\item \ahref{libref/Queue.html}{Module \texttt{Queue}: first-in first-out queues} +\item \ahref{libref/Random.html}{Module \texttt{Random}: pseudo-random number generator (PRNG)} +\item \ahref{libref/Scanf.html}{Module \texttt{Scanf}: formatted input functions} +\item \ahref{libref/Set.html}{Module \texttt{Set}: sets over ordered types} +\item \ahref{libref/Sort.html}{Module \texttt{Sort}: deprecated} +\item \ahref{libref/Spacetime.html}{Module \texttt{Spacetime}: memory profiler} +\item \ahref{libref/Stack.html}{Module \texttt{Stack}: last-in first-out stacks} +\item \ahref{libref/StdLabels.html}{Module \texttt{StdLabels}: Include modules \texttt{Array}, \texttt{List} and \texttt{String} with labels} +\item \ahref{libref/Stream.html}{Module \texttt{Stream}: streams and parsers} +\item \ahref{libref/String.html}{Module \texttt{String}: string operations} +\item \ahref{libref/StringLabels.html}{Module \texttt{StringLabels}: string operations (with labels)} +\item \ahref{libref/Sys.html}{Module \texttt{Sys}: system interface} +\item \ahref{libref/Uchar.html}{Module \texttt{Uchar}: Unicode characters} +\item \ahref{libref/Weak.html}{Module \texttt{Weak}: arrays of weak pointers} +\end{links} +\else +\input{Arg.tex} +\input{Array.tex} +\input{Buffer.tex} +\input{Bytes.tex} +\input{Callback.tex} +\input{Char.tex} +\input{Complex.tex} +\input{Digest.tex} +\input{Ephemeron.tex} +\input{Filename.tex} +\input{Format.tex} +\input{Gc.tex} +\input{Genlex.tex} +\input{Hashtbl.tex} +\input{Int32.tex} +\input{Int64.tex} +\input{Lazy.tex} +\input{Lexing.tex} +\input{List.tex} +\input{Map.tex} +\input{Marshal.tex} +\input{MoreLabels.tex} +\input{Nativeint.tex} +\input{Oo.tex} +\input{Parsing.tex} +\input{Printexc.tex} +\input{Printf.tex} +\input{Queue.tex} +\input{Random.tex} +\input{Scanf.tex} +\input{Set.tex} +\input{Sort.tex} +\input{Spacetime.tex} +\input{Stack.tex} +\input{StdLabels.tex} +\input{Stream.tex} +\input{String.tex} +\input{Sys.tex} +\input{Uchar.tex} +\input{Weak.tex} +\fi diff --git a/manual/manual/library/tk.mli b/manual/manual/library/tk.mli new file mode 100644 index 0000000000..d3c8d199fa --- /dev/null +++ b/manual/manual/library/tk.mli @@ -0,0 +1,192 @@ +(* $Id$ *) + +(** Basic functions and types for LablTk *) + +open Widget + +(** {6 Initialization and termination} *) + +val openTk : ?display:string -> ?clas:string -> unit -> toplevel widget + (** Initialize LablTk and open a toplevel window. + [display] is described according to the X11 conventions. + [clas] is used for the X11 resource mechanism. *) +val mainLoop : unit -> unit + (** Start the main event loop *) +val closeTk : unit -> unit + (** Quit the main loop and close all open windows. *) +val destroy : 'a Widget.widget -> unit + (** Destroy an individual widget. *) + +(** {6 Application wide commands} *) + +val update : unit -> unit + (** Synchronize display with internal state. *) + +val appname_get : unit -> string +val appname_set : string -> unit + (** Get or set the application name. *) + +(** {6 Dimensions} *) + +type units = [`Pix of int | `Cm of float | `In of float | `Mm of float | `Pt of float] +val pixels : units -> int + (** Converts various on-screen units to pixels, + respective to the default display. Available units are + pixels, centimeters, inches, millimeters and points *) + +(** {6 Widget layout commands} *) + +type anchor = [`Center|`E|`N|`Ne|`Nw|`S|`Se|`Sw|`W] +type fillMode = [`Both|`None|`X|`Y] +type side = [`Bottom|`Left|`Right|`Top] +val pack : + ?after:'a Widget.widget -> + ?anchor:anchor -> + ?before:'b Widget.widget -> + ?expand:bool -> + ?fill:fillMode -> + ?inside:'c Widget.widget -> + ?ipadx:int -> + ?ipady:int -> + ?padx:int -> + ?pady:int -> + ?side:side -> + 'd Widget.widget list -> unit + (** Pack a widget inside its parent, + using the standard layout engine. *) +val grid : + ?column:int -> + ?columnspan:int -> + ?inside:'a Widget.widget -> + ?ipadx:int -> + ?ipady:int -> + ?padx:int -> + ?pady:int -> + ?row:int -> + ?rowspan:int -> + ?sticky:string -> 'b Widget.widget list -> unit + (** Pack a widget inside its parent, using the grid layout engine. *) + +type borderMode = [`Ignore|`Inside|`Outside] +val place : + ?anchor:anchor -> + ?bordermode:borderMode -> + ?height:int -> + ?inside:'a Widget.widget -> + ?relheight:float -> + ?relwidth:float -> + ?relx:float -> + ?rely:float -> + ?width:int -> + ?x:int -> ?y:int -> 'b Widget.widget -> unit + (** Pack a widget inside its parent, at absolute coordinates. *) + +val raise_window : + ?above:'a Widget.widget -> 'b Widget.widget -> unit +val lower_window : + ?below:'a Widget.widget -> 'b Widget.widget -> unit + (** Raise or lower the window associated to a widget. *) + +(** {6 Event handling} *) + +type modifier = + [ `Control | `Shift | `Lock + | `Button1 | `Button2 | `Button3 | `Button4 | `Button5 + | `Double | `Triple + | `Mod1 | `Mod2 | `Mod3 | `Mod4 | `Mod5 | `Meta | `Alt ] + +type event = + [ `ButtonPress | `ButtonPressDetail of int + | `ButtonRelease | `ButtonReleaseDetail of int + | `Circulate | `ColorMap | `Configure | `Destroy + | `Enter | `Expose | `FocusIn | `FocusOut | `Gravity + | `KeyPress | `KeyPressDetail of string + | `KeyRelease | `KeyReleaseDetail of string + | `Leave | `Map | `Motion | `Property + | `Reparent | `Unmap | `Visibility + | `Modified of modifier list * event ] + +(** An event can be either a basic X event, or modified by a + key or mouse modifier. *) + +type eventInfo = + { mutable ev_Above: int; + mutable ev_ButtonNumber: int; + mutable ev_Count: int; + mutable ev_Detail: string; + mutable ev_Focus: bool; + mutable ev_Height: int; + mutable ev_KeyCode: int; + mutable ev_Mode: string; + mutable ev_OverrideRedirect: bool; + mutable ev_Place: string; + mutable ev_State: string; + mutable ev_Time: int; + mutable ev_Width: int; + mutable ev_MouseX: int; + mutable ev_MouseY: int; + mutable ev_Char: string; + mutable ev_BorderWidth: int; + mutable ev_SendEvent: bool; + mutable ev_KeySymString: string; + mutable ev_KeySymInt: int; + mutable ev_RootWindow: int; + mutable ev_SubWindow: int; + mutable ev_Type: int; + mutable ev_Widget: Widget.any Widget.widget; + mutable ev_RootX: int; + mutable ev_RootY: int } + +(** Event related information accessible in callbacks. *) + +type eventField = + [ `Above | `ButtonNumber | `Count | `Detail | `Focus | `Height + | `KeyCode | `Mode | `OverrideRedirect | `Place | `State + | `Time | `Width | `MouseX | `MouseY | `Char | `BorderWidth + | `SendEvent | `KeySymString | `KeySymInt | `RootWindow + | `SubWindow | `Type | `Widget | `RootX | `RootY ] + +(** In order to access the above event information, one has to pass + a list of required event fields to the [bind] function. *) + +val bind : + events:event list -> + ?extend:bool -> + ?breakable:bool -> + ?fields:eventField list -> + ?action:(eventInfo -> unit) -> + 'a Widget.widget -> unit + (** Bind a succession of [events] on a widget to an [action]. + If [extend] is true then then binding is added after existing + ones, otherwise it replaces them. + [breakable] should be true when [break] is to be called inside + the action. + [action] is called with the [fields] required set in + an [eventInfo] structure. Other fields should not be accessed. + If [action] is omitted then existing bindings are removed. *) + +val bind_class : + events:event list -> + ?extend:bool -> + ?breakable:bool -> + ?fields:eventField list -> + ?action:(eventInfo -> unit) -> + ?on:'a Widget.widget -> + string -> unit + (** Same thing for all widgets of a given class. If a widget + is given with label [~on:], the binding will be removed as + soon as it is destroyed. *) +val bind_tag : + events:event list -> + ?extend:bool -> + ?breakable:bool -> + ?fields:eventField list -> + ?action:(eventInfo -> unit) -> + ?on:'a Widget.widget -> + string -> unit + (** Same thing for all widgets having a given tag *) + +val break : unit -> unit + (** Used inside a bound action, do not call other actions + after this one. This is only possible if this action + was bound with [~breakable:true]. *) diff --git a/manual/manual/macros.hva b/manual/manual/macros.hva new file mode 100644 index 0000000000..54a7b1374e --- /dev/null +++ b/manual/manual/macros.hva @@ -0,0 +1,108 @@ +%%Colors for links +\def\visited@color{\#006000} +\def\link@color{\#00A000} +\def\hover@color{\@getstylecolor{subsection}} +\newstyle{a:link}{color:\link@color;text-decoration:underline;} +\newstyle{a:visited}{color:\visited@color;text-decoration:underline;} +\newstyle{a:hover}{color:black;text-decoration:none;background-color:\hover@color} +%%% +\newcommand{\input@color}{\htmlcolor{006000}} +\newcommand{\output@color}{\maroon} +\newcommand{\machine}{\tt} +\newenvironment{machineenv}{\begin{alltt}}{\end{alltt}} +\newcommand{\firstline}{\black\#\input@color\ } +\newcommand{\nextline}{\ \ } +\newcommand{\@zyva}{\firstline\renewcommand{\?}{\nextline}} +\newenvironment{camlunder}{\@style{U}}{} +\newcommand{\caml}{\begin{alltt}\renewcommand{\;}{}\renewcommand{\\}{\char92}\def\<{\begin{camlunder}}\def\>{\end{camlunder}}\activebracefalse} +\let\?=\@zyva +\newcommand{\endcaml}{\activebracetrue\end{alltt}} +\renewcommand{\:}{\renewcommand{\?}{\@zyva}\output@color} +\newcommand{\var}[1]{\textit{#1}} + +\newenvironment{library}{}{} +\newcounter{page} +\newenvironment{comment}{\begin{quote}}{\end{quote}} +\newcommand{\nth}[2]{\({#1}_{#2}\)} +\newenvironment{options}{\begin{description}}{\end{description}} + + +%%venant de macros.tex + +\def\versionspecific#1{\begin{quote}\textsf{#1:}\quad} +\def\unix{\versionspecific{Unix}} +\def\endunix{\end{quote}} +\def\macos{\versionspecific{MacOS~9}} +\def\endmacos{\end{quote}} +\def\windows{\versionspecific{Windows}} +\def\endwindows{\end{quote}} + +\def\requirements{\trivlist \item[\hskip\labelsep {\bf Requirements.}]} +\def\endrequirements{\endtrivlist} +\def\installation{\trivlist \item[\hskip\labelsep {\bf Installation.}]} +\def\endinstallation{\endtrivlist} +\def\troubleshooting{\trivlist \item[\hskip\labelsep {\bf Troubleshooting.}]} +\def\endtroubleshooting{\endtrivlist} + +\newtheorem{gcrule}{Rule} + +% Pour les tables de priorites et autres tableaux a deux colonnes, encadres + +\def\entree#1#2{#1 & #2 \\} +\def\tableau#1#2#3{% +\par\begin{center}% +\begin{tabular*}{.8\linewidth}{#1}% +\multicolumn{1}{c}{\textbf{#2}} & +\multicolumn{1}{c}{\textbf{#3}} \\ +%%#2 & #3 \\% +}% +\def\endtableau{\end{tabular*}\end{center}\par} + +% L'environnement library (pour composer les descriptions des modules +% de bibliotheque). + + +\def\restoreindent{\begingroup\let\@listI=\@savedlistI} +\def\endrestoreindent{\endgroup} + + +% PDF stuff + +\def\pdfchapterfold#1#2{} +\def\pdfsection#1{} +\def\pdfchapter{\pdfchapterfold{0}} + +%%% Pour camlidl + +\def\transl#1{$[\![\mbox{#1}]\!]$} + +% Pour l'index +\usepackage{multind} +\let\indexentry=\index +\renewcommand{\index}[1]{\indexentry{\jobname}{#1}} +\def\ikwd#1{\indexentry{\jobname.kwd}{#1}} +% nth + +\def\th{^{\mbox{\scriptsize th}}} +\renewcommand{\hbox}[1]{\mbox{#1}} + +% Notations pour les metavariables +\def\nmth#1#2#3{\({#1}_{#2}^{#3}\)} +\def\optvar#1{[\var{#1}\/]} +\def\event{��} +\def\fromoneto#1#2{$#1 = 1,\ldots{} , #2$} + +\newcommand{\vfill}{} +\def\number{} +\def\year{2013} + +% Pour alltt +\def\rminalltt#1{{\rm #1}} +\def\goodbreak{\ \\} +\def\@savedlistI{} + +%List of links with no space around items +\newstyle{.li-links}{margin:0ex 0ex;} +\newenvironment{links} +{\setenvclass{itemize}{ftoc2}\setenvclass{li-itemize}{li-links}\itemize} +{\enditemize} diff --git a/manual/manual/macros.tex b/manual/manual/macros.tex new file mode 100644 index 0000000000..5c2b162153 --- /dev/null +++ b/manual/manual/macros.tex @@ -0,0 +1,250 @@ +\makeatletter +% Pour hevea +\newif\ifouthtml\outhtmlfalse +\newcommand{\cutname}[1]{} +% Notations pour les metavariables +\def\var#1{{\it#1}} +\def\nth#1#2{${\it#1}_{#2}$} +\def\nmth#1#2#3{${\it#1}_{#2}^{#3}$} +\def\optvar#1{\textrm{[}\var{#1}\/\textrm{]}} +\def\event{$\bowtie$} +\def\fromoneto#1#2{$#1 = 1, \ldots, #2$} + +% Pour avoir les exposants sur la ligne au-dessus (???) + +\ifplaintext +\fontdimen14\tensy=12pt +\fi + +% Numerotation +\setcounter{secnumdepth}{2} % Pour numeroter les \subsection +\setcounter{tocdepth}{1} % Pour ne pas mettre les \subsection + % dans la table des matieres + +% Pour avoir "_" qui marche en mode math et en mode normal +\catcode`\_=13 +\catcode`\=8 +\def\_{\hbox{\tt\char95}} +\def_{\ifmmode\else\_\fi} + +\ifplaintext +\def\ttstretch{\tt} +\else +\def\ttstretch{\tt\spaceskip=5.77pt plus 1.83pt minus 1.22pt} +% La fonte cmr10 a normalement des espaces de 5.25pt non extensibles. +% En 11 pt ca fait 5.77 pt. On lui ajoute la meme flexibilite que +% cmr10 agrandie a 11 pt. +\fi + +% Pour la traduction "xxxx" -> {\machine{xxxx}} faite par texquote2 +\def\machine#1{\mbox{\ttstretch{#1}}} + +% Pour la traduction "\begin{verbatim}...\end{verbatim}" +% -> "\begin{machineenv}...\end{machineenv}" +% faite aussi par texquote2. +\newenvironment{machineenv}{\alltt}{\endalltt} + +% Environnements + +\newlength{\versionwidth} +\setbox0=\hbox{\bf Windows:} \setlength{\versionwidth}{\wd0} + +\def\versionspecific#1{ + \begin{description}\item[#1:]~\\} + +\def\unix{\versionspecific{Unix}} +\def\endunix{\end{description}} +%\def\macos{\versionspecific{MacOS 9}} +%\def\endmacos{\end{description}} +\def\windows{\versionspecific{Windows}} +\def\endwindows{\end{description}} + +\def\requirements{\trivlist \item[\hskip\labelsep {\bf Requirements.}]} +\def\endrequirements{\endtrivlist} +\def\installation{\trivlist \item[\hskip\labelsep {\bf Installation.}]} +\def\endinstallation{\endtrivlist} +\def\troubleshooting{\trivlist \item[\hskip\labelsep {\bf Troubleshooting.}]} +\def\endtroubleshooting{\endtrivlist} + +\newtheorem{gcrule}{Rule} + +% Pour les tables de priorites et autres tableaux a deux colonnes, encadres + +\def\tableau#1#2#3{% +\begin{center} +\begin{tabular}{#1} +\hline +#2 & #3 \\ +\hline +} +\def\endtableau{\hline\end{tabular}\end{center}} +\def\entree#1#2{#1 & #2 \\} + +% L'environnement option + +\def\optionitem[#1]{\if@noparitem \@donoparitem + \else \if@inlabel \indent \par \fi + \ifhmode \unskip\unskip \par \fi + \if@newlist \if@nobreak \@nbitem \else + \addpenalty\@beginparpenalty + \addvspace\@topsep \addvspace{-\parskip}\fi + \else \addpenalty\@itempenalty \addvspace\itemsep + \fi + \global\@inlabeltrue +\fi +\everypar{\global\@minipagefalse\global\@newlistfalse + \if@inlabel\global\@inlabelfalse \hskip -\parindent \box\@labels + \penalty\z@ \fi + \everypar{}}\global\@nobreakfalse +\if@noitemarg \@noitemargfalse \if@nmbrlist \refstepcounter{\@listctr}\fi \fi +\setbox\@tempboxa\hbox{\makelabel{#1}}% +\global\setbox\@labels +\ifdim \wd\@tempboxa >\labelwidth + \hbox{\unhbox\@labels + \hskip -\leftmargin + \box\@tempboxa}\hfil\break + \else + \hbox{\unhbox\@labels + \hskip -\leftmargin + \hbox to\leftmargin {\makelabel{#1}\hfil}} + \fi + \ignorespaces} + +\def\optionlabel#1{\bf #1} +\def\options{\list{}{\let\makelabel\optionlabel\let\@item\optionitem}} +\def\endoptions{\endlist} + +% L'environnement library (pour composer les descriptions des modules +% de bibliotheque). + +\def\comment{\penalty200\list{}{}\item[]} +\def\endcomment{\endlist\penalty-100} + +\def\library{ +\begingroup +\raggedright +\let\@savedlistI=\@listI% +\def\@listI{\leftmargin\leftmargini\parsep 0pt plus 1pt\topsep 0pt plus 2pt}% +\itemsep 0pt +\topsep 0pt plus 2pt +\partopsep 0pt +} + +\def\endlibrary{ +\endgroup +} + +\def\restoreindent{\begingroup\let\@listI=\@savedlistI} +\def\endrestoreindent{\endgroup} + +% ^^A...^^A: compose l'interieur en \tt, comme \verb + +\catcode`\^^A=\active +\def{% +\begingroup\catcode``=13\@noligs\ttstretch\let\do\@makeother\dospecials% +\def\@xobeysp{\leavevmode\penalty100\ }% +\@vobeyspaces\frenchspacing\catcode`\^^A=\active\def{\endgroup}} + +% Pour l'index + +\let\indexentry=\index +\def\index{\indexentry{\jobname}} +\def\ikwd{\indexentry{\jobname.kwd}} + +% Les en-tetes personnalises + +\pagestyle{myheadings} +\def\partmark#1{\markboth{Part \thepart. \ #1}{}} +\def\chaptermark#1{\markright{Chapter \thechapter. \ #1}} + +% nth + +\def\th{^{\hbox{\scriptsize th}}} + +% Pour annuler l'espacement vertical qui suit un "verbatim" +\def\cancelverbatim{\vspace{-\topsep}\vspace{-\parskip}}% exact. + +% Pour annuler l'espacement vertical entre deux \item consecutifs dans \options +\def\cancelitemspace{\vspace{-8mm}}% determine empiriquement + +% Pour faire la cesure apres _ dans les identificateurs +\def\={\discretionary{}{}{}} +\def\cuthere{\discretionary{}{}{}} + +% Pour la coupure en petits documents + +\let\mysection=\section + +%%% Augmenter l'espace entre numero de section +% et nom de section dans la table des matieres. + +\ifplaintext\else +\def\l@section{\@dottedtocline{1}{1.5em}{2.8em}} % D'origine: 2.3 +\fi + +% Pour alltt + +\def\rminalltt#1{{\rm #1}} + +% redefinition de l'environnement alltt pour que les {} \ et % soient +% dans la bonne fonte + +\let\@oldalltt=\alltt +\let\@oldendalltt=\endalltt +\renewenvironment{alltt}{% +\begingroup% +\renewcommand{\{}{\char`\{}% +\renewcommand{\}}{\char`\}}% +\renewcommand{\\}{\char`\\}% +\renewcommand{\%}{\char`\%}% +\@oldalltt% +}{% +\@oldendalltt% +\endgroup% +} + +% Index stuff -- cf multind.sty + +\def\printindex#1#2{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi + \columnseprule \z@ \columnsep 35pt + \newpage \phantomsection \twocolumn[{\Large\bf #2 \vskip4ex}] + \markright{\uppercase{#2}} + \addcontentsline{toc}{chapter}{#2} + \pdfsection{#2} + \@input{#1.ind}} + +% PDF stuff -- no longer needed, Hyperref does the job + +\def\pdfchapterfold#1#2{} +\def\pdfchapter#1{} +\def\pdfsection#1{} + +%\ifpdf +%\newcount\pdflabel +%\pdflabel=1 +%\def\pdfchapterfold#1#2{ +%\pdfdest num \pdflabel fit +%\pdfoutline goto num \pdflabel count #1 {\arabic{chapter}. #2} +%\global\advance\pdflabel by 1 +%} +%\def\pdfsection#1{ +%\pdfdest num \pdflabel fit +%\pdfoutline goto num \pdflabel {#1} +%\global\advance\pdflabel by 1 +%} +%\else +%\def\pdfchapterfold#1#2{} +%\def\pdfsection#1{} +%\fi +% +%\def\pdfchapter{\pdfchapterfold{0}} + +%%% Pour camlidl + +\def\transl#1{$[\![\mbox{#1}]\!]$} + +%%% Pour les references des modules +\newcommand{\moduleref}[1]{\ref{#1}} +%%% Fin des hacks + +\makeatother diff --git a/manual/manual/manual.hva b/manual/manual/manual.hva new file mode 100644 index 0000000000..4c8d59d93e --- /dev/null +++ b/manual/manual/manual.hva @@ -0,0 +1,4 @@ +\input{book.hva} +\input{fancysection.hva} +\input{macros.hva} +\newif\ifouthtml\outhtmltrue \ No newline at end of file diff --git a/manual/manual/manual.inf b/manual/manual/manual.inf new file mode 100644 index 0000000000..829e3cd326 --- /dev/null +++ b/manual/manual/manual.inf @@ -0,0 +1,113 @@ +\input{book.hva} +\renewcommand{\@indexsection}[1]{\chapter{#1}} +\newcommand{\black}{\htmlcolor{#000000}} +\newcommand{\machine}{\tt} +\newenvironment{machineenv}{\begin{alltt}}{\end{alltt}} +\newenvironment{camlunder}{\@style{U}}{} +\newcommand{\caml}{\begin{alltt}\renewcommand{\\}{\char92}\def\<{\begin{camlunder}}\def\>{\end{camlunder}}\activebracefalse} +\newcommand{\endcaml}{\activebracetrue\end{alltt}} +\newcommand{\?}{\black\#\blue } +\renewcommand{\:}{\maroon} +\newcommand{\var}[1]{\textit{#1}} + +\newenvironment{library}{}{} +\newcounter{page} +\newenvironment{comment}{\begin{quote}}{\end{quote}} +\newcommand{\nth}[2]{\({#1}_{#2}\)} +\newenvironment{options}{\begin{description}}{\end{description}} + + +%%venant de macros.tex +\newif\ifouthtml\outhtmlfalse +\def\versionspecific#1{ +\quad\textsf{#1:} +\begin{quote}} + +\def\unix{\versionspecific{Unix}} +\def\endunix{\end{quote}} +\def\macos{\versionspecific{MacOS}} +\def\endmacos{\end{quote}} +\def\windows{\versionspecific{Windows}} +\def\endwindows{\end{quote}} + +\def\requirements{\trivlist \item[\hskip\labelsep {\bf Requirements.}]} +\def\endrequirements{\endtrivlist} +\def\installation{\trivlist \item[\hskip\labelsep {\bf Installation.}]} +\def\endinstallation{\endtrivlist} +\def\troubleshooting{\trivlist \item[\hskip\labelsep {\bf Troubleshooting.}]} +\def\endtroubleshooting{\endtrivlist} + +\newtheorem{gcrule}{Rule} + +% Pour les tables de priorites et autres tableaux a deux colonnes, encadres + +%\def\entree#1#2{#1 & #2 \\} +%\def\tableau#1#2#3{% +%\par\begin{center}% +%\begin{tabular}{#1}% +%\multicolumn{1}{c}{\textbf{#2}} & +%\multicolumn{1}{c}{\textbf{#3}} \\ +%%#2 & #3 \\% +%}% +%\def\endtableau{\end{tabular}\end{center}\par} + +% Pour les tables de priorites et autres tableaux a deux colonnes, encadres + +\def\tableau#1#2#3{% +\begin{center} +\begin{tabular}{#1} +\hline +\multicolumn{1}{|c|}{\textbf{#2}} & \multicolumn{1}{c|}{\textbf{#3}} \\ +\hline +} +\def\endtableau{\hline\end{tabular}\end{center}} +\def\entree#1#2{#1 & #2 \\} + + + +% L'environnement library (pour composer les descriptions des modules +% de bibliotheque). + + +\def\restoreindent{\begingroup\let\@listI=\@savedlistI} +\def\endrestoreindent{\endgroup} + + +% PDF stuff + +\def\pdfchapterfold#1#2{} +\def\pdfsection#1{} +\def\pdfchapter{\pdfchapterfold{0}} + +%%% Pour camlidl + +\def\transl#1{$[\![\mbox{#1}]\!]$} + +% Pour l'index +\usepackage{multind} +\let\indexentry=\index +\renewcommand{\index}[1]{\indexentry{\jobname}{#1}} +\def\ikwd#1{\indexentry{\jobname.kwd}{#1}} + + +% nth +\def\th{^{\mbox{\scriptsize th}}} +\renewcommand{\hbox}[1]{\mbox{#1}} + +% Notations pour les metavariables +\def\nmth#1#2#3{\({#1}_{#2}^{#3}\)} +\def\optvar#1{[\var{#1}\/]} +\def\event{��} +\def\fromoneto#1#2{$#1 = 1,\ldots{} , #2$} + +\newcommand{\vfill}{} +\def\number{} +\def\year{2013} + +% Pour alltt + +\def\rminalltt#1{{\rm #1}} + +\def\goodbreak{\ \\} + +\def\@savedlistI{} diff --git a/manual/manual/manual.info.header b/manual/manual/manual.info.header new file mode 100644 index 0000000000..7466515837 --- /dev/null +++ b/manual/manual/manual.info.header @@ -0,0 +1,4 @@ +INFO-DIR-SECTION OCaml Programming Language +START-INFO-DIR-ENTRY +* ocaml: (ocaml). OCaml Reference Manual +END-INFO-DIR-ENTRY diff --git a/manual/manual/manual.tex b/manual/manual/manual.tex new file mode 100644 index 0000000000..f50cff41fa --- /dev/null +++ b/manual/manual/manual.tex @@ -0,0 +1,30 @@ +\documentclass[11pt]{book} +\usepackage[latin1]{inputenc} +%HEVEA\@def@charset{US-ASCII}% +\usepackage{alltt} +\usepackage{fullpage} +\usepackage{syntaxdef} +\usepackage{multind} +\usepackage{html} +\usepackage{textcomp} +\usepackage{caml-sl} +\usepackage{ocamldoc} +\usepackage{xspace} +\newif\ifplaintext +\plaintextfalse +%\newif\ifpdf +%\pdffalse +\input{macros.tex} + +\usepackage{hyperref} +%\makeatletter \def\@wrindex#1#2{\xdef \@indexfile{\csname #1@idxfile\endcsname}\@@wrindex#2||\\}\makeatother +\def\th{^{\hbox{\scriptsize th}}} + +\raggedbottom +\input{version.tex} + +%HEVEA\setcounter{cuttingdepth}{1} +%HEVEA\title{The OCaml system, release \ocamlversion} +\input{allfiles.tex} + + diff --git a/manual/manual/pdfmanual.tex b/manual/manual/pdfmanual.tex new file mode 100644 index 0000000000..98db4e6e28 --- /dev/null +++ b/manual/manual/pdfmanual.tex @@ -0,0 +1,31 @@ +%\pdfoutput=1 +\pdfpagewidth=21cm +\pdfpageheight=11in +\pdfcompresslevel=7 + +\documentclass[11pt]{book} + +\usepackage[latin1]{inputenc} +\usepackage{alltt} +\usepackage{fullpage} +\usepackage{syntaxdef} +\usepackage{multind} +\usepackage{html} +\usepackage{textcomp} +\usepackage{caml-sl} +\usepackage{ocamldoc} +\usepackage{xspace} + +\newif\ifplaintext +\plaintextfalse +%\newif\ifpdf +%\pdftrue +\input macros.tex + +\usepackage{hyperref} +\def\th{^{\hbox{\scriptsize th}}} + +\raggedbottom +\input{version.tex} + +\input allfiles.tex diff --git a/manual/manual/plaintext.tex b/manual/manual/plaintext.tex new file mode 100644 index 0000000000..86201b4b05 --- /dev/null +++ b/manual/manual/plaintext.tex @@ -0,0 +1,17 @@ +\documentclass[11pt]{report} + +\usepackage{plaintext} +\usepackage[latin1]{inputenc} +\usepackage{alltt} +\usepackage{fullpage} +\usepackage{syntaxdef} +\usepackage{multind} +\usepackage{html} +\usepackage{caml-sl} + +\newif\ifplaintext +\plaintexttrue +%\newif\ifpdf +%\pdffalse +\input macros.tex +\input allfiles.tex diff --git a/manual/manual/refman/.cvsignore b/manual/manual/refman/.cvsignore new file mode 100644 index 0000000000..81ccbe7105 --- /dev/null +++ b/manual/manual/refman/.cvsignore @@ -0,0 +1,2 @@ +*.tex +*.htex diff --git a/manual/manual/refman/.gitignore b/manual/manual/refman/.gitignore new file mode 100644 index 0000000000..81ccbe7105 --- /dev/null +++ b/manual/manual/refman/.gitignore @@ -0,0 +1,2 @@ +*.tex +*.htex diff --git a/manual/manual/refman/Makefile b/manual/manual/refman/Makefile new file mode 100644 index 0000000000..01aba6b409 --- /dev/null +++ b/manual/manual/refman/Makefile @@ -0,0 +1,25 @@ +FILES= refman.tex lex.tex names.tex values.tex const.tex types.tex \ + patterns.tex expr.tex typedecl.tex modtypes.tex modules.tex compunit.tex \ + exten.tex classes.tex + +TOPDIR=../../.. + +include $(TOPDIR)/Makefile.tools + +TRANSF=../../tools/transf +TEXQUOTE=../../tools/texquote2 + +ALLFILES=$(FILES) + +all: $(ALLFILES) + +clean: + rm -f $(ALLFILES) + +.SUFFIXES: +.SUFFIXES: .etex .tex + +.etex.tex: + $(OCAMLRUN) $(TRANSF) < $*.etex | $(TEXQUOTE) > $*.tex + +$(ALLFILES): $(TRANSF) $(TEXQUOTE) diff --git a/manual/manual/refman/classes.etex b/manual/manual/refman/classes.etex new file mode 100644 index 0000000000..a1b542f2da --- /dev/null +++ b/manual/manual/refman/classes.etex @@ -0,0 +1,496 @@ +\section{Classes} +\pdfsection{Classes} +%HEVEA\cutname{classes.html} +Classes are defined using a small language, similar to the module +language. + +\subsection{Class types} + +Class types are the class-level equivalent of type expressions: they +specify the general shape and type properties of classes. + +\ikwd{object\@\texttt{object}} +\ikwd{end\@\texttt{end}} +\ikwd{inherit\@\texttt{inherit}} +\ikwd{val\@\texttt{val}} +\ikwd{mutable\@\texttt{mutable}} +\ikwd{method\@\texttt{method}} +\ikwd{private\@\texttt{private}} +\ikwd{virtual\@\texttt{virtual}|see{\texttt{val}, \texttt{method}, \texttt{class}}} +\ikwd{constraint\@\texttt{constraint}} + +\begin{syntax} +class-type: + [['?']label-name':'] typexpr '->' class-type + | class-body-type +; +class-body-type: + 'object' ['(' typexpr ')'] {class-field-spec} 'end' + | ['[' typexpr {',' typexpr} ']'] classtype-path +; +%\end{syntax} \begin{syntax} +class-field-spec: + 'inherit' class-body-type + | 'val' ['mutable'] ['virtual'] inst-var-name ':' typexpr + | 'val' 'virtual' 'mutable' inst-var-name ':' typexpr + | 'method' ['private'] ['virtual'] method-name ':' poly-typexpr + | 'method' 'virtual' 'private' method-name ':' poly-typexpr + | 'constraint' typexpr '=' typexpr +\end{syntax} + +\subsubsection*{Simple class expressions} + +The expression @classtype-path@ is equivalent to the class type bound to +the name @classtype-path@. Similarly, the expression +@'[' typexpr_1 ',' \ldots typexpr_n ']' classtype-path@ is equivalent to +the parametric class type bound to the name @classtype-path@, in which +type parameters have been instantiated to respectively @typexpr_1@, +\ldots @typexpr_n@. + +\subsubsection*{Class function type} + +The class type expression @typexpr '->' class-type@ is the type of +class functions (functions from values to classes) that take as +argument a value of type @typexpr@ and return as result a class of +type @class-type@. + +\subsubsection*{Class body type} + +The class type expression +@'object' ['(' typexpr ')'] {class-field-spec} 'end'@ +is the type of a class body. It specifies its instance variables and +methods. In this type, @typexpr@ is matched against the self type, therefore +providing a name for the self type. + +A class body will match a class body type if it provides definitions +for all the components specified in the class body type, and these +definitions meet the type requirements given in the class body type. +Furthermore, all methods either virtual or public present in the class +body must also be present in the class body type (on the other hand, some +instance variables and concrete private methods may be omitted). A +virtual method will match a concrete method, which makes it possible +to forget its implementation. An immutable instance variable will match a +mutable instance variable. + +\subsubsection*{Inheritance} + +\ikwd{inherit\@\texttt{inherit}} + +The inheritance construct @'inherit' class-body-type@ provides for inclusion of +methods and instance variables from other class types. +The instance variable and method types from @class-body-type@ are added +into the current class type. + +\subsubsection*{Instance variable specification} + +\ikwd{val\@\texttt{val}} +\ikwd{mutable\@\texttt{mutable}} + +A specification of an instance variable is written +@'val' ['mutable'] ['virtual'] inst-var-name ':' typexpr@, where +@inst-var-name@ +is the name of the instance variable and @typexpr@ its expected type. +% +The flag @'mutable'@ indicates whether this instance variable can be +physically modified. +% +The flag @'virtual'@ indicates that this instance variable is not +initialized. It can be initialized later through inheritance. + +An instance variable specification will hide any previous +specification of an instance variable of the same name. + +\subsubsection*{Method specification} +\label{sec-methspec} + +\ikwd{method\@\texttt{method}} +\ikwd{private\@\texttt{private}} + +The specification of a method is written +@'method' ['private'] method-name ':' poly-typexpr@, where +@method-name@ is the name of the method and @poly-typexpr@ its +expected type, possibly polymorphic. The flag @'private'@ indicates +that the method cannot be accessed from outside the object. + +The polymorphism may be left implicit in public method specifications: +any type variable which is not bound to a class parameter and does not +appear elsewhere inside the class specification will be assumed to be +universal, and made polymorphic in the resulting method type. +Writing an explicit polymorphic type will disable this behaviour. + +If several specifications are present for the same method, they +must have compatible types. +Any non-private specification of a method forces it to be public. + +\subsubsection*{Virtual method specification} + +\ikwd{method\@\texttt{method}} +\ikwd{private\@\texttt{private}} + +A virtual method specification is written @'method' ['private'] +'virtual' method-name ':' poly-typexpr@, where @method-name@ is the +name of the method and @poly-typexpr@ its expected type. + +\subsubsection*{Constraints on type parameters} + +\ikwd{constraint\@\texttt{constraint}} + +The construct @'constraint' typexpr_1 '=' typexpr_2@ forces the two +type expressions to be equal. This is typically used to specify type +parameters: in this way, they can be bound to specific type +expressions. + +\subsection{Class expressions} + +Class expressions are the class-level equivalent of value expressions: +they evaluate to classes, thus providing implementations for the +specifications expressed in class types. + +\ikwd{object\@\texttt{object}} +\ikwd{end\@\texttt{end}} +\ikwd{fun\@\texttt{fun}} +\ikwd{let\@\texttt{let}} +\ikwd{and\@\texttt{and}} +\ikwd{inherit\@\texttt{inherit}} +\ikwd{as\@\texttt{as}} +\ikwd{val\@\texttt{val}} +\ikwd{mutable\@\texttt{mutable}} +\ikwd{method\@\texttt{method}} +\ikwd{private\@\texttt{private}} +\ikwd{constraint\@\texttt{constraint}} +\ikwd{initializer\@\texttt{initializer}} + +\begin{syntax} +class-expr: + class-path + | '[' typexpr {',' typexpr} ']' class-path + | '(' class-expr ')' + | '(' class-expr ':' class-type ')' + | class-expr {{argument}} + | 'fun' {{parameter}} '->' class-expr + | 'let' ['rec'] let-binding {'and' let-binding} 'in' class-expr + | 'object' class-body 'end' +; +%BEGIN LATEX +\end{syntax} \begin{syntax} +%END LATEX +class-field: + 'inherit' class-expr ['as' lowercase-ident] + | 'val' ['mutable'] inst-var-name [':' typexpr] '=' expr + | 'val' ['mutable'] 'virtual' inst-var-name ':' typexpr + | 'val' 'virtual' 'mutable' inst-var-name ':' typexpr + | 'method' ['private'] method-name {parameter} [':' typexpr] '=' expr + | 'method' ['private'] method-name ':' poly-typexpr '=' expr + | 'method' ['private'] 'virtual' method-name ':' poly-typexpr + | 'method' 'virtual' 'private' method-name ':' poly-typexpr + | 'constraint' typexpr '=' typexpr + | 'initializer' expr +\end{syntax} + +\subsubsection*{Simple class expressions} + +The expression @class-path@ evaluates to the class bound to the name +@class-path@. Similarly, the expression +@'[' typexpr_1 ',' \ldots typexpr_n ']' class-path@ +evaluates to the parametric class bound to the name @class-path@, +in which type parameters have been instantiated respectively to +@typexpr_1@, \ldots @typexpr_n@. + +The expression @'(' class-expr ')'@ evaluates to the same module as +@class-expr@. + +The expression @'(' class-expr ':' class-type ')'@ checks that +@class-type@ matches the type of @class-expr@ (that is, that the +implementation @class-expr@ meets the type specification +@class-type@). The whole expression evaluates to the same class as +@class-expr@, except that all components not specified in +@class-type@ are hidden and can no longer be accessed. + +\subsubsection*{Class application} + +Class application is denoted by juxtaposition of (possibly labeled) +expressions. It denotes the class whose constructor is the first +expression applied to the given arguments. The arguments are +evaluated as for expression application, but the constructor itself will +only be evaluated when objects are created. In particular, side-effects +caused by the application of the constructor will only occur at object +creation time. + +\subsubsection*{Class function} + +The expression @'fun' [['?']label-name':']pattern '->' class-expr@ evaluates +to a function from values to classes. +When this function is applied to a value \var{v}, this value is +matched against the pattern @pattern@ and the result is the result of +the evaluation of @class-expr@ in the extended environment. + +Conversion from functions with default values to functions with +patterns only works identically for class functions as for normal +functions. + +The expression +\begin{center} +@"fun" parameter_1 \ldots parameter_n "->" class-expr@ +\end{center} +is a short form for +\begin{center} +@"fun" parameter_1 "->" \ldots "fun" parameter_n "->" expr@ +\end{center} + +\subsubsection*{Local definitions} + +The {\tt let} and {\tt let rec} constructs bind value names locally, +as for the core language expressions. + +If a local definition occurs at the very beginning of a class +definition, it will be evaluated when the class is created (just as if +the definition was outside of the class). +Otherwise, it will be evaluated when the object constructor is called. + + +\subsubsection*{Class\label{ss:class-body} body} +\begin{syntax} +class-body: ['(' pattern [':' typexpr] ')'] { class-field } +\end{syntax} +The expression +@'object' class-body 'end'@ denotes +a class body. This is the prototype for an object : it lists the +instance variables and methods of an objet of this class. + +A class body is a class value: it is not evaluated at once. Rather, +its components are evaluated each time an object is created. + +In a class body, the pattern @'(' pattern [':' typexpr] ')'@ is +matched against self, therefore providing a binding for self and self +type. Self can only be used in method and initializers. + +Self type cannot be a closed object type, so that the class remains +extensible. + +Since OCaml 4.01, it is an error if the same method or instance +variable name is defined several times in the same class body. + +\subsubsection*{Inheritance} + +\ikwd{inherit\@\texttt{inherit}} + +The inheritance construct @'inherit' class-expr@ allows reusing +methods and instance variables from other classes. The class +expression @class-expr@ must evaluate to a class body. The instance +variables, methods and initializers from this class body are added +into the current class. The addition of a method will override any +previously defined method of the same name. + +\ikwd{as\@\texttt{as}} +An ancestor can be bound by appending @'as' lowercase-ident@ +to the inheritance construct. @lowercase-ident@ is not a true +variable and can only be used to select a method, i.e. in an expression +@lowercase-ident '#' method-name@. This gives access to the +method @method-name@ as it was defined in the parent class even if it is +redefined in the current class. +The scope of this ancestor binding is limited to the current class. +The ancestor method may be called from a subclass but only indirectly. + +\subsubsection*{Instance variable definition} + +\ikwd{val\@\texttt{val}} +\ikwd{mutable\@\texttt{mutable}} + +The definition @'val' ['mutable'] inst-var-name '=' expr@ adds an +instance variable @inst-var-name@ whose initial value is the value of +expression @expr@. +% +The flag @'mutable'@ allows physical modification of this variable by +methods. + +An instance variable can only be used in the methods and +initializers that follow its definition. + +Since version 3.10, redefinitions of a visible instance variable with +the same name do not create a new variable, but are merged, using the +last value for initialization. They must have identical types and +mutability. +However, if an instance variable is hidden by +omitting it from an interface, it will be kept distinct from +other instance variables with the same name. + +\subsubsection*{Virtual instance variable definition} + +\ikwd{val\@\texttt{val}} +\ikwd{mutable\@\texttt{mutable}} + +A variable specification is written @'val' ['mutable'] 'virtual' +inst-var-name ':' typexpr@. It specifies whether the variable is +modifiable, and gives its type. + +Virtual instance variables were added in version 3.10. + +\subsubsection*{Method definition} + +\ikwd{method\@\texttt{method}} +\ikwd{private\@\texttt{private}} + +A method definition is written @'method' method-name '=' expr@. The +definition of a method overrides any previous definition of this +method. The method will be public (that is, not private) if any of +the definition states so. + +A private method, @'method' 'private' method-name '=' expr@, is a +method that can only be invoked on self (from other methods of the +same object, defined in this class or one of its subclasses). This +invocation is performed using the expression +@value-name '#' method-name@, where @value-name@ is directly bound to +self at the beginning of the class definition. Private methods do +not appear in object types. A method may have both public and private +definitions, but as soon as there is a public one, all subsequent +definitions will be made public. + +Methods may have an explicitly polymorphic type, allowing them to be +used polymorphically in programs (even for the same object). The +explicit declaration may be done in one of three ways: (1) by giving an +explicit polymorphic type in the method definition, immediately after +the method name, {\em i.e.} +@'method' ['private'] method-name ':' {{"'" ident}} '.' typexpr '=' +expr@; (2) by a forward declaration of the explicit polymorphic type +through a virtual method definition; (3) by importing such a +declaration through inheritance and/or constraining the type of {\em +self}. + +Some special expressions are available in method bodies for +manipulating instance variables and duplicating self: +\begin{syntax} +expr: + \ldots + | inst-var-name '<-' expr + | '{<' [ inst-var-name '=' expr { ';' inst-var-name '=' expr } [';'] ] '>}' +\end{syntax} + +The expression @inst-var-name '<-' expr@ modifies in-place the current +object by replacing the value associated to @inst-var-name@ by the +value of @expr@. Of course, this instance variable must have been +declared mutable. + +The expression +@'{<' inst-var-name_1 '=' expr_1 ';' \ldots ';' inst-var-name_n '=' expr_n '>}'@ +evaluates to a copy of the current object in which the values of +instance variables @inst-var-name_1, \ldots, inst-var-name_n@ have +been replaced by the values of the corresponding expressions @expr_1, +\ldots, expr_n@. + +\subsubsection*{Virtual method definition} + +\ikwd{method\@\texttt{method}} +\ikwd{private\@\texttt{private}} + +A method specification is written @'method' ['private'] 'virtual' +method-name ':' poly-typexpr@. It specifies whether the method is +public or private, and gives its type. If the method is intended to be +polymorphic, the type must be explicitly polymorphic. + +\subsubsection*{Constraints on type parameters} + +\ikwd{constraint\@\texttt{constraint}} + +The construct @'constraint' typexpr_1 '=' typexpr_2@ forces the two +type expressions to be equals. This is typically used to specify type +parameters: in that way they can be bound to specific type +expressions. + +\subsubsection*{Initializers} + +\ikwd{initializer\@\texttt{initializer}} + +A class initializer @'initializer' expr@ specifies an expression that +will be evaluated whenever an object is created from the class, once +all its instance variables have been initialized. + +\subsection{Class definitions} +\label{s:classdef} + +\ikwd{class\@\texttt{class}} +\ikwd{and\@\texttt{and}} + +\begin{syntax} +class-definition: + 'class' class-binding { 'and' class-binding } +; +class-binding: + ['virtual'] ['[' type-parameters ']'] class-name + {parameter} [':' class-type] \\ '=' class-expr +; +type-parameters: + "'" ident { "," "'" ident } +\end{syntax} + +A class definition @'class' class-binding { 'and' class-binding }@ is +recursive. Each @class-binding@ defines a @class-name@ that can be +used in the whole expression except for inheritance. It can also be +used for inheritance, but only in the definitions that follow its own. + +A class binding binds the class name @class-name@ to the value of +expression @class-expr@. It also binds the class type @class-name@ to +the type of the class, and defines two type abbreviations : +@class-name@ and @'#' class-name@. The first one is the type of +objects of this class, while the second is more general as it unifies +with the type of any object belonging to a subclass (see +section~\ref{s:sharp-types}). + +\subsubsection*{Virtual class} + +A class must be flagged virtual if one of its methods is virtual (that +is, appears in the class type, but is not actually defined). +Objects cannot be created from a virtual class. + +\subsubsection*{Type parameters} + +The class type parameters correspond to the ones of the class type and +of the two type abbreviations defined by the class binding. They must +be bound to actual types in the class definition using type +constraints. So that the abbreviations are well-formed, type +variables of the inferred type of the class must either be type +parameters or be bound in the constraint clause. + +\subsection{Class specifications} +\label{s:class-spec} + +\ikwd{class\@\texttt{class}} +\ikwd{and\@\texttt{and}} + +\begin{syntax} +class-specification: + 'class' class-spec { 'and' class-spec } +; +class-spec: + ['virtual'] ['[' type-parameters ']'] class-name ':' + class-type +\end{syntax} + +This is the counterpart in signatures of class definitions. +A class specification matches a class definition if they have the same +type parameters and their types match. + +\subsection{Class type definitions} +\label{s:classtype} + +\ikwd{class\@\texttt{class}} +\ikwd{type\@\texttt{type}} +\ikwd{and\@\texttt{and}} + +\begin{syntax} +classtype-definition: + 'class' 'type' classtype-def + { 'and' classtype-def } +; +classtype-def: + ['virtual'] ['[' type-parameters ']'] class-name '=' class-body-type +\end{syntax} + +A class type definition @'class' class-name '=' class-body-type@ +defines an abbreviation @class-name@ for the class body type +@class-body-type@. As for class definitions, two type abbreviations +@class-name@ and @'#' class-name@ are also defined. The definition can +be parameterized by some type parameters. If any method in the class +type body is virtual, the definition must be flagged @'virtual'@. + +Two class type definitions match if they have the same type parameters +and they expand to matching types. diff --git a/manual/manual/refman/compunit.etex b/manual/manual/refman/compunit.etex new file mode 100644 index 0000000000..6c8c09f790 --- /dev/null +++ b/manual/manual/refman/compunit.etex @@ -0,0 +1,42 @@ +\section{Compilation units} +\pdfsection{Compilation units} +%HEVEA\cutname{compunit.html} + +\begin{syntax} +unit-interface: { specification [';;'] } +; +unit-implementation: [ module-items ] +\end{syntax} + +Compilation units bridge the module system and the separate +compilation system. A compilation unit is composed of two parts: an +interface and an implementation. The interface contains a sequence of +specifications, just as the inside of a @'sig' \ldots 'end'@ +signature expression. The implementation contains a sequence of +definitions and expressions, just as the inside of a +@'struct' \ldots 'end'@ module +expression. A compilation unit also has a name @unit-name@, derived +from the names of the files containing the interface and the +implementation (see chapter~\ref{c:camlc} for more details). A +compilation unit behaves roughly as the module definition +\begin{center} +@'module' unit-name ':' 'sig' unit-interface 'end' '=' + 'struct' unit-implementation 'end'@ +\end{center} + +A compilation unit can refer to other compilation units by their +names, as if they were regular modules. For instance, if "U" is a +compilation unit that defines a type "t", other compilation units can +refer to that type under the name "U.t"; they can also refer to "U" as +a whole structure. Except for names of other compilation units, a unit +interface or unit implementation must not have any other free variables. +In other terms, the type-checking and compilation of an interface or +implementation proceeds in the initial environment +\begin{center} +@name_1 ':' 'sig' specification_1 'end' \ldots + name_n ':' 'sig' specification_n 'end'@ +\end{center} +where @name_1 \ldots name_n@ are the names of the other +compilation units available in the search path (see +chapter~\ref{c:camlc} for more details) and @specification_1 \ldots +specification_n@ are their respective interfaces. diff --git a/manual/manual/refman/const.etex b/manual/manual/refman/const.etex new file mode 100644 index 0000000000..e0a18ece0e --- /dev/null +++ b/manual/manual/refman/const.etex @@ -0,0 +1,31 @@ +\section{Constants} +\pdfsection{Constants} +%HEVEA\cutname{const.html} + +\ikwd{false\@\texttt{false}} +\ikwd{true\@\texttt{true}} +\ikwd{begin\@\texttt{begin}} +\ikwd{end\@\texttt{end}} + +\begin{syntax} +constant: + integer-literal + | float-literal + | char-literal + | string-literal + | constr + | "false" + | "true" + | "("")" + | "begin" "end" + | "[""]" + | "[|""|]" + | "`"tag-name +\end{syntax} + +The syntactic class of constants comprises literals from the four +base types (integers, floating-point numbers, characters, character +strings), and constant constructors from both normal and polymorphic +variants, as well as the special constants @"false"@, @"true"@, @"("")"@, +@"[""]"@, and @"[|""|]"@, which behave like constant constructors, and +@"begin" "end"@, which is equivalent to @'('')'@. diff --git a/manual/manual/refman/expr.etex b/manual/manual/refman/expr.etex new file mode 100644 index 0000000000..18a1c4481b --- /dev/null +++ b/manual/manual/refman/expr.etex @@ -0,0 +1,947 @@ +\section{Expressions\label{s:value-expr}} +\pdfsection{Expressions} +%HEVEA\cutname{expr.html} +\ikwd{in\@\texttt{in}|see{\texttt{let}}} +\ikwd{and\@\texttt{and}} +\ikwd{rec\@\texttt{rec}|see{\texttt{let}, \texttt{module}}} +\ikwd{let\@\texttt{let}} +\ikwd{try\@\texttt{try}} +\ikwd{function\@\texttt{function}} +\ikwd{fun\@\texttt{fun}} +\ikwd{with\@\texttt{with}} +\ikwd{done\@\texttt{done}|see{\texttt{while}, \texttt{for}}} +\ikwd{do\@\texttt{do}|see{\texttt{while}, \texttt{for}}} +\ikwd{downto\@\texttt{downto}|see{\texttt{for}}} +\ikwd{to\@\texttt{to}|see{\texttt{for}}} +\ikwd{for\@\texttt{for}} +\ikwd{else\@\texttt{else}|see{\texttt{if}}} +\ikwd{then\@\texttt{then}|see{\texttt{if}}} +\ikwd{if\@\texttt{if}} +\ikwd{or\@\texttt{or}} +\ikwd{match\@\texttt{match}} +\ikwd{begin\@\texttt{begin}} +\ikwd{end\@\texttt{end}} +\ikwd{when\@\texttt{when}} +\ikwd{new\@\texttt{new}} +\ikwd{object\@\texttt{object}} +\ikwd{lazy\@\texttt{lazy}} + +\begin{syntax} +expr: + value-path + | constant + | '(' expr ')' + | 'begin' expr 'end' + | '(' expr ':' typexpr ')' + | expr {{',' expr}} + | constr expr + | "`"tag-name expr + | expr '::' expr + | '[' expr { ';' expr } [';'] ']' + | '[|' expr { ';' expr } [';'] '|]' + | '{' field [':' typexpr] '=' expr% + { ';' field [':' typexpr] '=' expr } [';'] '}' + | '{' expr 'with' field [':' typexpr] '=' expr% + { ';' field [':' typexpr] '=' expr } [';'] '}' + | expr {{ argument }} + | prefix-symbol expr + | '-' expr + | '-.' expr + | expr infix-op expr + | expr '.' field + | expr '.' field '<-' expr + | expr '.(' expr ')' + | expr '.(' expr ')' '<-' expr + | expr '.[' expr ']' + | expr '.[' expr ']' '<-' expr + | 'if' expr 'then' expr [ 'else' expr ] + | 'while' expr 'do' expr 'done' + | 'for' value-name '=' expr ( 'to' || 'downto' ) expr 'do' expr 'done' + | expr ';' expr + | 'match' expr 'with' pattern-matching + | 'function' pattern-matching + | 'fun' {{ parameter }} [ ':' typexpr ] '->' expr + | 'try' expr 'with' pattern-matching + | 'let' ['rec'] let-binding { 'and' let-binding } 'in' expr + | 'new' class-path + | 'object' class-body 'end' + | expr '#' method-name + | inst-var-name + | inst-var-name '<-' expr + | '(' expr ':>' typexpr ')' + | '(' expr ':' typexpr ':>' typexpr ')' + | '{<' [ inst-var-name '=' expr { ';' inst-var-name '=' expr } [';'] ] '>}' + | 'assert' expr + | 'lazy' expr + | 'let' 'module' module-name { '(' module-name ':' module-type ')' } + [ ':' module-type ] \\ '=' module-expr 'in' expr + +; +%BEGIN LATEX +\end{syntax} \begin{syntax} +%END LATEX +argument: + expr + | '~' label-name + | '~' label-name ':' expr + | '?' label-name + | '?' label-name ':' expr +; +%\end{syntax} \begin{syntax} +pattern-matching: + [ '|' ] pattern ['when' expr] '->' expr + { '|' pattern ['when' expr] '->' expr } +; +let-binding: + pattern '=' expr + | value-name { parameter } [':' typexpr] [':>' typexpr] '=' expr +; +parameter: + pattern + | '~' label-name + | '~' '(' label-name [':' typexpr] ')' + | '~' label-name ':' pattern + | '?' label-name + | '?' '(' label-name [':' typexpr] ['=' expr] ')' + | '?' label-name ':' pattern + | '?' label-name ':' '(' pattern [':' typexpr] ['=' expr] ')' +\end{syntax} + +The table below shows the relative precedences and associativity of +operators and non-closed constructions. The constructions with higher +precedence come first. For infix and prefix symbols, we write +``"*"\ldots'' to mean ``any symbol starting with "*"''. +\ikwd{or\@\texttt{or}}% +\ikwd{if\@\texttt{if}}% +\ikwd{fun\@\texttt{fun}}% +\ikwd{function\@\texttt{function}}% +\ikwd{match\@\texttt{match}}% +\ikwd{try\@\texttt{try}}% +\ikwd{let\@\texttt{let}}% +\ikwd{mod\@\texttt{mod}} +\ikwd{land\@\texttt{land}} +\ikwd{lor\@\texttt{lor}} +\ikwd{lxor\@\texttt{lxor}} +\ikwd{lsl\@\texttt{lsl}} +\ikwd{lsr\@\texttt{lsr}} +\ikwd{asr\@\texttt{asr}} +\begin{tableau}{|l|l|}{Construction or operator}{Associativity} +\entree{prefix-symbol}{--} +\entree{". .( .[ .{" (see section~\ref{s:bigarray-access})}{--} +\entree{"#"\ldots}{--} +\entree{function application, constructor application, tag + application, "assert", + "lazy"}{left} +\entree{"- -." (prefix)}{--} +\entree{"**"\ldots" lsl lsr asr"}{right} +\entree{"*"\ldots" /"\ldots" %"\ldots" mod land lor lxor"}{left} + %% "`"@ident@"`" +\entree{"+"\ldots" -"\ldots}{left} +\entree{"::"}{right} +\entree{{\tt \char64}\ldots " ^"\ldots}{right} +\entree{"="\ldots" <"\ldots" >"\ldots" |"\ldots" &"\ldots" $"\ldots" !="}{left} +\entree{"& &&"}{right} +\entree{"or ||"}{right} +\entree{","}{--} +\entree{"<- :="}{right} +\entree{"if"}{--} +\entree{";"}{right} +\entree{"let match fun function try"}{--} +\end{tableau} + +\subsection{Basic expressions} + +\subsubsection*{Constants} + +An expression consisting in a constant evaluates to this constant. + +\subsubsection*{Value paths} \label{expr:var} + +An expression consisting in an access path evaluates to the value bound to +this path in the current evaluation environment. The path can +be either a value name or an access path to a value component of a module. + +\subsubsection*{Parenthesized expressions} +\ikwd{begin\@\texttt{begin}} +\ikwd{end\@\texttt{end}} + +The expressions @'(' expr ')'@ and @'begin' expr 'end'@ have the same +value as @expr@. The two constructs are semantically equivalent, but it +is good style to use @'begin' \ldots 'end'@ inside control structures: +\begin{alltt} + if \ldots then begin \ldots ; \ldots end else begin \ldots ; \ldots end +\end{alltt} +and @'(' \ldots ')'@ for the other grouping situations. + +Parenthesized expressions can contain a type constraint, as in @'(' +expr ':' typexpr ')'@. This constraint forces the type of @expr@ to be +compatible with @typexpr@. + +Parenthesized expressions can also contain coercions +@'(' expr [':' typexpr] ':>' typexpr')'@ (see +subsection~\ref{s:coercions} below). + + +\subsubsection*{Function application} + +Function application is denoted by juxtaposition of (possibly labeled) +expressions. The expression @expr argument_1 \ldots argument_n@ +evaluates the expression @expr@ and those appearing in @argument_1@ +to @argument_n@. The expression @expr@ must evaluate to a +functional value $f$, which is then applied to the values of +@argument_1, \ldots, argument_n@. + +The order in which the expressions @expr, argument_1, \ldots, +argument_n@ are evaluated is not specified. + +Arguments and parameters are matched according to their respective +labels. Argument order is irrelevant, except among arguments with the +same label, or no label. + +If a parameter is specified as optional (label prefixed by @"?"@) in the +type of @expr@, the corresponding argument will be automatically +wrapped with the constructor "Some", except if the argument itself is +also prefixed by @"?"@, in which case it is passed as is. +% +If a non-labeled argument is passed, and its corresponding parameter +is preceded by one or several optional parameters, then these +parameters are {\em defaulted}, {\em i.e.} the value "None" will be +passed for them. +% +All other missing parameters (without corresponding argument), both +optional and non-optional, will be kept, and the result of the +function will still be a function of these missing parameters to the +body of $f$. + +As a special case, if the function has a known arity, all the +arguments are unlabeled, and their number matches the number of +non-optional parameters, then labels are ignored and non-optional +parameters are matched in their definition order. Optional arguments +are defaulted. + +In all cases but exact match of order and labels, without optional +parameters, the function type should be known at the application +point. This can be ensured by adding a type constraint. Principality +of the derivation can be checked in the "-principal" mode. + +\subsubsection*{Function definition} + +Two syntactic forms are provided to define functions. The first form +is introduced by the keyword "function": +\ikwd{function\@\texttt{function}} + +$$\begin{array}{rlll} +\token{function} & \textsl{pattern}_1 & \token{->} & \textsl{expr}_1 \\ +\token{|} & \ldots \\ +\token{|} & \textsl{pattern}_n & \token{->} & \textsl{expr}_n +\end{array}$$ +This expression evaluates to a functional value with one argument. +When this function is applied to a value \var{v}, this value is +matched against each pattern @pattern_1@ to @pattern_n@. +If one of these matchings succeeds, that is, if the value \var{v} +matches the pattern @pattern_i@ for some \var{i}, +then the expression @expr_i@ associated to the selected pattern +is evaluated, and its value becomes the value of the function +application. The evaluation of @expr_i@ takes place in an +environment enriched by the bindings performed during the matching. + +If several patterns match the argument \var{v}, the one that occurs +first in the function definition is selected. If none of the patterns +matches the argument, the exception "Match_failure" is raised. +% +\index{Matchfailure\@\verb`Match_failure`} + +\medskip + +The other form of function definition is introduced by the keyword "fun": +\ikwd{fun\@\texttt{fun}} +\begin{center} +@"fun" parameter_1 \ldots parameter_n "->" expr@ +\end{center} +This expression is equivalent to: +\begin{center} +@"fun" parameter_1 "->" \ldots "fun" parameter_n "->" expr@ +\end{center} + +An optional type constraint @typexpr@ can be added before "->" to enforce +the type of the result to be compatible with the constraint @typexpr@: +\begin{center} +@"fun" parameter_1 \ldots parameter_n ":" typexpr "->" expr@ +\end{center} +is equivalent to +\begin{center} + @"fun" parameter_1 "->" \ldots "fun" parameter_n "->" % + (expr ":" typexpr )@ +\end{center} +Beware of the small syntactic difference between a type constraint on +the last parameter +\begin{center} + @"fun" parameter_1 \ldots (parameter_n":"typexpr)"->" expr @ +\end{center} +and one on the result +\begin{center} + @"fun" parameter_1 \ldots parameter_n":" typexpr "->" expr @ +\end{center} + +The parameter patterns @"~"lab@ and @"~("lab [":" typ]")"@ +are shorthands for respectively @"~"lab":"lab@ and +@"~"lab":("lab [":" typ]")"@, and similarly for their optional +counterparts. + +A function of the form @"fun" "?" lab ":(" pattern '=' expr_0 ')' '->' +expr@ is equivalent to +\begin{center} +@"fun" "?" lab ":" ident '->' + "let" pattern '=' + "match" ident "with" "Some" ident "->" ident '|' "None" '->' expr_0 + "in" expr@ +\end{center} +where @ident@ +is a fresh variable, except that it is unspecified when @expr_0@ is evaluated. + +After these two transformations, expressions are of the form +\begin{center} +@"fun" [label_1] pattern_1 "->" \ldots "fun" [label_n] pattern_n "->" expr@ +\end{center} +If we ignore labels, which will only be meaningful at function +application, this is equivalent to +\begin{center} +@"function" pattern_1 "->" \ldots "function" pattern_n "->" expr@ +\end{center} +That is, the @"fun"@ expression above evaluates to a curried function +with \var{n} arguments: after applying this function $n$ times to the +values @@v@_1 \ldots @v@_n@, the values will be matched +in parallel against the patterns @pattern_1 \ldots pattern_n@. +If the matching succeeds, the function returns the value of @expr@ in +an environment enriched by the bindings performed during the matchings. +If the matching fails, the exception "Match_failure" is raised. + +\subsubsection*{Guards in pattern-matchings} + +\ikwd{when\@\texttt{when}} +The cases of a pattern matching (in the @"function"@, @"match"@ and +@"try"@ constructs) can include guard expressions, which are +arbitrary boolean expressions that must evaluate to "true" for the +match case to be selected. Guards occur just before the @"->"@ token and +are introduced by the @"when"@ keyword: + +$$\begin{array}{rlll} +\token{function} & \nt{pattern}_1 \; [\token{when} \; \nt{cond}_1] & \token{->} & \nt{expr}_1 \\ +\token{|} & \ldots \\ +\token{|} & \nt{pattern}_n \; [\token{when} \; \nt{cond}_n] & \token{->} & \nt{expr}_n +\end{array}$$ + + +Matching proceeds as described before, except that if the value +matches some pattern @pattern_i@ which has a guard @@cond@_i@, then the +expression @@cond@_i@ is evaluated (in an environment enriched by the +bindings performed during matching). If @@cond@_i@ evaluates to "true", +then @expr_i@ is evaluated and its value returned as the result of the +matching, as usual. But if @@cond@_i@ evaluates to "false", the matching +is resumed against the patterns following @pattern_i@. + +\subsubsection*{Local definitions} \label{s:localdef} + +\ikwd{let\@\texttt{let}} + +The @"let"@ and @"let" "rec"@ constructs bind value names locally. +The construct +\begin{center} +@"let" pattern_1 "=" expr_1 "and" \ldots "and" pattern_n "=" expr_n "in" expr@ +\end{center} +evaluates @expr_1 \ldots expr_n@ in some unspecified order and matches +their values against the patterns @pattern_1 \ldots pattern_n@. If the +matchings succeed, @expr@ is evaluated in the environment enriched by +the bindings performed during matching, and the value of @expr@ is +returned as the value of the whole @"let"@ expression. If one of the +matchings fails, the exception "Match_failure" is raised. +% +\index{Matchfailure\@\verb`Match_failure`} + +An alternate syntax is provided to bind variables to functional +values: instead of writing +\begin{center} +@"let" ident "=" "fun" parameter_1 \ldots parameter_m "->" expr@ +\end{center} +in a @"let"@ expression, one may instead write +\begin{center} +@"let" ident parameter_1 \ldots parameter_m "=" expr@ +\end{center} + +\medskip +\noindent +Recursive definitions of names are introduced by @"let" "rec"@: +\begin{center} +@"let" "rec" pattern_1 "=" expr_1 "and" \ldots "and" pattern_n "=" expr_n + "in" expr@ +\end{center} +The only difference with the @"let"@ construct described above is +that the bindings of names to values performed by the +pattern-matching are considered already performed when the expressions +@expr_1@ to @expr_n@ are evaluated. That is, the expressions @expr_1@ +to @expr_n@ can reference identifiers that are bound by one of the +patterns @pattern_1, \ldots, pattern_n@, and expect them to have the +same value as in @expr@, the body of the @"let" "rec"@ construct. + +The recursive definition is guaranteed to behave as described above if +the expressions @expr_1@ to @expr_n@ are function definitions +(@"fun" \ldots@ or @"function" \ldots@), and the patterns @pattern_1 +\ldots pattern_n@ are just value names, as in: +\begin{center} +@"let" "rec" name_1 "=" "fun" \ldots +"and" \ldots +"and" name_n "=" "fun" \ldots +"in" expr@ +\end{center} +This defines @name_1 \ldots name_n@ as mutually recursive functions +local to @expr@. + +The behavior of other forms of @"let" "rec"@ definitions is +implementation-dependent. The current implementation also supports +a certain class of recursive definitions of non-functional values, +as explained in section~\ref{s:letrecvalues}. + +\subsection{Control structures} + +\subsubsection*{Sequence} + +The expression @expr_1 ";" expr_2@ evaluates @expr_1@ first, then +@expr_2@, and returns the value of @expr_2@. + +\subsubsection*{Conditional} +\ikwd{if\@\texttt{if}} + +The expression @"if" expr_1 "then" expr_2 "else" expr_3@ evaluates to +the value of @expr_2@ if @expr_1@ evaluates to the boolean @"true"@, +and to the value of @expr_3@ if @expr_1@ evaluates to the boolean +@"false"@. + +The @"else" expr_3@ part can be omitted, in which case it defaults to +@"else" "()"@. + +\subsubsection*{Case expression}\ikwd{match\@\texttt{match}} + +The expression +$$\begin{array}{rlll} +\token{match} & \textsl{expr} \\ +\token{with} & \textsl{pattern}_1 & \token{->} & \textsl{expr}_1 \\ +\token{|} & \ldots \\ +\token{|} & \textsl{pattern}_n & \token{->} & \textsl{expr}_n +\end{array}$$ +matches the value of @expr@ against the patterns @pattern_1@ to +@pattern_n@. If the matching against @pattern_i@ succeeds, the +associated expression @expr_i@ is evaluated, and its value becomes the +value of the whole @'match'@ expression. The evaluation of +@expr_i@ takes place in an environment enriched by the bindings +performed during matching. If several patterns match the value of +@expr@, the one that occurs first in the @'match'@ expression is +selected. If none of the patterns match the value of @expr@, the +exception "Match_failure" is raised. +% +\index{Matchfailure\@\verb`Match_failure`} + +\subsubsection*{Boolean operators} + +The expression @expr_1 '&&' expr_2@ evaluates to @'true'@ if both +@expr_1@ and @expr_2@ evaluate to @'true'@; otherwise, it evaluates to +@'false'@. The first component, @expr_1@, is evaluated first. The +second component, @expr_2@, is not evaluated if the first component +evaluates to @'false'@. Hence, the expression @expr_1 '&&' expr_2@ behaves +exactly as +\begin{center} +@'if' expr_1 'then' expr_2 'else' 'false'@. +\end{center} + +The expression @expr_1 '||' expr_2@ evaluates to @'true'@ if one of +the expressions +@expr_1@ and @expr_2@ evaluates to @'true'@; otherwise, it evaluates to +@'false'@. The first component, @expr_1@, is evaluated first. The +second component, @expr_2@, is not evaluated if the first component +evaluates to @'true'@. Hence, the expression @expr_1 '||' expr_2@ behaves +exactly as +\begin{center} +@'if' expr_1 'then' 'true' 'else' expr_2@. +\end{center} + +\ikwd{or\@\texttt{or}} +The boolean operators @'&'@ and @'or'@ are deprecated synonyms for +(respectively) @'&&'@ and @'||'@. + +\subsubsection*{Loops} + +\ikwd{while\@\texttt{while}} +The expression @'while' expr_1 'do' expr_2 'done'@ repeatedly +evaluates @expr_2@ while @expr_1@ evaluates to @'true'@. The loop +condition @expr_1@ is evaluated and tested at the beginning of each +iteration. The whole @'while' \ldots 'done'@ expression evaluates to +the unit value @'()'@. + +\ikwd{for\@\texttt{for}} +The expression @'for' name '=' expr_1 'to' expr_2 'do' expr_3 'done'@ +first evaluates the expressions @expr_1@ and @expr_2@ (the boundaries) +into integer values \var{n} and \var{p}. Then, the loop body @expr_3@ is +repeatedly evaluated in an environment where @name@ is successively +bound to the values + $n$, $n+1$, \ldots, $p-1$, $p$. + The loop body is never evaluated if $n > p$. + + +The expression @'for' name '=' expr_1 'downto' expr_2 'do' expr_3 'done'@ +evaluates similarly, except that @name@ is successively bound to the values + $n$, $n-1$, \ldots, $p+1$, $p$. + The loop body is never evaluated if $n < p$. + + +In both cases, the whole @'for'@ expression evaluates to the unit +value @'()'@. + +\subsubsection*{Exception handling} +\ikwd{try\@\texttt{try}} + +The expression +$$\begin{array}{rlll} +\token{try~} & \textsl{expr} \\ +\token{with} & \textsl{pattern}_1 & \token{->} & \textsl{expr}_1 \\ +\token{|} & \ldots \\ +\token{|} & \textsl{pattern}_n & \token{->} & \textsl{expr}_n +\end{array}$$ +evaluates the expression @expr@ and returns its value if the +evaluation of @expr@ does not raise any exception. If the evaluation +of @expr@ raises an exception, the exception value is matched against +the patterns @pattern_1@ to @pattern_n@. If the matching against +@pattern_i@ succeeds, the associated expression @expr_i@ is evaluated, +and its value becomes the value of the whole @'try'@ expression. The +evaluation of @expr_i@ takes place in an environment enriched by the +bindings performed during matching. If several patterns match the value of +@expr@, the one that occurs first in the @'try'@ expression is +selected. If none of the patterns matches the value of @expr@, the +exception value is raised again, thereby transparently ``passing +through'' the @'try'@ construct. + +\subsection{Operations on data structures} + +\subsubsection*{Products} + +The expression @expr_1 ',' \ldots ',' expr_n@ evaluates to the +\var{n}-tuple of the values of expressions @expr_1@ to @expr_n@. The +evaluation order of the subexpressions is not specified. + +\subsubsection*{Variants} + +The expression @constr expr@ evaluates to the unary variant value +whose constructor is @constr@, and whose argument is the value of +@expr@. Similarly, the expression @constr '(' expr_1 ',' \ldots ',' +expr_n ')'@ evaluates to the n-ary variant value whose constructor is +@constr@ and whose arguments are the values of @expr_1, \ldots, +expr_n@. + +The expression @constr '('expr_1, \ldots, expr_n')'@ evaluates to the +variant value whose constructor is @constr@, and whose arguments are +the values of @expr_1 \ldots expr_n@. + +For lists, some syntactic sugar is provided. The expression +@expr_1 '::' expr_2@ stands for the constructor @'(' '::' ')' @ +applied to the arguments @'(' expr_1 ',' expr_2 ')'@, and therefore +evaluates to the list whose head is the value of @expr_1@ and whose tail +is the value of @expr_2@. The expression @'[' expr_1 ';' \ldots ';' +expr_n ']'@ is equivalent to @expr_1 '::' \ldots '::' expr_n '::' +'[]'@, and therefore evaluates to the list whose elements are the +values of @expr_1@ to @expr_n@. + +\subsubsection*{Polymorphic variants} + +The expression @"`"tag-name expr@ evaluates to the polymorphic variant +value whose tag is @tag-name@, and whose argument is the value of @expr@. + +\subsubsection*{Records} + +The expression @'{' field_1 '=' expr_1 ';' \ldots ';' field_n '=' +expr_n '}'@ evaluates to the record value +$\{ field_1 = v_1; \ldots; field_n = v_n \}$ +where $v_i$ is the value of @expr_i@ for \fromoneto{i}{n}. +The fields @field_1@ to @field_n@ must all belong to the same record +type; each field of this record type must appear exactly +once in the record expression, though they can appear in any +order. The order in which @expr_1@ to @expr_n@ are evaluated is not +specified. Optional type constraints can be added after each field +@'{' field_1 ':' typexpr_1 '=' expr_1 ';'% + \ldots ';' field_n ':' typexpr_n '=' expr_n '}'@ +to force the type of @field_k@ to be compatible with @typexpr_k@. + +The expression +@"{" expr "with" field_1 "=" expr_1 ";" \ldots ";" field_n "=" expr_n "}"@ +builds a fresh record with fields @field_1 \ldots field_n@ equal to +@expr_1 \ldots expr_n@, and all other fields having the same value as +in the record @expr@. In other terms, it returns a shallow copy of +the record @expr@, except for the fields @field_1 \ldots field_n@, +which are initialized to @expr_1 \ldots expr_n@. As previously, it is +possible to add an optional type constraint on each field being updated +with +@"{" expr "with" field_1 ':' typexpr_1 "=" expr_1 ";" % + \ldots ";" field_n ':' typexpr_n "=" expr_n "}"@. + +The expression @expr_1 '.' field@ evaluates @expr_1@ to a record +value, and returns the value associated to @field@ in this record +value. + +The expression @expr_1 '.' field '<-' expr_2@ evaluates @expr_1@ to a record +value, which is then modified in-place by replacing the value +associated to @field@ in this record by the value of +@expr_2@. This operation is permitted only if @field@ has been +declared @'mutable'@ in the definition of the record type. The whole +expression @expr_1 '.' field '<-' expr_2@ evaluates to the unit value +@'()'@. + +\subsubsection*{Arrays} + +The expression @'[|' expr_1 ';' \ldots ';' expr_n '|]'@ evaluates to +a \var{n}-element array, whose elements are initialized with the values of +@expr_1@ to @expr_n@ respectively. The order in which these +expressions are evaluated is unspecified. + +The expression @expr_1 '.(' expr_2 ')'@ returns the value of element +number @expr_2@ in the array denoted by @expr_1@. The first element +has number 0; the last element has number $n-1$, where \var{n} is the +size of the array. The exception "Invalid_argument" is raised if the +access is out of bounds. + +The expression @expr_1 '.(' expr_2 ')' '<-' expr_3@ modifies in-place +the array denoted by @expr_1@, replacing element number @expr_2@ by +the value of @expr_3@. The exception "Invalid_argument" is raised if +the access is out of bounds. The value of the whole expression is @'()'@. + +\subsubsection*{Strings} + +The expression @expr_1 '.[' expr_2 ']'@ returns the value of character +number @expr_2@ in the string denoted by @expr_1@. The first character +has number 0; the last character has number $n-1$, where \var{n} is the +length of the string. The exception "Invalid_argument" is raised if the +access is out of bounds. + +The expression @expr_1 '.[' expr_2 ']' '<-' expr_3@ modifies in-place +the string denoted by @expr_1@, replacing character number @expr_2@ by +the value of @expr_3@. The exception "Invalid_argument" is raised if +the access is out of bounds. The value of the whole expression is @'()'@. + +{\bf Note:} this possibility is offered only for backward +compatibility with older versions of OCaml and will be removed in a +future version. New code should use byte sequences and the "Bytes.set" +function. + +\subsection{Operators} +\ikwd{mod\@\texttt{mod}} +\ikwd{land\@\texttt{land}} +\ikwd{lor\@\texttt{lor}} +\ikwd{lxor\@\texttt{lxor}} +\ikwd{lsl\@\texttt{lsl}} +\ikwd{lsr\@\texttt{lsr}} +\ikwd{asr\@\texttt{asr}} + +Symbols from the class @infix-symbol@, as well as the keywords +@"*"@, @"+"@, @"-"@, @'-.'@, @"="@, @"!="@, @"<"@, @">"@, @"or"@, @"||"@, +@"&"@, @"&&"@, @":="@, @"mod"@, @"land"@, @"lor"@, @"lxor"@, @"lsl"@, @"lsr"@, +and @"asr"@ can appear in infix position (between two +expressions). Symbols from the class @prefix-symbol@, as well as +the keywords @"-"@ and @"-."@ +can appear in prefix position (in front of an expression). + +Infix and prefix symbols do not have a fixed meaning: they are simply +interpreted as applications of functions bound to the names +corresponding to the symbols. The expression @prefix-symbol expr@ is +interpreted as the application @'(' prefix-symbol ')' +expr@. Similarly, the expression @expr_1 infix-symbol expr_2@ is +interpreted as the application @'(' infix-symbol ')' expr_1 expr_2@. + +The table below lists the symbols defined in the initial environment +and their initial meaning. (See the description of the core +library module "Pervasives" in chapter~\ref{c:corelib} for more +details). Their meaning may be changed at any time using +@"let" "(" infix-op ")" name_1 name_2 "=" \ldots@ + +Note: the operators @'&&'@, @'||'@, and @'~-'@ are handled specially +and it is not advisable to change their meaning. + +The keywords @'-'@ and @'-.'@ can appear both as infix and +prefix operators. When they appear as prefix operators, they are +interpreted respectively as the functions @'(~-)'@ and @'(~-.)'@. + +%% Conversely, a regular function identifier can also be used as an infix +%% operator by enclosing it in backquotes: @expr_1 '`' ident '`' expr_2@ +%% is interpreted as the application @ident expr_1 expr_2@. + +\ikwd{mod\@\texttt{mod}}% +\ikwd{land\@\texttt{land}}% +\ikwd{lor\@\texttt{lor}}% +\ikwd{lxor\@\texttt{lxor}}% +\ikwd{lsl\@\texttt{lsl}}% +\ikwd{lsr\@\texttt{lsr}}% +\ikwd{asr\@\texttt{asr}}% +\begin{tableau}{|l|p{12cm}|}{Operator}{Initial meaning} +\entree{"+"}{Integer addition.} +\entree{"-" (infix)}{Integer subtraction.} +\entree{"~- -" (prefix)}{Integer negation.} +\entree{"*"}{Integer multiplication.} +\entree{"/"}{Integer division. + Raise "Division_by_zero" if second argument is zero.} +\entree{"mod"}{Integer modulus. Raise + "Division_by_zero" if second argument is zero.} +\entree{"land"}{Bitwise logical ``and'' on integers.} +\entree{"lor"}{Bitwise logical ``or'' on integers.} +\entree{"lxor"}{Bitwise logical ``exclusive or'' on integers.} +\entree{"lsl"}{Bitwise logical shift left on integers.} +\entree{"lsr"}{Bitwise logical shift right on integers.} +\entree{"asr"}{Bitwise arithmetic shift right on integers.} +\entree{"+."}{Floating-point addition.} +\entree{"-." (infix)}{Floating-point subtraction.} +\entree{"~-. -." (prefix)}{Floating-point negation.} +\entree{"*."}{Floating-point multiplication.} +\entree{"/."}{Floating-point division.} +\entree{"**"}{Floating-point exponentiation.} +\entree{{\tt\char64} }{List concatenation.} +\entree{"^" }{String concatenation.} +\entree{"!" }{Dereferencing (return the current + contents of a reference).} +\entree{":="}{Reference assignment (update the + reference given as first argument with the value of the second + argument).} +\entree{"=" }{Structural equality test.} +\entree{"<>" }{Structural inequality test.} +\entree{"==" }{Physical equality test.} +\entree{"!=" }{Physical inequality test.} +\entree{"<" }{Test ``less than''.} +\entree{"<=" }{Test ``less than or equal''.} +\entree{">" }{Test ``greater than''.} +\entree{">=" }{Test ``greater than or equal''.} +\entree{"&& &"}{Boolean conjunction.} +\entree{"|| or"}{Boolean disjunction.} +\end{tableau} + +\subsection{Objects} \label{s:objects} + +\subsubsection*{Object creation} + +\ikwd{new\@\texttt{new}} + +When @class-path@ evaluates to a class body, @'new' class-path@ +evaluates to a new object containing the instance variables and +methods of this class. + +When @class-path@ evaluates to a class function, @'new' class-path@ +evaluates to a function expecting the same number of arguments and +returning a new object of this class. + +\subsubsection*{Immediate object creation} + +\ikwd{object\@\texttt{object}} + +Creating directly an object through the @'object' class-body 'end'@ +construct is operationally equivalent to defining locally a @'class' +class-name '=' 'object' class-body 'end'@ ---see sections +\ref{ss:class-body} and following for the syntax of @class-body@--- +and immediately creating a single object from it by @'new' class-name@. + +The typing of immediate objects is slightly different from explicitly +defining a class in two respects. First, the inferred object type may +contain free type variables. Second, since the class body of an +immediate object will never be extended, its self type can be unified +with a closed object type. + +\subsubsection*{Method invocation} + +The expression @expr '#' method-name@ invokes the method +@method-name@ of the object denoted by @expr@. + +If @method-name@ is a polymorphic method, its type should be known at +the invocation site. This is true for instance if @expr@ is the name +of a fresh object (@'let' ident = 'new' class-path \dots @) or if +there is a type constraint. Principality of the derivation can be +checked in the "-principal" mode. + +\subsubsection*{Accessing and modifying instance variables} + +The instance variables of a class are visible only in the body of the +methods defined in the same class or a class that inherits from the +class defining the instance variables. The expression @inst-var-name@ +evaluates to the value of the given instance variable. The expression +@inst-var-name '<-' expr@ assigns the value of @expr@ to the instance +variable @inst-var-name@, which must be mutable. The whole expression +@inst-var-name '<-' expr@ evaluates to @"()"@. + + +\subsubsection*{Object duplication} + +An object can be duplicated using the library function "Oo.copy" +(see +\ifouthtml \ahref{libref/Oo.html}{Module \texttt{Oo}}\else +section~\ref{Oo}\fi). Inside a method, the expression +@ '{<' inst-var-name '=' expr { ';' inst-var-name '=' expr } '>}'@ +returns a copy of self with the given instance variables replaced by +the values of the associated expressions; other instance variables +have the same value in the returned object as in self. + +\subsection{Coercions} \label{s:coercions} + +Expressions whose type contains object or polymorphic variant types +can be explicitly coerced (weakened) to a supertype. +% +The expression @'('expr ':>' typexpr')'@ coerces the expression @expr@ +to type @typexpr@. +% +The expression @'('expr ':' typexpr_1 ':>' typexpr_2')'@ coerces the +expression @expr@ from type @typexpr_1@ to type @typexpr_2@. + +The former operator will sometimes fail to coerce an expression @expr@ +from a type @typ_1@ to a type @typ_2@ +even if type @typ_1@ is a subtype of type +@typ_2@: in the current implementation it only expands two levels of +type abbreviations containing objects and/or polymorphic variants, +keeping only recursion when it is explicit in the class type (for objects). +As an exception to the above algorithm, if both the inferred type of @expr@ +and @typ@ are ground ({\em i.e.} do not contain type variables), the +former operator behaves as the latter one, taking the inferred type of +@expr@ as @typ_1@. In case of failure with the former operator, +the latter one should be used. + +It is only possible to coerce an expression @expr@ from type +@typ_1@ to type @typ_2@, if the type of @expr@ is an instance of +@typ_1@ (like for a type annotation), and @typ_1@ is a subtype +of @typ_2@. The type of the coerced expression is an +instance of @typ_2@. If the types contain variables, +they may be instantiated by the subtyping algorithm, but this is only +done after determining whether @typ_1@ is a potential subtype of +@typ_2@. This means that typing may fail during this latter +unification step, even if some instance of @typ_1@ is a subtype of +some instance of @typ_2@. +% +In the following paragraphs we describe the subtyping relation used. + +\subsubsection*{Object types} + +A fixed object type admits as subtype any object type that includes all +its methods. The types of the methods shall be subtypes of those in +the supertype. Namely, +\begin{center} +@ '<' met_1 ':' typ_1 ';' \dots ';' met_n ':' typ_n '>' @ +\end{center} +is a supertype of +\begin{center} +@ '<' met_1 ':' typ@$'_1$@ ';' \dots ';' met_n ':' typ@$'_n$@ ';' +met@$_{n+1}$@ ':' typ@$'_{n+1}$@ ';' \dots ';' met@$_{n+m}$@ ':' typ@$'_{n+m}$@ +~[';' '..'] '>' @ +\end{center} +which may contain an ellipsis ".." if every @typ_i@ is a supertype of +the corresponding @typ@$'_i$. + +A monomorphic method type can be a supertype of a polymorphic method +type. Namely, if @typ@ is an instance of @typ@$'$, then @ "'"@a@_1 +\dots "'"@a@_n '.' typ@$'$ is a subtype of @typ@. + +Inside a class definition, newly defined types are not available for +subtyping, as the type abbreviations are not yet completely +defined. There is an exception for coercing @@self@@ to the (exact) +type of its class: this is allowed if the type of @@self@@ does not +appear in a contravariant position in the class type, {\em i.e.} if +there are no binary methods. + +\subsubsection*{Polymorphic variant types} + +A polymorphic variant type @typ@ is a subtype of another polymorphic +variant type @typ@$'$ if the upper bound of @typ@ ({\em i.e.} the +maximum set of constructors that may appear in an instance of @typ@) +is included in the lower bound of @typ@$'$, and the types of arguments +for the constructors of @typ@ are subtypes of those in +@typ@$'$. Namely, +\begin{center} +@ "["["<"] "`"C_1 "of" typ_1 "|" \dots "|" "`"C_n "of" typ_n "]" @ +\end{center} +which may be a shrinkable type, is a subtype of +\begin{center} +@ "["[">"] "`"C_1 "of" typ@$'_1$@ "|" \dots "|" "`"C_n "of" typ@$'_n$@ + "|" "`"C@$_{n+1}$@ "of" typ@$'_{n+1}$@ "|" \dots "|" "`"C@$_{n+m}$@ "of" + typ@$'_{n+m}$@ "]" @ +\end{center} +which may be an extensible type, if every @typ_i@ is a subtype of @typ@$'_i$. + +\subsubsection*{Variance} + +Other types do not introduce new subtyping, but they may propagate the +subtyping of their arguments. For instance, @typ_1 "*" typ_2@ is a +subtype of @typ@$'_1$@ "*" typ@$'_2$ when @typ_1@ and @typ_2@ are +respectively subtypes of @typ@$'_1$ and @typ@$'_2$. +For function types, the relation is more subtle: +@typ_1 "->" typ_2@ is a subtype of @typ@$'_1$@~"->" typ@$'_2$ +if @typ_1@ is a supertype of @typ@$'_1$ and @typ_2@ is a +subtype of @typ@$'_2$. For this reason, function types are covariant in +their second argument (like tuples), but contravariant in their first +argument. Mutable types, like "array" or "ref" are neither covariant +nor contravariant, they are nonvariant, that is they do not propagate +subtyping. + +For user-defined types, the variance is automatically inferred: a +parameter is covariant if it has only covariant occurrences, +contravariant if it has only contravariant occurrences, +variance-free if it has no occurrences, and nonvariant otherwise. +A variance-free parameter may change freely through subtyping, it does +not have to be a subtype or a supertype. +% +For abstract and private types, the variance must be given explicitly +(see section~\ref{s:type-defs}), +otherwise the default is nonvariant. This is also the case for +constrained arguments in type definitions. + + +\subsection{Other} + +\subsubsection*{Assertion checking} + + +\ikwd{assert\@\texttt{assert}} + +OCaml supports the @"assert"@ construct to check debugging assertions. +The expression @"assert" expr@ evaluates the expression @expr@ and +returns @"()"@ if @expr@ evaluates to @"true"@. If it evaluates to +@"false"@ the exception +"Assert_failure" is raised with the source file name and the +location of @expr@ as arguments. Assertion +checking can be turned off with the "-noassert" compiler option. In +this case, @expr@ is not evaluated at all. + +As a special case, @"assert false"@ is reduced to +@'raise' '('@"Assert_failure ..."@')'@, which gives it a polymorphic +type. This means that it can be used in place of any expression (for +example as a branch of any pattern-matching). It also means that +the @"assert false"@ ``assertions'' cannot be turned off by the +"-noassert" option. +% +\index{Assertfailure\@\verb`Assert_failure`} + +\subsubsection*{Lazy expressions} +\ikwd{lazy\@\texttt{lazy}} + +The expression @"lazy" expr@ returns a value \var{v} of type "Lazy.t" that +encapsulates the computation of @expr@. The argument @expr@ is not +evaluated at this point in the program. Instead, its evaluation will +be performed the first time the function "Lazy.force" is applied to the value +\var{v}, returning the actual value of @expr@. Subsequent applications +of "Lazy.force" to \var{v} do not evaluate @expr@ again. Applications +of "Lazy.force" may be implicit through pattern matching (see~\ref{s:lazypat}). + +\subsubsection*{Local modules} +\ikwd{let\@\texttt{let}} +\ikwd{module\@\texttt{module}} + +The expression +@"let" "module" module-name "=" module-expr "in" expr@ +locally binds the module expression @module-expr@ to the identifier +@module-name@ during the evaluation of the expression @expr@. +It then returns the value of @expr@. For example: +\begin{verbatim} + let remove_duplicates comparison_fun string_list = + let module StringSet = + Set.Make(struct type t = string + let compare = comparison_fun end) in + StringSet.elements + (List.fold_right StringSet.add string_list StringSet.empty) +\end{verbatim} + +%% \newpage diff --git a/manual/manual/refman/exten.etex b/manual/manual/refman/exten.etex new file mode 100644 index 0000000000..dde38500e8 --- /dev/null +++ b/manual/manual/refman/exten.etex @@ -0,0 +1,2407 @@ +\chapter{Language extensions} \label{c:extensions} +\pdfchapter{Language extensions} +%HEVEA\cutname{extn.html} +%%%%%%%%%%%%%%%%%%%%%%%%%% +% Specific macros: +\newcommand{\tq}{\textquotesingle} +%%%%%%%%%%%%%%%%%%%%%%%%%%% + +This chapter describes language extensions and convenience features +that are implemented in OCaml, but not described in the +OCaml reference manual. + +\section{Integer literals for types \texttt{int32}, \texttt{int64} + and \texttt{nativeint}} + +(Introduced in Objective Caml 3.07) + +\begin{syntax} +constant: ... + | int32-literal + | int64-literal + | nativeint-literal +; +int32-literal: integer-literal 'l' +; +int64-literal: integer-literal 'L' +; +nativeint-literal: integer-literal 'n' +\end{syntax} + +An integer literal can be followed by one of the letters "l", "L" or "n" +to indicate that this integer has type "int32", "int64" or "nativeint" +respectively, instead of the default type "int" for integer literals. +\index{int32\@\verb`int32`} +\index{int64\@\verb`int64`} +\index{nativeint\@\verb`nativeint`} +The library modules "Int32"[\moduleref{Int32}], +"Int64"[\moduleref{Int64}] and "Nativeint"[\moduleref{Nativeint}] +provide operations on these integer types. + +\section{Recursive definitions of values} \label{s:letrecvalues} + +(Introduced in Objective Caml 1.00) + +As mentioned in section~\ref{s:localdef}, the @'let' 'rec'@ binding +construct, in addition to the definition of recursive functions, +also supports a certain class of recursive definitions of +non-functional values, such as +\begin{center} +@"let" "rec" name_1 "=" "1" "::" name_2 +"and" name_2 "=" "2" "::" name_1 +"in" expr@ +\end{center} +which binds @name_1@ to the cyclic list "1::2::1::2::"\ldots, and +@name_2@ to the cyclic list "2::1::2::1::"\ldots +Informally, the class of accepted definitions consists of those +definitions where the defined names occur only inside function +bodies or as argument to a data constructor. + +More precisely, consider the expression: +\begin{center} +@"let" "rec" name_1 "=" expr_1 "and" \ldots "and" name_n "=" expr_n "in" expr@ +\end{center} +It will be accepted if each one of @expr_1 \ldots expr_n@ is +statically constructive with respect to @name_1 \ldots name_n@, +is not immediately linked to any of @name_1 \ldots name_n@, +and is not an array constructor whose arguments have abstract type. + +An expression @@e@@ is said to be {\em statically constructive +with respect to} the variables @name_1 \ldots name_n@ if at least +one of the following conditions is true: +\begin{itemize} +\item @@e@@ has no free occurrence of any of @name_1 \ldots name_n@ +\item @@e@@ is a variable +\item @@e@@ has the form @"fun" \ldots "->" \ldots@ +\item @@e@@ has the form @"function" \ldots "->" \ldots@ +\item @@e@@ has the form @"lazy" "(" \ldots ")"@ +\item @@e@@ has one of the following forms, where each one of + @expr_1 \ldots expr_m@ is statically constructive with respect to + @name_1 \ldots name_n@, and @expr_0@ is statically constructive with + respect to @name_1 \ldots name_n, xname_1 \ldots xname_m@: + \begin{itemize} + \item @"let" ["rec"] xname_1 "=" expr_1 "and" \ldots + "and" xname_m "=" expr_m "in" expr_0@ + \item @"let" "module" \ldots "in" expr_1@ + \item @constr "("expr_1"," \ldots "," expr_m")"@ + \item @"`"tag-name "("expr_1"," \ldots "," expr_m")"@ + \item @"[|" expr_1";" \ldots ";" expr_m "|]"@ + \item @"{" field_1 "=" expr_1";" \ldots ";" field_m = expr_m "}"@ + \item @"{" expr_1 "with" field_2 "=" expr_2";" \ldots ";" + field_m = expr_m "}"@ where @expr_1@ is not immediately + linked to @name_1 \ldots name_n@ + \item @"(" expr_1"," \ldots "," expr_m ")"@ + \item @expr_1";" \ldots ";" expr_m@ + \end{itemize} +\end{itemize} + +An expression @@e@@ is said to be {\em immediately linked to} the variable +@name@ in the following cases: +\begin{itemize} +\item @@e@@ is @name@ +\item @@e@@ has the form @expr_1";" \ldots ";" expr_m@ where @expr_m@ + is immediately linked to @name@ +\item @@e@@ has the form @"let" ["rec"] xname_1 "=" expr_1 "and" \ldots + "and" xname_m "=" expr_m "in" expr_0@ where @expr_0@ is immediately + linked to @name@ or to one of the @xname_i@ such that @expr_i@ + is immediately linked to @name@. +\end{itemize} + +\section{Lazy patterns} \label{s:lazypat} + +\ikwd{lazy\@\texttt{lazy}} + +(Introduced in Objective Caml 3.11) + +\begin{syntax} +pattern: ... + | 'lazy' pattern +\end{syntax} + +The pattern @"lazy" pattern@ matches a value \var{v} of type "Lazy.t", +provided @pattern@ matches the result of forcing \var{v} with +"Lazy.force". A successful match of a pattern containing @"lazy"@ +sub-patterns forces the corresponding parts of the value being matched, even +those that imply no test such as @"lazy" value-name@ or @"lazy" "_"@. +Matching a value with a @pattern-matching@ where some patterns +contain @"lazy"@ sub-patterns may imply forcing parts of the value, +even when the pattern selected in the end has no @"lazy"@ sub-pattern. + +For more information, see the description of module "Lazy" in the +standard library ( +\ifouthtml +\ahref{libref/Lazy.html}{Module \texttt{Lazy}}\else section~\ref{Lazy}\fi). +% +\index{Lazy (module)\@\verb`Lazy` (module)}% +\index{force\@\verb`force`}% + +\section{Recursive modules} \label{s-recursive-modules} +\ikwd{module\@\texttt{module}} +\ikwd{and\@\texttt{and}} + +(Introduced in Objective Caml 3.07) + +% TODO: relaxed syntax + +\begin{syntax} +definition: + ... + | 'module' 'rec' module-name ':' module-type '=' module-expr \\ + { 'and' module-name ':' module-type '=' module-expr } +; +specification: + ... + | 'module' 'rec' module-name ':' module-type + { 'and' module-name':' module-type } +\end{syntax} + +Recursive module definitions, introduced by the @"module rec"@ \ldots +@"and"@ \ldots\ construction, generalize regular module definitions +@'module' module-name '=' module-expr@ and module specifications +@'module' module-name ':' module-type@ by allowing the defining +@module-expr@ and the @module-type@ to refer recursively to the module +identifiers being defined. A typical example of a recursive module +definition is: +\begin{verbatim} + module rec A : sig + type t = Leaf of string | Node of ASet.t + val compare: t -> t -> int + end + = struct + type t = Leaf of string | Node of ASet.t + let compare t1 t2 = + match (t1, t2) with + (Leaf s1, Leaf s2) -> Pervasives.compare s1 s2 + | (Leaf _, Node _) -> 1 + | (Node _, Leaf _) -> -1 + | (Node n1, Node n2) -> ASet.compare n1 n2 + end + and ASet : Set.S with type elt = A.t + = Set.Make(A) +\end{verbatim} +It can be given the following specification: +\begin{verbatim} + module rec A : sig + type t = Leaf of string | Node of ASet.t + val compare: t -> t -> int + end + and ASet : Set.S with type elt = A.t +\end{verbatim} + +This is an experimental extension of OCaml: the class of +recursive definitions accepted, as well as its dynamic semantics are +not final and subject to change in future releases. + +Currently, the compiler requires that all dependency cycles between +the recursively-defined module identifiers go through at least one +``safe'' module. A module is ``safe'' if all value definitions that +it contains have function types @typexpr_1 '->' typexpr_2@. Evaluation of a +recursive module definition proceeds by building initial values for +the safe modules involved, binding all (functional) values to +@'fun' '_' '->' 'raise' @"Undefined_recursive_module". The defining +module expressions are then evaluated, and the initial values +for the safe modules are replaced by the values thus computed. If a +function component of a safe module is applied during this computation +(which corresponds to an ill-founded recursive definition), the +"Undefined_recursive_module" exception is raised. + +Note that, in the @specification@ case, the @module-type@s must be +parenthesized if they use the @'with' mod-constraint@ construct. + +\section{Private types} +\ikwd{private\@\texttt{private}} + +Private type declarations in module signatures, of the form +"type t = private ...", enable libraries to +reveal some, but not all aspects of the implementation of a type to +clients of the library. In this respect, they strike a middle ground +between abstract type declarations, where no information is revealed +on the type implementation, and data type definitions and type +abbreviations, where all aspects of the type implementation are +publicized. Private type declarations come in three flavors: for +variant and record types (section~\ref{s-private-types-variant}), +for type abbreviations (section~\ref{s-private-types-abbrev}), +and for row types (section~\ref{s-private-rows}). + +\subsection{Private variant and record types} \label{s-private-types-variant} + +(Introduced in Objective Caml 3.07) + +\begin{syntax} +type-representation: + ... + | '=' 'private' [ '|' ] constr-decl { '|' constr-decl } + | '=' 'private' record-decl +\end{syntax} + +Values of a variant or record type declared @"private"@ +can be de-structured normally in pattern-matching or via +the @expr '.' field@ notation for record accesses. However, values of +these types cannot be constructed directly by constructor application +or record construction. Moreover, assignment on a mutable field of a +private record type is not allowed. + +The typical use of private types is in the export signature of a +module, to ensure that construction of values of the private type always +go through the functions provided by the module, while still allowing +pattern-matching outside the defining module. For example: +\begin{verbatim} + module M : sig + type t = private A | B of int + val a : t + val b : int -> t + end + = struct + type t = A | B of int + let a = A + let b n = assert (n > 0); B n + end +\end{verbatim} +Here, the @"private"@ declaration ensures that in any value of type +"M.t", the argument to the "B" constructor is always a positive integer. + +With respect to the variance of their parameters, private types are +handled like abstract types. That is, if a private type has +parameters, their variance is the one explicitly given by prefixing +the parameter by a `"+"' or a `"-"', it is invariant otherwise. + +\subsection{Private type abbreviations} \label{s-private-types-abbrev} + +(Introduced in Objective Caml 3.11) + +\begin{syntax} +type-equation: + ... + | '=' 'private' typexpr +\end{syntax} + +Unlike a regular type abbreviation, a private type abbreviation +declares a type that is distinct from its implementation type @typexpr@. +However, coercions from the type to @typexpr@ are permitted. +Moreover, the compiler ``knows'' the implementation type and can take +advantage of this knowledge to perform type-directed optimizations. +For ambiguity reasons, @typexpr@ cannot be an object or polymorphic +variant type, but a similar behaviour can be obtained through private +row types. + +The following example uses a private type abbreviation to define a +module of nonnegative integers: +\begin{verbatim} + module N : sig + type t = private int + val of_int: int -> t + val to_int: t -> int + end + = struct + type t = int + let of_int n = assert (n >= 0); n + let to_int n = n + end +\end{verbatim} +The type "N.t" is incompatible with "int", ensuring that nonnegative +integers and regular integers are not confused. However, if "x" has +type "N.t", the coercion "(x :> int)" is legal and returns the +underlying integer, just like "N.to_int x". Deep coercions are also +supported: if "l" has type "N.t list", the coercion "(l :> int list)" +returns the list of underlying integers, like "List.map N.to_int l" +but without copying the list "l". + +Note that the coercion @"(" expr ":>" typexpr ")"@ is actually an abbreviated +form, +and will only work in presence of private abbreviations if neither the +type of @expr@ nor @typexpr@ contain any type variables. If they do, +you must use the full form @"(" expr ":" typexpr_1 ":>" typexpr_2 ")"@ where +@typexpr_1@ is the expected type of @expr@. Concretely, this would be "(x : +N.t :> int)" and "(l : N.t list :> int list)" for the above examples. + +\subsection{Private row types} \label{s-private-rows} +\ikwd{private\@\texttt{private}} + +(Introduced in Objective Caml 3.09) + +\begin{syntax} +type-equation: + ... + | '=' 'private' typexpr +\end{syntax} + +Private row types are type abbreviations where part of the +structure of the type is left abstract. Concretely @typexpr@ in the +above should denote either an object type or a polymorphic variant +type, with some possibility of refinement left. If the private +declaration is used in an interface, the corresponding implementation +may either provide a ground instance, or a refined private type. +\begin{verbatim} + module M : sig type c = private < x : int; .. > val o : c end = + struct + class c = object method x = 3 method y = 2 end + let o = new c + end +\end{verbatim} +This declaration does more than hiding the "y" method, it also makes +the type "c" incompatible with any other closed object type, meaning +that only "o" will be of type "c". In that respect it behaves +similarly to private record types. But private row types are +more flexible with respect to incremental refinement. This feature can +be used in combination with functors. +\begin{verbatim} + module F(X : sig type c = private < x : int; .. > end) = + struct + let get_x (o : X.c) = o#x + end + module G(X : sig type c = private < x : int; y : int; .. > end) = + struct + include F(X) + let get_y (o : X.c) = o#y + end +\end{verbatim} + +A polymorphic variant type [t], for example +\begin{verbatim} + type t = [ `A of int | `B of bool ] +\end{verbatim} +can be refined in two ways. A definition [u] may add new field to [t], +and the declaration +\begin{verbatim} + type u = private [> t] +\end{verbatim} +will keep those new fields abstract. Construction of values of type +[u] is possible using the known variants of [t], but any +pattern-matching will require a default case to handle the potential +extra fields. Dually, a declaration [u] may restrict the fields of [t] +through abstraction: the declaration +\begin{verbatim} + type v = private [< t > `A] +\end{verbatim} +corresponds to private variant types. One cannot create a value of the +private type [v], except using the constructors that are explicitly +listed as present, "(`A n)" in this example; yet, when +patter-matching on a [v], one should assume that any of the +constructors of [t] could be present. + +Similarly to abstract types, the variance of type parameters +is not inferred, and must be given explicitly. + + +\section{Local opens} +\ikwd{let\@\texttt{let}} +\ikwd{open\@\texttt{open}} + +(Introduced in OCaml 3.12, extended to patterns in 4.03) + +\begin{syntax} +expr: + ... + | "let" "open" module-path "in" expr + | module-path '.(' expr ')' +; +pattern: + ... + | module-path '.(' pattern ')' +\end{syntax} + +The expressions +@"let" "open" module-path "in" expr@ +and +@module-path'.('expr')'@ are strictly equivalent. On the pattern side, +only the pattern @module-path'.('pattern')'@ is available. These +constructions locally open the module referred to by the module path +@module-path@ in the respective scope of the expression @expr@ or +pattern @pattern@. + +Restricting opening to the scope of a single expression or pattern +instead of a whole structure allows one to benefit from shorter syntax +to refer to components of the opened module, without polluting the +global scope. Also, this can make the code easier to read (the open +statement is closer to where it is used) and to refactor (because the +code fragment is more self-contained). + +\paragraph{Local opens for delimited expressions or patterns} (Introduced in OCaml 4.02) + +\begin{syntax} +expr: + ... + | module-path '.[' expr ']' + | module-path '.[|' expr '|]' + | module-path '.{' expr '}' + | module-path '.{<' expr '>}' +; +pattern: + ... + | module-path '.[' pattern ']' + | module-path '.[|' pattern '|]' + | module-path '.{' pattern '}' +\end{syntax} + +When the body of a local open expression or pattern is delimited by +@'[' ']'@, @'[|' '|]'@, or @'{' '}'@, the parentheses can be omitted. +For expression, parentheses can also be omitted for @'{<' '>}'@. +For example, @module-path'.['expr']'@ is equivalent to +@module-path'.(['expr'])'@, and @module-path'.[|' pattern '|]'@ is +equivalent to @module-path'.([|' pattern '|])'@. + +\section{Record and object notations} +\ikwd{with\@\texttt{with}} + +(Introduced in OCaml 3.12, object copy notation added in Ocaml 4.03) + +\begin{syntax} +pattern: + ... + | '{' field ['=' pattern] { ';' field ['=' pattern] } [';' '_' ] [';'] '}' +; +expr: + ... + | '{' field ['=' expr] { ';' field ['=' expr] } [';'] '}' + | '{' expr 'with' field ['=' expr] { ';' field ['=' expr] } [';'] '}' + | '{' '<' expr 'with' field ['=' expr] { ';' field ['=' expr] } [';'] '>' '}' + +\end{syntax} + +In a record pattern, a record construction expression or an object copy expression, +a single identifier @id@ stands for @id '=' id@, and a qualified identifier +@module-path '.' id@ stands for @module-path '.' id '=' id@. +For example, assuming the record type +\begin{verbatim} + type point = { x: float; y: float } +\end{verbatim} +has been declared, the following expressions are equivalent: +\begin{verbatim} + let x = 1. and y = 2. in { x = x; y = y }, + let x = 1. and y = 2. in { x; y }, + let x = 1. and y = 2. in { x = x; y } +\end{verbatim} +On the object side, all following methods are equivalent: +\begin{verbatim} + object + val x=0. val y=0. val z=0. + method f_0 x y = {< x; y >} + method f_1 x y = {< x = x; y >} + method f_2 x y = {< x=x ; y = y >} + end +\end{verbatim} +Likewise, the following functions are equivalent: +\begin{verbatim} + fun {x = x; y = y} -> x +. y + fun {x; y} -> x +. y +\end{verbatim} + +Optionally, a record pattern can be terminated by @';' '_'@ to convey the +fact that not all fields of the record type are listed in the record +pattern and that it is intentional. By default, the compiler ignores +the @';' '_'@ annotation. If warning 9 is turned on, +the compiler will warn when a record pattern fails to list all fields of +the corresponding record type and is not terminated by @';' '_'@. +Continuing the "point" example above, +\begin{verbatim} + fun {x} -> x +. 1. +\end{verbatim} +\noindent will warn if warning 9 is on, while +\begin{verbatim} + fun {x; _} -> x +. 1. +\end{verbatim} +\noindent will not warn. This warning can help spot program points where +record patterns may need to be modified after new fields are added to a +record type. + +\section{Explicit polymorphic type annotations} +\ikwd{let\@\texttt{let}} + +(Introduced in OCaml 3.12) + +\begin{syntax} +let-binding: + ... + | value-name ':' poly-typexpr '=' expr +\end{syntax} + +Polymorphic type annotations in @"let"@-definitions behave in a way +similar to polymorphic methods: they explicitly require the defined +value to be polymorphic, and allow one to use this polymorphism in +recursive occurrences (when using @"let" "rec"@). Note however that this +is a normal polymorphic type, unifiable with any instance of +itself. + +There are two possible applications of this feature. One is polymorphic +recursion: +\begin{verbatim} + type 'a t = Leaf of 'a | Node of ('a * 'a) t + let rec depth : 'a. 'a t -> 'b = function + Leaf _ -> 1 + | Node x -> 1 + depth x +\end{verbatim} +Note that "'b" is not explicitly polymorphic here, and it will +actually be unified with "int". + +The other application is to ensure that some definition is sufficiently +polymorphic. +\caml +\?let id : \tq\-a. \tq\-a -> \tq\-a = \ x+1\> ;; +\:Error: This definition has type int -> int which is less general than +\: \tq\-a. \tq\-a -> \tq\-a +\endcaml + +\section{Locally abstract types} +\ikwd{type\@\texttt{type}} +\ikwd{fun\@\texttt{fun}} + +(Introduced in OCaml 3.12, short syntax added in 4.03) + +\begin{syntax} +parameter: + ... + | '(' "type" {{typeconstr-name}} ')' +\end{syntax} + +The expression @"fun" '(' "type" typeconstr-name ')' "->" expr@ introduces a +type constructor named @typeconstr-name@ which is considered abstract +in the scope of the sub-expression, but then replaced by a fresh type +variable. Note that contrary to what the syntax could suggest, the +expression @"fun" '(' "type" typeconstr-name ')' "->" expr@ itself does not +suspend the evaluation of @expr@ as a regular abstraction would. The +syntax has been chosen to fit nicely in the context of function +declarations, where it is generally used. It is possible to freely mix +regular function parameters with pseudo type parameters, as in: +\begin{verbatim} + let f = fun (type t) (foo : t list) -> ... +\end{verbatim} +and even use the alternative syntax for declaring functions: +\begin{verbatim} + let f (type t) (foo : t list) = ... +\end{verbatim} +If several locally abstract types need to be introduced, it is possible to use +the syntax +@"fun" '(' "type" typeconstr-name_1 \ldots typeconstr-name_n ')' "->" expr@ +as syntactic sugar for @"fun" '(' "type" typeconstr-name_1 ')' "->" \ldots "->" +"fun" '(' "type" typeconstr-name_n ')' "->" expr@. For instance, +\begin{verbatim} + let f = fun (type t u v) -> fun (foo : (t * u * v) list) -> ... + let f' (type t u v) (foo : (t * u * v) list) = ... +\end{verbatim} + +This construction is useful because the type constructors it introduces +can be used in places where a type variable is not allowed. For +instance, one can use it to define an exception in a local module +within a polymorphic function. +\begin{verbatim} + let f (type t) () = + let module M = struct exception E of t end in + (fun x -> M.E x), (function M.E x -> Some x | _ -> None) +\end{verbatim} + +Here is another example: +\begin{verbatim} + let sort_uniq (type s) (cmp : s -> s -> int) = + let module S = Set.Make(struct type t = s let compare = cmp end) in + fun l -> + S.elements (List.fold_right S.add l S.empty) +\end{verbatim} + +It is also extremely useful for first-class modules (see +section~\ref{s-first-class-modules}) and generalized algebraic datatypes +(GADTs: see section~\ref{s:gadts}). + +\paragraph{Polymorphic syntax} (Introduced in OCaml 4.00) + +\begin{syntax} +let-binding: + ... + | value-name ':' 'type' {{ typeconstr-name }} '.' typexpr '=' expr +; +class-field: + ... + | 'method' ['private'] method-name ':' 'type' + {{ typeconstr-name }} '.' typexpr '=' expr + | 'method!' ['private'] method-name ':' 'type' + {{ typeconstr-name }} '.' typexpr '=' expr +\end{syntax} + +The @"(type" typeconstr-name")"@ syntax construction by itself does not make +polymorphic the type variable it introduces, but it can be combined +with explicit polymorphic annotations where needed. +The above rule is provided as syntactic sugar to make this easier: +\begin{verbatim} + let rec f : type t1 t2. t1 * t2 list -> t1 = ... +\end{verbatim} +\noindent +is automatically expanded into +\begin{verbatim} + let rec f : 't1 't2. 't1 * 't2 list -> 't1 = + fun (type t1) (type t2) -> (... : t1 * t2 list -> t1) +\end{verbatim} +This syntax can be very useful when defining recursive functions involving +GADTs, see the section~\ref{s:gadts} for a more detailed explanation. + +The same feature is provided for method definitions. +The @'method!'@ form combines this extension with the +``explicit overriding'' extension described in +section~\ref{s:explicit-overriding}. + +\section{First-class modules}\label{s-first-class-modules} +\ikwd{module\@\texttt{module}} +\ikwd{val\@\texttt{val}} +\ikwd{with\@\texttt{with}} +\ikwd{and\@\texttt{and}} + +(Introduced in OCaml 3.12; pattern syntax and package type inference +introduced in 4.00; structural comparison of package types introduced in 4.02.) + +\begin{syntax} +typexpr: + ... + | '(''module' package-type')' +; +module-expr: + ... + | '(''val' expr [':' package-type]')' +; +expr: + ... + | '(''module' module-expr [':' package-type]')' +; +pattern: + ... + | '(''module' module-name [':' package-type]')' +; +package-type: + modtype-path + | modtype-path 'with' package-constraint { 'and' package-constraint } +; +package-constraint: + 'type' typeconstr '=' typexpr +; +\end{syntax} + +Modules are typically thought of as static components. This extension +makes it possible to pack a module as a first-class value, which can +later be dynamically unpacked into a module. + +The expression @'(' 'module' module-expr ':' package-type ')'@ converts the +module (structure or functor) denoted by module expression @module-expr@ +to a value of the core language that encapsulates this module. The +type of this core language value is @'(' 'module' package-type ')'@. +The @package-type@ annotation can be omitted if it can be inferred +from the context. + +Conversely, the module expression @'(' 'val' expr ':' package-type ')'@ +evaluates the core language expression @expr@ to a value, which must +have type @'module' package-type@, and extracts the module that was +encapsulated in this value. Again @package-type@ can be omitted if the +type of @expr@ is known. + +The pattern @'(' 'module' module-name ':' package-type ')'@ matches a +package with type @package-type@ and binds it to @module-name@. +It is not allowed in toplevel let bindings. +Again @package-type@ can be omitted if it can be inferred from the +enclosing pattern. + +The @package-type@ syntactic class appearing in the @'(' 'module' +package-type ')'@ type expression and in the annotated forms represents a +subset of module types. +This subset consists of named module types with optional constraints +of a limited form: only non-parametrized types can be specified. + +For type-checking purposes (and starting from OCaml 4.02), package types +are compared using the structural comparison of module types. + +In general, the module expression @'(' "val" expr ":" package-type +')'@ cannot be used in the body of a functor, because this could cause +unsoundness in conjunction with applicative functors. +Since OCaml 4.02, this is relaxed in two ways: +if @package-type@ does not contain nominal type declarations ({\em + i.e.} types that are created with a proper identity), then this +expression can be used anywhere, and even if it contains such types +it can be used inside the body of a generative +functor, described in section~\ref{s:generative-functors}. +It can also be used anywhere in the context of a local module binding +@'let' 'module' module-name '=' '(' "val" expr_1 ":" package-type ')' + "in" expr_2@. + +\paragraph{Basic example} A typical use of first-class modules is to +select at run-time among several implementations of a signature. +Each implementation is a structure that we can encapsulate as a +first-class module, then store in a data structure such as a hash +table: +\begin{verbatim} + module type DEVICE = sig ... end + let devices : (string, (module DEVICE)) Hashtbl.t = Hashtbl.create 17 + + module SVG = struct ... end + let _ = Hashtbl.add devices "SVG" (module SVG : DEVICE) + + module PDF = struct ... end + let _ = Hashtbl.add devices "PDF" (module PDF: DEVICE) +\end{verbatim} +We can then select one implementation based on command-line +arguments, for instance: +\begin{verbatim} + module Device = + (val (try Hashtbl.find devices (parse_cmdline()) + with Not_found -> eprintf "Unknown device %s\n"; exit 2) + : DEVICE) +\end{verbatim} +Alternatively, the selection can be performed within a function: +\begin{verbatim} + let draw_using_device device_name picture = + let module Device = + (val (Hashtbl.find_devices device_name) : DEVICE) + in + Device.draw picture +\end{verbatim} + +\paragraph{Advanced examples} +With first-class modules, it is possible to parametrize some code over the +implementation of a module without using a functor. + +\begin{verbatim} + let sort (type s) (module Set : Set.S with type elt = s) l = + Set.elements (List.fold_right Set.add l Set.empty) + val sort : (module Set.S with type elt = 'a) -> 'a list -> 'a list +\end{verbatim} + +To use this function, one can wrap the "Set.Make" functor: + +\begin{verbatim} + let make_set (type s) cmp = + let module S = Set.Make(struct + type t = s + let compare = cmp + end) in + (module S : Set.S with type elt = s) + val make_set : ('a -> 'a -> int) -> (module Set.S with type elt = 'a) +\end{verbatim} + +\iffalse +Another advanced use of first-class module is to encode existential +types. In particular, they can be used to simulate generalized +algebraic data types (GADT). To demonstrate this, we first define a type +of witnesses for type equalities: + +\begin{verbatim} + module TypEq : sig + type ('a, 'b) t + val apply: ('a, 'b) t -> 'a -> 'b + val refl: ('a, 'a) t + val sym: ('a, 'b) t -> ('b, 'a) t + end = struct + type ('a, 'b) t = ('a -> 'b) * ('b -> 'a) + let refl = (fun x -> x), (fun x -> x) + let apply (f, _) x = f x + let sym (f, g) = (g, f) + end +\end{verbatim} + +We can then define a parametrized algebraic data type whose +constructors provide some information about the type parameter: + +\begin{verbatim} + module rec Typ : sig + module type PAIR = sig + type t and t1 and t2 + val eq: (t, t1 * t2) TypEq.t + val t1: t1 Typ.typ + val t2: t2 Typ.typ + end + + type 'a typ = + | Int of ('a, int) TypEq.t + | String of ('a, string) TypEq.t + | Pair of (module PAIR with type t = 'a) + end = Typ +\end{verbatim} + +Values of type "'a typ" are supposed to be runtime representations for +the type "'a". The constructors "Int" and "String" are easy: they +directly give a witness of type equality between the parameter "'a" +and the ground types "int" (resp. "string"). The constructor "Pair" is +more complex. One wants to give a witness of type equality between +"'a" and a type of the form "t1 * t2" together with the representations +for "t1" and "t2". However, these two types are unknown. The code above +shows how to use first-class modules to simulate existentials. + +Here is how to construct values of type "'a typ": + +\begin{verbatim} + let int = Typ.Int TypEq.refl + + let str = Typ.String TypEq.refl + + let pair (type s1) (type s2) t1 t2 = + let module P = struct + type t = s1 * s2 + type t1 = s1 + type t2 = s2 + let eq = TypEq.refl + let t1 = t1 + let t2 = t2 + end in + let pair = (module P : Typ.PAIR with type t = s1 * s2) in + Typ.Pair pair +\end{verbatim} + +And finally, here is an example of a polymorphic function that takes the +runtime representation of some type "'a" and a value of the same type, +then pretty-prints the value into a string: + +\begin{verbatim} + open Typ + let rec to_string: 'a. 'a Typ.typ -> 'a -> string = + fun (type s) t x -> + match t with + | Int eq -> string_of_int (TypEq.apply eq x) + | String eq -> Printf.sprintf "%S" (TypEq.apply eq x) + | 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)" (to_string P.t1 x1) (to_string P.t2 x2) +\end{verbatim} + +Note that this function uses an explicit polymorphic annotation to obtain +polymorphic recursion. +\fi + +\section{Recovering the type of a module} + +\ikwd{module\@\texttt{module}} +\ikwd{type\@\texttt{type}} +\ikwd{of\@\texttt{of}} +\ikwd{include\@\texttt{include}} + +(Introduced in OCaml 3.12) + +\begin{syntax} +module-type: + ... + | 'module' 'type' 'of' module-expr +\end{syntax} + +The construction @'module' 'type' 'of' module-expr@ expands to the module type +(signature or functor type) inferred for the module expression @module-expr@. +To make this module type reusable in many situations, it is +intentionally not strengthened: abstract types and datatypes are not +explicitly related with the types of the original module. +For the same reason, module aliases in the inferred type are expanded. + +A typical use, in conjunction with the signature-level @'include'@ +construct, is to extend the signature of an existing structure. +In that case, one wants to keep the types equal to types in the +original module. This can done using the following idiom. +\begin{verbatim} + module type MYHASH = sig + include module type of struct include Hashtbl end + val replace: ('a, 'b) t -> 'a -> 'b -> unit + end +\end{verbatim} +The signature "MYHASH" then contains all the fields of the signature +of the module "Hashtbl" (with strengthened type definitions), plus the +new field "replace". An implementation of this signature can be +obtained easily by using the @'include'@ construct again, but this +time at the structure level: +\begin{verbatim} + module MyHash : MYHASH = struct + include Hashtbl + let replace t k v = remove t k; add t k v + end +\end{verbatim} + +Another application where the absence of strengthening comes handy, is +to provide an alternative implementation for an existing module. +\begin{verbatim} + module MySet : module type of Set = struct + ... + end +\end{verbatim} +This idiom guarantees that "Myset" is compatible with Set, but allows +it to represent sets internally in a different way. + +\section{Substituting inside a signature} +\ikwd{with\@\texttt{with}} +\ikwd{module\@\texttt{module}} +\ikwd{type\@\texttt{type}} + +(Introduced in OCaml 3.12) + +\begin{syntax} +mod-constraint: + ... + | 'type' [type-params] typeconstr-name ':=' typexpr + | 'module' module-name ':=' extended-module-path +\end{syntax} + +``Destructive'' substitution (@'with' ... ':=' ...@) behaves essentially like +normal signature constraints (@'with' ... '=' ...@), but it additionally removes +the redefined type or module from the signature. There are a number of +restrictions: one can only remove types and modules at the outermost +level (not inside submodules), and in the case of @'with type'@ the +definition must be another type constructor with the same type +parameters. + +A natural application of destructive substitution is merging two +signatures sharing a type name. +\begin{verbatim} + module type Printable = sig + type t + val print : Format.formatter -> t -> unit + end + module type Comparable = sig + type t + val compare : t -> t -> int + end + module type PrintableComparable = sig + include Printable + include Comparable with type t := t + end +\end{verbatim} + +One can also use this to completely remove a field: +\caml +\?module type S = Comparable with type t := int;; +\:module type S = sig val compare : int -> int -> int end +\endcaml +or to rename one: +\caml +\?module type S = sig +\? type u +\? include Comparable with type t := u +\?end;; +\:module type S = sig type u val compare : u -> u -> int end +\endcaml + +Note that you can also remove manifest types, by substituting with the +same type. +\caml +\?module type ComparableInt = Comparable with type t = int ;; +\:module type ComparableInt = sig type t = int val compare : t -> t -> int end +\?module type CompareInt = ComparableInt with type t := int ;; +\:module type CompareInt = sig val compare : int -> int -> int end +\endcaml + +\section{Type-level module aliases} +\ikwd{module\@\texttt{module}} +\label{s:module-alias} + +(Introduced in OCaml 4.02) + +\begin{syntax} +specification: + ... + | 'module' module-name '=' module-path +\end{syntax} + +The above specification, inside a signature, only matches a module +definition equal to @module-path@. Conversely, a type-level module +alias can be matched by itself, or by any supertype of the type of the +module it references. + +There are several restrictions on @module-path@: +\begin{enumerate} +\item it should be of the form \(M_0.M_1...M_n\) ({\em i.e.} without + functor applications); +\item inside the body of a functor, \(M_0\) should not be one of the + functor parameters; +\item inside a recursive module definition, \(M_0\) should not be one of + the recursively defined modules. +\end{enumerate} + +Such specifications are also inferred. Namely, when @P@ is a path +satisfying the above constraints, +\caml +\?module N = P +\endcaml +has type +\caml +\:module N = P +\endcaml + +Type-level module aliases are used when checking module path +equalities. That is, in a context where module name @N@ is known to be +an alias for @P@, not only these two module paths check as equal, but +@F(N)@ and @F(P)@ are also recognized as equal. In the default +compilation mode, this is the only difference with the previous +approach of module aliases having just the same module type as the +module they reference. + +When the compiler flag @'-no-alias-deps'@ is enabled, type-level +module aliases are also exploited to avoid introducing dependencies +between compilation units. Namely, a module alias referring to a +module inside another compilation unit does not introduce a link-time +dependency on that compilation unit, as long as it is not +dereferenced; it still introduces a compile-time dependency if the +interface needs to be read, {\em i.e.} if the module is a submodule +of the compilation unit, or if some type components are referred to. +Additionally, accessing a module alias introduces a link-time +dependency on the compilation unit containing the module referenced by +the alias, rather than the compilation unit containing the alias. +Note that these differences in link-time behavior may be incompatible +with the previous behavior, as some compilation units might not be +extracted from libraries, and their side-effects ignored. + +These weakened dependencies make possible to use module aliases in +place of the @'-pack'@ mechanism. Suppose that you have a library +@'Mylib'@ composed of modules @'A'@ and @'B'@. Using @'-pack'@, one +would issue the command line +\begin{verbatim} + ocamlc -pack a.cmo b.cmo -o mylib.cmo +\end{verbatim} +and as a result obtain a @'Mylib'@ compilation unit, containing +physically @'A'@ and @'B'@ as submodules, and with no dependencies on +their respective compilation units. +Here is a concrete example of a possible alternative approach: +\begin{enumerate} +\item Rename the files containing @'A'@ and @'B'@ to @'Mylib_A'@ and + @'Mylib_B'@. +\item Create a packing interface @'Mylib.ml'@, containing the + following lines. +\begin{verbatim} + module A = Mylib_A + module B = Mylib_B +\end{verbatim} +\item Compile @'Mylib.ml'@ using @'-no-alias-deps'@, and the other + files using @'-no-alias-deps'@ and @'-open' 'Mylib'@ (the last one is + equivalent to adding the line @'open!' 'Mylib'@ at the top of each + file). +\begin{verbatim} + ocamlc -c -no-alias-deps Mylib.ml + ocamlc -c -no-alias-deps -open Mylib Mylib_*.mli Mylib_*.ml +\end{verbatim} +\item Finally, create a library containing all the compilation units, + and export all the compiled interfaces. +\begin{verbatim} + ocamlc -a Mylib*.cmo -o Mylib.cma +\end{verbatim} +\end{enumerate} +This approach lets you access @'A'@ and @'B'@ directly inside the +library, and as @'Mylib.A'@ and @'Mylib.B'@ from outside. +It also has the advantage that @'Mylib'@ is no longer monolithic: if +you use @'Mylib.A'@, only @'Mylib_A'@ will be linked in, not +@'Mylib_B'@. +%Note that in the above @'Mylib.cmo'@ is actually empty, and one could +%name the interface @'Mylib.mli'@, but this would require that all +%clients are compiled with the @'-no-alias-deps'@ flag. + +\section{Explicit overriding in class definitions}\label{s:explicit-overriding} +\ikwd{method.\@\texttt{method\char33}} +\ikwd{val.\@\texttt{val\char33}} +\ikwd{inherit.\@\texttt{inherit\char33}} + +(Introduced in OCaml 3.12) + +\begin{syntax} +class-field: + ... + | 'inherit!' class-expr ['as' lowercase-ident] + | 'val!' ['mutable'] inst-var-name [':' typexpr] '=' expr + | 'method!' ['private'] method-name {parameter} [':' typexpr] '=' expr + | 'method!' ['private'] method-name ':' poly-typexpr '=' expr +\end{syntax} + +The keywords @"inherit!"@, @"val!"@ and @"method!"@ have the same semantics +as @"inherit"@, @"val"@ and @"method"@, but they additionally require the +definition they introduce to be an overriding. Namely, @"method!"@ +requires @method-name@ to be already defined in this class, @"val!"@ +requires @inst-var-name@ to be already defined in this class, and +@"inherit!"@ requires @class-expr@ to override some definitions. +If no such overriding occurs, an error is signaled. + +As a side-effect, these 3 keywords avoid the warnings~7 +(method override) and~13 (instance variable override). +Note that warning~7 is disabled by default. + +\section{Overriding in open statements}\label{s:explicit-overriding-open} +\ikwd{open.\@\texttt{open\char33}} + +(Introduced in OCaml 4.01) + +\begin{syntax} +definition: + ... + | 'open!' module-path +; +specification: + ... + | 'open!' module-path +; +expr: + ... + | 'let' 'open!' module-path 'in' expr +\end{syntax} + +Since OCaml 4.01, @"open"@ statements shadowing an existing identifier +(which is later used) trigger the warning 44. Adding a @"!"@ +character after the @"open"@ keyword indicates that such a shadowing is +intentional and should not trigger the warning. + + +\section{Generalized algebraic datatypes} \ikwd{type\@\texttt{type}} +\ikwd{match\@\texttt{match}} \label{s:gadts} + +(Introduced in OCaml 4.00) + +\begin{syntax} +constr-decl: + ... + | constr-name ':' [ constr-args '->' ] typexpr +; +type-param: + ... + | [variance] '_' +\end{syntax} + +Generalized algebraic datatypes, or GADTs, extend usual sum types in +two ways: constraints on type parameters may change depending on the +value constructor, and some type variables may be existentially +quantified. +Adding constraints is done by giving an explicit return type +(the rightmost @typexpr@ in the above syntax), where type parameters +are instantiated. +This return type must use the same type constructor as the type being +defined, and have the same number of parameters. +Variables are made existential when they appear inside a constructor's +argument, but not in its return type. + +Since the use of a return type often eliminates the need to name type +parameters in the left-hand side of a type definition, one can replace +them with anonymous types @"_"@ in that case. + +The constraints associated to each constructor can be recovered +through pattern-matching. +Namely, if the type of the scrutinee of a pattern-matching contains +a locally abstract type, this type can be refined according to the +constructor used. +These extra constraints are only valid inside the corresponding branch +of the pattern-matching. +If a constructor has some existential variables, fresh locally +abstract types are generated, and they must not escape the +scope of this branch. + +\paragraph{Recursive functions} + +Here is a concrete example: +\begin{verbatim} + type _ term = + | Int : int -> int term + | Add : (int -> int -> int) term + | App : ('b -> 'a) term * 'b term -> 'a term + + let rec eval : type a. a term -> a = function + | Int n -> n (* a = int *) + | Add -> (fun x y -> x+y) (* a = int -> int -> int *) + | App(f,x) -> (eval f) (eval x) + (* eval called at types (b->a) and b for fresh b *) + + let two = eval (App (App (Add, Int 1), Int 1)) + val two : int = 2 +\end{verbatim} +It is important to remark that the function "eval" is using the +polymorphic syntax for locally abstract types. When defining a recursive +function that manipulates a GADT, explicit polymorphic recursion should +generally be used. For instance, the following definition fails with a +type error: +\begin{verbatim} + let rec eval (type a) : a term -> a = function + | Int n -> n + | Add -> (fun x y -> x+y) + | App(f,x) -> (eval f) (eval x) +(* ^ + Error: This expression has type ($App_'b -> a) term but an expression was + expected of type 'a + The type constructor $App_'b would escape its scope +*) +\end{verbatim} +In absence of an explicit polymorphic annotation, a monomorphic type +is inferred for the recursive function. If a recursive call occurs +inside the function definition at a type that involves an existential +GADT type variable, this variable flows to the type of the recursive +function, and thus escapes its scope. In the above example, this happens +in the branch "App(f,x)" when "eval" is called with "f" as an argument. +In this branch, the type of "f" is "($App_ 'b-> a)". The prefix "$" in +"$App_ 'b" denotes an existential type named by the compiler +(see~\ref{p:existential-names}). Since the type of "eval" is +"'a term -> 'a", the call "eval f" makes the existential type "$App_'b" +flow to the type variable "'a" and escape its scope. This triggers the +above error. + +\paragraph{Type inference} + +Type inference for GADTs is notoriously hard. +This is due to the fact some types may become ambiguous when escaping +from a branch. +For instance, in the "Int" case above, "n" could have either type "int" +or "a", and they are not equivalent outside of that branch. +As a first approximation, type inference will always work if a +pattern-matching is annotated with types containing no free type +variables (both on the scrutinee and the return type). +This is the case in the above example, thanks to the type annotation +containing only locally abstract types. + +In practice, type inference is a bit more clever than that: type +annotations do not need to be immediately on the pattern-matching, and +the types do not have to be always closed. +As a result, it is usually enough to only annotate functions, as in +the example above. Type annotations are +propagated in two ways: for the scrutinee, they follow the flow of +type inference, in a way similar to polymorphic methods; for the +return type, they follow the structure of the program, they are split +on functions, propagated to all branches of a pattern matching, +and go through tuples, records, and sum types. +Moreover, the notion of ambiguity used is stronger: a type is only +seen as ambiguous if it was mixed with incompatible types (equated by +constraints), without type annotations between them. +For instance, the following program types correctly. +\begin{verbatim} + let rec sum : type a. a term -> _ = fun x -> + let y = + match x with + | Int n -> n + | Add -> 0 + | App(f,x) -> sum f + sum x + in y + 1 + val sum : 'a term -> int = +\end{verbatim} +Here the return type "int" is never mixed with "a", so it is seen as +non-ambiguous, and can be inferred. +When using such partial type annotations we strongly suggest +specifying the "-principal" mode, to check that inference is +principal. + +The exhaustiveness check is aware of GADT constraints, and can +automatically infer that some cases cannot happen. +For instance, the following pattern matching is correctly seen as +exhaustive (the "Add" case cannot happen). +\begin{verbatim} + let get_int : int term -> int = function + | Int n -> n + | App(_,_) -> 0 +\end{verbatim} + + +\paragraph{Refutation cases and redundancy} (Introduced in OCaml 4.03) + +Usually, the exhaustiveness check only tries to check whether the +cases omitted from the pattern matching are typable or not. +However, you can force it to try harder by adding {\em refutation cases}: +\begin{syntax} +matching-case: + pattern ['when' expr] '->' expr + | pattern '->' '.' +\end{syntax} +In presence of a refutation case, the exhaustiveness check will first +compute the intersection of the pattern with the complement of the +cases preceding it. It then checks whether the resulting patterns can +really match any concrete values by trying to type-check them. +Wild cards in the generated patterns are handled in a special way: if +their type is a variant type with only GADT constructors, then the +pattern is split into the different constructors, in order to check whether +any of them is possible (this splitting is not done for arguments of these +constructors, to avoid non-termination.) We also split tuples and +variant types with only one case, since they may contain GADTs inside. +For instance, the following code is deemed exhaustive: + +\begin{verbatim} + type _ t = + | Int : int t + | Bool : bool t + + let deep : (char t * int) option -> char = function + | None -> 'c' + | _ -> . +\end{verbatim} + +Namely, the inferred remaining case is "Some _", which is split into +"Some (Int, _)" and "Some (Bool, _)", which are both untypable. +Note that the refutation case could be omitted here, because it is +automatically added when there is only one case in the pattern +matching. + +Another addition is that the redundancy check is now aware of GADTs: a +case will be detected as redundant if it could be replaced by a +refutation case using the same pattern. + +\paragraph{Advanced examples} +The "term" type we have defined above is an {\em indexed} type, where +a type parameter reflects a property of the value contents. +Another use of GADTs is {\em singleton} types, where a GADT value +represents exactly one type. This value can be used as runtime +representation for this type, and a function receiving it can have a +polytypic behavior. + +Here is an example of a polymorphic function that takes the +runtime representation of some type "t" and a value of the same type, +then pretty-prints the value as a string: +\begin{verbatim} + type _ typ = + | Int : int typ + | String : string typ + | Pair : 'a typ * 'b typ -> ('a * 'b) typ + + let rec to_string: type t. t typ -> t -> string = + fun t x -> + match t with + | Int -> string_of_int x + | String -> Printf.sprintf "%S" x + | Pair(t1,t2) -> + let (x1, x2) = x in + Printf.sprintf "(%s,%s)" (to_string t1 x1) (to_string t2 x2) +\end{verbatim} + +Another frequent application of GADTs is equality witnesses. +\begin{verbatim} + type (_,_) eq = Eq : ('a,'a) eq + + let cast : type a b. (a,b) eq -> a -> b = fun Eq x -> x +\end{verbatim} +Here type "eq" has only one constructor, and by matching on it one +adds a local constraint allowing the conversion between "a" and "b". +By building such equality witnesses, one can make equal types which +are syntactically different. + +Here is an example using both singleton types and equality witnesses +to implement dynamic types. +\begin{verbatim} + let rec eq_type : type a b. a typ -> b typ -> (a,b) eq option = + fun a b -> + match a, b with + | Int, Int -> Some Eq + | String, String -> Some Eq + | Pair(a1,a2), Pair(b1,b2) -> + begin match eq_type a1 b1, eq_type a2 b2 with + | Some Eq, Some Eq -> Some Eq + | _ -> None + end + | _ -> None + + type dyn = Dyn : 'a typ * 'a -> dyn + + let get_dyn : type a. a typ -> dyn -> a option = + fun a (Dyn(b,x)) -> + match eq_type a b with + | None -> None + | Some Eq -> Some x +\end{verbatim} + +\paragraph{Existential type names in error messages}% +\label{p:existential-names} +(Updated in OCaml 4.03.0) + +The typing of pattern matching in presence of GADT can generate many +existential types. When necessary, error messages refer to these +existential types using compiler-generated names. Currently, the +compiler generates these names according to the following nomenclature: +\begin{itemize} +\item First, types whose name starts with a "$" are existentials. +\item "$Constr_'a" denotes an existential type introduced for the type +variable "'a" of the GADT constructor "Constr": +\caml +\? type any = Any : \tq\-name -> any +\? let escape (Any x) = \;; +\: Error: This expression has type $Any_\tq\-name +\: but an expression was expected of type \tq\-a +\: The type constructor $Any_\tq\-name would escape its scope +\endcaml +\item "$Constr" denotes an existential type introduced for an anonymous +type variable in the GADT constructor "Constr": +\caml +\? type any = Any : _ -> any +\? let escape (Any x) = \;; +\: Error: This expression has type $Any but an expression was expected of type +\: \tq\-a +\: The type constructor $Any would escape its scope +\endcaml +\item "$'a" if the existential variable was unified with the type +variable "'a" during typing: +\caml +\? type (\tq\-arg,\tq\-result,\tq\-aux) fn = +\? | Fun: (\tq\-a ->\tq\-b) -> (\tq\-a,\tq\-b,unit) fn +\? | Mem1: (\tq\-a ->\tq\-b) * \tq\-a * \tq\-b -> (\tq\-a, \tq\-b, \tq\-a * \tq\-b) fn + +\? let apply: (\tq\-arg,\tq\-result, _ ) fn -> \tq\-arg -> \tq\-result = fun f x -> +\? match f with +\? | Fun f -> f x +\? | \ -> if x = y then fy else f x;; + +\: Error: This pattern matches values of type +\: ($\tq\-arg, $\tq\-result, $\tq\-arg * $\tq\-result) fn +\: but a pattern was expected which matches values of type +\: ($\tq\-arg, $\tq\-result, unit) fn +\: Type $\tq\-arg * $\tq\-result is not compatible with type unit +\endcaml +\item "$n" (n a number) is an internally generated existential +which could not be named using one of the previous schemes. +\end{itemize} + +As shown by the last item, the current behavior is imperfect +and may be improved in future versions. + +\paragraph{Equations on non-local abstract types} (Introduced in OCaml +4.04) + +GADT pattern-matching may also add type equations to non-local +abstract types. The behaviour is the same as with local abstract +types. Reusing the above "eq" type, one can write: +\begin{verbatim} + module M : sig type t val x : t val e : (x,int) eq end = struct + type t = int + let x = 33 + let e = Eq + end + + let x : int = let Eq = M.e in M.x +\end{verbatim} + +Of course, not all abstract types can be refined, as this would +contradict the exhaustiveness check. Namely, builtin types (those +defined by the compiler itself, such as "int" or "array"), and +abstract types defined by the local module, are non-instantiable, and +as such cause a type error rather than introduce an equation. + +\section{Syntax for Bigarray access}\label{s:bigarray-access} + +(Introduced in Objective Caml 3.00) + +\begin{syntax} +expr: + ... + | expr '.{' expr { ',' expr } '}' + | expr '.{' expr { ',' expr } '}' '<-' expr +\end{syntax} + +This extension provides syntactic sugar for getting and setting +elements in the arrays provided by the +"Bigarray"[\moduleref{Bigarray}] library. + +The short expressions are translated into calls to functions of the +"Bigarray" module as described in the following table. + +\begin{tableau}{|l|l|}{expression}{translation} +\entree{@expr_0'.{'expr_1'}'@} + {"Bigarray.Array1.get "@expr_0 expr_1@} +\entree{@expr_0'.{'expr_1'}' '<-'expr@} + {"Bigarray.Array1.set "@expr_0 expr_1 expr@} +\entree{@expr_0'.{'expr_1',' expr_2'}'@} + {"Bigarray.Array2.get "@expr_0 expr_1 expr_2@} +\entree{@expr_0'.{'expr_1',' expr_2'}' '<-'expr@} + {"Bigarray.Array2.set "@expr_0 expr_1 expr_2 expr@} +\entree{@expr_0'.{'expr_1',' expr_2',' expr_3'}'@} + {"Bigarray.Array3.get "@expr_0 expr_1 expr_2 expr_3@} +\entree{@expr_0'.{'expr_1',' expr_2',' expr_3'}' '<-'expr@} + {"Bigarray.Array3.set "@expr_0 expr_1 expr_2 expr_3 expr@} +\entree{@expr_0'.{'expr_1',' \ldots',' expr_n'}'@} + {"Bigarray.Genarray.get "@ expr_0 '[|' expr_1',' \ldots ',' + expr_n '|]'@} +\entree{@expr_0'.{'expr_1',' \ldots',' expr_n'}' '<-'expr@} + {"Bigarray.Genarray.set "@ expr_0 '[|' expr_1',' \ldots ',' + expr_n '|]' expr@} +\end{tableau} + +The last two entries are valid for any $n > 3$. + +\section{Attributes}\label{s:attributes} + +\ikwd{when\@\texttt{when}} + +(Introduced in OCaml 4.02, +infix notations for constructs other than expressions added in 4.03) + +Attributes are ``decorations'' of the syntax tree which are mostly +ignored by the type-checker but can be used by external tools. An +attribute is made of an identifier and a payload, which can be a +structure, a type expression (prefixed with ":"), a signature +(prefixed with ":") or a pattern (prefixed with "?") optionally +followed by a "when" clause: + + +\begin{syntax} +attr-id: + lowercase-ident + | capitalized-ident + | attr-id '.' attr-id +; +attr-payload: + [ module-items ] + | ':' typexpr + | ':' [ specification ] + | '?' pattern ['when' expr] +; +\end{syntax} + +The first form of attributes is attached with a postfix notation on +``algebraic'' categories: + +\begin{syntax} +attribute: + '[@' attr-id attr-payload ']' +; +expr: ... + | expr attribute +; +typexpr: ... + | typexpr attribute +; +pattern: ... + | pattern attribute +; +module-expr: ... + | module-expr attribute +; +module-type: ... + | module-type attribute +; +class-expr: ... + | class-expr attribute +; +class-type: ... + | class-type attribute +; +\end{syntax} + +This form of attributes can also be inserted after the @'`'tag-name@ +in polymorphic variant type expressions (@tag-spec-first@, @tag-spec@, +@tag-spec-full@) or after the @method-name@ in @method-type@. + +The same syntactic form is also used to attach attributes to labels and +constructors in type declarations: + +\begin{syntax} +field-decl: + ['mutable'] field-name ':' poly-typexpr {attribute} +; +constr-decl: + (constr-name || '()') [ 'of' constr-args ] {attribute} +; +\end{syntax} + +Note: when a label declaration is followed by a semi-colon, attributes +can also be put after the semi-colon (in which case they are merged to +those specified before). + + +The second form of attributes are attached to ``blocks'' such as type +declarations, class fields, etc: + +\begin{syntax} +item-attribute: + '[@@' attr-id attr-payload ']' +; +typedef: ... + | typedef item-attribute +; +exception-definition: + 'exception' constr-decl + | 'exception' constr-name '=' constr +; +module-items: + [';;'] ( definition || expr { item-attribute } ) { [';;'] definition || ';;' expr { item-attribute } } [';;'] +; +class-binding: ... + | class-binding item-attribute +; +class-spec: ... + | class-spec item-attribute +; +classtype-def: ... + | classtype-def item-attribute +; +definition: + 'let' ['rec'] let-binding { 'and' let-binding } + | 'external' value-name ':' typexpr '=' external-declaration { item-attribute } + | type-definition + | exception-definition { item-attribute } + | class-definition + | classtype-definition + | 'module' module-name { '(' module-name ':' module-type ')' } + [ ':' module-type ] \\ '=' module-expr { item-attribute } + | 'module' 'type' modtype-name '=' module-type { item-attribute } + | 'open' module-path { item-attribute } + | 'include' module-expr { item-attribute } + | 'module' 'rec' module-name ':' module-type '=' \\ + module-expr { item-attribute } \\ + { 'and' module-name ':' module-type '=' module-expr \\ + { item-attribute } } +; +specification: + 'val' value-name ':' typexpr { item-attribute } + | 'external' value-name ':' typexpr '=' external-declaration { item-attribute } + | type-definition + | 'exception' constr-decl { item-attribute } + | class-specification + | classtype-definition + | 'module' module-name ':' module-type { item-attribute } + | 'module' module-name { '(' module-name ':' module-type ')' } + ':' module-type { item-attribute } + | 'module' 'type' modtype-name { item-attribute } + | 'module' 'type' modtype-name '=' module-type { item-attribute } + | 'open' module-path { item-attribute } + | 'include' module-type { item-attribute } +; +class-field-spec: ... + | class-field-spec item-attribute +; +class-field: ... + | class-field item-attribute +; +\end{syntax} + +A third form of attributes appears as stand-alone structure or +signature items in the module or class sub-languages. They are not +attached to any specific node in the syntax tree: + +\begin{syntax} +floating-attribute: + '[@@@' attr-id attr-payload ']' +; +definition: ... + | floating-attribute +; +specification: ... + | floating-attribute +; +class-field-spec: ... + | floating-attribute +; +class-field: ... + | floating-attribute +; +\end{syntax} + +(Note: contrary to what the grammar above describes, @item-attributes@ +cannot be attached to these floating attributes in @class-field-spec@ +and @class-field@.) + + +It is also possible to specify attributes using an infix syntax. For instance: + +\begin{verbatim} +let[@foo] x = 2 in x + 1 === (let x = 2 [@@foo] in x + 1) +begin[@foo][@bar x] ... end === (begin ... end)[@foo][@@bar x] +module[@foo] M = ... === module M = ... [@@foo] +type[@foo] t = T === type t = T [@@foo] +method[@foo] m = ... === method m = ... [@@foo] +\end{verbatim} + +For "let", the attributes are applied to each bindings: + +\begin{verbatim} +let[@foo] x = 2 and y = 3 in x + y === (let x = 2 [@@foo] and y = 3 in x + y) +let[@foo] x = 2 +and[@bar] y = 3 in x + y === (let x = 2 [@@foo] and y = 3 [@bar] in x + y) +\end{verbatim} + + +\subsection{Built-in attributes} +\label{ss:builtin-attributes} + +Some attributes are understood by the type-checker: +\begin{itemize} +\item + ``ocaml.warning'' or ``warning'', with a string literal payload. + This can be used as floating attributes in a + signature/structure/object/object type. The string is parsed and has + the same effect as the "-w" command-line option, in the scope between + the attribute and the end of the current + signature/structure/object/object type. The attribute can also be + used on an expression, + in which case its scope is limited to that expression. + Note that it is not well-defined which scope is used for a specific + warning. This is implementation dependant and can change between versions. + For instance, warnings triggered by the ``ppwarning'' attribute (see below) + are issued using the global warning configuration. +\item + ``ocaml.warnerror'' or ``warnerror'', with a string literal payload. + Same as ``ocaml.warning'', for the "-warn-error" command-line option. +\item + ``ocaml.deprecated'' or ``deprecated''. + Can be applied to most kind of items in signatures or + structures. When the element is later referenced, a warning (3) is + triggered. If the payload of the attribute is a string literal, + the warning message includes this text. It is also possible + to use this ``ocaml.deprecated'' as a floating attribute + on top of an ``.mli'' file (i.e. before any other non-attribute + item) or on top of an ``.ml'' file without a corresponding + interface; this marks the unit itself as being deprecated. +\item + ``ocaml.deprecated_mutable'' or ``deprecated_mutable''. + Can be applied to a mutable record label. If the label is later + used to modify the field (with ``expr.l <- expr''), a warning (3) + will be triggered. If the payload of the attribute is a string literal, + the warning message includes this text. +\item + ``ocaml.ppwarning'' or ``ppwarning'', in any context, with + a string literal payload. The text is reported as warning (22) + by the compiler (currently, the warning location is the location + of the string payload). This is mostly useful for preprocessors which + need to communicate warnings to the user. This could also be used + to mark explicitly some code location for further inspection. +\item + ``ocaml.warn_on_literal_pattern'' or ``warn_on_literal_pattern'' annotate + constructors in type definition. A warning (52) is then emitted when this + constructor is pattern matched with a constant literal as argument. This + attribute denotes constructors whose argument is purely informative and + may change in the future. Therefore, pattern matching on this argument + with a constant literal is unreliable. For instance, all built-in exception + constructors are marked as ``warn_on_literal_pattern''. + Note that, due to an implementation limitation, this warning (52) is only + triggered for single argument constructor. +\item + ``ocaml.tailcall'' or ``tailcall'' can be applied to function + application in order to check that the call is tailcall optimized. + If it it not the case, a warning (51) is emitted. +\item + ``ocaml.inline'' or ``inline'' take either ``never'', ``always'' + or nothing as payload on a function or functor definition. If no payload + is provided, the default value is ``always''. This payload controls when + applications of the annotated functions should be inlined. +\item + ``ocaml.inlined'' or ``inlined'' can be applied to any function or functor + application to check that the call is inlined by the compiler. If the call + is not inlined, a warning (55) is emitted. +\item + ``ocaml.noalloc'', ``ocaml.unboxed''and ``ocaml.untagged'' or + ``noalloc'', ``unboxed'' and ``untagged'' can be used on external + definitions to obtain finer control over the C-to-OCaml interface. See + \ref{s:C-cheaper-call} for more details. +\item + ``ocaml.immediate'' or ``immediate'' applied on an abstract type mark the type as + having a non-pointer implementation (e.g. ``int'', ``bool'', ``char'' or + enumerated types). Mutation of these immediate types does not activate the + garbage collector's write barrier, which can significantly boost performance in + programs relying heavily on mutable state. +\item + "ocaml.unboxed" or "unboxed" can be used on a type definition if the + type is a single-field record or a concrete type with a single + constructor that has a single argument. It tells the compiler to + optimize the representation of the type by removing the block that + represents the record or the constructor (i.e. a value of this type + is physically equal to its argument). In the case of GADTs, an + additional restriction applies: the argument must not be an + existential variable, represented by an existential type variable, + or an abstract type constructor applied to an existential type + variable. +\item + "ocaml.boxed" or "boxed" can be used on type definitions to mean + the opposite of "ocaml.unboxed": keep the unoptimized + representation of the type. When there is no annotation, the + default is currently "boxed" but it may change in the future. +\end{itemize} + +\begin{verbatim} +module X = struct + [@@@warning "+9"] (* locally enable warning 9 in this structure *) + ... +end + [@@deprecated "Please use module 'Y' instead."] + +let x = begin[@warning "+9"] ... end in .... + +type t = A | B + [@@deprecated "Please use type 's' instead."] + +let f x = + assert (x >= 0) [@ppwarning "TODO: remove this later"]; + +let rec no_op = function + | [] -> () + | _ :: q -> (no_op[@tailcall]) q;; + +let f x = x [@@inline] + +let () = (f[@inlined]) () + +type fragile = + | Int of int [@warn_on_literal_pattern] + | String of string [@warn_on_literal_pattern] + +let f = function +| Int 0 | String "constant" -> () (* trigger warning 52 *) +| _ -> () + +module Immediate: sig + type t [@@immediate] + val x: t ref +end = struct + type t = A | B + let x = ref 0 +end + .... + +\end{verbatim} + + +\section{Extension nodes}\label{s:extension-nodes} + +(Introduced in OCaml 4.02, +infix notations for constructs other than expressions added in 4.03, +infix notation (e1 ;\%ext e2) added in 4.04. +) + +Extension nodes are generic placeholders in the syntax tree. They are +rejected by the type-checker and are intended to be ``expanded'' by external +tools such as "-ppx" rewriters. + +Extension nodes share the same notion of identifier and payload as +attributes~\ref{s:attributes}. + +The first form of extension node is used for ``algebraic'' categories: + +\begin{syntax} +extension: + '[%' attr-id attr-payload ']' +; +expr: ... + | extension +; +typexpr: ... + | extension +; +pattern: ... + | extension +; +module-expr: ... + | extension +; +module-type: ... + | extension +; +class-expr: ... + | extension +; +class-type: ... + | extension +; +\end{syntax} + +A second form of extension node can be used in structures and +signatures, both in the module and object languages: + +\begin{syntax} +item-extension: + '[%%' attr-id attr-payload ']' +; +definition: ... + | item-extension +; +specification: ... + | item-extension +; +class-field-spec: ... + | item-extension +; +class-field: + | item-extension +; +\end{syntax} + +An infix form is available for extension nodes when +the payload is of the same kind +(expression with expression, pattern with pattern ...). + +Examples: + +\begin{verbatim} +let%foo x = 2 in x + 1 === [%foo let x = 2 in x + 1] +begin%foo ... end === [%foo begin ... end] +x ;%foo 2 === [%foo x; 2] +module%foo M = .. === [%%foo module M = ... ] +val%foo x : t === [%%foo: val x : t] +\end{verbatim} + +When this form is used together with the infix syntax for attributes, +the attributes are considered to apply to the payload: + +\begin{verbatim} +fun%foo[@bar] x -> x + 1 === [%foo (fun x -> x + 1)[@foo ] ]; +\end{verbatim} + +\subsection{Built-in extension nodes} + +(Introduced in OCaml 4.03) + +Some extension nodes are understood by the compiler itself: +\begin{itemize} + \item + ``ocaml.extension_constructor'' or ``extension_constructor'' + take as payload a constructor from an extensible variant type + (see \ref{s:extensible-variants}) and return its extension + constructor slot. +\end{itemize} + +\begin{verbatim} +type t = .. +type t += X of int | Y of string +let x = [%extension_constructor X] +let y = [%extension_constructor Y] +\end{verbatim} +\caml +\? x <> y;; +\:- : bool = true +\endcaml + +\section{Quoted strings}\label{s:quoted-strings} + +(Introduced in OCaml 4.02) + +Quoted strings provide a different lexical syntax to write string +literals in OCaml code. This can be used to embed pieces of foreign +syntax fragments in OCaml code, to be interpret by a "-ppx" filter or +just a library. + +\begin{syntax} +string-literal: ... + | '{' quoted-string-id '|' ........ '|' quoted-string-id '}' +; +quoted-string-id: + { 'a'...'z' || '_' } +; +\end{syntax} + +The opening delimiter has the form "{id|" where "id" is a (possibly + empty) sequence of lowercase letters and underscores. The + corresponding closing delimiter is "|id}" (with the same +identifier). Unlike regular OCaml string literals, quoted +strings do not interpret any character in a special way. + +Example: + +\begin{verbatim} +String.length {|\"|} (* returns 2 *) +String.length {foo|\"|foo} (* returns 2 *) +\end{verbatim} + + +\section{Exception cases in pattern matching}\label{s:exception-match} + +(Introduced in OCaml 4.02) + +A new form of exception patterns is allowed, only as a toplevel +pattern under a "match"..."with" pattern-matching (other occurrences +are rejected by the type-checker). + +\begin{syntax} +pattern: ... + | 'exception' pattern +; +\end{syntax} + +Cases with such a toplevel pattern are called ``exception cases'', +as opposed to regular ``value cases''. Exception cases are applied +when the evaluation of the matched expression raises an exception. +The exception value is then matched against all the exception cases +and re-raised if none of them accept the exception (as for a +"try"..."with" block). Since the bodies of all exception and value +cases is outside the scope of the exception handler, they are all +considered to be in tail-position: if the "match"..."with" block +itself is in tail position in the current function, any function call +in tail position in one of the case bodies results in an actual tail +call. + +It is an error if all cases are exception cases in a given pattern +matching. + +\section{Extensible variant types}\label{s:extensible-variants} + +(Introduced in OCaml 4.02) + +\begin{syntax} +type-representation: + ... + | '=' '..' +; +specification: + ... + | 'type' [type-params] typeconstr type-extension-spec +; +definition: + ... + | 'type' [type-params] typeconstr type-extension-def +; +type-extension-spec: '+=' ['private'] ['|'] constr-decl { '|' constr-decl } +; +type-extension-def: '+=' ['private'] ['|'] constr-def { '|' constr-def } +; +constr-def: + constr-decl + | constr-name '=' constr +; +\end{syntax} + +Extensible variant types are variant types which can be extended with +new variant constructors. Extensible variant types are defined using +"..". New variant constructors are added using "+=". +\begin{verbatim} + type attr = .. + + type attr += Str of string + + type attr += + | Int of int + | Float of float +\end{verbatim} + +Pattern matching on an extensible variant type requires a default case +to handle unknown variant constructors: +\begin{verbatim} + let to_string = function + | Str s -> s + | Int i -> string_of_int i + | Float f -> string_of_float f + | _ -> "?" +\end{verbatim} + +A preexisting example of an extensible variant type is the built-in +"exn" type used for exceptions. Indeed, exception constructors can be +declared using the type extension syntax: +\begin{verbatim} + type exn += Exc of int +\end{verbatim} + +Extensible variant constructors can be rebound to a different name. This +allows exporting variants from another module. +\begin{verbatim} + type Expr.attr += Str = Expr.Str +\end{verbatim} + +Extensible variant constructors can be declared "private". As with +regular variants, this prevents them from being constructed directly by +constructor application while still allowing them to be de-structured in +pattern-matching. + + +\section{Generative functors}\label{s:generative-functors} + +(Introduced in OCaml 4.02) + +\begin{syntax} +module-expr: + ... + | 'functor' '()' '->' module-expr + | module-expr '()' +; +definition: + ... + | 'module' module-name { '(' module-name ':' module-type ')' || '()' } + [ ':' module-type ] \\ '=' module-expr +; +module-type: + ... + | 'functor' '()' '->' module-type +; +specification: + ... + | 'module' module-name { '(' module-name ':' module-type ')' || '()' } + ':' module-type +; +\end{syntax} + +A generative functor takes a unit "()" argument. +In order to use it, one must necessarily apply it to this unit argument, +ensuring that all type components in the result of the functor behave +in a generative way, {\em i.e.} they are different from types obtained +by other applications of the same functor. +This is equivalent to taking an argument of signature "sig end", and always +applying to "struct end", but not to some defined module (in the +latter case, applying twice to the same module would return identical +types). + +As a side-effect of this generativity, one is allowed to unpack +first-class modules in the body of generative functors. + +\section{Extension-only syntax} +(Introduced in OCaml 4.02.2, extended in 4.03) + +Some syntactic constructions are accepted during parsing and rejected +during type checking. These syntactic constructions can therefore not +be used directly in vanilla OCaml. However, "-ppx" rewriters and other +external tools can exploit this parser leniency to extend the language +with these new syntactic constructions by rewriting them to +vanilla constructions. +\subsection{Extension operators} \label{s:ext-ops} +(Introduced in OCaml 4.02.2) +\begin{syntax} +infix-symbol: + ... + | "#" {operator-chars} "#" {operator-char '|' "#"} +; +\end{syntax} + +Operator names starting with a "#" character and containing more than +one "#" character are reserved for extensions. + +\subsection{Extension literals} +(Introduced in OCaml 4.03) +\begin{syntax} +float-literal: + ... + | ["-"] ("0"\ldots"9") { "0"\ldots"9"||"_" } ["." { "0"\ldots"9"||"_" }] + [("e"||"E") ["+"||"-"] ("0"\ldots"9") { "0"\ldots"9"||"_" }] + ["g"\ldots"z"||"G"\ldots"Z"] + | ["-"] ("0x"||"0X") + ("0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f") + { "0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f"||"_" }\\ + ["." { "0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f"||"_" } + [("p"||"P") ["+"||"-"] ("0"\ldots"9") { "0"\ldots"9"||"_" }] + ["g"\ldots"z"||"G"\ldots"Z"] +; +int-literal: + ... + | ["-"] ("0"\ldots"9") { "0"\ldots"9" || "_" }["g"\ldots"z"||"G"\ldots"Z"] + | ["-"] ("0x"||"0X") ("0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f") + { "0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f"||"_" } + ["g"\ldots"z"||"G"\ldots"Z"] + | ["-"] ("0o"||"0O") ("0"\ldots"7") { "0"\ldots"7"||"_" } + ["g"\ldots"z"||"G"\ldots"Z"] + | ["-"] ("0b"||"0B") ("0"\ldots"1") { "0"\ldots"1"||"_" } + ["g"\ldots"z"||"G"\ldots"Z"] +; +\end{syntax} +Int and float literals followed by an one-letter identifier in the +range @["g".."z"||"G".."Z"]@ are extension-only literals. + +\section{Inline records} +(Introduced in OCaml 4.03) +\begin{syntax} + constr-args: + ... + | record-decl +; +\end{syntax} + +The arguments of a sum-type constructors can now be defined using the +same syntax as records. Mutable and polymorphic fields are allowed. +GADT syntax is supported. Attributes can be specified on individual +fields. + +Syntactically, building or matching constructors with such an inline +record argument is similar to working with a unary constructor whose +unique argument is a declared record type. A pattern can bind +the inline record as a pseudo-value, but the record cannot escape the +scope of the binding and can only be used with the dot-notation to +extract or modify fields or to build new constructor values. + +\begin{verbatim} +type t = + | Point of {width: int; mutable x: float; mutable y: float} + | ... + +let v = Point {width = 10; x = 0.; y = 0.} + +let scale l = function + | Point p -> Point {p with x = l * p.x; y = l * p.y} + | .... + +let print = function + | Point {x; y; _} -> Printf.printf "%f/%f" x y + | .... + +let reset = function + | Point p -> p.x <- 0.; p.y <- 0. + | ... + +let invalid = function + | Point p -> p (* INVALID *) + | ... +\end{verbatim} + + +\section{Local exceptions} +\ikwd{let\@\texttt{let}} +\ikwd{exception\@\texttt{exception}} + +(Introduced in OCaml 4.04) + +It is possible to define local exceptions in expressions: + +\begin{syntax} +expr: + ... + | "let" "exception" constr-decl "in" expr +\end{syntax} + + +The syntactic scope of the exception constructor is the inner +expression, but nothing prevents exception values created with this +constructor from escaping this scope. Two executions of the definition +above result in two incompatible exception constructors (as for any +exception definition). + + +\section{Documentation comments} +(Introduced in OCaml 4.03) + +Comments which start with "**" are treated specially by the +compiler. They are automatically converted during parsing into +attributes (see \ref{s:attributes}) to allow tools to process them as +documentation. + +Such comments can take three forms: {\em floating comments}, {\em item +comments} and {\em label comments}. Any comment starting with "**" which +does not match one of these forms will cause the compiler to emit +warning 50. + +Comments which start with "**" are also used by the ocamldoc +documentation generator (see \ref{c:ocamldoc}). The three comment forms +recognised by the compiler are a subset of the forms accepted by +ocamldoc (see \ref{s:ocamldoc-comments}). + +\subsection{Floating comments} + +Comments surrounded by blank lines that appear within structures, +signatures, classes or class types are converted into +@floating-attribute@s. For example: + +\begin{verbatim} +type t = T + +(** Now some definitions for [t] *) + +let mkT = T +\end{verbatim} + +will be converted to: + +\begin{verbatim} +type t = T + +[@@@ocaml.text " Now some definitions for [t] "] + +let mkT = T +\end{verbatim} + +\subsection{Item comments} + +Comments which appear {\em immediately before} or {\em immediately +after} a structure item, signature item, class item or class type item +are converted into @item-attribute@s. Immediately before or immediately +after means that there must be no blank lines, ";;", or other +documentation comments between them. For example: + +\begin{verbatim} +type t = T +(** A description of [t] *) + +\end{verbatim} + +or + +\begin{verbatim} + +(** A description of [t] *) +type t = T +\end{verbatim} + +will be converted to: + +\begin{verbatim} +type t = T +[@@ocaml.doc " A description of [t] "] +\end{verbatim} + +Note that, if a comment appears immediately next to multiple items, +as in: + +\begin{verbatim} +type t = T +(** An ambiguous comment *) +type s = S +\end{verbatim} + +then it will be attached to both items: + +\begin{verbatim} +type t = T +[@@ocaml.doc " An ambiguous comment "] +type s = S +[@@ocaml.doc " An ambiguous comment "] +\end{verbatim} + +and the compiler will emit warning 50. + +\subsection{Label comments} + +Comments which appear {\em immediately after} a labelled argument, +record field, variant constructor, object method or polymorphic variant +constructor are are converted into @attribute@s. Immediately +after means that there must be no blank lines or other documentation +comments between them. For example: + +\begin{verbatim} +type t1 = lbl:int (** Labelled argument *) -> unit + +type t2 = { + fld: int; (** Record field *) + fld2: float; +} + +type t3 = + | Cstr of string (** Variant constructor *) + | Cstr2 of string + +type t4 = < meth: int * int; (** Object method *) > + +type t5 = [ + `PCstr (** Polymorphic variant constructor *) +] +\end{verbatim} + +will be converted to: + +\begin{verbatim} +type t1 = lbl:(int [@ocaml.doc " Labelled argument "]) -> unit + +type t2 = { + fld: int [@ocaml.doc " Record field "]; + fld2: float; +} + +type t3 = + | Cstr of string [@ocaml.doc " Variant constructor "] + | Cstr2 of string + +type t4 = < meth : int * int [@ocaml.doc " Object method "] > + +type t5 = [ + `PCstr [@ocaml.doc " Polymorphic variant constructor "] +] +\end{verbatim} + +Note that label comments take precedence over item comments, so: + +\begin{verbatim} +type t = T of string +(** Attaches to T not t *) +\end{verbatim} + +will be converted to: + +\begin{verbatim} +type t = T of string [@ocaml.doc " Attaches to T not t "] +\end{verbatim} + +whilst: + +\begin{verbatim} +type t = T of string +(** Attaches to T not t *) +(** Attaches to t *) +\end{verbatim} + +will be converted to: + +\begin{verbatim} +type t = T of string [@ocaml.doc " Attaches to T not t "] +[@@ocaml.doc " Attaches to t "] +\end{verbatim} + +In the absence of meaningful comment on the last constructor of +a type, an empty comment~"(**)" can be used instead: + +\begin{verbatim} +type t = T of string +(**) +(** Attaches to t *) +\end{verbatim} + +will be converted directly to + +\begin{verbatim} +type t = T of string +[@@ocaml.doc " Attaches to t "] +\end{verbatim} diff --git a/manual/manual/refman/lex.etex b/manual/manual/refman/lex.etex new file mode 100644 index 0000000000..61af92e2cc --- /dev/null +++ b/manual/manual/refman/lex.etex @@ -0,0 +1,290 @@ +\section{Lexical conventions} +\pdfsection{Lexical conventions} +%HEVEA\cutname{lex.html} +\subsubsection*{Blanks} + +The following characters are considered as blanks: space, +horizontal tabulation, carriage return, line feed and form feed. Blanks are +ignored, but they separate adjacent identifiers, literals and +keywords that would otherwise be confused as one single identifier, +literal or keyword. + +\subsubsection*{Comments} + +Comments are introduced by the two characters @"(*"@, with no +intervening blanks, and terminated by the characters @"*)"@, with +no intervening blanks. Comments are treated as blank characters. +Comments do not occur inside string or character literals. Nested +comments are handled correctly. + +\subsubsection*{Identifiers} + +\begin{syntax} +ident: ( letter || "_" ) { letter || "0" \ldots "9" || "_" || "'" } ; +capitalized-ident: ("A" \ldots "Z") { letter || "0" \ldots "9" || "_" || "'" } ; +lowercase-ident: + ("a" \ldots "z" || "_") { letter || "0" \ldots "9" || "_" || "'" } ; +letter: "A" \ldots "Z" || "a" \ldots "z" +\end{syntax} + +Identifiers are sequences of letters, digits, "_" (the underscore +character), and "'" (the single quote), starting with a +letter or an underscore. +Letters contain at least the 52 lowercase and uppercase +letters from the ASCII set. The current implementation +also recognizes as letters some characters from the ISO +8859-1 set (characters 192--214 and 216--222 as uppercase letters; +characters 223--246 and 248--255 as lowercase letters). This +feature is deprecated and should be avoided for future compatibility. + +All characters in an identifier are +meaningful. The current implementation accepts identifiers up to +16000000 characters in length. + +In many places, OCaml makes a distinction between capitalized +identifiers and identifiers that begin with a lowercase letter. The +underscore character is considered a lowercase letter for this +purpose. + +\subsubsection*{Integer literals} + +\begin{syntax} +integer-literal: + ["-"] ("0"\ldots"9") { "0"\ldots"9" || "_" } + | ["-"] ("0x"||"0X") ("0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f") + { "0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f"||"_" } + | ["-"] ("0o"||"0O") ("0"\ldots"7") { "0"\ldots"7"||"_" } + | ["-"] ("0b"||"0B") ("0"\ldots"1") { "0"\ldots"1"||"_" } +\end{syntax} + +An integer literal is a sequence of one or more digits, optionally +preceded by a minus sign. By default, integer literals are in decimal +(radix 10). The following prefixes select a different radix: +\begin{tableau}{|l|l|}{Prefix}{Radix} +\entree{"0x", "0X"}{hexadecimal (radix 16)} +\entree{"0o", "0O"}{octal (radix 8)} +\entree{"0b", "0B"}{binary (radix 2)} +\end{tableau} +(The initial @"0"@ is the digit zero; the @"O"@ for octal is the letter O.) +The interpretation of integer literals that fall outside the range of +representable integer values is undefined. + +For convenience and readability, underscore characters (@"_"@) are accepted +(and ignored) within integer literals. + +\subsubsection*{Floating-point literals} + +\begin{syntax} +float-literal: + ["-"] ("0"\ldots"9") { "0"\ldots"9"||"_" } ["." { "0"\ldots"9"||"_" }] + [("e"||"E") ["+"||"-"] ("0"\ldots"9") { "0"\ldots"9"||"_" }] + | ["-"] ("0x"||"0X") + ("0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f") + { "0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f"||"_" }\\ + ["." { "0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f"||"_" } + [("p"||"P") ["+"||"-"] ("0"\ldots"9") { "0"\ldots"9"||"_" }] +\end{syntax} + +Floating-point decimal literals consist in an integer part, a +fractional part and +an exponent part. The integer part is a sequence of one or more +digits, optionally preceded by a minus sign. The fractional part is a +decimal point followed by zero, one or more digits. +The exponent part is the character @"e"@ or @"E"@ followed by an +optional @"+"@ or @"-"@ sign, followed by one or more digits. It is +interpreted as a power of 10. +The fractional part or the exponent part can be omitted but not both, to +avoid ambiguity with integer literals. +The interpretation of floating-point literals that fall outside the +range of representable floating-point values is undefined. + +Floating-point hexadecimal literals are denoted with the @"0x"@ or @"0X"@ +prefix. The syntax is similar to that of floating-point decimal +literals, with the following differences. +The integer part and the fractional part use hexadecimal +digits. The exponent part starts with the character @"p"@ or @"P"@. +It is written in decimal and interpreted as a power of 2. + +For convenience and readability, underscore characters (@"_"@) are accepted +(and ignored) within floating-point literals. + +\subsubsection*{Character literals} +\label{s:characterliteral} + +\begin{syntax} +char-literal: + "'" regular-char "'" + | "'" escape-sequence "'" +; +escape-sequence: + "\" ( "\" || '"' || "'" || "n" || "t" || "b" || "r" || space ) + | "\" ("0"\ldots"9") ("0"\ldots"9") ("0"\ldots"9") + | "\x" ("0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f") + ("0"\ldots"9"||"A"\ldots"F"||"a"\ldots"f") + | "\o" ("0"\ldots"3") ("0"\ldots"7") ("0"\ldots"7") +\end{syntax} + +Character literals are delimited by @"'"@ (single quote) characters. +The two single quotes enclose either one character different from +@"'"@ and @'\'@, or one of the escape sequences below: +\begin{tableau}{|l|l|}{Sequence}{Character denoted} +\entree{"\\\\"}{backslash ("\\")} +\entree{"\\\""}{double quote ("\"")} +\entree{"\\'"}{single quote ("'")} +\entree{"\\n"}{linefeed (LF)} +\entree{"\\r"}{carriage return (CR)} +\entree{"\\t"}{horizontal tabulation (TAB)} +\entree{"\\b"}{backspace (BS)} +\entree{"\\"\var{space}}{space (SPC)} +\entree{"\\"\var{ddd}}{the character with ASCII code \var{ddd} in decimal} +\entree{"\\x"\var{hh}}{the character with ASCII code \var{hh} in hexadecimal} +\entree{"\\o"\var{ooo}}{the character with ASCII code \var{ooo} in octal} +\end{tableau} + +\subsubsection*{String literals} +\label{s:stringliteral} + +\begin{syntax} +string-literal: + '"' { string-character } '"' +; +string-character: + regular-string-char + | escape-sequence + | '\' newline { space || tab } +\end{syntax} + +String literals are delimited by @'"'@ (double quote) characters. +The two double quotes enclose a sequence of either characters +different from @'"'@ and @'\'@, or escape sequences from the +table given above for character literals. + +To allow splitting long string literals across lines, the sequence +"\\"\var{newline}~\var{spaces-or-tabs} (a backslash at the end of a line +followed by any number of spaces and horizontal tabulations at the +beginning of the next line) is ignored inside string literals. + +The current implementation places practically no restrictions on the +length of string literals. + +\subsubsection*{Naming labels} +\label{s:labelname} + +To avoid ambiguities, naming labels in expressions cannot just be defined +syntactically as the sequence of the three tokens "~", @ident@ and +":", and have to be defined at the lexical level. + +\begin{syntax} +label-name: lowercase-ident +; +label: "~" label-name ":" +; +optlabel: "?" label-name ":" +\end{syntax} + +Naming labels come in two flavours: @label@ for normal arguments and +@optlabel@ for optional ones. They are simply distinguished by their +first character, either "~" or "?". + +Despite @label@ and @optlabel@ being lexical entities in expressions, +their expansions @'~' label-name ':'@ and @'?' label-name ':'@ will be +used in grammars, for the sake of readability. Note also that inside +type expressions, this expansion can be taken literally, {\em i.e.} +there are really 3 tokens, with optional blanks between them. + +\subsubsection*{Prefix and infix symbols} + +%% || '`' lowercase-ident '`' + +\begin{syntax} +infix-symbol: + ('=' || '<' || '>' || '@' || '^' || '|' || '&' || + '+' || '-' || '*' || '/' || '$' || '%') { operator-char } + | "#" {{ operator-char }} +; +prefix-symbol: + '!' { operator-char } + | ('?' || '~') {{ operator-char }} +; +operator-char: + '!' || '$' || '%' || '&' || '*' || '+' || '-' || '.' || + '/' || ':' || '<' || '=' || '>' || '?' || '@' || + '^' || '|' || '~' +\end{syntax} + +Sequences of ``operator characters'', such as "<=>" or "!!", +are read as a single token from the @infix-symbol@ or @prefix-symbol@ +class. These symbols are parsed as prefix and infix operators inside +expressions, but otherwise behave like normal identifiers. +%% Identifiers starting with a lowercase letter and enclosed +%% between backquote characters @'`' lowercase-ident '`'@ are also parsed +%% as infix operators. + +\subsubsection*{Keywords} + +The identifiers below are reserved as keywords, and cannot be employed +otherwise: +\begin{verbatim} + and as assert asr begin class + constraint do done downto else end + exception external false for fun function + functor if in include inherit initializer + land lazy let lor lsl lsr + lxor match method mod module mutable + new nonrec object of open or + private rec sig struct then to + true try type val virtual when + while with +\end{verbatim} +% +\goodbreak% +% +The following character sequences are also keywords: +% +%% FIXME the token >] is not used anywhere in the syntax +% +\begin{alltt} +" != # & && ' ( ) * + , -" +" -. -> . .. : :: := :> ; ;; <" +" <- = > >] >} ? [ [< [> [| ]" +" _ ` { {< | |] || } ~" +\end{alltt} +% +Note that the following identifiers are keywords of the Camlp4 +extensions and should be avoided for compatibility reasons. +% +\begin{verbatim} + parser value $ $$ $: <: << >> ?? +\end{verbatim} + +\subsubsection*{Ambiguities} + +Lexical ambiguities are resolved according to the ``longest match'' +rule: when a character sequence can be decomposed into two tokens in +several different ways, the decomposition retained is the one with the +longest first token. + +\subsubsection*{Line number directives} + +\begin{syntax} +linenum-directive: + '#' {{"0" \ldots "9"}} + | '#' {{"0" \ldots "9"}} '"' { string-character } '"' +\end{syntax} + +Preprocessors that generate OCaml source code can insert line number +directives in their output so that error messages produced by the +compiler contain line numbers and file names referring to the source +file before preprocessing, instead of after preprocessing. +A line number directive is composed of a @"#"@ (sharp sign), followed by +a positive integer (the source line number), optionally followed by a +character string (the source file name). +Line number directives are treated as blanks during lexical +analysis. + +% FIXME spaces and tabs are allowed before and after the number +% FIXME ``string-character'' is inaccurate: everything is allowed except +% CR, LF, and doublequote; moreover, backslash escapes are not +% interpreted (especially backslash-doublequote) +% FIXME any number of random characters are allowed (and ignored) at the +% end of the line, except CR and LF. diff --git a/manual/manual/refman/modtypes.etex b/manual/manual/refman/modtypes.etex new file mode 100644 index 0000000000..00f91b75f8 --- /dev/null +++ b/manual/manual/refman/modtypes.etex @@ -0,0 +1,296 @@ +\section{Module types (module specifications)} +\pdfsection{Module types (module specifications)} +%HEVEA\cutname{modtypes.html} + +Module types are the module-level equivalent of type expressions: they +specify the general shape and type properties of modules. + +\ikwd{sig\@\texttt{sig}} +\ikwd{end\@\texttt{end}} +\ikwd{functor\@\texttt{functor}} +\ikwd{with\@\texttt{with}} +\ikwd{and\@\texttt{and}} +\ikwd{val\@\texttt{val}} +\ikwd{external\@\texttt{external}} +\ikwd{type\@\texttt{type}} +\ikwd{exception\@\texttt{exception}} +\ikwd{class\@\texttt{class}} +\ikwd{module\@\texttt{module}} +\ikwd{open\@\texttt{open}} +\ikwd{include\@\texttt{include}} + +\begin{syntax} +module-type: + modtype-path + | 'sig' { specification [';;'] } 'end' + | 'functor' '(' module-name ':' module-type ')' '->' module-type + | module-type '->' module-type + | module-type 'with' mod-constraint { 'and' mod-constraint } + | '(' module-type ')' +; +mod-constraint: + 'type' [type-params] typeconstr type-equation { type-constraint } + | 'module' module-path '=' extended-module-path +; +%BEGIN LATEX +\end{syntax} +\begin{syntax} +%END LATEX +specification: + 'val' value-name ':' typexpr + | 'external' value-name ':' typexpr '=' external-declaration + | type-definition + | 'exception' constr-decl + | class-specification + | classtype-definition + | 'module' module-name ':' module-type + | 'module' module-name { '(' module-name ':' module-type ')' } + ':' module-type + | 'module' 'type' modtype-name + | 'module' 'type' modtype-name '=' module-type + | 'open' module-path + | 'include' module-type +\end{syntax} + +\subsection{Simple module types} + +The expression @modtype-path@ is equivalent to the module type bound +to the name @modtype-path@. +The expression @'(' module-type ')'@ denotes the same type as +@module-type@. + +\subsection{Signatures} + +\ikwd{sig\@\texttt{sig}} +\ikwd{end\@\texttt{end}} + +Signatures are type specifications for structures. Signatures +@'sig' \ldots 'end'@ are collections of type specifications for value +names, type names, exceptions, module names and module type names. A +structure will match a signature if the structure provides definitions +(implementations) for all the names specified in the signature (and +possibly more), and these definitions meet the type requirements given +in the signature. + +An optional @";;"@ is allowed after each specification in a +signature. It serves as a syntactic separator with no semantic +meaning. + +\subsubsection*{Value specifications} + +\ikwd{val\@\texttt{val}} + +A specification of a value component in a signature is written +@'val' value-name ':' typexpr@, where @value-name@ is the name of the +value and @typexpr@ its expected type. + +\ikwd{external\@\texttt{external}} + +The form @'external' value-name ':' typexpr '=' external-declaration@ +is similar, except that it requires in addition the name to be +implemented as the external function specified in @external-declaration@ +(see chapter~\ref{c:intf-c}). + +\subsubsection*{Type specifications} + +\ikwd{type\@\texttt{type}} + +A specification of one or several type components in a signature is +written @'type' typedef { 'and' typedef }@ and consists of a sequence +of mutually recursive definitions of type names. + +Each type definition in the signature specifies an optional type +equation @'=' typexpr@ and an optional type representation +@'=' constr-decl \ldots@ or @'=' '{' field-decl \ldots '}'@. +The implementation of the type name in a matching structure must +be compatible with the type expression specified in the equation (if +given), and have the specified representation (if given). Conversely, +users of that signature will be able to rely on the type equation +or type representation, if given. More precisely, we have the +following four situations: + +\begin{description} +\item[Abstract type: no equation, no representation.] ~ \\ +Names that are defined as abstract types in a signature can be +implemented in a matching structure by any kind of type definition +(provided it has the same number of type parameters). The exact +implementation of the type will be hidden to the users of the +structure. In particular, if the type is implemented as a variant type +or record type, the associated constructors and fields will not be +accessible to the users; if the type is implemented as an +abbreviation, the type equality between the type name and the +right-hand side of the abbreviation will be hidden from the users of the +structure. Users of the structure consider that type as incompatible +with any other type: a fresh type has been generated. + +\item[Type abbreviation: an equation @'=' typexpr@, no representation.] ~ \\ +The type name must be implemented by a type compatible with @typexpr@. +All users of the structure know that the type name is +compatible with @typexpr@. + +\item[New variant type or record type: no equation, a representation.] ~ \\ +The type name must be implemented by a variant type or record type +with exactly the constructors or fields specified. All users of the +structure have access to the constructors or fields, and can use them +to create or inspect values of that type. However, users of the +structure consider that type as incompatible with any other type: a +fresh type has been generated. + +\item[Re-exported variant type or record type: an equation, +a representation.] ~ \\ +This case combines the previous two: the representation of the type is +made visible to all users, and no fresh type is generated. +\end{description} + +\subsubsection*{Exception specification} + +\ikwd{exception\@\texttt{exception}} + +The specification @'exception' constr-decl@ in a signature requires the +matching structure to provide an exception with the name and arguments +specified in the definition, and makes the exception available to all +users of the structure. + +\subsubsection*{Class specifications} + +\ikwd{class\@\texttt{class}} + +A specification of one or several classes in a signature is written +@'class' class-spec { 'and' class-spec }@ and consists of a sequence +of mutually recursive definitions of class names. + +Class specifications are described more precisely in +section~\ref{s:class-spec}. + +\subsubsection*{Class type specifications} + +\ikwd{class\@\texttt{class}} +\ikwd{type\@\texttt{type}} + +A specification of one or several classe types in a signature is +written @'class' 'type' classtype-def@ @{ 'and' classtype-def }@ and +consists of a sequence of mutually recursive definitions of class type +names. Class type specifications are described more precisely in +section~\ref{s:classtype}. + +\subsubsection*{Module specifications} + +\ikwd{module\@\texttt{module}} + +A specification of a module component in a signature is written +@'module' module-name ':' module-type@, where @module-name@ is the +name of the module component and @module-type@ its expected type. +Modules can be nested arbitrarily; in particular, functors can appear +as components of structures and functor types as components of +signatures. + +For specifying a module component that is a functor, one may write +\begin{center} +@'module' module-name '(' name_1 ':' module-type_1 ')' + \ldots '(' name_n ':' module-type_n ')' + ':' module-type@ +\end{center} +instead of +\begin{center} +@'module' module-name ':' + 'functor' '(' name_1 ':' module-type_1 ')' '->' \ldots + '->' module-type@ +\end{center} + +\subsubsection*{Module type specifications} + +\ikwd{type\@\texttt{type}} +\ikwd{module\@\texttt{module}} + +A module type component of a signature can be specified either as a +manifest module type or as an abstract module type. + +An abstract module type specification +@'module' 'type' modtype-name@ allows the name @modtype-name@ to be +implemented by any module type in a matching signature, but hides the +implementation of the module type to all users of the signature. + +A manifest module type specification +@'module' 'type' modtype-name '=' module-type@ +requires the name @modtype-name@ to be implemented by the module type +@module-type@ in a matching signature, but makes the equality between +@modtype-name@ and @module-type@ apparent to all users of the signature. + +\subsubsection{Opening a module path} + +\ikwd{open\@\texttt{open}} + +The expression @'open' module-path@ in a signature does not specify +any components. It simply affects the parsing of the following items +of the signature, allowing components of the module denoted by +@module-path@ to be referred to by their simple names @name@ instead of +path accesses @module-path '.' name@. The scope of the @"open"@ +stops at the end of the signature expression. + +\subsubsection{Including a signature} + +\ikwd{include\@\texttt{include}} + +The expression @'include' module-type@ in a signature performs textual +inclusion of the components of the signature denoted by @module-type@. +It behaves as if the components of the included signature were copied +at the location of the @'include'@. The @module-type@ argument must +refer to a module type that is a signature, not a functor type. + +\subsection{Functor types} + +\ikwd{functor\@\texttt{functor}} + +The module type expression +@'functor' '(' module-name ':' module-type_1 ')' '->' module-type_2@ +is the type of functors (functions from modules to modules) that take +as argument a module of type @module-type_1@ and return as result a +module of type @module-type_2@. The module type @module-type_2@ can +use the name @module-name@ to refer to type components of the actual +argument of the functor. If the type @module-type_2@ does not +depend on type components of @module-name@, the module type expression +can be simplified with the alternative short syntax +@ module-type_1 '->' module-type_2 @. +No restrictions are placed on the type of the functor argument; in +particular, a functor may take another functor as argument +(``higher-order'' functor). + +\subsection{The "with" operator} + +\ikwd{with\@\texttt{with}} + +Assuming @module-type@ denotes a signature, the expression +@module-type 'with' mod-constraint@ @{ 'and' mod-constraint }@ denotes +the same signature where type equations have been added to some of the +type specifications, as described by the constraints following the +"with" keyword. The constraint @'type' [type-parameters] typeconstr +'=' typexpr@ adds the type equation @'=' typexpr@ to the specification +of the type component named @typeconstr@ of the constrained signature. +The constraint @'module' module-path '=' extended-module-path@ adds +type equations to all type components of the sub-structure denoted by +@module-path@, making them equivalent to the corresponding type +components of the structure denoted by @extended-module-path@. + +For instance, if the module type name "S" is bound to the signature +\begin{verbatim} + sig type t module M: (sig type u end) end +\end{verbatim} +then "S with type t=int" denotes the signature +\begin{verbatim} + sig type t=int module M: (sig type u end) end +\end{verbatim} +and "S with module M = N" denotes the signature +\begin{verbatim} + sig type t module M: (sig type u=N.u end) end +\end{verbatim} +A functor taking two arguments of type "S" that share their "t" component +is written +\begin{verbatim} + functor (A: S) (B: S with type t = A.t) ... +\end{verbatim} + +Constraints are added left to right. After each constraint has been +applied, the resulting signature must be a subtype of the signature +before the constraint was applied. Thus, the @'with'@ operator can +only add information on the type components of a signature, but never +remove information. diff --git a/manual/manual/refman/modules.etex b/manual/manual/refman/modules.etex new file mode 100644 index 0000000000..d9bd2db95d --- /dev/null +++ b/manual/manual/refman/modules.etex @@ -0,0 +1,232 @@ +\section{Module\label{s:module-expr} expressions (module implementations)} +\pdfsection{Module expressions (module implementations)} +%HEVEA\cutname{modules.html} + +Module expressions are the module-level equivalent of value +expressions: they evaluate to modules, thus providing implementations +for the specifications expressed in module types. + +\ikwd{struct\@\texttt{struct}} +\ikwd{end\@\texttt{end}} +\ikwd{functor\@\texttt{functor}} +\ikwd{let\@\texttt{let}} +\ikwd{and\@\texttt{and}} +\ikwd{external\@\texttt{external}} +\ikwd{type\@\texttt{type}} +\ikwd{exception\@\texttt{exception}} +\ikwd{class\@\texttt{class}} +\ikwd{module\@\texttt{module}} +\ikwd{open\@\texttt{open}} +\ikwd{include\@\texttt{include}} + +\begin{syntax} +module-expr: + module-path + | 'struct' [ module-items ] 'end' + | 'functor' '(' module-name ':' module-type ')' '->' module-expr + | module-expr '(' module-expr ')' + | '(' module-expr ')' + | '(' module-expr ':' module-type ')' +; +module-items: + {';;'} ( definition || expr ) { {';;'} ( definition || ';;' expr) } {';;'} +; +%\end{syntax} \begin{syntax} +definition: + 'let' ['rec'] let-binding { 'and' let-binding } + | 'external' value-name ':' typexpr '=' external-declaration + | type-definition + | exception-definition + | class-definition + | classtype-definition + | 'module' module-name { '(' module-name ':' module-type ')' } + [ ':' module-type ] \\ '=' module-expr + | 'module' 'type' modtype-name '=' module-type + | 'open' module-path + | 'include' module-expr +\end{syntax} + +\subsection{Simple module expressions} + +The expression @module-path@ evaluates to the module bound to the name +@module-path@. + +The expression @'(' module-expr ')'@ evaluates to the same module as +@module-expr@. + +The expression @'(' module-expr ':' module-type ')'@ checks that the +type of @module-expr@ is a subtype of @module-type@, that is, that all +components specified in @module-type@ are implemented in +@module-expr@, and their implementation meets the requirements given +in @module-type@. In other terms, it checks that the implementation +@module-expr@ meets the type specification @module-type@. The whole +expression evaluates to the same module as @module-expr@, except that +all components not specified in @module-type@ are hidden and can no +longer be accessed. + +\subsection{Structures} + +\ikwd{struct\@\texttt{struct}} +\ikwd{end\@\texttt{end}} + +Structures @'struct' \ldots 'end'@ are collections of definitions for +value names, type names, exceptions, module names and module type +names. The definitions are evaluated in the order in which they appear +in the structure. The scopes of the bindings performed by the +definitions extend to the end of the structure. As a consequence, a +definition may refer to names bound by earlier definitions in the same +structure. + +For compatibility with toplevel phrases (chapter~\ref{c:camllight}), +optional @";;"@ are allowed after and before each definition in a structure. These +@";;"@ have no semantic meanings. Similarly, an @expr@ preceded by ";;" is allowed as +a component of a structure. It is equivalent to @'let' '_' '=' expr@, i.e. @expr@ is +evaluated for its side-effects but is not bound to any identifier. If @expr@ is +the first component of a structure, the preceding ";;" can be omitted. + +\subsubsection*{Value definitions} + +\ikwd{let\@\texttt{let}} + +A value definition @'let' ['rec'] let-binding { 'and' let-binding }@ +bind value names in the same way as a @'let' \ldots 'in' \ldots@ expression +(see section~\ref{s:localdef}). The value names appearing in the +left-hand sides of the bindings are bound to the corresponding values +in the right-hand sides. + +\ikwd{external\@\texttt{external}} + +A value definition @'external' value-name ':' typexpr '=' external-declaration@ +implements @value-name@ as the external function specified in +@external-declaration@ (see chapter~\ref{c:intf-c}). + +\subsubsection*{Type definitions} + +\ikwd{type\@\texttt{type}} + +A definition of one or several type components is written +@'type' typedef { 'and' typedef }@ and consists of a sequence +of mutually recursive definitions of type names. + +\subsubsection*{Exception definitions} + +\ikwd{exception\@\texttt{exception}} + +Exceptions are defined with the syntax @'exception' constr-decl@ +or @'exception' constr-name '=' constr@. + +\subsubsection*{Class definitions} + +\ikwd{class\@\texttt{class}} + +A definition of one or several classes is written @'class' +class-binding { 'and' class-binding }@ and consists of a sequence of +mutually recursive definitions of class names. Class definitions are +described more precisely in section~\ref{s:classdef}. + +\subsubsection*{Class type definitions} + +\ikwd{class\@\texttt{class}} +\ikwd{type\@\texttt{type}} + +A definition of one or several classes is written +@'class' 'type' classtype-def { 'and' classtype-def }@ and consists of +a sequence of mutually recursive definitions of class type names. +Class type definitions are described more precisely in +section~\ref{s:classtype}. + +\subsubsection*{Module definitions} + +\ikwd{module\@\texttt{module}} + +The basic form for defining a module component is +@'module' module-name '=' module-expr@, which evaluates @module-expr@ and binds +the result to the name @module-name@. + +One can write +\begin{center} +@'module' module-name ':' module-type '=' module-expr@ +\end{center} +instead of +\begin{center} +@'module' module-name '=' '(' module-expr ':' module-type ')'@. +\end{center} +Another derived form is +\begin{center} +@'module' module-name '(' name_1 ':' module-type_1 ')' \ldots + '(' name_n ':' module-type_n ')' '=' module-expr@ +\end{center} +which is equivalent to +\begin{center} +@'module' module-name '=' + 'functor' '(' name_1 ':' module-type_1 ')' '->' \ldots + '->' module-expr@ +\end{center} + +\subsubsection*{Module type definitions} + +\ikwd{type\@\texttt{type}} +\ikwd{module\@\texttt{module}} + +A definition for a module type is written +@'module' 'type' modtype-name '=' module-type@. +It binds the name @modtype-name@ to the module type denoted by the +expression @module-type@. + +\subsubsection*{Opening a module path} + +\ikwd{open\@\texttt{open}} + +The expression @'open' module-path@ in a structure does not define any +components nor perform any bindings. It simply affects the parsing of +the following items of the structure, allowing components of the +module denoted by @module-path@ to be referred to by their simple names +@name@ instead of path accesses @module-path '.' name@. The scope of +the @"open"@ stops at the end of the structure expression. + +\subsubsection*{Including the components of another structure} + +\ikwd{include\@\texttt{include}} + +The expression @'include' module-expr@ in a structure re-exports in +the current structure all definitions of the structure denoted by +@module-expr@. For instance, if the identifier "S" is bound to the +module +\begin{verbatim} + struct type t = int let x = 2 end +\end{verbatim} +the module expression +\begin{verbatim} + struct include S let y = (x + 1 : t) end +\end{verbatim} +is equivalent to the module expression +\begin{verbatim} + struct type t = S.t let x = S.x let y = (x + 1 : t) end +\end{verbatim} +The difference between @'open'@ and @'include'@ is that @'open'@ +simply provides short names for the components of the opened +structure, without defining any components of the current structure, +while @'include'@ also adds definitions for the components of the +included structure. + +\subsection{Functors} + +\subsubsection*{Functor definition} + +\ikwd{functor\@\texttt{functor}} + +The expression @'functor' '(' module-name ':' module-type ')' '->' +module-expr@ evaluates to a functor that takes as argument modules of +the type @module-type_1@, binds @module-name@ to these modules, +evaluates @module-expr@ in the extended environment, and returns the +resulting modules as results. No restrictions are placed on the type of the +functor argument; in particular, a functor may take another functor as +argument (``higher-order'' functor). + +\subsubsection*{Functor application} + +The expression @module-expr_1 '(' module-expr_2 ')'@ evaluates +@module-expr_1@ to a functor and @module-expr_2@ to a module, and +applies the former to the latter. The type of @module-expr_2@ must +match the type expected for the arguments of the functor @module-expr_1@. + diff --git a/manual/manual/refman/names.etex b/manual/manual/refman/names.etex new file mode 100644 index 0000000000..bad503395b --- /dev/null +++ b/manual/manual/refman/names.etex @@ -0,0 +1,148 @@ +\section{Names} \label{s:names} +\pdfsection{Names} +%HEVEA\cutname{names.html} + +Identifiers are used to give names to several classes of language +objects and refer to these objects by name later: +\begin{itemize} +\item value names (syntactic class @value-name@), +\item value constructors and exception constructors (class @constr-name@), +\item labels (@label-name@, defined in section~\ref{s:labelname}), +\item polymorphic variant tags (@tag-name@), +\item type constructors (@typeconstr-name@), +\item record fields (@field-name@), +\item class names (@class-name@), +\item method names (@method-name@), +\item instance variable names (@inst-var-name@), +\item module names (@module-name@), +\item module type names (@modtype-name@). +\end{itemize} +These eleven name spaces are distinguished both by the context and by the +capitalization of the identifier: whether the first letter of the +identifier is in lowercase (written @lowercase-ident@ below) or in +uppercase (written @capitalized-ident@). Underscore is considered a +lowercase letter for this purpose. + +\subsubsection*{Naming objects} +\ikwd{mod\@\texttt{mod}} +\ikwd{land\@\texttt{land}} +\ikwd{lor\@\texttt{lor}} +\ikwd{lxor\@\texttt{lxor}} +\ikwd{lsl\@\texttt{lsl}} +\ikwd{lsr\@\texttt{lsr}} +\ikwd{asr\@\texttt{asr}} + +\begin{syntax} +value-name: + lowercase-ident + | '(' operator-name ')' +; +operator-name: + prefix-symbol || infix-op +; +infix-op: + infix-symbol + | '*' || '+' || '-' || '-.' || '=' || '!=' || '<' || '>' || 'or' || '||' + || '&' || '&&' || ':=' + | 'mod' || 'land' || 'lor' || 'lxor' || 'lsl' || 'lsr' || 'asr' +; +constr-name: + capitalized-ident +; +tag-name: + capitalized-ident +; +typeconstr-name: + lowercase-ident +; +field-name: + lowercase-ident +; +module-name: + capitalized-ident +; +modtype-name: + ident +; +class-name: + lowercase-ident +; +inst-var-name: + lowercase-ident +; +method-name: + lowercase-ident +\end{syntax} +As shown above, prefix and infix symbols as well as some keywords can +be used as value names, provided they are written between parentheses. +The capitalization rules are summarized in the table below. + +\begin{tableau}{|l|l|}{Name space}{Case of first letter} +\entree{Values}{lowercase} +\entree{Constructors}{uppercase} +\entree{Labels}{lowercase} +\entree{Polymorphic variant tags}{uppercase} +\entree{Exceptions}{uppercase} +\entree{Type constructors}{lowercase} +\entree{Record fields}{lowercase} +\entree{Classes}{lowercase} +\entree{Instance variables}{lowercase} +\entree{Methods}{lowercase} +\entree{Modules}{uppercase} +\entree{Module types}{any} +\end{tableau} + +{\it Note on polymorphic variant tags:\/} the current implementation accepts +lowercase variant tags in addition to capitalized variant tags, but we +suggest you avoid lowercase variant tags for portability and +compatibility with future OCaml versions. + +\subsubsection*{Referring to named objects} + +\begin{syntax} +value-path: + [ module-path '.' ] value-name +; +constr: + [ module-path '.' ] constr-name +; +typeconstr: + [ extended-module-path '.' ] typeconstr-name +; +field: + [ module-path '.' ] field-name +; +modtype-path: + [ extended-module-path '.' ] modtype-name +; +class-path: + [ module-path '.' ] class-name +; +classtype-path: + [ extended-module-path '.' ] class-name +; +module-path: + module-name { '.' module-name } +; +extended-module-path: + extended-module-name { '.' extended-module-name } +; +extended-module-name: + module-name { '(' extended-module-path ')' } +\end{syntax} + +A named object can be referred to either by its name (following the +usual static scoping rules for names) or by an access path @prefix '.' name@, +where @prefix@ designates a module and @name@ is the name of an object +defined in that module. The first component of the path, @prefix@, is +either a simple module name or an access path @name_1 '.' name_2 \ldots@, +in case the defining module is itself nested inside other modules. +For referring to type constructors, module types, or class types, +the @prefix@ can +also contain simple functor applications (as in the syntactic class +@extended-module-path@ above) in case the defining module is the +result of a functor application. + +Label names, tag names, method names and instance variable names need +not be qualified: the former three are global labels, while the latter +are local to a class. diff --git a/manual/manual/refman/patterns.etex b/manual/manual/refman/patterns.etex new file mode 100644 index 0000000000..50c2b8a2d2 --- /dev/null +++ b/manual/manual/refman/patterns.etex @@ -0,0 +1,165 @@ +\section{Patterns} +\pdfsection{Patterns} +\ikwd{as\@\texttt{as}} +%HEVEA\cutname{patterns.html} +\begin{syntax} +pattern: + value-name + | '_' + | constant + | pattern 'as' value-name + | '(' pattern ')' + | '(' pattern ':' typexpr ')' + | pattern '|' pattern + | constr pattern + | "`"tag-name pattern + | "#"typeconstr + | pattern {{ ',' pattern }} + | '{' field [':' typexpr] '=' pattern% + { ';' field [':' typexpr] '=' pattern } [ ';' ] '}' + | '[' pattern { ';' pattern } [ ';' ] ']' + | pattern '::' pattern + | '[|' pattern { ';' pattern } [ ';' ] '|]' + | char-literal '..' char-literal +\end{syntax} + +The table below shows the relative precedences and associativity of +operators and non-closed pattern constructions. The constructions with +higher precedences come first. +\ikwd{as\@\texttt{as}} +\begin{tableau}{|l|l|}{Operator}{Associativity} +\entree{".."}{--} +\entree{"lazy" (see section~\ref{s:lazypat})}{--} +\entree{Constructor application, Tag application}{right} +\entree{"::"}{right} +\entree{","}{--} +\entree{"|"}{left} +\entree{"as"}{--} +\end{tableau} + +Patterns are templates that allow selecting data structures of a +given shape, and binding identifiers to components of the data +structure. This selection operation is called pattern matching; its +outcome is either ``this value does not match this pattern'', or +``this value matches this pattern, resulting in the following bindings +of names to values''. + +\subsubsection*{Variable patterns} + +A pattern that consists in a value name matches any value, +binding the name to the value. The pattern @"_"@ also matches +any value, but does not bind any name. + +Patterns are {\em linear\/}: a variable cannot be bound several times by +a given pattern. In particular, there is no way to test for equality +between two parts of a data structure using only a pattern (but +@"when"@ guards can be used for this purpose). + +\subsubsection*{Constant patterns} + +A pattern consisting in a constant matches the values that +are equal to this constant. + +%% FIXME for negative numbers, blanks are allowed between the minus +%% sign and the first digit. + +\subsubsection*{Alias patterns} +\ikwd{as\@\texttt{as}} + +The pattern @pattern_1 "as" value-name@ matches the same values as +@pattern_1@. If the matching against @pattern_1@ is successful, +the name @value-name@ is bound to the matched value, in addition to the +bindings performed by the matching against @pattern_1@. + +\subsubsection*{Parenthesized patterns} + +The pattern @"(" pattern_1 ")"@ matches the same values as +@pattern_1@. A type constraint can appear in a +parenthesized pattern, as in @"(" pattern_1 ":" typexpr ")"@. This +constraint forces the type of @pattern_1@ to be compatible with +@typexpr@. + +\subsubsection*{``Or'' patterns} + +The pattern @pattern_1 "|" pattern_2@ represents the logical ``or'' of +the two patterns @pattern_1@ and @pattern_2@. A value matches +@pattern_1 "|" pattern_2@ if it matches @pattern_1@ or +@pattern_2@. The two sub-patterns @pattern_1@ and @pattern_2@ +must bind exactly the same identifiers to values having the same types. +Matching is performed from left to right. +More precisely, +in case some value~$v$ matches @pattern_1 "|" pattern_2@, the bindings +performed are those of @pattern_1@ when $v$ matches @pattern_1@. +Otherwise, value~$v$ matches @pattern_2@ whose bindings are performed. + + +\subsubsection*{Variant patterns} + +The pattern @constr '(' pattern_1 ',' \ldots ',' pattern_n ')'@ matches +all variants whose +constructor is equal to @constr@, and whose arguments match +@pattern_1 \ldots pattern_n@. It is a type error if $n$ is not the +number of arguments expected by the constructor. + +The pattern @constr '_'@ matches all variants whose constructor is +@constr@. + +The pattern @pattern_1 "::" pattern_2@ matches non-empty lists whose +heads match @pattern_1@, and whose tails match @pattern_2@. + +The pattern @"[" pattern_1 ";" \ldots ";" pattern_n "]"@ matches lists +of length $n$ whose elements match @pattern_1@ \ldots @pattern_n@, +respectively. This pattern behaves like +@pattern_1 "::" \ldots "::" pattern_n "::" "[]"@. + +\subsubsection*{Polymorphic variant patterns} + +The pattern @"`"tag-name pattern_1@ matches all polymorphic variants +whose tag is equal to @tag-name@, and whose argument matches +@pattern_1@. + +\subsubsection*{Polymorphic variant abbreviation patterns} + +If the type @["('a,'b,"\ldots")"] typeconstr = "[" "`"tag-name_1 typexpr_1 "|" +\ldots "|" "`"tag-name_n typexpr_n"]"@ is defined, then the pattern @"#"typeconstr@ +is a shorthand for the following or-pattern: +@"(" "`"tag-name_1"(_" ":" typexpr_1")" "|" \ldots "|" "`"tag-name_n"(_" +":" typexpr_n"))"@. It matches all values of type @"[<" typeconstr "]"@. + +\subsubsection*{Tuple patterns} + +The pattern @pattern_1 "," \ldots "," pattern_n@ matches $n$-tuples +whose components match the patterns @pattern_1@ through @pattern_n@. That +is, the pattern matches the tuple values $(v_1, \ldots, v_n)$ such that +@pattern_i@ matches $v_i$ for \fromoneto{i}{n}. + +\subsubsection*{Record patterns} + +The pattern @"{" field_1 "=" pattern_1 ";" \ldots ";" field_n "=" +pattern_n "}"@ matches records that define at least the fields +@field_1@ through @field_n@, and such that the value associated to +@field_i@ matches the pattern @pattern_i@, for \fromoneto{i}{n}. +The record value can define more fields than @field_1@ \ldots +@field_n@; the values associated to these extra fields are not taken +into account for matching. Optional type constraints can be added field +by field with @"{" field_1 ":" typexpr_1 "=" pattern_1 ";"% +\ldots ";"field_n ":" typexpr_n "=" pattern_n "}"@ to force the type +of @field_k@ to be compatible with @typexpr_k@. + +\subsubsection*{Array patterns} + +The pattern @"[|" pattern_1 ";" \ldots ";" pattern_n "|]"@ +matches arrays of length $n$ such that the $i$-th array element +matches the pattern @pattern_i@, for \fromoneto{i}{n}. + +\subsubsection*{Range patterns} + +The pattern +@"'" @c@ "'" ".." "'" @d@ "'"@ is a shorthand for the pattern +\begin{center} +@"'" @c@ "'" "|" "'" @c@_1 "'" "|" "'" @c@_2 "'" "|" \ldots + "|" "'" @c@_n "'" "|" "'" @d@ "'"@ +\end{center} +where \nth{c}{1}, \nth{c}{2}, \ldots, \nth{c}{n} are the characters +that occur between \var{c} and \var{d} in the ASCII character set. For +instance, the pattern "'0'"@'..'@"'9'" matches all characters that are digits. diff --git a/manual/manual/refman/refman.etex b/manual/manual/refman/refman.etex new file mode 100644 index 0000000000..a7daea0231 --- /dev/null +++ b/manual/manual/refman/refman.etex @@ -0,0 +1,48 @@ +\chapter{The OCaml language} \label{c:refman} +\pdfchapterfold{-12}{Reference manual for the OCaml language} +%HEVEA\cutname{language.html} + +%better html output that way, sniff. +%HEVEA\subsection*{Foreword} +%BEGIN LATEX +\section*{Foreword} +%END LATEX + +This document is intended as a reference manual for the OCaml +language. It lists the language constructs, and gives their precise +syntax and informal semantics. It is by no means a tutorial +introduction to the language: there is not a single example. A good +working knowledge of OCaml is assumed. + +No attempt has been made at mathematical rigor: words are employed +with their intuitive meaning, without further definition. As a +consequence, the typing rules have been left out, by lack of the +mathematical framework required to express them, while they are +definitely part of a full formal definition of the language. + + +\subsection*{Notations} + +The syntax of the language is given in BNF-like notation. Terminal +symbols are set in typewriter font (@'like' 'this'@). +Non-terminal symbols are set in italic font (@like that@). +Square brackets @[\ldots]@ denote optional components. Curly brackets +@{\ldots}@ denotes zero, one or several repetitions of the enclosed +components. Curly brackets with a trailing plus sign @{{\ldots}}@ +denote one or several repetitions of the enclosed components. +Parentheses @(\ldots)@ denote grouping. + +%HEVEA\cutdef{section} +\input{lex} +\input{values} +\input{names} +\input{types} +\input{const} +\input{patterns} +\input{expr} +\input{typedecl} +\input{classes} +\input{modtypes} +\input{modules} +\input{compunit} +%HEVEA\cutend diff --git a/manual/manual/refman/typedecl.etex b/manual/manual/refman/typedecl.etex new file mode 100644 index 0000000000..024796b745 --- /dev/null +++ b/manual/manual/refman/typedecl.etex @@ -0,0 +1,218 @@ +\section{Type and exception definitions} +%HEVEA\cutname{typedecl.html}% +\pdfsection{Type and exception definitions} + +\subsection{Type definitions} +\label{s:type-defs} + +Type definitions bind type constructors to data types: either +variant types, record types, type abbreviations, or abstract data +types. They also bind the value constructors and record fields +associated with the definition. + +\ikwd{type\@\texttt{type}} +\ikwd{and\@\texttt{and}} +\ikwd{nonrec\@\texttt{nonrec}} +\ikwd{of\@\texttt{of}} + +\begin{syntax} +type-definition: + 'type' ['nonrec'] typedef { 'and' typedef } +; +typedef: + [type-params] typeconstr-name type-information +; +type-information: + [type-equation] [type-representation] { type-constraint } +; +type-equation: + '=' typexpr +; +type-representation: + '=' ['|'] constr-decl { '|' constr-decl } + | '=' record-decl +; +type-params: + type-param + | '(' type-param { "," type-param } ')' +; +type-param: + [variance] "'" ident +; +variance: + '+' + | '-' +; +record-decl: + '{' field-decl { ';' field-decl } [';'] '}' +; +constr-decl: + (constr-name || '[]' || '(::)') [ 'of' constr-args ] +; +constr-args: + typexpr { '*' typexpr } +; +field-decl: + ['mutable'] field-name ':' poly-typexpr +; +type-constraint: + 'constraint' "'" ident '=' typexpr +\end{syntax} +\ikwd{mutable\@\texttt{mutable}} +\ikwd{constraint\@\texttt{constraint}} + +Type definitions are introduced by the "type" keyword, and +consist in one or several simple definitions, possibly mutually +recursive, separated by the "and" keyword. Each simple definition +defines one type constructor. + +A simple definition consists in a lowercase identifier, possibly +preceded by one or several type parameters, and followed by an +optional type equation, then an optional type representation, and then +a constraint clause. The identifier is the name of the type +constructor being defined. + +In the right-hand side of type definitions, references to one of the +type constructor name being defined are considered as recursive, +unless "type" is followed by "nonrec". The "nonrec" keyword was +introduced in OCaml 4.02.2. + +The optional type parameters are either one type variable @"'" ident@, +for type constructors with one parameter, or a list of type variables +@"('"ident_1,\ldots,"'"ident_n")"@, for type constructors with several +parameters. Each type parameter may be prefixed by a variance +constraint @"+"@ (resp. @"-"@) indicating that the parameter is +covariant (resp. contravariant). These type parameters can appear in +the type expressions of the right-hand side of the definition, +optionally restricted by a variance constraint ; {\em i.e.\/} a +covariant parameter may only appear on the right side of a functional +arrow (more precisely, follow the left branch of an even number of +arrows), and a contravariant parameter only the left side (left branch of +an odd number of arrows). If the type has a representation or +an equation, and the parameter is free ({\em i.e.\/} not bound via a +type constraint to a constructed type), its variance constraint is +checked but subtyping {\em etc.\/} will use the inferred variance of the +parameter, which may be less restrictive; otherwise ({\em i.e.\/} for abstract +types or non-free parameters), the variance must be given explicitly, +and the parameter is invariant if no variance is given. + +The optional type equation @'=' typexpr@ makes the defined type +equivalent to the type expression @typexpr@: +one can be substituted for the other during typing. +If no type equation is given, a new type is generated: the defined type +is incompatible with any other type. + +The optional type representation describes the data structure +representing the defined type, by giving the list of associated +constructors (if it is a variant type) or associated fields (if it is +a record type). If no type representation is given, nothing is +assumed on the structure of the type besides what is stated in the +optional type equation. + +The type representation @'=' ['|'] constr-decl { '|' constr-decl }@ +describes a variant type. The constructor declarations +@constr-decl_1, \ldots, constr-decl_n@ describe the constructors +associated to this variant type. The constructor +declaration @constr-name 'of' typexpr_1 '*' \ldots '*' typexpr_n@ +declares the name @constr-name@ as a non-constant constructor, whose +arguments have types @typexpr_1@ \ldots @typexpr_n@. +The constructor declaration @constr-name@ +declares the name @constr-name@ as a constant +constructor. Constructor names must be capitalized. + +The type representation @'=' '{' field-decl { ';' field-decl } [';'] '}'@ +describes a record type. The field declarations @field-decl_1, \ldots, +field-decl_n@ describe the fields associated to this record type. +The field declaration @field-name ':' poly-typexpr@ declares +@field-name@ as a field whose argument has type @poly-typexpr@. +The field declaration @'mutable' field-name ':' poly-typexpr@ +\ikwd{mutable\@\texttt{mutable}} +behaves similarly; in addition, it allows physical modification of +this field. +Immutable fields are covariant, mutable fields are non-variant. +Both mutable and immutable fields may have a explicitly polymorphic +types. The polymorphism of the contents is statically checked whenever +a record value is created or modified. Extracted values may have their +types instantiated. + +The two components of a type definition, the optional equation and the +optional representation, can be combined independently, giving +rise to four typical situations: + +\begin{description} +\item[Abstract type: no equation, no representation.] ~\\ +When appearing in a module signature, this definition specifies +nothing on the type constructor, besides its number of parameters: +its representation is hidden and it is assumed incompatible with any +other type. + +\item[Type abbreviation: an equation, no representation.] ~\\ +This defines the type constructor as an abbreviation for the type +expression on the right of the @'='@ sign. + +\item[New variant type or record type: no equation, a representation.] ~\\ +This generates a new type constructor and defines associated +constructors or fields, through which values of that type can be +directly built or inspected. + +\item[Re-exported variant type or record type: an equation, +a representation.] ~\\ +In this case, the type constructor is defined as an abbreviation for +the type expression given in the equation, but in addition the +constructors or fields given in the representation remain attached to +the defined type constructor. The type expression in the equation part +must agree with the representation: it must be of the same kind +(record or variant) and have exactly the same constructors or fields, +in the same order, with the same arguments. +\end{description} + +The type variables appearing as type parameters can optionally be +prefixed by "+" or "-" to indicate that the type constructor is +covariant or contravariant with respect to this parameter. This +variance information is used to decide subtyping relations when +checking the validity of @":>"@ coercions (see section \ref{s:coercions}). + +For instance, "type +'a t" declares "t" as an abstract type that is +covariant in its parameter; this means that if the type $\tau$ is a +subtype of the type $\sigma$, then $\tau " t"$ is a subtype of $\sigma +" t"$. Similarly, "type -'a t" declares that the abstract type "t" is +contravariant in its parameter: if $\tau$ is a subtype of $\sigma$, then +$\sigma " t"$ is a subtype of $\tau " t"$. If no "+" or "-" variance +annotation is given, the type constructor is assumed non-variant in the +corresponding parameter. For instance, the abstract type declaration +"type 'a t" means that $\tau " t"$ is neither a subtype nor a +supertype of $\sigma " t"$ if $\tau$ is subtype of $\sigma$. + +The variance indicated by the "+" and "-" annotations on parameters +is enforced only for abstract and private types, or when there are +type constraints. +Otherwise, for abbreviations, variant and record types without type +constraints, the variance properties of the type constructor +are inferred from its definition, and the variance annotations are +only checked for conformance with the definition. + +\ikwd{constraint\@\texttt{constraint}} +The construct @ 'constraint' "'" ident '=' typexpr @ allows the +specification of +type parameters. Any actual type argument corresponding to the type +parameter @ident@ has to be an instance of @typexpr@ (more precisely, +@ident@ and @typexpr@ are unified). Type variables of @typexpr@ can +appear in the type equation and the type declaration. + +\subsection{Exception definitions} \label{s:excdef} +\ikwd{exception\@\texttt{exception}} + +\begin{syntax} +exception-definition: + 'exception' constr-decl + | 'exception' constr-name '=' constr +\end{syntax} + +Exception definitions add new constructors to the built-in variant +type \verb"exn" of exception values. The constructors are declared as +for a definition of a variant type. + +The form @'exception' constr-decl@ +generates a new exception, distinct from all other exceptions in the system. +The form @'exception' constr-name '=' constr@ +gives an alternate name to an existing exception. diff --git a/manual/manual/refman/types.etex b/manual/manual/refman/types.etex new file mode 100644 index 0000000000..765866ae42 --- /dev/null +++ b/manual/manual/refman/types.etex @@ -0,0 +1,239 @@ +\section{Type expressions} +\pdfsection{Type expressions} +%HEVEA\cutname{types.html} +\ikwd{as\@\texttt{as}} + +\begin{syntax} +typexpr: + "'" ident + | "_" + | '(' typexpr ')' + | [['?']label-name':'] typexpr '->' typexpr + | typexpr {{ '*' typexpr }} + | typeconstr + | typexpr typeconstr + | '(' typexpr { ',' typexpr } ')' typeconstr + | typexpr 'as' "'" ident + | polymorphic-variant-type + | '<' ['..'] '>' + | '<' method-type { ';' method-type } [';' || ';' '..'] '>' + | '#' class-path + | typexpr '#' class-path + | '(' typexpr { ',' typexpr } ')' '#' class-path +; +poly-typexpr: + typexpr + | {{ "'" ident }} '.' typexpr +; +method-type: + method-name ':' poly-typexpr +\end{syntax} + +The table below shows the relative precedences and associativity of +operators and non-closed type constructions. The constructions with +higher precedences come first. +\ikwd{as\@\texttt{as}} +\begin{tableau}{|l|l|}{Operator}{Associativity} +\entree{Type constructor application}{--} +\entree{"#"}{--} +\entree{"*"}{--} +\entree{"->"}{right} +\entree{"as"}{--} +\end{tableau} + +Type expressions denote types in definitions of data types as well as +in type constraints over patterns and expressions. + +\subsubsection*{Type variables} + +The type expression @"'" ident@ stands for the type variable named +@ident@. The type expression @"_"@ stands for either an anonymous type +variable or anonymous type parameters. In data type definitions, type +variables are names for the data type parameters. In type constraints, +they represent unspecified types that can be instantiated by any type +to satisfy the type constraint. In general the scope of a named type +variable is the whole top-level phrase where it appears, and it can +only be generalized when leaving this scope. Anonymous variables have +no such restriction. In the following cases, the scope of named type +variables is restricted to the type expression where they appear: +1) for universal (explicitly polymorphic) type variables; +2) for type variables that only appear in public method specifications +(as those variables will be made universal, as described in +section~\ref{sec-methspec}); +3) for variables used as aliases, when the type they are aliased to +would be invalid in the scope of the enclosing definition ({\it i.e.} +when it contains free universal type variables, or locally +defined types.) + +\subsubsection*{Parenthesized types} + +The type expression @"(" typexpr ")"@ denotes the same type as +@typexpr@. + +\subsubsection*{Function types} + +The type expression @typexpr_1 '->' typexpr_2@ denotes the type of +functions mapping arguments of type @typexpr_1@ to results of type +@typexpr_2@. + +@label-name ':' typexpr_1 '->' typexpr_2@ denotes the same function type, but +the argument is labeled @label@. + +@'?' label-name ':' typexpr_1 '->' typexpr_2@ denotes the type of functions +mapping an optional labeled argument of type @typexpr_1@ to results of +type @typexpr_2@. That is, the physical type of the function will be +@typexpr_1 "option" '->' typexpr_2@. + +\subsubsection*{Tuple types} + +The type expression @typexpr_1 '*' \ldots '*' typexpr_n@ +denotes the type of tuples whose elements belong to types @typexpr_1, +\ldots typexpr_n@ respectively. + +\subsubsection*{Constructed types} + +Type constructors with no parameter, as in @typeconstr@, are type +expressions. + +The type expression @typexpr typeconstr@, where @typeconstr@ is a type +constructor with one parameter, denotes the application of the unary type +constructor @typeconstr@ to the type @typexpr@. + +The type expression @(typexpr_1,\ldots,typexpr_n) typeconstr@, where +@typeconstr@ is a type constructor with $n$ parameters, denotes the +application of the $n$-ary type constructor @typeconstr@ to the types +@typexpr_1@ through @typexpr_n@. + +In the type expression @ "_" typeconstr @, the anonymous type expression +@ "_" @ stands in for anonymous type parameters and is equivalent to +@ ("_", \ldots,"_") @ with as many repetitions of "_" as the arity of +@typeconstr@. + +\subsubsection*{Aliased and recursive types} + +\ikwd{as\@\texttt{as}} + +The type expression @typexpr 'as' "'" ident@ denotes the same type as +@typexpr@, and also binds the type variable @ident@ to type @typexpr@ both +in @typexpr@ and in other types. In general the scope of an alias is +the same as for a named type variable, and covers the whole enclosing +definition. If the type variable +@ident@ actually occurs in @typexpr@, a recursive type is created. Recursive +types for which there exists a recursive path that does not contain +an object or polymorphic variant type constructor are rejected, except +when the "-rectypes" mode is selected. + +If @"'" ident@ denotes an explicit polymorphic variable, and @typexpr@ +denotes either an object or polymorphic variant type, the row variable +of @typexpr@ is captured by @"'" ident@, and quantified upon. + +\subsubsection*{Polymorphic variant types} +\ikwd{of\@\texttt{of}} + +\begin{syntax} +polymorphic-variant-type: + '[' tag-spec-first { '|' tag-spec } ']' + | '[>' [ tag-spec ] { '|' tag-spec } ']' + | '[<' ['|'] tag-spec-full { '|' tag-spec-full } + [ '>' {{ '`'tag-name }} ] ']' +; +%\end{syntax} \begin{syntax} +tag-spec-first: + '`'tag-name [ 'of' typexpr ] + | [ typexpr ] '|' tag-spec +; +tag-spec: + '`'tag-name [ 'of' typexpr ] + | typexpr +; +tag-spec-full: + '`'tag-name [ 'of' ['&'] typexpr { '&' typexpr } ] + | typexpr +\end{syntax} + +Polymorphic variant types describe the values a polymorphic variant +may take. + +The first case is an exact variant type: all possible tags are +known, with their associated types, and they can all be present. +Its structure is fully known. + +The second case is an open variant type, describing a polymorphic +variant value: it gives the list of all tags the value could take, +with their associated types. This type is still compatible with a +variant type containing more tags. A special case is the unknown +type, which does not define any tag, and is compatible with any +variant type. + +The third case is a closed variant type. It gives information about +all the possible tags and their associated types, and which tags are +known to potentially appear in values. The exact variant type (first +case) is +just an abbreviation for a closed variant type where all possible tags +are also potentially present. + +In all three cases, tags may be either specified directly in the +@'`'tag-name ["of" typexpr]@ form, or indirectly through a type +expression, which must expand to an +exact variant type, whose tag specifications are inserted in its +place. + +Full specifications of variant tags are only used for non-exact closed +types. They can be understood as a conjunctive type for the argument: +it is intended to have all the types enumerated in the +specification. + +Such conjunctive constraints may be unsatisfiable. In such a case the +corresponding tag may not be used in a value of this type. This +does not mean that the whole type is not valid: one can still use +other available tags. +Conjunctive constraints are mainly intended as output from the type +checker. When they are used in source programs, unsolvable constraints +may cause early failures. + +\subsubsection*{Object types} + +An object type +@'<' [method-type { ';' method-type }] '>'@ +is a record of method types. + +Each method may have an explicit polymorphic type: @{{ "'" ident }} +'.' typexpr@. Explicit polymorphic variables have a local scope, and +an explicit polymorphic type can only be unified to an +equivalent one, where only the order and names of polymorphic +variables may change. + +The type @'<' {method-type ';'} '..' '>'@ is the +type of an object whose method names and types are described by +@method-type_1, \ldots, method-type_n@, and possibly some other +methods represented by the ellipsis. This ellipsis actually is +a special kind of type variable (called {\em row variable} in the +literature) that stands for any number of extra method types. + +\subsubsection*{\#-types} +\label{s:sharp-types} + +The type @'#' class-path@ is a special kind of abbreviation. This +abbreviation unifies with the type of any object belonging to a subclass +of class @class-path@. +% +It is handled in a special way as it usually hides a type variable (an +ellipsis, representing the methods that may be added in a subclass). +In particular, it vanishes when the ellipsis gets instantiated. +% +Each type expression @'#' class-path@ defines a new type variable, so +type @'#' class-path '->' '#' class-path@ is usually not the same as +type @('#' class-path 'as' "'" ident) '->' "'" ident@. +% + +Use of \#-types to abbreviate polymorphic variant types is deprecated. +If @@t@@ is an exact variant type then @"#"@t@@ translates to @"[<" @t@"]"@, +and @"#"@t@"[>" "`"tag_1 \dots"`"tag_k"]"@ translates to +@"[<" @t@ ">" "`"tag_1 \dots"`"tag_k"]"@ + +\subsubsection*{Variant and record types} + +There are no type expressions describing (defined) variant types nor +record types, since those are always named, i.e. defined before use +and referred to by name. Type definitions are described in +section~\ref{s:type-defs}. diff --git a/manual/manual/refman/values.etex b/manual/manual/refman/values.etex new file mode 100644 index 0000000000..d5d01f0f28 --- /dev/null +++ b/manual/manual/refman/values.etex @@ -0,0 +1,97 @@ +\section{Values} +\pdfsection{Values} +%HEVEA\cutname{values.html} + +This section describes the kinds of values that are manipulated by +OCaml programs. + +\subsection{Base values} + +\subsubsection*{Integer numbers} + +Integer values are integer numbers from $-2^{30}$ to $2^{30}-1$, that +is $-1073741824$ to $1073741823$. The implementation may support a +wider range of integer values: on 64-bit platforms, the current +implementation supports integers ranging from $-2^{62}$ to $2^{62}-1$. + +\subsubsection*{Floating-point numbers} + +Floating-point values are numbers in floating-point representation. +The current implementation uses double-precision floating-point +numbers conforming to the IEEE 754 standard, with 53 bits of mantissa +and an exponent ranging from $-1022$ to $1023$. + +\subsubsection*{Characters} + +Character values are represented as 8-bit integers between 0 and 255. +Character codes between 0 and 127 are interpreted following the ASCII +standard. The current implementation interprets character codes +between 128 and 255 following the ISO 8859-1 standard. + +\subsubsection*{Character strings} \label{s:string-val} + +String values are finite sequences of characters. The current +implementation supports strings containing up to $2^{24} - 5$ +characters (16777211 characters); on 64-bit platforms, the limit is +$2^{57} - 9$. + +\subsection{Tuples} + +Tuples of values are written @'('@v@_1',' \ldots',' @v@_n')'@, standing for the +$n$-tuple of values @@v@_1@ to @@v@_n@. The current implementation +supports tuple of up to $2^{22} - 1$ elements (4194303 elements). + +\subsection{Records} + +Record values are labeled tuples of values. The record value written +@'{' field_1 '=' @v@_1';' \ldots';' field_n '=' @v@_n '}'@ associates the value +@@v@_i@ to the record field @field_i@, for $i = 1 \ldots n$. The current +implementation supports records with up to $2^{22} - 1$ fields +(4194303 fields). + +\subsection{Arrays} + +Arrays are finite, variable-sized sequences of values of the same +type. The current implementation supports arrays containing up to +$2^{22} - 1$ elements (4194303 elements) unless the elements are +floating-point numbers (2097151 elements in this case); on 64-bit +platforms, the limit is $2^{54} - 1$ for all arrays. + +\subsection{Variant values} + +Variant values are either a constant constructor, or a non-constant +constructor applied to a number of values. The former case is written +@constr@; the latter case is written @constr '('@v@_1',' ... ',' @v@_n +')'@, where the @@v@_i@ are said to be the arguments of the non-constant +constructor @constr@. The parentheses may be omitted if there is only +one argument. + +The following constants are treated like built-in constant +constructors: +\begin{tableau}{|l|l|}{Constant}{Constructor} +\entree{"false"}{the boolean false} +\entree{"true"}{the boolean true} +\entree{"()"}{the ``unit'' value} +\entree{"[]"}{the empty list} +\end{tableau} + +The current implementation limits each variant type to have at most +246 non-constant constructors and $2^{30}-1$ constant constructors. + +\subsection{Polymorphic variants} + +Polymorphic variants are an alternate form of variant values, not +belonging explicitly to a predefined variant type, and following +specific typing rules. They can be either constant, written +@"`"tag-name@, or non-constant, written @"`"tag-name'('@v@')'@. + +\subsection{Functions} + +Functional values are mappings from values to values. + +\subsection{Objects} + +Objects are composed of a hidden internal state which is a +record of instance variables, and a set of methods for accessing and +modifying these variables. The structure of an object is described by +the toplevel class that created it. diff --git a/manual/manual/style.css b/manual/manual/style.css new file mode 100644 index 0000000000..05d8e0b0df --- /dev/null +++ b/manual/manual/style.css @@ -0,0 +1,30 @@ +a:visited {color : #416DFF; text-decoration : none; } +a:link {color : #416DFF; text-decoration : none;} +a:hover {color : Red; text-decoration : none; background-color: #5FFF88} +a:active {color : Red; text-decoration : underline; } +.keyword { font-weight : bold ; color : Red } +.keywordsign { color : #C04600 } +.comment { color : Green } +.constructor { color : Blue } +.type { color : #5C6585 } +.string { color : Maroon } +.warning { color : Red ; font-weight : bold } +.info { margin-left : 3em; margin-right : 3em } +.code { color : #465F91 ; } +h1 { font-size : 20pt ; text-align: center; } +h2 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ;padding: 2px; } +h3 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90DDFF ;padding: 2px; } +h4 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90EDFF ;padding: 2px; } +h5 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90FDFF ;padding: 2px; } +h6 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ; padding: 2px; } +div.h7 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90DDFF ; padding: 2px; } +div.h8 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #F0FFFF ; padding: 2px; } +div.h9 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #FFFFFF ; padding: 2px; } +.typetable { border-style : hidden } +.indextable { border-style : hidden } +.paramstable { border-style : hidden ; padding: 5pt 5pt} +body { background-color : White } +tr { background-color : White } +td.typefieldcomment { background-color : #FFFFFF } +pre { margin-bottom: 4px } +div.sig_block {margin-left: 2em} \ No newline at end of file diff --git a/manual/manual/texstuff/.cvsignore b/manual/manual/texstuff/.cvsignore new file mode 100644 index 0000000000..84eade834c --- /dev/null +++ b/manual/manual/texstuff/.cvsignore @@ -0,0 +1,13 @@ +*.aux +*.dvi +*.idx +*.ilg +*.ind +*.log +*.toc +*.ipr +*.txt +*.pdf +*.ps +pdfmanual.out +manual.out diff --git a/manual/manual/texstuff/.gitignore b/manual/manual/texstuff/.gitignore new file mode 100644 index 0000000000..84eade834c --- /dev/null +++ b/manual/manual/texstuff/.gitignore @@ -0,0 +1,13 @@ +*.aux +*.dvi +*.idx +*.ilg +*.ind +*.log +*.toc +*.ipr +*.txt +*.pdf +*.ps +pdfmanual.out +manual.out diff --git a/manual/manual/textman/.cvsignore b/manual/manual/textman/.cvsignore new file mode 100644 index 0000000000..7247584502 --- /dev/null +++ b/manual/manual/textman/.cvsignore @@ -0,0 +1,5 @@ +manual.txt +manual.hmanual.kwd +*.haux +*.hind +*.htoc diff --git a/manual/manual/textman/.gitignore b/manual/manual/textman/.gitignore new file mode 100644 index 0000000000..7247584502 --- /dev/null +++ b/manual/manual/textman/.gitignore @@ -0,0 +1,5 @@ +manual.txt +manual.hmanual.kwd +*.haux +*.hind +*.htoc diff --git a/manual/manual/tutorials/.cvsignore b/manual/manual/tutorials/.cvsignore new file mode 100644 index 0000000000..81ccbe7105 --- /dev/null +++ b/manual/manual/tutorials/.cvsignore @@ -0,0 +1,2 @@ +*.tex +*.htex diff --git a/manual/manual/tutorials/.gitignore b/manual/manual/tutorials/.gitignore new file mode 100644 index 0000000000..81ccbe7105 --- /dev/null +++ b/manual/manual/tutorials/.gitignore @@ -0,0 +1,2 @@ +*.tex +*.htex diff --git a/manual/manual/tutorials/Makefile b/manual/manual/tutorials/Makefile new file mode 100644 index 0000000000..292eac9038 --- /dev/null +++ b/manual/manual/tutorials/Makefile @@ -0,0 +1,22 @@ +FILES= coreexamples.tex lablexamples.tex objectexamples.tex moduleexamples.tex advexamples.tex + +TOPDIR=../../.. +include $(TOPDIR)/Makefile.tools + +CAMLLATEX= $(OCAMLRUN) ../../tools/caml-tex2 +TEXQUOTE=../../tools/texquote2 + +ALLFILES=$(FILES) + +all: $(ALLFILES) + +clean: + rm -f $(ALLFILES) + +.SUFFIXES: +.SUFFIXES: .etex .tex + +.etex.tex: + $(CAMLLATEX) -caml "TERM=norepeat $(OCAML)" -n 80 -o - $*.etex | $(TEXQUOTE) > $*.tex + +$(ALLFILES): $(CAMLLATEX) $(TEXQUOTE) diff --git a/manual/manual/tutorials/advexamples.etex b/manual/manual/tutorials/advexamples.etex new file mode 100644 index 0000000000..fff3f10836 --- /dev/null +++ b/manual/manual/tutorials/advexamples.etex @@ -0,0 +1,644 @@ +\chapter{Advanced examples with classes and modules} +\pdfchapterfold{-3}{Tutorial: Advanced examples with classes and modules} +%HEVEA\cutname{advexamples.html} +\label{c:advexamples} + +{\it (Chapter written by Didier R�my)} + +\bigskip + +\noindent + +In this chapter, we show some larger examples using objects, classes +and modules. We review many of the object features simultaneously on +the example of a bank account. We show how modules taken from the +standard library can be expressed as classes. Lastly, we describe a +programming pattern know of as {\em virtual types} through the example +of window managers. + +\section{Extended example: bank accounts} +\pdfsection{Extended example: bank accounts} +\label{ss:bank-accounts} + +In this section, we illustrate most aspects of Object and inheritance +by refining, debugging, and specializing the following +initial naive definition of a simple bank account. (We reuse the +module "Euro" defined at the end of chapter~\ref{c:objectexamples}.) +\begin{caml_eval} +module type MONEY = + sig + type t + class c : float -> + object ('a) + val repr : t + method value : t + method print : unit + method times : float -> 'a + method leq : 'a -> bool + method plus : 'a -> 'a + end + end;; +module Euro : MONEY = + struct + type t = float + class c x = + object (self : 'a) + val repr = x + method value = repr + method print = print_float repr + method times k = {< repr = k *. x >} + method leq (p : 'a) = repr <= p#value + method plus (p : 'a) = {< repr = x +. p#value >} + end + end;; +\end{caml_eval} +\begin{caml_example} +let euro = new Euro.c;; +let zero = euro 0.;; +let neg x = x#times (-1.);; +class account = + object + val mutable balance = zero + method balance = balance + method deposit x = balance <- balance # plus x + method withdraw x = + if x#leq balance then (balance <- balance # plus (neg x); x) else zero + end;; +let c = new account in c # deposit (euro 100.); c # withdraw (euro 50.);; +\end{caml_example} +We now refine this definition with a method to compute interest. +\begin{caml_example} +class account_with_interests = + object (self) + inherit account + method private interest = self # deposit (self # balance # times 0.03) + end;; +\end{caml_example} +We make the method "interest" private, since clearly it should not be +called freely from the outside. Here, it is only made accessible to subclasses +that will manage monthly or yearly updates of the account. + +We should soon fix a bug in the current definition: the deposit method can +be used for withdrawing money by depositing negative amounts. We can +fix this directly: +\begin{caml_example} +class safe_account = + object + inherit account + method deposit x = if zero#leq x then balance <- balance#plus x + end;; +\end{caml_example} +However, the bug might be fixed more safely by the following definition: +\begin{caml_example} +class safe_account = + object + inherit account as unsafe + method deposit x = + if zero#leq x then unsafe # deposit x + else raise (Invalid_argument "deposit") + end;; +\end{caml_example} +In particular, this does not require the knowledge of the implementation of +the method "deposit". + +To keep track of operations, we extend the class with a mutable field +"history" and a private method "trace" to add an operation in the +log. Then each method to be traced is redefined. +\begin{caml_example} +type 'a operation = Deposit of 'a | Retrieval of 'a;; +class account_with_history = + object (self) + inherit safe_account as super + val mutable history = [] + method private trace x = history <- x :: history + method deposit x = self#trace (Deposit x); super#deposit x + method withdraw x = self#trace (Retrieval x); super#withdraw x + method history = List.rev history + end;; +\end{caml_example} +%% \label{ss:bank:initializer} +One may wish to open an account and simultaneously deposit some initial +amount. Although the initial implementation did not address this +requirement, it can be achieved by using an initializer. +\begin{caml_example} +class account_with_deposit x = + object + inherit account_with_history + initializer balance <- x + end;; +\end{caml_example} +A better alternative is: +\begin{caml_example} +class account_with_deposit x = + object (self) + inherit account_with_history + initializer self#deposit x + end;; +\end{caml_example} +Indeed, the latter is safer since the call to "deposit" will automatically +benefit from safety checks and from the trace. +Let's test it: +\begin{caml_example} +let ccp = new account_with_deposit (euro 100.) in +let _balance = ccp#withdraw (euro 50.) in +ccp#history;; +\end{caml_example} +Closing an account can be done with the following polymorphic function: +\begin{caml_example} +let close c = c#withdraw c#balance;; +\end{caml_example} +Of course, this applies to all sorts of accounts. + +Finally, we gather several versions of the account into a module "Account" +abstracted over some currency. +\begin{caml_example*} +let today () = (01,01,2000) (* an approximation *) +module Account (M:MONEY) = + struct + type m = M.c + let m = new M.c + let zero = m 0. + + class bank = + object (self) + val mutable balance = zero + method balance = balance + val mutable history = [] + method private trace x = history <- x::history + method deposit x = + self#trace (Deposit x); + if zero#leq x then balance <- balance # plus x + else raise (Invalid_argument "deposit") + method withdraw x = + if x#leq balance then + (balance <- balance # plus (neg x); self#trace (Retrieval x); x) + else zero + method history = List.rev history + end + + class type client_view = + object + method deposit : m -> unit + method history : m operation list + method withdraw : m -> m + method balance : m + end + + class virtual check_client x = + let y = if (m 100.)#leq x then x + else raise (Failure "Insufficient initial deposit") in + object (self) initializer self#deposit y end + + module Client (B : sig class bank : client_view end) = + struct + class account x : client_view = + object + inherit B.bank + inherit check_client x + end + + let discount x = + let c = new account x in + if today() < (1998,10,30) then c # deposit (m 100.); c + end + end;; +\end{caml_example*} +This shows the use of modules to group several class definitions that can in +fact be thought of as a single unit. This unit would be provided by a bank +for both internal and external uses. +This is implemented as a functor that abstracts over the currency so that +the same code can be used to provide accounts in different currencies. + +The class "bank" is the {\em real} implementation of the bank account (it +could have been inlined). This is the one that will be used for further +extensions, refinements, etc. Conversely, the client will only be given the client view. +\begin{caml_example*} +module Euro_account = Account(Euro);; +module Client = Euro_account.Client (Euro_account);; +new Client.account (new Euro.c 100.);; +\end{caml_example*} +Hence, the clients do not have direct access to the "balance", nor the +"history" of their own accounts. Their only way to change their balance is +to deposit or withdraw money. It is important to give the clients +a class and not just the ability to create accounts (such as the +promotional "discount" account), so that they can +personalize their account. +For instance, a client may refine the "deposit" and "withdraw" methods +so as to do his own financial bookkeeping, automatically. On the +other hand, the function "discount" is given as such, with no +possibility for further personalization. + +It is important to provide the client's view as a functor +"Client" so that client accounts can still be built after a possible +specialization of the "bank". +The functor "Client" may remain unchanged and be passed +the new definition to initialize a client's view of the extended account. +\begin{caml_example*} +module Investment_account (M : MONEY) = + struct + type m = M.c + module A = Account(M) + + class bank = + object + inherit A.bank as super + method deposit x = + if (new M.c 1000.)#leq x then + print_string "Would you like to invest?"; + super#deposit x + end + + module Client = A.Client + end;; +\end{caml_example*} +\begin{caml_eval} +module Euro_account = Investment_account (Euro);; +module Client = Euro_account.Client (Euro_account);; +new Client.account (new Euro.c 100.);; +\end{caml_eval} +The functor "Client" may also be redefined when some new features of the +account can be given to the client. +\begin{caml_example*} +module Internet_account (M : MONEY) = + struct + type m = M.c + module A = Account(M) + + class bank = + object + inherit A.bank + method mail s = print_string s + end + + class type client_view = + object + method deposit : m -> unit + method history : m operation list + method withdraw : m -> m + method balance : m + method mail : string -> unit + end + + module Client (B : sig class bank : client_view end) = + struct + class account x : client_view = + object + inherit B.bank + inherit A.check_client x + end + end + end;; +\end{caml_example*} +\begin{caml_eval} +module Euro_account = Internet_account (Euro);; +module Client = Euro_account.Client (Euro_account);; +new Client.account (new Euro.c 100.);; +\end{caml_eval} + + +\section{Simple modules as classes} +\pdfsection{Simple modules as classes} +\label{ss:modules-as-classes} + +One may wonder whether it is possible to treat primitive types such as +integers and strings as objects. Although this is usually uninteresting +for integers or strings, there may be some situations where +this is desirable. The class "money" above is such an example. +We show here how to do it for strings. + +\subsection{Strings} +\label{module:string} + +A naive definition of strings as objects could be: +\begin{caml_example} +class ostring s = + object + method get n = String.get s n + method print = print_string s + method escaped = new ostring (String.escaped s) + end;; +\end{caml_example} +However, the method "escaped" returns an object of the class "ostring", +and not an object of the current class. Hence, if the class is further +extended, the method "escaped" will only return an object of the parent +class. +\begin{caml_example} +class sub_string s = + object + inherit ostring s + method sub start len = new sub_string (String.sub s start len) + end;; +\end{caml_example} +As seen in section \ref{ss:binary-methods}, the solution is to use +functional update instead. We need to create an instance variable +containing the representation "s" of the string. +\begin{caml_example} +class better_string s = + object + val repr = s + method get n = String.get repr n + method print = print_string repr + method escaped = {< repr = String.escaped repr >} + method sub start len = {< repr = String.sub s start len >} + end;; +\end{caml_example} +As shown in the inferred type, the methods "escaped" and "sub" now return +objects of the same type as the one of the class. + +Another difficulty is the implementation of the method "concat". +In order to concatenate a string with another string of the same class, +one must be able to access the instance variable externally. Thus, a method +"repr" returning s must be defined. Here is the correct definition of +strings: +\begin{caml_example} +class ostring s = + object (self : 'mytype) + val repr = s + method repr = repr + method get n = String.get repr n + method print = print_string repr + method escaped = {< repr = String.escaped repr >} + method sub start len = {< repr = String.sub s start len >} + method concat (t : 'mytype) = {< repr = repr ^ t#repr >} + end;; +\end{caml_example} +Another constructor of the class string can be defined to return a new +string of a given length: +\begin{caml_example} +class cstring n = ostring (String.make n ' ');; +\end{caml_example} +Here, exposing the representation of strings is probably harmless. We do +could also hide the representation of strings as we hid the currency in the +class "money" of section~\ref{ss:friends}. + +\subsubsection{Stacks} +\label{module:stack} + +There is sometimes an alternative between using modules or classes for +parametric data types. +Indeed, there are situations when the two approaches are quite similar. +For instance, a stack can be straightforwardly implemented as a class: +\begin{caml_example} +exception Empty;; +class ['a] stack = + object + val mutable l = ([] : 'a list) + method push x = l <- x::l + method pop = match l with [] -> raise Empty | a::l' -> l <- l'; a + method clear = l <- [] + method length = List.length l + end;; +\end{caml_example} +However, writing a method for iterating over a stack is more +problematic. A method "fold" would have type +"('b -> 'a -> 'b) -> 'b -> 'b". Here "'a" is the parameter of the stack. +The parameter "'b" is not related to the class "'a stack" but to the +argument that will be passed to the method "fold". +%The intuition is that method "fold" should be polymorphic, i.e. of type +%"All ('a) ('b -> 'a -> 'b) -> 'b -> 'b". +A naive approach is to make "'b" an extra parameter of class "stack": +\begin{caml_example} +class ['a, 'b] stack2 = + object + inherit ['a] stack + method fold f (x : 'b) = List.fold_left f x l + end;; +\end{caml_example} +However, the method "fold" of a given object can only be +applied to functions that all have the same type: +\begin{caml_example} +let s = new stack2;; +s#fold ( + ) 0;; +s;; +\end{caml_example} +A better solution is to use polymorphic methods, which were +introduced in OCaml version 3.05. Polymorphic methods makes +it possible to treat the type variable "'b" in the type of "fold" as +universally quantified, giving "fold" the polymorphic type +"Forall 'b. ('b -> 'a -> 'b) -> 'b -> 'b". +An explicit type declaration on the method "fold" is required, since +the type checker cannot infer the polymorphic type by itself. +\begin{caml_example} +class ['a] stack3 = + object + inherit ['a] stack + method fold : 'b. ('b -> 'a -> 'b) -> 'b -> 'b + = fun f x -> List.fold_left f x l + end;; +\end{caml_example} + +% However, the nice correspondence between the implementations of stacks as +% modules or classes is a very particular case. + +% XXX Maps + +\subsection{Hashtbl} +\label{module:hashtbl} + +A simplified version of object-oriented hash tables should have the +following class type. +\begin{caml_example} +class type ['a, 'b] hash_table = + object + method find : 'a -> 'b + method add : 'a -> 'b -> unit + end;; +\end{caml_example} +A simple implementation, which is quite reasonable for small hash tables is +to use an association list: +\begin{caml_example} +class ['a, 'b] small_hashtbl : ['a, 'b] hash_table = + object + val mutable table = [] + method find key = List.assoc key table + method add key valeur = table <- (key, valeur) :: table + end;; +\end{caml_example} +A better implementation, and one that scales up better, is to use a +true hash table\ldots\ whose elements are small hash tables! +\begin{caml_example} +class ['a, 'b] hashtbl size : ['a, 'b] hash_table = + object (self) + val table = Array.init size (fun i -> new small_hashtbl) + method private hash key = + (Hashtbl.hash key) mod (Array.length table) + method find key = table.(self#hash key) # find key + method add key = table.(self#hash key) # add key + end;; +\end{caml_example} + +% problem + +% solution + +\subsection{Sets} +\label{module:set} + +Implementing sets leads to another difficulty. Indeed, the method +"union" needs to be able to access the internal representation of +another object of the same class. + +This is another instance of friend functions as seen in section +\ref{ss:friends}. Indeed, this is the same mechanism used in the module +"Set" in the absence of objects. + +In the object-oriented version of sets, we only need to add an additional +method "tag" to return the representation of a set. Since sets are +parametric in the type of elements, the method "tag" has a parametric type +"'a tag", concrete within +the module definition but abstract in its signature. +From outside, it will then be guaranteed that two objects with a method "tag" +of the same type will share the same representation. +\begin{caml_example*} +module type SET = + sig + type 'a tag + class ['a] c : + object ('b) + method is_empty : bool + method mem : 'a -> bool + method add : 'a -> 'b + method union : 'b -> 'b + method iter : ('a -> unit) -> unit + method tag : 'a tag + end + end;; +module Set : SET = + struct + let rec merge l1 l2 = + match l1 with + [] -> l2 + | h1 :: t1 -> + match l2 with + [] -> l1 + | h2 :: t2 -> + if h1 < h2 then h1 :: merge t1 l2 + else if h1 > h2 then h2 :: merge l1 t2 + else merge t1 l2 + type 'a tag = 'a list + class ['a] c = + object (_ : 'b) + val repr = ([] : 'a list) + method is_empty = (repr = []) + method mem x = List.exists (( = ) x) repr + method add x = {< repr = merge [x] repr >} + method union (s : 'b) = {< repr = merge repr s#tag >} + method iter (f : 'a -> unit) = List.iter f repr + method tag = repr + end + end;; +\end{caml_example*} + +\section{The subject/observer pattern} +\pdfsection{The subject/observer pattern} +\label{ss:subject-observer} + +The following example, known as the subject/observer pattern, is often +presented in the literature as a difficult inheritance problem with +inter-connected classes. +The general pattern amounts to the definition a pair of two +classes that recursively interact with one another. + +The class "observer" has a distinguished method "notify" that requires +two arguments, a subject and an event to execute an action. +\begin{caml_example} +class virtual ['subject, 'event] observer = + object + method virtual notify : 'subject -> 'event -> unit + end;; +\end{caml_example} +The class "subject" remembers a list of observers in an instance variable, +and has a distinguished method "notify_observers" to broadcast the message +"notify" to all observers with a particular event "e". +\begin{caml_example} +class ['observer, 'event] subject = + object (self) + val mutable observers = ([]:'observer list) + method add_observer obs = observers <- (obs :: observers) + method notify_observers (e : 'event) = + List.iter (fun x -> x#notify self e) observers + end;; +\end{caml_example} +The difficulty usually lies in defining instances of the pattern above +by inheritance. This can be done in a natural and obvious manner in +OCaml, as shown on the following example manipulating windows. +\begin{caml_example} +type event = Raise | Resize | Move;; +let string_of_event = function + Raise -> "Raise" | Resize -> "Resize" | Move -> "Move";; +let count = ref 0;; +class ['observer] window_subject = + let id = count := succ !count; !count in + object (self) + inherit ['observer, event] subject + val mutable position = 0 + method identity = id + method move x = position <- position + x; self#notify_observers Move + method draw = Printf.printf "{Position = %d}\n" position; + end;; +class ['subject] window_observer = + object + inherit ['subject, event] observer + method notify s e = s#draw + end;; +\end{caml_example} +As can be expected, the type of "window" is recursive. +\begin{caml_example} +let window = new window_subject;; +\end{caml_example} +However, the two classes of "window_subject" and "window_observer" are not +mutually recursive. +\begin{caml_example} +let window_observer = new window_observer;; +window#add_observer window_observer;; +window#move 1;; +\end{caml_example} + +Classes "window_observer" and "window_subject" can still be extended by +inheritance. For instance, one may enrich the "subject" with new +behaviors and refine the behavior of the observer. +\begin{caml_example} +class ['observer] richer_window_subject = + object (self) + inherit ['observer] window_subject + val mutable size = 1 + method resize x = size <- size + x; self#notify_observers Resize + val mutable top = false + method raise = top <- true; self#notify_observers Raise + method draw = Printf.printf "{Position = %d; Size = %d}\n" position size; + end;; +class ['subject] richer_window_observer = + object + inherit ['subject] window_observer as super + method notify s e = if e <> Raise then s#raise; super#notify s e + end;; +\end{caml_example} +We can also create a different kind of observer: +\begin{caml_example} +class ['subject] trace_observer = + object + inherit ['subject, event] observer + method notify s e = + Printf.printf + "\n" s#identity (string_of_event e) + end;; +\end{caml_example} +and attach several observers to the same object: +\begin{caml_example} +let window = new richer_window_subject;; +window#add_observer (new richer_window_observer);; +window#add_observer (new trace_observer);; +window#move 1; window#resize 2;; +\end{caml_example} + +%\subsection{Classes used as modules with inheritance} +% +% to be filled for next release... +% +% an example of stateless objects used to provide inheritance in modules +% + + +% LocalWords: objectexamples bsection init caml val int Oo succ incr ref +% LocalWords: typecheck leq bool cp eval sig struct ABSPOINT Abspoint iter neg +% LocalWords: accu mem rec repr Euro euro ccp inlined ostring len concat OCaml diff --git a/manual/manual/tutorials/coreexamples.etex b/manual/manual/tutorials/coreexamples.etex new file mode 100644 index 0000000000..81713a48f6 --- /dev/null +++ b/manual/manual/tutorials/coreexamples.etex @@ -0,0 +1,613 @@ +\chapter{The core language} \label{c:core-xamples} +\pdfchapterfold{-9}{Tutorial: The core language} +%HEVEA\cutname{coreexamples.html} + +This part of the manual is a tutorial introduction to the +OCaml language. A good familiarity with programming in a conventional +languages (say, Pascal or C) is assumed, but no prior exposure to +functional languages is required. The present chapter introduces the +core language. Chapter~\ref{c:moduleexamples} deals with the +module system, chapter~\ref{c:objectexamples} with the +object-oriented features, chapter~\ref{c:labl-examples} with +extensions to the core language (labeled arguments and polymorphic +variants), and chapter~\ref{c:advexamples} gives some advanced examples. + +\section{Basics} +\pdfsection{Basics} + +For this overview of OCaml, we use the interactive system, which +is started by running "ocaml" from the Unix shell, or by launching the +"OCamlwin.exe" application under Windows. This tutorial is presented +as the transcript of a session with the interactive system: +lines starting with "#" represent user input; the system responses are +printed below, without a leading "#". + +Under the interactive system, the user types OCaml phrases terminated +by ";;" in response to the "#" prompt, and the system compiles them +on the fly, executes them, and prints the outcome of evaluation. +Phrases are either simple expressions, or "let" definitions of +identifiers (either values or functions). +\begin{caml_example} +1+2*3;; +let pi = 4.0 *. atan 1.0;; +let square x = x *. x;; +square (sin pi) +. square (cos pi);; +\end{caml_example} +The OCaml system computes both the value and the type for +each phrase. Even function parameters need no explicit type declaration: +the system infers their types from their usage in the +function. Notice also that integers and floating-point numbers are +distinct types, with distinct operators: "+" and "*" operate on +integers, but "+." and "*." operate on floats. +\begin{caml_example} +1.0 * 2;; +\end{caml_example} + +Recursive functions are defined with the "let rec" binding: +\begin{caml_example} +let rec fib n = + if n < 2 then n else fib (n-1) + fib (n-2);; +fib 10;; +\end{caml_example} + +\section{Data types} +\pdfsection{Data types} + +In addition to integers and floating-point numbers, OCaml offers the +usual basic data types: booleans, characters, and immutable character strings. +\begin{caml_example} +(1 < 2) = false;; +'a';; +"Hello world";; +\end{caml_example} + +Predefined data structures include tuples, arrays, and lists. General +mechanisms for defining your own data structures are also provided. +They will be covered in more details later; for now, we concentrate on lists. +Lists are either given in extension as a bracketed list of +semicolon-separated elements, or built from the empty list "[]" +(pronounce ``nil'') by adding elements in front using the "::" +(``cons'') operator. +\begin{caml_example} +let l = ["is"; "a"; "tale"; "told"; "etc."];; +"Life" :: l;; +\end{caml_example} +As with all other OCaml data structures, lists do not need to be +explicitly allocated and deallocated from memory: all memory +management is entirely automatic in OCaml. Similarly, there is no +explicit handling of pointers: the OCaml compiler silently introduces +pointers where necessary. + +As with most OCaml data structures, inspecting and destructuring lists +is performed by pattern-matching. List patterns have the exact same +shape as list expressions, with identifier representing unspecified +parts of the list. As an example, here is insertion sort on a list: +\begin{caml_example} +let rec sort lst = + match lst with + [] -> [] + | head :: tail -> insert head (sort tail) +and insert elt lst = + match lst with + [] -> [elt] + | head :: tail -> if elt <= head then elt :: lst else head :: insert elt tail +;; +sort l;; +\end{caml_example} + +The type inferred for "sort", "'a list -> 'a list", means that "sort" +can actually apply to lists of any type, and returns a list of the +same type. The type "'a" is a {\em type variable}, and stands for any +given type. The reason why "sort" can apply to lists of any type is +that the comparisons ("=", "<=", etc.) are {\em polymorphic} in OCaml: +they operate between any two values of the same type. This makes +"sort" itself polymorphic over all list types. +\begin{caml_example} +sort [6;2;5;3];; +sort [3.14; 2.718];; +\end{caml_example} + +The "sort" function above does not modify its input list: it builds +and returns a new list containing the same elements as the input list, +in ascending order. There is actually no way in OCaml to modify +in-place a list once it is built: we say that lists are {\em immutable} +data structures. Most OCaml data structures are immutable, but a few +(most notably arrays) are {\em mutable}, meaning that they can be +modified in-place at any time. + +\section{Functions as values} +\pdfsection{Functions as values} + +OCaml is a functional language: functions in the full mathematical +sense are supported and can be passed around freely just as any other +piece of data. For instance, here is a "deriv" function that takes any +float function as argument and returns an approximation of its +derivative function: +\begin{caml_example} +let deriv f dx = function x -> (f (x +. dx) -. f x) /. dx;; +let sin' = deriv sin 1e-6;; +sin' pi;; +\end{caml_example} +Even function composition is definable: +\begin{caml_example} +let compose f g = function x -> f (g x);; +let cos2 = compose square cos;; +\end{caml_example} + +Functions that take other functions as arguments are called +``functionals'', or ``higher-order functions''. Functionals are +especially useful to provide iterators or similar generic operations +over a data structure. For instance, the standard OCaml library +provides a "List.map" functional that applies a given function to each +element of a list, and returns the list of the results: +\begin{caml_example} +List.map (function n -> n * 2 + 1) [0;1;2;3;4];; +\end{caml_example} +This functional, along with a number of other list and array +functionals, is predefined because it is often useful, but there is +nothing magic with it: it can easily be defined as follows. +\begin{caml_example} +let rec map f l = + match l with + [] -> [] + | hd :: tl -> f hd :: map f tl;; +\end{caml_example} + +\section{Records and variants} +\pdfsection{Records and variants} +\label{s:tut-recvariants} + +User-defined data structures include records and variants. Both are +defined with the "type" declaration. Here, we declare a record type to +represent rational numbers. +\begin{caml_example} +type ratio = {num: int; denom: int};; +let add_ratio r1 r2 = + {num = r1.num * r2.denom + r2.num * r1.denom; + denom = r1.denom * r2.denom};; +add_ratio {num=1; denom=3} {num=2; denom=5};; +\end{caml_example} + +The declaration of a variant type lists all possible shapes for values +of that type. Each case is identified by a name, called a constructor, +which serves both for constructing values of the variant type and +inspecting them by pattern-matching. Constructor names are capitalized +to distinguish them from variable names (which must start with a +lowercase letter). For instance, here is a variant +type for doing mixed arithmetic (integers and floats): +\begin{caml_example} +type number = Int of int | Float of float | Error;; +\end{caml_example} +This declaration expresses that a value of type "number" is either an +integer, a floating-point number, or the constant "Error" representing +the result of an invalid operation (e.g. a division by zero). + +Enumerated types are a special case of variant types, where all +alternatives are constants: +\begin{caml_example} +type sign = Positive | Negative;; +let sign_int n = if n >= 0 then Positive else Negative;; +\end{caml_example} + +To define arithmetic operations for the "number" type, we use +pattern-matching on the two numbers involved: +\begin{caml_example} +let add_num n1 n2 = + match (n1, n2) with + (Int i1, Int i2) -> + (* Check for overflow of integer addition *) + if sign_int i1 = sign_int i2 && sign_int (i1 + i2) <> sign_int i1 + then Float(float i1 +. float i2) + else Int(i1 + i2) + | (Int i1, Float f2) -> Float(float i1 +. f2) + | (Float f1, Int i2) -> Float(f1 +. float i2) + | (Float f1, Float f2) -> Float(f1 +. f2) + | (Error, _) -> Error + | (_, Error) -> Error;; +add_num (Int 123) (Float 3.14159);; +\end{caml_example} + +The most common usage of variant types is to describe recursive data +structures. Consider for example the type of binary trees: +\begin{caml_example} +type 'a btree = Empty | Node of 'a * 'a btree * 'a btree;; +\end{caml_example} +This definition reads as follows: a binary tree containing values of +type "'a" (an arbitrary type) is either empty, or is a node containing +one value of type "'a" and two subtrees containing also values of type +"'a", that is, two "'a btree". + +Operations on binary trees are naturally expressed as recursive functions +following the same structure as the type definition itself. For +instance, here are functions performing lookup and insertion in +ordered binary trees (elements increase from left to right): +\begin{caml_example} +let rec member x btree = + match btree with + Empty -> false + | Node(y, left, right) -> + if x = y then true else + if x < y then member x left else member x right;; +let rec insert x btree = + match btree with + Empty -> Node(x, Empty, Empty) + | Node(y, left, right) -> + if x <= y then Node(y, insert x left, right) + else Node(y, left, insert x right);; +\end{caml_example} + +\section{Imperative features} +\pdfsection{Imperative features} + +Though all examples so far were written in purely applicative style, +OCaml is also equipped with full imperative features. This includes the +usual "while" and "for" loops, as well as mutable data structures such +as arrays. Arrays are either given in extension between "[|" and "|]" +brackets, or allocated and initialized with the "Array.make" +function, then filled up later by assignments. For instance, the +function below sums two vectors (represented as float arrays) componentwise. +\begin{caml_example} +let add_vect v1 v2 = + let len = min (Array.length v1) (Array.length v2) in + let res = Array.make len 0.0 in + for i = 0 to len - 1 do + res.(i) <- v1.(i) +. v2.(i) + done; + res;; +add_vect [| 1.0; 2.0 |] [| 3.0; 4.0 |];; +\end{caml_example} + +Record fields can also be modified by assignment, provided they are +declared "mutable" in the definition of the record type: +\begin{caml_example} +type mutable_point = { mutable x: float; mutable y: float };; +let translate p dx dy = + p.x <- p.x +. dx; p.y <- p.y +. dy;; +let mypoint = { x = 0.0; y = 0.0 };; +translate mypoint 1.0 2.0;; +mypoint;; +\end{caml_example} + +OCaml has no built-in notion of variable -- identifiers whose current +value can be changed by assignment. (The "let" binding is not an +assignment, it introduces a new identifier with a new scope.) +However, the standard library provides references, which are mutable +indirection cells (or one-element arrays), with operators "!" to fetch +the current contents of the reference and ":=" to assign the contents. +Variables can then be emulated by "let"-binding a reference. For +instance, here is an in-place insertion sort over arrays: +\begin{caml_example} +let insertion_sort a = + for i = 1 to Array.length a - 1 do + let val_i = a.(i) in + let j = ref i in + while !j > 0 && val_i < a.(!j - 1) do + a.(!j) <- a.(!j - 1); + j := !j - 1 + done; + a.(!j) <- val_i + done;; +\end{caml_example} + +References are also useful to write functions that maintain a current +state between two calls to the function. For instance, the following +pseudo-random number generator keeps the last returned number in a +reference: +\begin{caml_example} +let current_rand = ref 0;; +let random () = + current_rand := !current_rand * 25713 + 1345; + !current_rand;; +\end{caml_example} + +Again, there is nothing magical with references: they are implemented as +a single-field mutable record, as follows. +\begin{caml_example} +type 'a ref = { mutable contents: 'a };; +let ( ! ) r = r.contents;; +let ( := ) r newval = r.contents <- newval;; +\end{caml_example} + +In some special cases, you may need to store a polymorphic function in +a data structure, keeping its polymorphism. Without user-provided +type annotations, this is not allowed, as polymorphism is only +introduced on a global level. However, you can give explicitly +polymorphic types to record fields. +\begin{caml_example} +type idref = { mutable id: 'a. 'a -> 'a };; +let r = {id = fun x -> x};; +let g s = (s.id 1, s.id true);; +r.id <- (fun x -> print_string "called id\n"; x);; +g r;; +\end{caml_example} + +\section{Exceptions} +\pdfsection{Exceptions} + +OCaml provides exceptions for signalling and handling exceptional +conditions. Exceptions can also be used as a general-purpose non-local +control structure. Exceptions are declared with the "exception" +construct, and signalled with the "raise" operator. For instance, the +function below for taking the head of a list uses an exception to +signal the case where an empty list is given. +\begin{caml_example} +exception Empty_list;; +let head l = + match l with + [] -> raise Empty_list + | hd :: tl -> hd;; +head [1;2];; +head [];; +\end{caml_example} + +Exceptions are used throughout the standard library to signal cases +where the library functions cannot complete normally. For instance, +the "List.assoc" function, which returns the data associated with a +given key in a list of (key, data) pairs, raises the predefined +exception "Not_found" when the key does not appear in the list: +\begin{caml_example} +List.assoc 1 [(0, "zero"); (1, "one")];; +List.assoc 2 [(0, "zero"); (1, "one")];; +\end{caml_example} + +Exceptions can be trapped with the "try"\ldots"with" construct: +\begin{caml_example} +let name_of_binary_digit digit = + try + List.assoc digit [0, "zero"; 1, "one"] + with Not_found -> + "not a binary digit";; +name_of_binary_digit 0;; +name_of_binary_digit (-1);; +\end{caml_example} + +The "with" part is actually a regular pattern-matching on the +exception value. Thus, several exceptions can be caught by one +"try"\ldots"with" construct. Also, finalization can be performed by +trapping all exceptions, performing the finalization, then raising +again the exception: +\begin{caml_example} +let temporarily_set_reference ref newval funct = + let oldval = !ref in + try + ref := newval; + let res = funct () in + ref := oldval; + res + with x -> + ref := oldval; + raise x;; +\end{caml_example} + +\section{Symbolic processing of expressions} +\pdfsection{Symbolic processing of expressions} + +We finish this introduction with a more complete example +representative of the use of OCaml for symbolic processing: formal +manipulations of arithmetic expressions containing variables. The +following variant type describes the expressions we shall manipulate: +\begin{caml_example} +type expression = + Const of float + | Var of string + | Sum of expression * expression (* e1 + e2 *) + | Diff of expression * expression (* e1 - e2 *) + | Prod of expression * expression (* e1 * e2 *) + | Quot of expression * expression (* e1 / e2 *) +;; +\end{caml_example} + +We first define a function to evaluate an expression given an +environment that maps variable names to their values. For simplicity, +the environment is represented as an association list. +\begin{caml_example} +exception Unbound_variable of string;; +let rec eval env exp = + match exp with + Const c -> c + | Var v -> + (try List.assoc v env with Not_found -> raise (Unbound_variable v)) + | Sum(f, g) -> eval env f +. eval env g + | Diff(f, g) -> eval env f -. eval env g + | Prod(f, g) -> eval env f *. eval env g + | Quot(f, g) -> eval env f /. eval env g;; +eval [("x", 1.0); ("y", 3.14)] (Prod(Sum(Var "x", Const 2.0), Var "y"));; +\end{caml_example} + +Now for a real symbolic processing, we define the derivative of an +expression with respect to a variable "dv": +\begin{caml_example} +let rec deriv exp dv = + match exp with + Const c -> Const 0.0 + | Var v -> if v = dv then Const 1.0 else Const 0.0 + | Sum(f, g) -> Sum(deriv f dv, deriv g dv) + | Diff(f, g) -> Diff(deriv f dv, deriv g dv) + | Prod(f, g) -> Sum(Prod(f, deriv g dv), Prod(deriv f dv, g)) + | Quot(f, g) -> Quot(Diff(Prod(deriv f dv, g), Prod(f, deriv g dv)), + Prod(g, g)) +;; +deriv (Quot(Const 1.0, Var "x")) "x";; +\end{caml_example} + +\section{Pretty-printing} +\pdfsection{Pretty-printing} + +As shown in the examples above, the internal representation (also +called {\em abstract syntax\/}) of expressions quickly becomes hard to +read and write as the expressions get larger. We need a printer and a +parser to go back and forth between the abstract syntax and the {\em +concrete syntax}, which in the case of expressions is the familiar +algebraic notation (e.g. "2*x+1"). + +For the printing function, we take into account the usual precedence +rules (i.e. "*" binds tighter than "+") to avoid printing unnecessary +parentheses. To this end, we maintain the current operator precedence +and print parentheses around an operator only if its precedence is +less than the current precedence. +\begin{caml_example} +let print_expr exp = + (* Local function definitions *) + let open_paren prec op_prec = + if prec > op_prec then print_string "(" in + let close_paren prec op_prec = + if prec > op_prec then print_string ")" in + let rec print prec exp = (* prec is the current precedence *) + match exp with + Const c -> print_float c + | Var v -> print_string v + | Sum(f, g) -> + open_paren prec 0; + print 0 f; print_string " + "; print 0 g; + close_paren prec 0 + | Diff(f, g) -> + open_paren prec 0; + print 0 f; print_string " - "; print 1 g; + close_paren prec 0 + | Prod(f, g) -> + open_paren prec 2; + print 2 f; print_string " * "; print 2 g; + close_paren prec 2 + | Quot(f, g) -> + open_paren prec 2; + print 2 f; print_string " / "; print 3 g; + close_paren prec 2 + in print 0 exp;; +let e = Sum(Prod(Const 2.0, Var "x"), Const 1.0);; +print_expr e; print_newline ();; +print_expr (deriv e "x"); print_newline ();; +\end{caml_example} + +%%%%%%%%%%% Should be moved to the camlp4 documentation. +%% Parsing (transforming concrete syntax into abstract syntax) is usually +%% more delicate. OCaml offers several tools to help write parsers: +%% on the one hand, OCaml versions of the lexer generator Lex and the +%% parser generator Yacc (see chapter~\ref{c:ocamlyacc}), which handle +%% LALR(1) languages using push-down automata; on the other hand, a +%% predefined type of streams (of characters or tokens) and +%% pattern-matching over streams, which facilitate the writing of +%% recursive-descent parsers for LL(1) languages. An example using +%% "ocamllex" and "ocamlyacc" is given in +%% chapter~\ref{c:ocamlyacc}. Here, we will use stream parsers. +%% The syntactic support for stream parsers is provided by the Camlp4 +%% preprocessor, which can be loaded into the interactive toplevel via +%% the "#load" directives below. +%% +%% \begin{caml_example} +%% #load "dynlink.cma";; +%% #load "camlp4o.cma";; +%% open Genlex;; +%% let lexer = make_lexer ["("; ")"; "+"; "-"; "*"; "/"];; +%% \end{caml_example} +%% For the lexical analysis phase (transformation of the input text into +%% a stream of tokens), we use a ``generic'' lexer provided in the +%% standard library module "Genlex". The "make_lexer" function takes a +%% list of keywords and returns a lexing function that ``tokenizes'' an +%% input stream of characters. Tokens are either identifiers, keywords, +%% or literals (integer, floats, characters, strings). Whitespace and +%% comments are skipped. +%% \begin{caml_example} +%% let token_stream = lexer (Stream.of_string "1.0 +x");; +%% Stream.next token_stream;; +%% Stream.next token_stream;; +%% Stream.next token_stream;; +%% \end{caml_example} +%% +%% The parser itself operates by pattern-matching on the stream of +%% tokens. As usual with recursive descent parsers, we use several +%% intermediate parsing functions to reflect the precedence and +%% associativity of operators. Pattern-matching over streams is more +%% powerful than on regular data structures, as it allows recursive calls +%% to parsing functions inside the patterns, for matching sub-components of +%% the input stream. See the Camlp4 documentation for more details. +%% +%% %Already said above +%% %In order to use stream parsers at toplevel, we must first load the +%% %"camlp4" preprocessor. +%% %\begin{caml_example} +%% %#load"camlp4o.cma";; +%% %\end{caml_example} +%% %Then we are ready to define our parser. +%% \begin{caml_example} +%% let rec parse_expr = parser +%% [< e1 = parse_mult; e = parse_more_adds e1 >] -> e +%% and parse_more_adds e1 = parser +%% [< 'Kwd "+"; e2 = parse_mult; e = parse_more_adds (Sum(e1, e2)) >] -> e +%% | [< 'Kwd "-"; e2 = parse_mult; e = parse_more_adds (Diff(e1, e2)) >] -> e +%% | [< >] -> e1 +%% and parse_mult = parser +%% [< e1 = parse_simple; e = parse_more_mults e1 >] -> e +%% and parse_more_mults e1 = parser +%% [< 'Kwd "*"; e2 = parse_simple; e = parse_more_mults (Prod(e1, e2)) >] -> e +%% | [< 'Kwd "/"; e2 = parse_simple; e = parse_more_mults (Quot(e1, e2)) >] -> e +%% | [< >] -> e1 +%% and parse_simple = parser +%% [< 'Ident s >] -> Var s +%% | [< 'Int i >] -> Const(float i) +%% | [< 'Float f >] -> Const f +%% | [< 'Kwd "("; e = parse_expr; 'Kwd ")" >] -> e;; +%% let parse_expression = parser [< e = parse_expr; _ = Stream.empty >] -> e;; +%% \end{caml_example} +%% +%% Composing the lexer and parser, we finally obtain a function to read +%% an expression from a character string: +%% \begin{caml_example} +%% let read_expression s = parse_expression (lexer (Stream.of_string s));; +%% read_expression "2*(x+y)";; +%% \end{caml_example} +%% A small puzzle: why do we get different results in the following two +%% examples? +%% \begin{caml_example} +%% read_expression "x - 1";; +%% read_expression "x-1";; +%% \end{caml_example} +%% Answer: the generic lexer provided by "Genlex" recognizes negative +%% integer literals as one integer token. Hence, "x-1" is read as +%% the token "Ident \"x\"" followed by the token "Int(-1)"; this sequence +%% does not match any of the parser rules. On the other hand, +%% the second space in "x - 1" causes the lexer to return the three +%% expected tokens: "Ident \"x\"", then "Kwd \"-\"", then "Int(1)". + +\section{Standalone OCaml programs} +\pdfsection{Standalone OCaml programs} + +All examples given so far were executed under the interactive system. +OCaml code can also be compiled separately and executed +non-interactively using the batch compilers "ocamlc" and "ocamlopt". +The source code must be put in a file with extension ".ml". It +consists of a sequence of phrases, which will be evaluated at runtime +in their order of appearance in the source file. Unlike in interactive +mode, types and values are not printed automatically; the program must +call printing functions explicitly to produce some output. Here is a +sample standalone program to print Fibonacci numbers: +\begin{verbatim} +(* File fib.ml *) +let rec fib n = + if n < 2 then 1 else fib (n-1) + fib (n-2);; +let main () = + let arg = int_of_string Sys.argv.(1) in + print_int (fib arg); + print_newline (); + exit 0;; +main ();; +\end{verbatim} +"Sys.argv" is an array of strings containing the command-line +parameters. "Sys.argv.(1)" is thus the first command-line parameter. +The program above is compiled and executed with the following shell +commands: +\begin{verbatim} +$ ocamlc -o fib fib.ml +$ ./fib 10 +89 +$ ./fib 20 +10946 +\end{verbatim} + +More complex standalone OCaml programs are typically composed of +multiple source files, and can link with precompiled libraries. +Chapters~\ref{c:camlc} and~\ref{c:nativecomp} explain how to use the +batch compilers "ocamlc" and "ocamlopt". Recompilation of +multi-file OCaml projects can be automated using third-party +build systems, such as the +\href{https://github.com/ocaml/ocamlbuild/}{ocamlbuild} +compilation manager. diff --git a/manual/manual/tutorials/lablexamples.etex b/manual/manual/tutorials/lablexamples.etex new file mode 100644 index 0000000000..4f373151ea --- /dev/null +++ b/manual/manual/tutorials/lablexamples.etex @@ -0,0 +1,491 @@ +\chapter{Labels and variants} \label{c:labl-examples} +\pdfchapterfold{-2}{Tutorial: Labels and variants} +%HEVEA\cutname{lablexamples.html} +{\it (Chapter written by Jacques Garrigue)} + +\bigskip + +\noindent This chapter gives an overview of the new features in +OCaml 3: labels, and polymorphic variants. + +\section{Labels} +\pdfsection{Labels} + +If you have a look at modules ending in "Labels" in the standard +library, you will see that function types have annotations you did not +have in the functions you defined yourself. + +\begin{caml_example} +ListLabels.map;; +StringLabels.sub;; +\end{caml_example} + +Such annotations of the form "name:" are called {\em labels}. They are +meant to document the code, allow more checking, and give more +flexibility to function application. +You can give such names to arguments in your programs, by prefixing them +with a tilde "~". + +\begin{caml_example} +let f ~x ~y = x - y;; +let x = 3 and y = 2 in f ~x ~y;; +\end{caml_example} + +When you want to use distinct names for the variable and the label +appearing in the type, you can use a naming label of the form +"~name:". This also applies when the argument is not a variable. + +\begin{caml_example} +let f ~x:x1 ~y:y1 = x1 - y1;; +f ~x:3 ~y:2;; +\end{caml_example} + +Labels obey the same rules as other identifiers in OCaml, that is you +cannot use a reserved keyword (like "in" or "to") as label. + +Formal parameters and arguments are matched according to their +respective labels\footnote{This correspond to the commuting label mode +of Objective Caml 3.00 through 3.02, with some additional flexibility +on total applications. The so-called classic mode ("-nolabels" +options) is now deprecated for normal use.}, the absence of label +being interpreted as the empty label. +% +This allows commuting arguments in applications. One can also +partially apply a function on any argument, creating a new function of +the remaining parameters. + +\begin{caml_example} +let f ~x ~y = x - y;; +f ~y:2 ~x:3;; +ListLabels.fold_left;; +ListLabels.fold_left [1;2;3] ~init:0 ~f:( + );; +ListLabels.fold_left ~init:0;; +\end{caml_example} + +If several arguments of a function bear the same label (or no label), +they will not commute among themselves, and order matters. But they +can still commute with other arguments. + +\begin{caml_example} +let hline ~x:x1 ~x:x2 ~y = (x1, x2, y);; +hline ~x:3 ~y:2 ~x:5;; +\end{caml_example} + +As an exception to the above parameter matching rules, if an +application is total (omitting all optional arguments), labels may be +omitted. +In practice, many applications are total, so that labels can often be +omitted. +\begin{caml_example} +f 3 2;; +ListLabels.map succ [1;2;3];; +\end{caml_example} +But beware that functions like "ListLabels.fold_left" whose result +type is a type variable will never be considered as totally applied. +\begin{caml_example} +ListLabels.fold_left ( + ) 0 [1;2;3];; +\end{caml_example} + +When a function is passed as an argument to a higher-order function, +labels must match in both types. Neither adding nor removing labels +are allowed. +\begin{caml_example} +let h g = g ~x:3 ~y:2;; +h f;; +h ( + );; +\end{caml_example} +Note that when you don't need an argument, you can still use a wildcard +pattern, but you must prefix it with the label. +\begin{caml_example} +h (fun ~x:_ ~y -> y+1);; +\end{caml_example} + +\subsection{Optional arguments} + +An interesting feature of labeled arguments is that they can be made +optional. For optional parameters, the question mark "?" replaces the +tilde "~" of non-optional ones, and the label is also prefixed by "?" +in the function type. +Default values may be given for such optional parameters. + +\begin{caml_example} +let bump ?(step = 1) x = x + step;; +bump 2;; +bump ~step:3 2;; +\end{caml_example} + +A function taking some optional arguments must also take at least one +non-optional argument. The criterion for deciding whether an optional +argument has been omitted is the non-labeled application of an +argument appearing after this optional argument in the function type. +Note that if that argument is labeled, you will only be able to +eliminate optional arguments through the special case for total +applications. + +\begin{caml_example} +let test ?(x = 0) ?(y = 0) () ?(z = 0) () = (x, y, z);; +test ();; +test ~x:2 () ~z:3 ();; +\end{caml_example} + +Optional parameters may also commute with non-optional or unlabeled +ones, as long as they are applied simultaneously. By nature, optional +arguments do not commute with unlabeled arguments applied +independently. +\begin{caml_example} +test ~y:2 ~x:3 () ();; +test () () ~z:1 ~y:2 ~x:3;; +(test () ()) ~z:1;; +\end{caml_example} +Here "(test () ())" is already "(0,0,0)" and cannot be further +applied. + +Optional arguments are actually implemented as option types. If +you do not give a default value, you have access to their internal +representation, "type 'a option = None | Some of 'a". You can then +provide different behaviors when an argument is present or not. + +\begin{caml_example} +let bump ?step x = + match step with + | None -> x * 2 + | Some y -> x + y +;; +\end{caml_example} + +It may also be useful to relay an optional argument from a function +call to another. This can be done by prefixing the applied argument +with "?". This question mark disables the wrapping of optional +argument in an option type. + +\begin{caml_example} +let test2 ?x ?y () = test ?x ?y () ();; +test2 ?x:None;; +\end{caml_example} + +\subsection{Labels and type inference} +\label{ss:label-inference} + +While they provide an increased comfort for writing function +applications, labels and optional arguments have the pitfall that they +cannot be inferred as completely as the rest of the language. + +You can see it in the following two examples. +\begin{caml_example} +let h' g = g ~y:2 ~x:3;; +h' f;; +let bump_it bump x = + bump ~step:2 x;; +bump_it bump 1;; +\end{caml_example} +The first case is simple: "g" is passed "~y" and then "~x", but "f" +expects "~x" and then "~y". This is correctly handled if we know the +type of "g" to be "x:int -> y:int -> int" in advance, but otherwise +this causes the above type clash. The simplest workaround is to apply +formal parameters in a standard order. + +The second example is more subtle: while we intended the argument +"bump" to be of type "?step:int -> int -> int", it is inferred as +"step:int -> int -> 'a". +% +These two types being incompatible (internally normal and optional +arguments are different), a type error occurs when applying "bump_it" +to the real "bump". + +We will not try here to explain in detail how type inference works. +One must just understand that there is not enough information in the +above program to deduce the correct type of "g" or "bump". That is, +there is no way to know whether an argument is optional or not, or +which is the correct order, by looking only at how a function is +applied. The strategy used by the compiler is to assume that there are +no optional arguments, and that applications are done in the right +order. + +The right way to solve this problem for optional parameters is to add +a type annotation to the argument "bump". +\begin{caml_example} +let bump_it (bump : ?step:int -> int -> int) x = + bump ~step:2 x;; +bump_it bump 1;; +\end{caml_example} +In practice, such problems appear mostly when using objects whose +methods have optional arguments, so that writing the type of object +arguments is often a good idea. + +Normally the compiler generates a type error if you attempt to pass to +a function a parameter whose type is different from the expected one. +However, in the specific case where the expected type is a non-labeled +function type, and the argument is a function expecting optional +parameters, the compiler will attempt to transform the argument to +have it match the expected type, by passing "None" for all optional +parameters. + +\begin{caml_example} +let twice f (x : int) = f(f x);; +twice bump 2;; +\end{caml_example} + +This transformation is coherent with the intended semantics, +including side-effects. That is, if the application of optional +parameters shall produce side-effects, these are delayed until the +received function is really applied to an argument. + +\subsection{Suggestions for labeling} + +Like for names, choosing labels for functions is not an easy task. A +good labeling is a labeling which + +\begin{itemize} +\item makes programs more readable, +\item is easy to remember, +\item when possible, allows useful partial applications. +\end{itemize} + +We explain here the rules we applied when labeling OCaml +libraries. + +To speak in an ``object-oriented'' way, one can consider that each +function has a main argument, its {\em object}, and other arguments +related with its action, the {\em parameters}. To permit the +combination of functions through functionals in commuting label mode, the +object will not be labeled. Its role is clear from the function +itself. The parameters are labeled with names reminding of +their nature or their role. The best labels combine nature and +role. When this is not possible the role is to be preferred, since the +nature will +often be given by the type itself. Obscure abbreviations should be +avoided. +\begin{alltt} +"ListLabels.map : f:('a -> 'b) -> 'a list -> 'b list" +UnixLabels.write : file_descr -> buf:bytes -> pos:int -> len:int -> unit +\end{alltt} + +When there are several objects of same nature and role, they are all +left unlabeled. +\begin{alltt} +"ListLabels.iter2 : f:('a -> 'b -> 'c) -> 'a list -> 'b list -> unit" +\end{alltt} + +When there is no preferable object, all arguments are labeled. +\begin{alltt} +BytesLabels.blit : + src:bytes -> src_pos:int -> dst:bytes -> dst_pos:int -> len:int -> unit +\end{alltt} + +However, when there is only one argument, it is often left unlabeled. +\begin{alltt} +BytesLabels.create : int -> bytes +\end{alltt} +This principle also applies to functions of several arguments whose +return type is a type variable, as long as the role of each argument +is not ambiguous. Labeling such functions may lead to awkward error +messages when one attempts to omit labels in an application, as we +have seen with "ListLabels.fold_left". + +Here are some of the label names you will find throughout the +libraries. + +\begin{tableau}{|l|l|}{Label}{Meaning} +\entree{"f:"}{a function to be applied} +\entree{"pos:"}{a position in a string, array or byte sequence} +\entree{"len:"}{a length} +\entree{"buf:"}{a byte sequence or string used as buffer} +\entree{"src:"}{the source of an operation} +\entree{"dst:"}{the destination of an operation} +\entree{"init:"}{the initial value for an iterator} +\entree{"cmp:"}{a comparison function, {\it e.g.} "Pervasives.compare"} +\entree{"mode:"}{an operation mode or a flag list} +\end{tableau} + +All these are only suggestions, but keep in mind that the +choice of labels is essential for readability. Bizarre choices will +make the program harder to maintain. + +In the ideal, the right function name with right labels should be +enough to understand the function's meaning. Since one can get this +information with OCamlBrowser or the "ocaml" toplevel, the documentation +is only used when a more detailed specification is needed. + +\begin{caml_eval} +#label false;; +\end{caml_eval} + + +\section{Polymorphic variants} +\pdfsection{Polymorphic variants} + +Variants as presented in section~\ref{s:tut-recvariants} are a +powerful tool to build data structures and algorithms. However they +sometimes lack flexibility when used in modular programming. This is +due to the fact that every constructor is assigned to an unique type +when defined and used. Even if the same name appears in the definition +of multiple types, the constructor itself belongs to only one type. +Therefore, one cannot decide that a given constructor belongs to +multiple types, or consider a value of some type to belong to some +other type with more constructors. + +With polymorphic variants, this original assumption is removed. That +is, a variant tag does not belong to any type in particular, the type +system will just check that it is an admissible value according to its +use. You need not define a type before using a variant tag. A variant +type will be inferred independently for each of its uses. + +\subsection*{Basic use} + +In programs, polymorphic variants work like usual ones. You just have +to prefix their names with a backquote character "`". +\begin{caml_example} +[`On; `Off];; +`Number 1;; +let f = function `On -> 1 | `Off -> 0 | `Number n -> n;; +List.map f [`On; `Off];; +\end{caml_example} +"[>`Off|`On] list" means that to match this list, you should at +least be able to match "`Off" and "`On", without argument. +"[<`On|`Off|`Number of int]" means that "f" may be applied to "`Off", +"`On" (both without argument), or "`Number" $n$ where +$n$ is an integer. +The ">" and "<" inside the variant types show that they may still be +refined, either by defining more tags or by allowing less. As such, they +contain an implicit type variable. Because each of the variant types +appears only once in the whole type, their implicit type variables are +not shown. + +The above variant types were polymorphic, allowing further refinement. +When writing type annotations, one will most often describe fixed +variant types, that is types that cannot be refined. This is +also the case for type abbreviations. Such types do not contain "<" or +">", but just an enumeration of the tags and their associated types, +just like in a normal datatype definition. +\begin{caml_example} +type 'a vlist = [`Nil | `Cons of 'a * 'a vlist];; +let rec map f : 'a vlist -> 'b vlist = function + | `Nil -> `Nil + | `Cons(a, l) -> `Cons(f a, map f l) +;; +\end{caml_example} + +\subsection*{Advanced use} + +Type-checking polymorphic variants is a subtle thing, and some +expressions may result in more complex type information. + +\begin{caml_example} +let f = function `A -> `C | `B -> `D | x -> x;; +f `E;; +\end{caml_example} +Here we are seeing two phenomena. First, since this matching is open +(the last case catches any tag), we obtain the type "[> `A | `B]" +rather than "[< `A | `B]" in a closed matching. Then, since "x" is +returned as is, input and return types are identical. The notation "as +'a" denotes such type sharing. If we apply "f" to yet another tag +"`E", it gets added to the list. + +\begin{caml_example} +let f1 = function `A x -> x = 1 | `B -> true | `C -> false +let f2 = function `A x -> x = "a" | `B -> true ;; +let f x = f1 x && f2 x;; +\end{caml_example} +Here "f1" and "f2" both accept the variant tags "`A" and "`B", but the +argument of "`A" is "int" for "f1" and "string" for "f2". In "f"'s +type "`C", only accepted by "f1", disappears, but both argument types +appear for "`A" as "int & string". This means that if we +pass the variant tag "`A" to "f", its argument should be {\em both} +"int" and "string". Since there is no such value, "f" cannot be +applied to "`A", and "`B" is the only accepted input. + +Even if a value has a fixed variant type, one can still give it a +larger type through coercions. Coercions are normally written with +both the source type and the destination type, but in simple cases the +source type may be omitted. +\begin{caml_example} +type 'a wlist = [`Nil | `Cons of 'a * 'a wlist | `Snoc of 'a wlist * 'a];; +let wlist_of_vlist l = (l : 'a vlist :> 'a wlist);; +let open_vlist l = (l : 'a vlist :> [> 'a vlist]);; +fun x -> (x :> [`A|`B|`C]);; +\end{caml_example} + +You may also selectively coerce values through pattern matching. +\begin{caml_example} +let split_cases = function + | `Nil | `Cons _ as x -> `A x + | `Snoc _ as x -> `B x +;; +\end{caml_example} +When an or-pattern composed of variant tags is wrapped inside an +alias-pattern, the alias is given a type containing only the tags +enumerated in the or-pattern. This allows for many useful idioms, like +incremental definition of functions. + +\begin{caml_example} +let num x = `Num x +let eval1 eval (`Num x) = x +let rec eval x = eval1 eval x ;; +let plus x y = `Plus(x,y) +let eval2 eval = function + | `Plus(x,y) -> eval x + eval y + | `Num _ as x -> eval1 eval x +let rec eval x = eval2 eval x ;; +\end{caml_example} + +To make this even more comfortable, you may use type definitions as +abbreviations for or-patterns. That is, if you have defined "type +myvariant = [`Tag1 of int | `Tag2 of bool]", then the pattern "#myvariant" is +equivalent to writing "(`Tag1(_ : int) | `Tag2(_ : bool))". +\begin{caml_eval} +type myvariant = [`Tag1 of int | `Tag2 of bool];; +\end{caml_eval} + +Such abbreviations may be used alone, +\begin{caml_example} +let f = function + | #myvariant -> "myvariant" + | `Tag3 -> "Tag3";; +\end{caml_example} +or combined with with aliases. +\begin{caml_example} +let g1 = function `Tag1 _ -> "Tag1" | `Tag2 _ -> "Tag2";; +let g = function + | #myvariant as x -> g1 x + | `Tag3 -> "Tag3";; +\end{caml_example} + +\subsection{Weaknesses of polymorphic variants} + +After seeing the power of polymorphic variants, one may wonder why +they were added to core language variants, rather than replacing them. + +The answer is twofold. One first aspect is that while being pretty +efficient, the lack of static type information allows for less +optimizations, and makes polymorphic variants slightly heavier than +core language ones. However noticeable differences would only +appear on huge data structures. + +More important is the fact that polymorphic variants, while being +type-safe, result in a weaker type discipline. That is, core language +variants do actually much more than ensuring type-safety, they also +check that you use only declared constructors, that all constructors +present in a data-structure are compatible, and they enforce typing +constraints to their parameters. + +For this reason, you must be more careful about making types explicit +when you use polymorphic variants. When you write a library, this is +easy since you can describe exact types in interfaces, but for simple +programs you are probably better off with core language variants. + +Beware also that some idioms make trivial errors very hard to find. +For instance, the following code is probably wrong but the compiler +has no way to see it. +\begin{caml_example} +type abc = [`A | `B | `C] ;; +let f = function + | `As -> "A" + | #abc -> "other" ;; +let f : abc -> string = f ;; +\end{caml_example} +You can avoid such risks by annotating the definition itself. +\begin{caml_example} +let f : abc -> string = function + | `As -> "A" + | #abc -> "other" ;; +\end{caml_example} diff --git a/manual/manual/tutorials/moduleexamples.etex b/manual/manual/tutorials/moduleexamples.etex new file mode 100644 index 0000000000..b53a0143a6 --- /dev/null +++ b/manual/manual/tutorials/moduleexamples.etex @@ -0,0 +1,311 @@ +\chapter{The module system} \label{c:moduleexamples} +\pdfchapterfold{-5}{Tutorial: The module system} +%HEVEA\cutname{moduleexamples.html} + +This chapter introduces the module system of OCaml. + +\section{Structures} +\pdfsection{Structures} + +A primary motivation for modules is to package together related +definitions (such as the definitions of a data type and associated +operations over that type) and enforce a consistent naming scheme for +these definitions. This avoids running out of names or accidentally +confusing names. Such a package is called a {\em structure} and +is introduced by the "struct"\ldots"end" construct, which contains an +arbitrary sequence of definitions. The structure is usually given a +name with the "module" binding. Here is for instance a structure +packaging together a type of priority queues and their operations: +\begin{caml_example} +module PrioQueue = + struct + type priority = int + type 'a queue = Empty | Node of priority * 'a * 'a queue * 'a queue + let empty = Empty + let rec insert queue prio elt = + match queue with + Empty -> Node(prio, elt, Empty, Empty) + | Node(p, e, left, right) -> + if prio <= p + then Node(prio, elt, insert right p e, left) + else Node(p, e, insert right prio elt, left) + exception Queue_is_empty + let rec remove_top = function + Empty -> raise Queue_is_empty + | Node(prio, elt, left, Empty) -> left + | Node(prio, elt, Empty, right) -> right + | Node(prio, elt, (Node(lprio, lelt, _, _) as left), + (Node(rprio, relt, _, _) as right)) -> + if lprio <= rprio + then Node(lprio, lelt, remove_top left, right) + else Node(rprio, relt, left, remove_top right) + let extract = function + Empty -> raise Queue_is_empty + | Node(prio, elt, _, _) as queue -> (prio, elt, remove_top queue) + end;; +\end{caml_example} +Outside the structure, its components can be referred to using the +``dot notation'', that is, identifiers qualified by a structure name. +For instance, "PrioQueue.insert" is the function "insert" defined +inside the structure "PrioQueue" and "PrioQueue.queue" is the type +"queue" defined in "PrioQueue". +\begin{caml_example} +PrioQueue.insert PrioQueue.empty 1 "hello";; +\end{caml_example} + +\section{Signatures} +\pdfsection{Signatures} + +Signatures are interfaces for structures. A signature specifies +which components of a structure are accessible from the outside, and +with which type. It can be used to hide some components of a structure +(e.g. local function definitions) or export some components with a +restricted type. For instance, the signature below specifies the three +priority queue operations "empty", "insert" and "extract", but not the +auxiliary function "remove_top". Similarly, it makes the "queue" type +abstract (by not providing its actual representation as a concrete type). +\begin{caml_example} +module type PRIOQUEUE = + sig + type priority = int (* still concrete *) + type 'a queue (* now abstract *) + val empty : 'a queue + val insert : 'a queue -> int -> 'a -> 'a queue + val extract : 'a queue -> int * 'a * 'a queue + exception Queue_is_empty + end;; +\end{caml_example} +Restricting the "PrioQueue" structure by this signature results in +another view of the "PrioQueue" structure where the "remove_top" +function is not accessible and the actual representation of priority +queues is hidden: +\begin{caml_example} +module AbstractPrioQueue = (PrioQueue : PRIOQUEUE);; +AbstractPrioQueue.remove_top;; +AbstractPrioQueue.insert AbstractPrioQueue.empty 1 "hello";; +\end{caml_example} +The restriction can also be performed during the definition of the +structure, as in +\begin{verbatim} +module PrioQueue = (struct ... end : PRIOQUEUE);; +\end{verbatim} +An alternate syntax is provided for the above: +\begin{verbatim} +module PrioQueue : PRIOQUEUE = struct ... end;; +\end{verbatim} + +\section{Functors} +\pdfsection{Functors} + +Functors are ``functions'' from structures to structures. They are used to +express parameterized structures: a structure \var{A} parameterized by a +structure \var{B} is simply a functor \var{F} with a formal parameter +\var{B} (along with the expected signature for \var{B}) which returns +the actual structure \var{A} itself. The functor \var{F} can then be +applied to one or several implementations \nth{B}{1} \ldots \nth{B}{n} +of \var{B}, yielding the corresponding structures +\nth{A}{1} \ldots \nth{A}{n}. + +For instance, here is a structure implementing sets as sorted lists, +parameterized by a structure providing the type of the set elements +and an ordering function over this type (used to keep the sets +sorted): +\begin{caml_example} +type comparison = Less | Equal | Greater;; +module type ORDERED_TYPE = + sig + type t + val compare: t -> t -> comparison + end;; +module Set = + functor (Elt: ORDERED_TYPE) -> + struct + type element = Elt.t + type set = element list + let empty = [] + let rec add x s = + match s with + [] -> [x] + | hd::tl -> + match Elt.compare x hd with + Equal -> s (* x is already in s *) + | Less -> x :: s (* x is smaller than all elements of s *) + | Greater -> hd :: add x tl + let rec member x s = + match s with + [] -> false + | hd::tl -> + match Elt.compare x hd with + Equal -> true (* x belongs to s *) + | Less -> false (* x is smaller than all elements of s *) + | Greater -> member x tl + end;; +\end{caml_example} +By applying the "Set" functor to a structure implementing an ordered +type, we obtain set operations for this type: +\begin{caml_example} +module OrderedString = + struct + type t = string + let compare x y = if x = y then Equal else if x < y then Less else Greater + end;; +module StringSet = Set(OrderedString);; +StringSet.member "bar" (StringSet.add "foo" StringSet.empty);; +\end{caml_example} + +\section{Functors and type abstraction} +\pdfsection{Functors and type abstraction} + +As in the "PrioQueue" example, it would be good style to hide the +actual implementation of the type "set", so that users of the +structure will not rely on sets being lists, and we can switch later +to another, more efficient representation of sets without breaking +their code. This can be achieved by restricting "Set" by a suitable +functor signature: +\begin{caml_example} +module type SETFUNCTOR = + functor (Elt: ORDERED_TYPE) -> + sig + type element = Elt.t (* concrete *) + type set (* abstract *) + val empty : set + val add : element -> set -> set + val member : element -> set -> bool + end;; +module AbstractSet = (Set : SETFUNCTOR);; +module AbstractStringSet = AbstractSet(OrderedString);; +AbstractStringSet.add "gee" AbstractStringSet.empty;; +\end{caml_example} + +In an attempt to write the type constraint above more elegantly, +one may wish to name the signature of the structure +returned by the functor, then use that signature in the constraint: +\begin{caml_example} +module type SET = + sig + type element + type set + val empty : set + val add : element -> set -> set + val member : element -> set -> bool + end;; +module WrongSet = (Set : functor(Elt: ORDERED_TYPE) -> SET);; +module WrongStringSet = WrongSet(OrderedString);; +WrongStringSet.add "gee" WrongStringSet.empty;; +\end{caml_example} +The problem here is that "SET" specifies the type "element" +abstractly, so that the type equality between "element" in the result +of the functor and "t" in its argument is forgotten. Consequently, +"WrongStringSet.element" is not the same type as "string", and the +operations of "WrongStringSet" cannot be applied to strings. +As demonstrated above, it is important that the type "element" in the +signature "SET" be declared equal to "Elt.t"; unfortunately, this is +impossible above since "SET" is defined in a context where "Elt" does +not exist. To overcome this difficulty, OCaml provides a +"with type" construct over signatures that allows enriching a signature +with extra type equalities: +\begin{caml_example} +module AbstractSet2 = + (Set : functor(Elt: ORDERED_TYPE) -> (SET with type element = Elt.t));; +\end{caml_example} + +As in the case of simple structures, an alternate syntax is provided +for defining functors and restricting their result: +\begin{verbatim} +module AbstractSet2(Elt: ORDERED_TYPE) : (SET with type element = Elt.t) = + struct ... end;; +\end{verbatim} + +Abstracting a type component in a functor result is a powerful +technique that provides a high degree of type safety, as we now +illustrate. Consider an ordering over character strings that is +different from the standard ordering implemented in the +"OrderedString" structure. For instance, we compare strings without +distinguishing upper and lower case. +\begin{caml_example} +module NoCaseString = + struct + type t = string + let compare s1 s2 = + OrderedString.compare (String.lowercase_ascii s1) (String.lowercase_ascii s2) + end;; +module NoCaseStringSet = AbstractSet(NoCaseString);; +NoCaseStringSet.add "FOO" AbstractStringSet.empty;; +\end{caml_example} +Note that the two types "AbstractStringSet.set" and +"NoCaseStringSet.set" are not compatible, and values of these +two types do not match. This is the correct behavior: even though both +set types contain elements of the same type (strings), they are built +upon different orderings of that type, and different invariants need +to be maintained by the operations (being strictly increasing for the +standard ordering and for the case-insensitive ordering). Applying +operations from "AbstractStringSet" to values of type +"NoCaseStringSet.set" could give incorrect results, or build +lists that violate the invariants of "NoCaseStringSet". + +\section{Modules and separate compilation} +\pdfsection{Modules and separate compilation} + +All examples of modules so far have been given in the context of the +interactive system. However, modules are most useful for large, +batch-compiled programs. For these programs, it is a practical +necessity to split the source into several files, called compilation +units, that can be compiled separately, thus minimizing recompilation +after changes. + +In OCaml, compilation units are special cases of structures +and signatures, and the relationship between the units can be +explained easily in terms of the module system. A compilation unit \var{A} +comprises two files: +\begin{itemize} +\item the implementation file \var{A}".ml", which contains a sequence +of definitions, analogous to the inside of a "struct"\ldots"end" +construct; +\item the interface file \var{A}".mli", which contains a sequence of +specifications, analogous to the inside of a "sig"\ldots"end" +construct. +\end{itemize} +These two files together define a structure named \var{A} as if +the following definition was entered at top-level: +\begin{alltt} +module \var{A}: sig (* \hbox{contents of file} \var{A}.mli *) end + = struct (* \hbox{contents of file} \var{A}.ml *) end;; +\end{alltt} +The files that define the compilation units can be compiled separately +using the "ocamlc -c" command (the "-c" option means ``compile only, do +not try to link''); this produces compiled interface files (with +extension ".cmi") and compiled object code files (with extension +".cmo"). When all units have been compiled, their ".cmo" files are +linked together using the "ocamlc" command. For instance, the following +commands compile and link a program composed of two compilation units +"Aux" and "Main": +\begin{verbatim} +$ ocamlc -c Aux.mli # produces aux.cmi +$ ocamlc -c Aux.ml # produces aux.cmo +$ ocamlc -c Main.mli # produces main.cmi +$ ocamlc -c Main.ml # produces main.cmo +$ ocamlc -o theprogram Aux.cmo Main.cmo +\end{verbatim} +The program behaves exactly as if the following phrases were entered +at top-level: +\begin{alltt} +module Aux: sig (* \rminalltt{contents of} Aux.mli *) end + = struct (* \rminalltt{contents of} Aux.ml *) end;; +module Main: sig (* \rminalltt{contents of} Main.mli *) end + = struct (* \rminalltt{contents of} Main.ml *) end;; +\end{alltt} +In particular, "Main" can refer to "Aux": the definitions and +declarations contained in "Main.ml" and "Main.mli" can refer to +definition in "Aux.ml", using the "Aux."\var{ident} notation, provided +these definitions are exported in "Aux.mli". + +The order in which the ".cmo" files are given to "ocamlc" during the +linking phase determines the order in which the module definitions +occur. Hence, in the example above, "Aux" appears first and "Main" can +refer to it, but "Aux" cannot refer to "Main". + +Note that only top-level structures can be mapped to +separately-compiled files, but neither functors nor module types. +However, all module-class objects can appear as components of a +structure, so the solution is to put the functor or module type +inside a structure, which can then be mapped to a file. diff --git a/manual/manual/tutorials/objectexamples.etex b/manual/manual/tutorials/objectexamples.etex new file mode 100644 index 0000000000..0563459acf --- /dev/null +++ b/manual/manual/tutorials/objectexamples.etex @@ -0,0 +1,1266 @@ +\chapter{Objects in OCaml} +\label{c:objectexamples} +\pdfchapterfold{-15}{Tutorial: Objects in OCaml} +%HEVEA\cutname{objectexamples.html} +{\it (Chapter written by J�r�me Vouillon, Didier R�my and Jacques Garrigue)} + +\bigskip + +\noindent This chapter gives an overview of the object-oriented features of +OCaml. Note that the relation between object, class and type +in OCaml is very different from that in mainstream +object-oriented languages like Java or C++, so that you should not +assume that similar keywords mean the same thing. + +\begin{htmlonly} + +\ref{ss:classes-and-objects} Classes and objects \\ +\ref{ss:immediate-objects} Immediate objects \\ +\ref{ss:reference-to-self} Reference to self \\ +\ref{ss:initializers} Initializers \\ +\ref{ss:virtual-methods} Virtual methods \\ +\ref{ss:private-methods} Private methods \\ +\ref{ss:class-interfaces} Class interfaces \\ +\ref{ss:inheritance} Inheritance \\ +\ref{ss:multiple-inheritance} Multiple inheritance \\ +\ref{ss:parameterized-classes} Parameterized classes \\ +\ref{ss:polymorphic-methods} Polymorphic methods \\ +\ref{ss:using-coercions} Using coercions \\ +\ref{ss:functional-objects} Functional objects \\ +\ref{ss:cloning-objects} Cloning objects \\ +\ref{ss:recursive-classes} Recursive classes \\ +\ref{ss:binary-methods} Binary methods \\ +\ref{ss:friends} Friends \\ + +%%\ref{s:advanced-examples} {\bf Advanced examples} +%% +%%\ref{ss:bank-accounts} An extended example of bank accounts \\ +%%\ref{ss:modules-as-classes} Simple modules as classes: +%% \ref{module:string} Strings +%% \ref{module:stack} Stacks +%% \ref{module:hashtbl} Hash tables +%% \ref{module:set} Sets \\ +%%\ref{ss:subject-observer} The subject/observer pattern \\ + +\end{htmlonly} + +\section{Classes and objects} +\pdfsection{Classes and objects} +\label{ss:classes-and-objects} + +The class "point" below defines one instance variable "x" and two methods +"get_x" and "move". The initial value of the instance variable is "0". +The variable "x" is declared mutable, so the method "move" can change +its value. +\begin{caml_example} +class point = + object + val mutable x = 0 + method get_x = x + method move d = x <- x + d + end;; +\end{caml_example} + +We now create a new point "p", instance of the "point" class. +\begin{caml_example} +let p = new point;; +\end{caml_example} +Note that the type of "p" is "point". This is an abbreviation +automatically defined by the class definition above. It stands for the +object type " unit>", listing the methods +of class "point" along with their types. + +We now invoke some methods to "p": +\begin{caml_example} +p#get_x;; +p#move 3;; +p#get_x;; +\end{caml_example} + +The evaluation of the body of a class only takes place at object +creation time. Therefore, in the following example, the instance +variable "x" is initialized to different values for two different +objects. +\begin{caml_example} +let x0 = ref 0;; +class point = + object + val mutable x = incr x0; !x0 + method get_x = x + method move d = x <- x + d + end;; +new point#get_x;; +new point#get_x;; +\end{caml_example} + +The class "point" can also be abstracted over the initial values of +the "x" coordinate. +\begin{caml_example} +class point = fun x_init -> + object + val mutable x = x_init + method get_x = x + method move d = x <- x + d + end;; +\end{caml_example} +Like in function definitions, the definition above can be +abbreviated as: +\begin{caml_example} +class point x_init = + object + val mutable x = x_init + method get_x = x + method move d = x <- x + d + end;; +\end{caml_example} +An instance of the class "point" is now a function that expects an +initial parameter to create a point object: +\begin{caml_example} +new point;; +let p = new point 7;; +\end{caml_example} +The parameter "x_init" is, of course, visible in the whole body of the +definition, including methods. For instance, the method "get_offset" +in the class below returns the position of the object relative to its +initial position. +\begin{caml_example} +class point x_init = + object + val mutable x = x_init + method get_x = x + method get_offset = x - x_init + method move d = x <- x + d + end;; +\end{caml_example} +%Instance variables can only be used inside methods. For instance it would +%not be possible to define +%\begin{caml_example} +%class point x_init = +% object +% val mutable x = x_init +% val origin = x +% method get_offset = x - origin +% method move d = x <- x + d +% end;; +%\end{caml_example} +Expressions can be evaluated and bound before defining the object body +of the class. This is useful to enforce invariants. For instance, +points can be automatically adjusted to the nearest point on a grid, +as follows: +\begin{caml_example} +class adjusted_point x_init = + let origin = (x_init / 10) * 10 in + object + val mutable x = origin + method get_x = x + method get_offset = x - origin + method move d = x <- x + d + end;; +\end{caml_example} +(One could also raise an exception if the "x_init" coordinate is not +on the grid.) In fact, the same effect could here be obtained by +calling the definition of class "point" with the value of the +"origin". +\begin{caml_example} +class adjusted_point x_init = point ((x_init / 10) * 10);; +\end{caml_example} +An alternate solution would have been to define the adjustment in +a special allocation function: +\begin{caml_example} +let new_adjusted_point x_init = new point ((x_init / 10) * 10);; +\end{caml_example} +However, the former pattern is generally more appropriate, since +the code for adjustment is part of the definition of the class and will be +inherited. + +This ability provides class constructors as can be found in other +languages. Several constructors can be defined this way to build objects of +the same class but with different initialization patterns; an +alternative is to use initializers, as described below in section +\ref{ss:initializers}. + +\section{Immediate objects} +\pdfsection{Immediate objects} +\label{ss:immediate-objects} + +There is another, more direct way to create an object: create it +without going through a class. + +The syntax is exactly the same as for class expressions, but the +result is a single object rather than a class. All the constructs +described in the rest of this section also apply to immediate objects. +\begin{caml_example} +let p = + object + val mutable x = 0 + method get_x = x + method move d = x <- x + d + end;; +p#get_x;; +p#move 3;; +p#get_x;; +\end{caml_example} + +Unlike classes, which cannot be defined inside an expression, +immediate objects can appear anywhere, using variables from their +environment. +\begin{caml_example} +let minmax x y = + if x < y then object method min = x method max = y end + else object method min = y method max = x end;; +\end{caml_example} + +Immediate objects have two weaknesses compared to classes: their types +are not abbreviated, and you cannot inherit from them. But these two +weaknesses can be advantages in some situations, as we will see +in sections \ref{ss:reference-to-self} and \ref{ss:parameterized-classes}. + +\section{Reference to self} +\pdfsection{Reference to self} +\label{ss:reference-to-self} + +A method or an initializer can send messages to self (that is, +the current object). For that, self must be explicitly bound, here to +the variable "s" ("s" could be any identifier, even though we will +often choose the name "self".) +\begin{caml_example} +class printable_point x_init = + object (s) + val mutable x = x_init + method get_x = x + method move d = x <- x + d + method print = print_int s#get_x + end;; +let p = new printable_point 7;; +p#print;; +\end{caml_example} +Dynamically, the variable "s" is bound at the invocation of a method. In +particular, when the class "printable_point" is inherited, the variable +"s" will be correctly bound to the object of the subclass. + +A common problem with self is that, as its type may be extended in +subclasses, you cannot fix it in advance. Here is a simple example. +\begin{caml_example} +let ints = ref [];; +class my_int = + object (self) + method n = 1 + method register = ints := self :: !ints + end;; +\end{caml_example} +You can ignore the first two lines of the error message. What matters +is the last one: putting self into an external reference would make it +impossible to extend it through inheritance. +We will see in section \ref{ss:using-coercions} a workaround to this +problem. +Note however that, since immediate objects are not extensible, the +problem does not occur with them. +\begin{caml_example} +let my_int = + object (self) + method n = 1 + method register = ints := self :: !ints + end;; +\end{caml_example} + +\section{Initializers} +\pdfsection{Initializers} +\label{ss:initializers} + +Let-bindings within class definitions are evaluated before the object +is constructed. It is also possible to evaluate an expression +immediately after the object has been built. Such code is written as +an anonymous hidden method called an initializer. Therefore, it can +access self and the instance variables. +\begin{caml_example} +class printable_point x_init = + let origin = (x_init / 10) * 10 in + object (self) + val mutable x = origin + method get_x = x + method move d = x <- x + d + method print = print_int self#get_x + initializer print_string "new point at "; self#print; print_newline () + end;; +let p = new printable_point 17;; +\end{caml_example} +Initializers cannot be overridden. On the contrary, all initializers are +evaluated sequentially. +Initializers are particularly useful to enforce invariants. +Another example can be seen in section \ref{ss:bank-accounts}. + + +\section{Virtual methods} +\pdfsection{Virtual methods and variables} +\label{ss:virtual-methods} + +It is possible to declare a method without actually defining it, using +the keyword "virtual". This method will be provided later in +subclasses. A class containing virtual methods must be flagged +"virtual", and cannot be instantiated (that is, no object of this class +can be created). It still defines type abbreviations (treating virtual methods +as other methods.) +\begin{caml_example} +class virtual abstract_point x_init = + object (self) + method virtual get_x : int + method get_offset = self#get_x - x_init + method virtual move : int -> unit + end;; +class point x_init = + object + inherit abstract_point x_init + val mutable x = x_init + method get_x = x + method move d = x <- x + d + end;; +\end{caml_example} + +Instance variables can also be declared as virtual, with the same effect +as with methods. +\begin{caml_example} +class virtual abstract_point2 = + object + val mutable virtual x : int + method move d = x <- x + d + end;; +class point2 x_init = + object + inherit abstract_point2 + val mutable x = x_init + method get_offset = x - x_init + end;; +\end{caml_example} + +\section{Private methods} +\pdfsection{Private methods} +\label{ss:private-methods} + +Private methods are methods that do not appear in object interfaces. +They can only be invoked from other methods of the same object. +\begin{caml_example} +class restricted_point x_init = + object (self) + val mutable x = x_init + method get_x = x + method private move d = x <- x + d + method bump = self#move 1 + end;; +let p = new restricted_point 0;; +p#move 10;; +p#bump;; +\end{caml_example} +Note that this is not the same thing as private and protected methods +in Java or C++, which can be called from other objects of the same +class. This is a direct consequence of the independence between types +and classes in OCaml: two unrelated classes may produce +objects of the same type, and there is no way at the type level to +ensure that an object comes from a specific class. However a possible +encoding of friend methods is given in section \ref{ss:friends}. + +Private methods are inherited (they are by default visible in subclasses), +unless they are hidden by signature matching, as described below. + +Private methods can be made public in a subclass. +\begin{caml_example} +class point_again x = + object (self) + inherit restricted_point x + method virtual move : _ + end;; +\end{caml_example} +The annotation "virtual" here is only used to mention a method without +providing its definition. Since we didn't add the "private" +annotation, this makes the method public, keeping the original +definition. + +An alternative definition is +\begin{caml_example} +class point_again x = + object (self : < move : _; ..> ) + inherit restricted_point x + end;; +\end{caml_example} +The constraint on self's type is requiring a public "move" method, and +this is sufficient to override "private". + +One could think that a private method should remain private in a subclass. +However, since the method is visible in a subclass, it is always possible +to pick its code and define a method of the same name that runs that +code, so yet another (heavier) solution would be: +\begin{caml_example} +class point_again x = + object + inherit restricted_point x as super + method move = super#move + end;; +\end{caml_example} + +Of course, private methods can also be virtual. Then, the keywords must +appear in this order "method private virtual". + +\section{Class interfaces} +\pdfsection{Class interfaces} +\label{ss:class-interfaces} + + +%XXX Differentiate class type and class interface ? + +Class interfaces are inferred from class definitions. They may also +be defined directly and used to restrict the type of a class. Like class +declarations, they also define a new type abbreviation. +\begin{caml_example} +class type restricted_point_type = + object + method get_x : int + method bump : unit +end;; +fun (x : restricted_point_type) -> x;; +\end{caml_example} +In addition to program documentation, class interfaces can be used to +constrain the type of a class. Both concrete instance variables and concrete +private methods can be hidden by a class type constraint. Public +methods and virtual members, however, cannot. +\begin{caml_example} +class restricted_point' x = (restricted_point x : restricted_point_type);; +\end{caml_example} +Or, equivalently: +\begin{caml_example} +class restricted_point' = (restricted_point : int -> restricted_point_type);; +\end{caml_example} +The interface of a class can also be specified in a module +signature, and used to restrict the inferred signature of a module. +\begin{caml_example} +module type POINT = sig + class restricted_point' : int -> + object + method get_x : int + method bump : unit + end +end;; +module Point : POINT = struct + class restricted_point' = restricted_point +end;; +\end{caml_example} + +\section{Inheritance} +\pdfsection{Inheritance} +\label{ss:inheritance} + +We illustrate inheritance by defining a class of colored points that +inherits from the class of points. This class has all instance +variables and all methods of class "point", plus a new instance +variable "c" and a new method "color". +\begin{caml_example} +class colored_point x (c : string) = + object + inherit point x + val c = c + method color = c + end;; +let p' = new colored_point 5 "red";; +p'#get_x, p'#color;; +\end{caml_example} +A point and a colored point have incompatible types, since a point has +no method "color". However, the function "get_x" below is a generic +function applying method "get_x" to any object "p" that has this +method (and possibly some others, which are represented by an ellipsis +in the type). Thus, it applies to both points and colored points. +\begin{caml_example} +let get_succ_x p = p#get_x + 1;; +get_succ_x p + get_succ_x p';; +\end{caml_example} +Methods need not be declared previously, as shown by the example: +\begin{caml_example} +let set_x p = p#set_x;; +let incr p = set_x p (get_succ_x p);; +\end{caml_example} + +\section{Multiple inheritance} +\pdfsection{Multiple inheritance} +\label{ss:multiple-inheritance} + +Multiple inheritance is allowed. Only the last definition of a method +is kept: the redefinition in a subclass of a method that was visible in +the parent class overrides the definition in the parent class. +Previous definitions of a method can be reused by binding the related +ancestor. Below, "super" is bound to the ancestor "printable_point". +The name "super" is a pseudo value identifier that can only be used to +invoke a super-class method, as in "super#print". +\begin{caml_example} +class printable_colored_point y c = + object (self) + val c = c + method color = c + inherit printable_point y as super + method print = + print_string "("; + super#print; + print_string ", "; + print_string (self#color); + print_string ")" + end;; +let p' = new printable_colored_point 17 "red";; +p'#print;; +\end{caml_example} +A private method that has been hidden in the parent class is no longer +visible, and is thus not overridden. Since initializers are treated as +private methods, all initializers along the class hierarchy are evaluated, +in the order they are introduced. + +\section{Parameterized classes} +\pdfsection{Parameterized classes} +\label{ss:parameterized-classes} + +Reference cells can be implemented as objects. +The naive definition fails to typecheck: +\begin{caml_example} +class oref x_init = + object + val mutable x = x_init + method get = x + method set y = x <- y + end;; +\end{caml_example} +The reason is that at least one of the methods has a polymorphic type +(here, the type of the value stored in the reference cell), thus +either the class should be parametric, or the method type should be +constrained to a monomorphic type. A monomorphic instance of the class could +be defined by: +\begin{caml_example} +class oref (x_init:int) = + object + val mutable x = x_init + method get = x + method set y = x <- y + end;; +\end{caml_example} +Note that since immediate objects do not define a class type, they have +no such restriction. +\begin{caml_example} +let new_oref x_init = + object + val mutable x = x_init + method get = x + method set y = x <- y + end;; +\end{caml_example} +On the other hand, a class for polymorphic references must explicitly +list the type parameters in its declaration. Class type parameters are +listed between "[" and "]". The type parameters must also be +bound somewhere in the class body by a type constraint. +\begin{caml_example} +class ['a] oref x_init = + object + val mutable x = (x_init : 'a) + method get = x + method set y = x <- y + end;; +let r = new oref 1 in r#set 2; (r#get);; +\end{caml_example} +The type parameter in the declaration may actually be constrained in the +body of the class definition. In the class type, the actual value of +the type parameter is displayed in the "constraint" clause. +\begin{caml_example} +class ['a] oref_succ (x_init:'a) = + object + val mutable x = x_init + 1 + method get = x + method set y = x <- y + end;; +\end{caml_example} +Let us consider a more complex example: define a circle, whose center +may be any kind of point. We put an additional type +constraint in method "move", since no free variables must remain +unaccounted for by the class type parameters. +\begin{caml_example} +class ['a] circle (c : 'a) = + object + val mutable center = c + method center = center + method set_center c = center <- c + method move = (center#move : int -> unit) + end;; +\end{caml_example} +An alternate definition of "circle", using a "constraint" clause in +the class definition, is shown below. The type "#point" used below in +the "constraint" clause is an abbreviation produced by the definition +of class "point". This abbreviation unifies with the type of any +object belonging to a subclass of class "point". It actually expands to +"< get_x : int; move : int -> unit; .. >". This leads to the following +alternate definition of "circle", which has slightly stronger +constraints on its argument, as we now expect "center" to have a +method "get_x". +\begin{caml_example} +class ['a] circle (c : 'a) = + object + constraint 'a = #point + val mutable center = c + method center = center + method set_center c = center <- c + method move = center#move + end;; +\end{caml_example} +The class "colored_circle" is a specialized version of class +"circle" that requires the type of the center to unify with +"#colored_point", and adds a method "color". Note that when specializing a +parameterized class, the instance of type parameter must always be +explicitly given. It is again written between "[" and "]". +\begin{caml_example} +class ['a] colored_circle c = + object + constraint 'a = #colored_point + inherit ['a] circle c + method color = center#color + end;; +\end{caml_example} + +\section{Polymorphic methods} +\pdfsection{Polymorphic methods} +\label{ss:polymorphic-methods} + +While parameterized classes may be polymorphic in their contents, they +are not enough to allow polymorphism of method use. + +A classical example is defining an iterator. +\begin{caml_example} +List.fold_left;; +class ['a] intlist (l : int list) = + object + method empty = (l = []) + method fold f (accu : 'a) = List.fold_left f accu l + end;; +\end{caml_example} +At first look, we seem to have a polymorphic iterator, however this +does not work in practice. +\begin{caml_example} +let l = new intlist [1; 2; 3];; +l#fold (fun x y -> x+y) 0;; +l;; +l#fold (fun s x -> s ^ string_of_int x ^ " ") "";; +\end{caml_example} +Our iterator works, as shows its first use for summation. However, +since objects themselves are not polymorphic (only their constructors +are), using the "fold" method fixes its type for this individual object. +Our next attempt to use it as a string iterator fails. + +The problem here is that quantification was wrongly located: it is +not the class we want to be polymorphic, but the "fold" method. +This can be achieved by giving an explicitly polymorphic type in the +method definition. +\begin{caml_example} +class intlist (l : int list) = + object + method empty = (l = []) + method fold : 'a. ('a -> int -> 'a) -> 'a -> 'a = + fun f accu -> List.fold_left f accu l + end;; +let l = new intlist [1; 2; 3];; +l#fold (fun x y -> x+y) 0;; +l#fold (fun s x -> s ^ string_of_int x ^ " ") "";; +\end{caml_example} +As you can see in the class type shown by the compiler, while +polymorphic method types must be fully explicit in class definitions +(appearing immediately after the method name), quantified type +variables can be left implicit in class descriptions. Why require types +to be explicit? The problem is that "(int -> int -> int) -> int -> +int" would also be a valid type for "fold", and it happens to be +incompatible with the polymorphic type we gave (automatic +instantiation only works for toplevel types variables, not for inner +quantifiers, where it becomes an undecidable problem.) So the compiler +cannot choose between those two types, and must be helped. + +However, the type can be completely omitted in the class definition if +it is already known, through inheritance or type constraints on self. +Here is an example of method overriding. +\begin{caml_example*} +class intlist_rev l = + object + inherit intlist l + method fold f accu = List.fold_left f accu (List.rev l) + end;; +\end{caml_example*} +The following idiom separates description and definition. +\begin{caml_example*} +class type ['a] iterator = + object method fold : ('b -> 'a -> 'b) -> 'b -> 'b end;; +class intlist l = + object (self : int #iterator) + method empty = (l = []) + method fold f accu = List.fold_left f accu l + end;; +\end{caml_example*} +Note here the "(self : int #iterator)" idiom, which ensures that this +object implements the interface "iterator". + +Polymorphic methods are called in exactly the same way as normal +methods, but you should be aware of some limitations of type +inference. Namely, a polymorphic method can only be called if its +type is known at the call site. Otherwise, the method will be assumed +to be monomorphic, and given an incompatible type. +\begin{caml_example} +let sum lst = lst#fold (fun x y -> x+y) 0;; +sum l;; +\end{caml_example} +The workaround is easy: you should put a type constraint on the +parameter. +\begin{caml_example} +let sum (lst : _ #iterator) = lst#fold (fun x y -> x+y) 0;; +\end{caml_example} +Of course the constraint may also be an explicit method type. +Only occurences of quantified variables are required. +\begin{caml_example} +let sum lst = + (lst : < fold : 'a. ('a -> _ -> 'a) -> 'a -> 'a; .. >)#fold (+) 0;; +\end{caml_example} + +Another use of polymorphic methods is to allow some form of implicit +subtyping in method arguments. We have already seen in section +\ref{ss:inheritance} how some functions may be polymorphic in the +class of their argument. This can be extended to methods. +\begin{caml_example} +class type point0 = object method get_x : int end;; +class distance_point x = + object + inherit point x + method distance : 'a. (#point0 as 'a) -> int = + fun other -> abs (other#get_x - x) + end;; +let p = new distance_point 3 in +(p#distance (new point 8), p#distance (new colored_point 1 "blue"));; +\end{caml_example} +Note here the special syntax "(#point0 as 'a)" we have to use to +quantify the extensible part of "#point0". As for the variable binder, +it can be omitted in class specifications. If you want polymorphism +inside object field it must be quantified independently. +\begin{caml_example} +class multi_poly = + object + method m1 : 'a. (< n1 : 'b. 'b -> 'b; .. > as 'a) -> _ = + fun o -> o#n1 true, o#n1 "hello" + method m2 : 'a 'b. (< n2 : 'b -> bool; .. > as 'a) -> 'b -> _ = + fun o x -> o#n2 x + end;; +\end{caml_example} +In method "m1", "o" must be an object with at least a method "n1", +itself polymorphic. In method "m2", the argument of "n2" and "x" must +have the same type, which is quantified at the same level as "'a". + +\section{Using coercions} +\pdfsection{Using coercions} +\label{ss:using-coercions} + +Subtyping is never implicit. There are, however, two ways to perform +subtyping. The most general construction is fully explicit: both the +domain and the codomain of the type coercion must be given. + +We have seen that points and colored points have incompatible types. +For instance, they cannot be mixed in the same list. However, a +colored point can be coerced to a point, hiding its "color" method: +\begin{caml_example} +let colored_point_to_point cp = (cp : colored_point :> point);; +let p = new point 3 and q = new colored_point 4 "blue";; +let l = [p; (colored_point_to_point q)];; +\end{caml_example} +An object of type "t" can be seen as an object of type "t'" +only if "t" is a subtype of "t'". For instance, a point cannot be +seen as a colored point. +\begin{caml_example} +(p : point :> colored_point);; +\end{caml_example} +Indeed, narrowing coercions without runtime checks would be unsafe. +Runtime type checks might raise exceptions, and they would require +the presence of type information at runtime, which is not the case in +the OCaml system. +For these reasons, there is no such operation available in the language. + +Be aware that subtyping and inheritance are not related. Inheritance is a +syntactic relation between classes while subtyping is a semantic relation +between types. For instance, the class of colored points could have been +defined directly, without inheriting from the class of points; the type of +colored points would remain unchanged and thus still be a subtype of +points. +% Conversely, the class "int_comparable" inherits from class +%"comparable", but type "int_comparable" is not a subtype of "comparable". +%\begin{caml_example} +%function x -> (x : int_comparable :> comparable);; +%\end{caml_example} + +The domain of a coercion can often be omitted. For instance, one can +define: +\begin{caml_example} +let to_point cp = (cp :> point);; +\end{caml_example} +In this case, the function "colored_point_to_point" is an instance of the +function "to_point". This is not always true, however. The fully +explicit coercion is more precise and is sometimes unavoidable. +Consider, for example, the following class: +\begin{caml_example} +class c0 = object method m = {< >} method n = 0 end;; +\end{caml_example} +The object type "c0" is an abbreviation for " as 'a". +Consider now the type declaration: +\begin{caml_example} +class type c1 = object method m : c1 end;; +\end{caml_example} +The object type "c1" is an abbreviation for the type " as 'a". +The coercion from an object of type "c0" to an object of type "c1" is +correct: +\begin{caml_example} +fun (x:c0) -> (x : c0 :> c1);; +\end{caml_example} +%%% FIXME come up with a better example. +% However, the domain of the coercion cannot be omitted here: +% \begin{caml_example} +% fun (x:c0) -> (x :> c1);; +% \end{caml_example} +However, the domain of the coercion cannot always be omitted. +In that case, the solution is to use the explicit form. +% +Sometimes, a change in the class-type definition can also solve the problem +\begin{caml_example} +class type c2 = object ('a) method m : 'a end;; +fun (x:c0) -> (x :> c2);; +\end{caml_example} +While class types "c1" and "c2" are different, both object types +"c1" and "c2" expand to the same object type (same method names and types). +Yet, when the domain of a coercion is left implicit and its co-domain +is an abbreviation of a known class type, then the class type, rather +than the object type, is used to derive the coercion function. This +allows leaving the domain implicit in most cases when coercing form a +subclass to its superclass. +% +The type of a coercion can always be seen as below: +\begin{caml_example} +let to_c1 x = (x :> c1);; +let to_c2 x = (x :> c2);; +\end{caml_example} +Note the difference between these two coercions: in the case of "to_c2", +the type +"#c2 = < m : 'a; .. > as 'a" is polymorphically recursive (according +to the explicit recursion in the class type of "c2"); hence the +success of applying this coercion to an object of class "c0". +On the other hand, in the first case, "c1" was only expanded and +unrolled twice to obtain "< m : < m : c1; .. >; .. >" (remember "#c1 = +< m : c1; .. >"), without introducing recursion. +You may also note that the type of "to_c2" is "#c2 -> c2" while +the type of "to_c1" is more general than "#c1 -> c1". This is not always true, +since there are class types for which some instances of "#c" are not subtypes +of "c", as explained in section~\ref{ss:binary-methods}. Yet, for +parameterless classes the coercion "(_ :> c)" is always more general than +"(_ : #c :> c)". +%If a class type exposes the type of self through one of its parameters, this +%is no longer true. Here is a counter-example. +%\begin{caml_example} +%class type ['a] c = object ('a) method m : 'a end;; +%let to_c x = (x :> _ c);; +%\end{caml_example} + + +A common problem may occur when one tries to define a coercion to a +class "c" while defining class "c". The problem is due to the type +abbreviation not being completely defined yet, and so its subtypes are not +clearly known. Then, a coercion "(_ :> c)" or "(_ : #c :> c)" is taken to be +the identity function, as in +\begin{caml_example} +function x -> (x :> 'a);; +\end{caml_example} +As a consequence, if the coercion is applied to "self", as in the +following example, the type of "self" is unified with the closed type +"c" (a closed object type is an object type without ellipsis). This +would constrain the type of self be closed and is thus rejected. +Indeed, the type of self cannot be closed: this would prevent any +further extension of the class. Therefore, a type error is generated +when the unification of this type with another type would result in a +closed object type. +\begin{caml_example} +class c = object method m = 1 end +and d = object (self) + inherit c + method n = 2 + method as_c = (self :> c) +end;; +\end{caml_example} +However, the most common instance of this problem, coercing self to +its current class, is detected as a special case by the type checker, +and properly typed. +\begin{caml_example} +class c = object (self) method m = (self :> c) end;; +\end{caml_example} +This allows the following idiom, keeping a list of all objects +belonging to a class or its subclasses: +\begin{caml_example} +let all_c = ref [];; +class c (m : int) = + object (self) + method m = m + initializer all_c := (self :> c) :: !all_c + end;; +\end{caml_example} +This idiom can in turn be used to retrieve an object whose type has +been weakened: +\begin{caml_example} +let rec lookup_obj obj = function [] -> raise Not_found + | obj' :: l -> + if (obj :> < >) = (obj' :> < >) then obj' else lookup_obj obj l ;; +let lookup_c obj = lookup_obj obj !all_c;; +\end{caml_example} +The type "< m : int >" we see here is just the expansion of "c", due +to the use of a reference; we have succeeded in getting back an object +of type "c". + +\medskip +The previous coercion problem can often be avoided by first +defining the abbreviation, using a class type: +\begin{caml_example} +class type c' = object method m : int end;; +class c : c' = object method m = 1 end +and d = object (self) + inherit c + method n = 2 + method as_c = (self :> c') +end;; +\end{caml_example} +It is also possible to use a virtual class. Inheriting from this class +simultaneously forces all methods of "c" to have the same +type as the methods of "c'". +\begin{caml_example} +class virtual c' = object method virtual m : int end;; +class c = object (self) inherit c' method m = 1 end;; +\end{caml_example} +One could think of defining the type abbreviation directly: +\begin{caml_example*} +type c' = ;; +\end{caml_example*} +However, the abbreviation "#c'" cannot be defined directly in a similar way. +It can only be defined by a class or a class-type definition. +This is because a "#"-abbreviation carries an implicit anonymous +variable ".." that cannot be explicitly named. +The closer you get to it is: +\begin{caml_example*} +type 'a c'_class = 'a constraint 'a = < m : int; .. >;; +\end{caml_example*} +with an extra type variable capturing the open object type. + +\section{Functional objects} +\pdfsection{Functional objects} +\label{ss:functional-objects} + +It is possible to write a version of class "point" without assignments +on the instance variables. The override construct "{< ... >}" returns a copy of +``self'' (that is, the current object), possibly changing the value of +some instance variables. +\begin{caml_example} +class functional_point y = + object + val x = y + method get_x = x + method move d = {< x = x + d >} + end;; +let p = new functional_point 7;; +p#get_x;; +(p#move 3)#get_x;; +p#get_x;; +\end{caml_example} +Note that the type abbreviation "functional_point" is recursive, which can +be seen in the class type of "functional_point": the type of self is "'a" +and "'a" appears inside the type of the method "move". + +The above definition of "functional_point" is not equivalent +to the following: +\begin{caml_example} +class bad_functional_point y = + object + val x = y + method get_x = x + method move d = new bad_functional_point (x+d) + end;; +\end{caml_example} +While objects of either class will behave the same, objects of their +subclasses will be different. In a subclass of "bad_functional_point", +the method "move" will +keep returning an object of the parent class. On the contrary, in a +subclass of "functional_point", the method "move" will return an +object of the subclass. + +Functional update is often used in conjunction with binary methods +as illustrated in section \ref{module:string}. + +\section{Cloning objects} +\pdfsection{Cloning objects} +\label{ss:cloning-objects} + +Objects can also be cloned, whether they are functional or imperative. +The library function "Oo.copy" makes a shallow copy of an object. That is, +it returns a new object that has the same methods and instance +variables as its argument. The +instance variables are copied but their contents are shared. +Assigning a new value to an instance variable of the copy (using a method +call) will not affect instance variables of the original, and conversely. +A deeper assignment (for example if the instance variable is a reference cell) +will of course affect both the original and the copy. + +The type of "Oo.copy" is the following: +\begin{caml_example} +Oo.copy;; +\end{caml_example} +The keyword "as" in that type binds the type variable "'a" to +the object type "< .. >". Therefore, "Oo.copy" takes an object with +any methods (represented by the ellipsis), and returns an object of +the same type. The type of "Oo.copy" is different from type "< .. > -> +< .. >" as each ellipsis represents a different set of methods. +Ellipsis actually behaves as a type variable. +\begin{caml_example} +let p = new point 5;; +let q = Oo.copy p;; +q#move 7; (p#get_x, q#get_x);; +\end{caml_example} +In fact, "Oo.copy p" will behave as "p#copy" assuming that a public +method "copy" with body "{< >}" has been defined in the class of "p". + +Objects can be compared using the generic comparison functions "=" and "<>". +Two objects are equal if and only if they are physically equal. In +particular, an object and its copy are not equal. +\begin{caml_example} +let q = Oo.copy p;; +p = q, p = p;; +\end{caml_example} +Other generic comparisons such as ("<", "<=", ...) can also be used on +objects. The +relation "<" defines an unspecified but strict ordering on objects. The +ordering relationship between two objects is fixed once for all after the +two objects have been created and it is not affected by mutation of fields. + +Cloning and override have a non empty intersection. +They are interchangeable when used within an object and without +overriding any field: +\begin{caml_example} +class copy = + object + method copy = {< >} + end;; +class copy = + object (self) + method copy = Oo.copy self + end;; +\end{caml_example} +Only the override can be used to actually override fields, and +only the "Oo.copy" primitive can be used externally. + +Cloning can also be used to provide facilities for saving and +restoring the state of objects. +\begin{caml_example} +class backup = + object (self : 'mytype) + val mutable copy = None + method save = copy <- Some {< copy = None >} + method restore = match copy with Some x -> x | None -> self + end;; +\end{caml_example} +The above definition will only backup one level. +The backup facility can be added to any class by using multiple inheritance. +\begin{caml_example} +class ['a] backup_ref x = object inherit ['a] oref x inherit backup end;; +let rec get p n = if n = 0 then p # get else get (p # restore) (n-1);; +let p = new backup_ref 0 in +p # save; p # set 1; p # save; p # set 2; +[get p 0; get p 1; get p 2; get p 3; get p 4];; +\end{caml_example} +We can define a variant of backup that retains all copies. (We also +add a method "clear" to manually erase all copies.) +\begin{caml_example} +class backup = + object (self : 'mytype) + val mutable copy = None + method save = copy <- Some {< >} + method restore = match copy with Some x -> x | None -> self + method clear = copy <- None + end;; +\end{caml_example} +\begin{caml_example} +class ['a] backup_ref x = object inherit ['a] oref x inherit backup end;; +let p = new backup_ref 0 in +p # save; p # set 1; p # save; p # set 2; +[get p 0; get p 1; get p 2; get p 3; get p 4];; +\end{caml_example} + + + +\section{Recursive classes} +\pdfsection{Recursive classes} +\label{ss:recursive-classes} + +Recursive classes can be used to define objects whose types are +mutually recursive. +\begin{caml_example} +class window = + object + val mutable top_widget = (None : widget option) + method top_widget = top_widget + end +and widget (w : window) = + object + val window = w + method window = window + end;; +\end{caml_example} +Although their types are mutually recursive, the classes "widget" and +"window" are themselves independent. + + +\section{Binary methods} +\pdfsection{Binary methods} +\label{ss:binary-methods} + +A binary method is a method which takes an argument of the same type +as self. The class "comparable" below is a template for classes with a +binary method "leq" of type "'a -> bool" where the type variable "'a" +is bound to the type of self. Therefore, "#comparable" expands to "< +leq : 'a -> bool; .. > as 'a". We see here that the binder "as" also +allows writing recursive types. +\begin{caml_example} +class virtual comparable = + object (_ : 'a) + method virtual leq : 'a -> bool + end;; +\end{caml_example} +We then define a subclass "money" of "comparable". The class "money" +simply wraps floats as comparable objects. We will extend it below with +more operations. We have to use a type constraint on the class parameter "x" +because the primitive "<=" is a polymorphic function in +OCaml. The "inherit" clause ensures that the type of objects +of this class is an instance of "#comparable". +\begin{caml_example} +class money (x : float) = + object + inherit comparable + val repr = x + method value = repr + method leq p = repr <= p#value + end;; +\end{caml_example} +% not explained: mutability can be hidden +Note that the type "money" is not a subtype of type +"comparable", as the self type appears in contravariant position +in the type of method "leq". +Indeed, an object "m" of class "money" has a method "leq" +that expects an argument of type "money" since it accesses +its "value" method. Considering "m" of type "comparable" would allow a +call to method "leq" on "m" with an argument that does not have a method +"value", which would be an error. + +Similarly, the type "money2" below is not a subtype of type "money". +\begin{caml_example} +class money2 x = + object + inherit money x + method times k = {< repr = k *. repr >} + end;; +\end{caml_example} +It is however possible to define functions that manipulate objects of +type either "money" or "money2": the function "min" +will return the minimum of any two objects whose type unifies with +"#comparable". The type of "min" is not the same as "#comparable -> +#comparable -> #comparable", as the abbreviation "#comparable" hides a +type variable (an ellipsis). Each occurrence of this abbreviation +generates a new variable. +\begin{caml_example} +let min (x : #comparable) y = + if x#leq y then x else y;; +\end{caml_example} +This function can be applied to objects of type "money" +or "money2". +\begin{caml_example} +(min (new money 1.3) (new money 3.1))#value;; +(min (new money2 5.0) (new money2 3.14))#value;; +\end{caml_example} + +More examples of binary methods can be found in sections +\ref{module:string} and \ref{module:set}. + +Note the use of override for method "times". +Writing "new money2 (k *. repr)" instead of "{< repr = k *. repr >}" +would not behave well with inheritance: in a subclass "money3" of "money2" +the "times" method would return an object of class "money2" but not of class +"money3" as would be expected. + +The class "money" could naturally carry another binary method. Here is a +direct definition: +\begin{caml_example} +class money x = + object (self : 'a) + val repr = x + method value = repr + method print = print_float repr + method times k = {< repr = k *. x >} + method leq (p : 'a) = repr <= p#value + method plus (p : 'a) = {< repr = x +. p#value >} + end;; +\end{caml_example} + +\section{Friends} +\pdfsection{Friends} +\label{ss:friends} + +The above class "money" reveals a problem that often occurs with binary +methods. In order to interact with other objects of the same class, the +representation of "money" objects must be revealed, using a method such as +"value". If we remove all binary methods (here "plus" and "leq"), +the representation can easily be hidden inside objects by removing the method +"value" as well. However, this is not possible as soon as some binary +method requires access to the representation of objects of the same +class (other than self). +\begin{caml_example} +class safe_money x = + object (self : 'a) + val repr = x + method print = print_float repr + method times k = {< repr = k *. x >} + end;; +\end{caml_example} +Here, the representation of the object is known only to a particular object. +To make it available to other objects of the same class, we are forced to +make it available to the whole world. However we can easily restrict the +visibility of the representation using the module system. +\begin{caml_example*} +module type MONEY = + sig + type t + class c : float -> + object ('a) + val repr : t + method value : t + method print : unit + method times : float -> 'a + method leq : 'a -> bool + method plus : 'a -> 'a + end + end;; +module Euro : MONEY = + struct + type t = float + class c x = + object (self : 'a) + val repr = x + method value = repr + method print = print_float repr + method times k = {< repr = k *. x >} + method leq (p : 'a) = repr <= p#value + method plus (p : 'a) = {< repr = x +. p#value >} + end + end;; +\end{caml_example*} +Another example of friend functions may be found in section +\ref{module:set}. These examples occur when a group of objects (here +objects of the same class) and functions should see each others internal +representation, while their representation should be hidden from the +outside. The solution is always to define all friends in the same module, +give access to the representation and use a signature constraint to make the +representation abstract outside the module. + + + +% LocalWords: typecheck monomorphic uncaptured Subtyping subtyping leq repr Oo +% LocalWords: val sig bool Euro struct OCaml Vouillon Didier int ref incr init +% LocalWords: succ mytype rec + diff --git a/manual/styles/altindex.sty b/manual/styles/altindex.sty new file mode 100644 index 0000000000..d236e71416 --- /dev/null +++ b/manual/styles/altindex.sty @@ -0,0 +1,39 @@ +%% An attempt to have several index files +%% +%% Defines \altindex{filename}{word to index} +%% and \makealtindex{filename} +%% +%% It is possible to define a macro for each index as follows: +%% \newcommand{\myindex}{\altindex{myindexfile}} +%% +%% This code is not really clean, there are still a number of things +%% that I don't understand... but it works. + +%% \makealtindex{filename} opens filename.idx for writing. + +\def\makealtindex#1{\if@filesw + \expandafter\newwrite\csname @#1altindexfile\endcsname + \immediate\openout\expandafter\csname @#1altindexfile\endcsname=#1.idx + \typeout{Writing alternate index file #1.idx}\fi} + +%% \@wraltindex makes the assumes that a trailing `\fi' will get bound +%% to #2. So, it `eats' it as second parameter and reinserts it. +%% Quick and dirty, I know... +%% Writes the index entry #3 into #1. + +\def\@wraltindex#1#2#3{\let\thepage\relax + \xdef\@gtempa{\write#1{\string + \indexentry{#3}{\thepage}}}\fi\endgroup\@gtempa + \if@nobreak \ifvmode\nobreak\fi\fi\@esphack} + +%% \altindex{filename}{index entry} does nothing if +%% \@altindexfile is \relax (i.e. filename.idx not open). +%% Otherwise, writes the index entry, and closes the whole stuff (some +%% groups, and some \if). + +\def\altindex#1{\@bsphack\begingroup + \def\protect##1{\string##1\space}\@sanitize + \@ifundefined{@#1altindexfile}% + {\endgroup\@esphack}% + {\@wraltindex{\expandafter\csname @#1altindexfile\endcsname}} +} diff --git a/manual/styles/caml-sl.sty b/manual/styles/caml-sl.sty new file mode 100644 index 0000000000..c4061e4a4d --- /dev/null +++ b/manual/styles/caml-sl.sty @@ -0,0 +1,43 @@ +% CAML style option, for use with the caml-latex filter. + +\typeout{Document Style option `caml-sl' <7 Apr 92>.} + +{\catcode`\^^M=\active % + \gdef\@camlinputline#1^^M{\normalsize\tt\# #1\par} % + \gdef\@camloutputline#1^^M{\small\ttfamily\slshape#1\par} } % +\def\@camlblankline{\medskip} +\chardef\@camlbackslash="5C +\def\@bunderline{\setbox0\hbox\bgroup\let\par\@parinunderline} + +\def \@parinunderline {\futurelet \@next \@@parinunderline} +\def \@@parinunderline {\ifx \@next \? \let \@do \@@par@inunderline \else \let \@do \@@@parinunderline \fi \@do} +\def \@@par@inunderline #1{\@eunderline\@oldpar\?\@bunderline} +\def \@@@parinunderline {\@eunderline\@oldpar\@bunderline} +\def\@eunderline{\egroup\underline{\box0}} +\def\@camlnoop{} + +\def\caml{ + \bgroup + \flushleft + \parindent 0pt + \parskip 0pt + \let\do\@makeother\dospecials + \catcode13=\active % 13 = ^M = CR + \catcode92=0 % 92 = \ + \catcode32=\active % 32 = SPC + \frenchspacing + \@vobeyspaces + \let\@oldpar\par + \let\?\@camlinputline + \let\:\@camloutputline + \let\;\@camlblankline + \let\<\@bunderline + \let\>\@eunderline + \let\\\@camlbackslash + \let\-\@camlnoop +} + +\def\endcaml{ + \endflushleft + \egroup\noindent +} diff --git a/manual/styles/caml.sty b/manual/styles/caml.sty new file mode 100644 index 0000000000..3f5753caaa --- /dev/null +++ b/manual/styles/caml.sty @@ -0,0 +1,31 @@ +% CAML style option, for use with the caml-latex filter. + +\typeout{Document Style option `caml' <7 Apr 92>.} + +{\catcode`\^^M=\active % + \gdef\@camlinputline#1^^M{\tt\##1\par} % + \gdef\@camloutputline#1^^M{\tt#1\par} } % +\def\@camlblankline{\medskip} +\chardef\@camlbackslash="5C + +\def\caml{ + \bgroup + \flushleft + \parindent 0pt + \parskip 0pt + \let\do\@makeother\dospecials + \catcode`\^^M=\active + \catcode`\\=0 + \catcode`\ \active + \frenchspacing + \@vobeyspaces + \let\?\@camlinputline + \let\:\@camloutputline + \let\;\@camlblankline + \let\\\@camlbackslash +} + +\def\endcaml{ + \endflushleft + \egroup\noindent +} diff --git a/manual/styles/doc.tfm b/manual/styles/doc.tfm new file mode 100644 index 0000000000..d010f29edd Binary files /dev/null and b/manual/styles/doc.tfm differ diff --git a/manual/styles/docbf.tfm b/manual/styles/docbf.tfm new file mode 100644 index 0000000000..d010f29edd Binary files /dev/null and b/manual/styles/docbf.tfm differ diff --git a/manual/styles/docit.tfm b/manual/styles/docit.tfm new file mode 100644 index 0000000000..d010f29edd Binary files /dev/null and b/manual/styles/docit.tfm differ diff --git a/manual/styles/docmi.tfm b/manual/styles/docmi.tfm new file mode 100644 index 0000000000..d010f29edd Binary files /dev/null and b/manual/styles/docmi.tfm differ diff --git a/manual/styles/docrm.tfm b/manual/styles/docrm.tfm new file mode 100644 index 0000000000..d010f29edd Binary files /dev/null and b/manual/styles/docrm.tfm differ diff --git a/manual/styles/doctt.tfm b/manual/styles/doctt.tfm new file mode 100644 index 0000000000..d010f29edd Binary files /dev/null and b/manual/styles/doctt.tfm differ diff --git a/manual/styles/fullpage.sty b/manual/styles/fullpage.sty new file mode 100644 index 0000000000..6ecbeb761b --- /dev/null +++ b/manual/styles/fullpage.sty @@ -0,0 +1,2 @@ +\marginparwidth 0pt \oddsidemargin 0pt \evensidemargin 0pt \marginparsep 0pt +\topmargin 0pt \textwidth 6.5in \textheight 8.5 in diff --git a/manual/styles/html.sty b/manual/styles/html.sty new file mode 100644 index 0000000000..6a9e92535c --- /dev/null +++ b/manual/styles/html.sty @@ -0,0 +1,222 @@ +% LaTeX2HTML Version 0.6.4 : html.sty +% +% This file contains definitions of LaTeX commands which are +% processed in a special way by the translator. +% For example, there are commands for embedding external hypertext links, +% for cross-references between documents or for including +% raw HTML. +% This file includes the comments.sty file v2.0 by Victor Eijkhout +% In most cases these commands do nothing when processed by LaTeX. + +% Modifications: +% +% nd = Nikos Drakos +% jz = Jelle van Zeijl + +% jz 22-APR-94 - Added support for htmlref +% nd - Created + + + +% Exit if the style file is already loaded +% (suggested by Lee Shombert +\ifx \htmlstyloaded\relax \endinput\else\let\htmlstyloaded\relax\fi + +%%% LINKS TO EXTERNAL DOCUMENTS +% +% This can be used to provide links to arbitrary documents. +% The first argumment should be the text that is going to be +% highlighted and the second argument a URL. +% The hyperlink will appear as a hyperlink in the HTML +% document and as a footnote in the dvi or ps files. +% +\newcommand{\htmladdnormallinkfoot}[2]{ #1\footnote{#2}} + +% This is an alternative definition of the command above which +% will ignore the URL in the dvi or ps files. +\newcommand{\htmladdnormallink}[2]{ #1 } + +% This command takes as argument a URL pointing to an image. +% The image will be embedded in the HTML document but will +% be ignored in the dvi and ps files. +% +\newcommand{\htmladdimg}[1]{ } + +%%% CROSS-REFERENCES BETWEEN (LOCAL OR REMOTE) DOCUMENTS +% +% This can be used to refer to symbolic labels in other Latex +% documents that have already been processed by the translator. +% The arguments should be: +% #1 : the URL to the directory containing the external document +% #2 : the path to the labels.pl file of the external document. +% If the external document lives on a remote machine then labels.pl +% must be copied on the local machine. +% +%e.g. \externallabels{http://cbl.leeds.ac.uk/nikos/WWW/doc/tex2html/latex2html} +% {/usr/cblelca/nikos/tmp/labels.pl} +% The arguments are ignored in the dvi and ps files. +% +\newcommand{\externallabels}[2]{ } + +% This complements the \externallabels command above. The argument +% should be a label defined in another latex document and will be +% ignored in the dvi and ps files. +% +\newcommand{\externalref}[1]{ } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Comment.sty version 2.0, 19 June 1992 +% selectively in/exclude pieces of text: the user can define new +% comment versions, and each is controlled separately. +% This style can be used with plain TeX or LaTeX, and probably +% most other packages too. +% +% Examples of use in LaTeX and TeX follow \endinput +% +% Author +% Victor Eijkhout +% Department of Computer Science +% University Tennessee at Knoxville +% 104 Ayres Hall +% Knoxville, TN 37996 +% USA +% +% eijkhout@cs.utk.edu +% +% Usage: all text included in between +% \comment ... \endcomment +% or \begin{comment} ... \end{comment} +% is discarded. The closing command should appear on a line +% of its own. No starting spaces, nothing after it. +% This environment should work with arbitrary amounts +% of comment. +% +% Other 'comment' environments are defined by +% and are selected/deselected with +% \includecomment{versiona} +% \excludecoment{versionb} +% +% These environments are used as +% \versiona ... \endversiona +% or \begin{versiona} ... \end{versiona} +% with the closing command again on a line of its own. +% +% Basic approach: +% to comment something out, scoop up every line in verbatim mode +% as macro argument, then throw it away. +% For inclusions, both the opening and closing comands +% are defined as noop +% +% Changed \next to \html@next to prevent clashes with other sty files +% (mike@emn.fr) +% Changed \html@next to \htmlnext so the \makeatletter and +% \makeatother commands could be removed (they were cuasing other +% style files - changebar.sty - to crash) (nikos@cbl.leeds.ac.uk) + + +\def\makeinnocent#1{\catcode`#1=12 } +\def\csarg#1#2{\expandafter#1\csname#2\endcsname} + +\def\ThrowAwayComment#1{\begingroup + \def\CurrentComment{#1}% + \let\do\makeinnocent \dospecials + \makeinnocent\^^L% and whatever other special cases + \endlinechar`\^^M \catcode`\^^M=12 \xComment} +{\catcode`\^^M=12 \endlinechar=-1 % + \gdef\xComment#1^^M{\def\test{#1} + \csarg\ifx{PlainEnd\CurrentComment Test}\test + \let\htmlnext\endgroup + \else \csarg\ifx{LaLaEnd\CurrentComment Test}\test + \edef\htmlnext{\endgroup\noexpand\end{\CurrentComment}} + \else \let\htmlnext\xComment + \fi \fi \htmlnext} +} + +\def\includecomment + #1{\expandafter\def\csname#1\endcsname{}% + \expandafter\def\csname end#1\endcsname{}} +\def\excludecomment + #1{\expandafter\def\csname#1\endcsname{\ThrowAwayComment{#1}}% + {\escapechar=-1\relax + \csarg\xdef{PlainEnd#1Test}{\string\\end#1}% + \csarg\xdef{LaLaEnd#1Test}{\string\\end\string\{#1\string\}}% + }} + +\excludecomment{comment} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%% RAW HTML +% +% Enclose raw HTML between a \begin{rawhtml} and \end{rawhtml}. +% The html environment ignores its body +% +\excludecomment{rawhtml} + +%%% HTML ONLY +% +% Enclose LaTeX constructs which will only appear in the +% HTML output and will be ignored by LaTeX with +% \begin{htmlonly} and \end{htmlonly} +% +\excludecomment{htmlonly} + +%%% LaTeX ONLY +% Enclose LaTeX constructs which will only appear in the +% DVI output and will be ignored by latex2html with +%\begin{latexonly} and \end{latexonly} +% +\newenvironment{latexonly}{}{} + +%%% HYPERREF +% Suggested by Eric M. Carol +% Similar to \ref but accepts conditional text. +% The first argument is HTML text which will become ``hyperized'' +% (underlined). +% The second and third arguments are text which will appear only in the paper +% version (DVI file), enclosing the fourth argument which is a reference to a label. +% +%e.g. \hyperref{using the tracer}{using the tracer (see Section}{)}{trace} +% where there is a corresponding \label{trace} +% +\newcommand{\hyperref}[4]{#2\ref{#4}#3} + +%%% HTMLREF +% Reference in HTML version only. +% Mix between \htmladdnormallink and \hyperref. +% First arg is text for in both versions, second is label for use in HTML +% version. +\newcommand{\htmlref}[2]{#1} + +%%% HTMLIMAGE +% This command can be used inside any environment that is converted +% into an inlined image (eg a "figure" environment) in order to change +% the way the image will be translated. The argument of \htmlimage +% is really a string of options separated by commas ie +% [scale=],[external],[thumbnail= +% The scale option allows control over the size of the final image. +% The ``external'' option will cause the image not to be inlined +% (images are inlined by default). External images will be accessible +% via a hypertext link. +% The ``thumbnail'' option will cause a small inlined image to be +% placed in the caption. The size of the thumbnail depends on the +% reduction factor. The use of the ``thumbnail'' option implies +% the ``external'' option. +% +% Example: +% \htmlimage{scale=1.5,external,thumbnail=0.2} +% will cause a small thumbnail image 1/5th of the original size to be +% placed in the final document, pointing to an external image 1.5 +% times bigger than the original. +% +\newcommand{\htmlimage}[1]{} + +%%% HTMLADDTONAVIGATION +% This command appends its argument to the buttons in the navigation +% panel. It is ignored by LaTeX. +% +% Example: +% \htmladdtonavigation{\htmladdnormallink +% {\htmladdimg{http://server/path/to/gif}} +% {http://server/path}} +\newcommand{\htmladdtonavigation}[1]{} diff --git a/manual/styles/isolatin.sty b/manual/styles/isolatin.sty new file mode 100644 index 0000000000..9a6850979d --- /dev/null +++ b/manual/styles/isolatin.sty @@ -0,0 +1,174 @@ +% 1-Jun-1992 +% +% File bases on iso1ibm.tex Version 1.0 of May, 9 1990 +\message{ISO-latin-1 input coding, version 0.9 of 1-Jun-1992.} +% +% For input of 8 bits character. +% This allows reading ISO-8859 Latin-1 codes. +% +\chardef \atcode = \the \catcode `\@ +\catcode `\@ = 11 +% +\catcode160=13 \def^^a0{{\bf?}} % 160 '240, "a0 +\catcode161=13 \def^^a1{!`} % 161 '241, "a1 +\catcode162=13 \def^^a2{{\bf?}} % 162 '242, "a2 +\catcode163=13 \def^^a3{\pounds{}} % 163 '243, "a3 +\catcode164=13 \def^^a4{{\bf?}} % 164 '244, "a4 +\catcode165=13 \def^^a5{{\bf?}} % 165 '245, "a5 +\catcode166=13 \def^^a6{$\vert$} % 166 '246, "a6 +\catcode167=13 \def^^a7{\S{}} % 167 '247, "a7 \S{} ISO-1, +\catcode168=13 \def^^a8{\"{ }} % 168 '250, "a8 +\catcode169=13 \def^^a9{\copyright{}}% 169, '251, "a9 +\catcode170=13 \def^^aa{{\bf?}} % 170 '252, "aa +\catcode171=13 % 171 '253, "ab, +\@ifundefined{lguill}{\def^^ab{$<<$}}{\def^^ab{\lguill}} +\catcode172=13 \def^^ac{{\bf?}} % 172 '254, "ac +\catcode173=13 \def^^ad{{\bf?}} % 173 '255 "ad +\catcode174=13 \def^^ae{{\bf?}} % 174 '256, "ae +\catcode175=13 \def^^af{{\bf?}} % 175 '257, "af +\catcode176=13 \def^^b0{{\bf?}} % 176 '260, "b0 ?? \No +\catcode177=13 \def^^b1{$\pm$} % 177 '261, "b1 ISO-1 plus-minus +\catcode178=13 \def^^b2{${}^2$} % 178, '262, "b2 +\catcode179=13 \def^^b3{${}^3$} % 179, '263, "b3 +\catcode180=13 \def^^b4{\'{ }} % 180, '264, "b4 +\catcode181=13 \def^^b5{{\bf?}} % 181, '265, "b5 +\catcode182=13 \def^^b6{\P{}} % 182, '266, "b6 +\catcode183=13 \def^^b7{$\cdot$} % 183, '267, "b7 +\catcode184=13 \def^^b8{\c{ }} % 184, '270, "b8 +\catcode185=13 \def^^b9{${}^1$} % 185, '271, "b9 +\catcode186=13 \def^^ba{{\bf?}} % 186, '272, "ba +\catcode187=13 % 187, '273, "bb +\@ifundefined{rguill}{\def^^bb{$>>$}}{\def^^bb{\rguill}} +\catcode188=13 \def^^bc{$\frac 1 4$} % 188, '274, "bc +\catcode189=13 \def^^bd{$\frac 1 2$} % 189, '275, "bd +\catcode190=13 \def^^be{$\frac 3 4$} % 190, '276, "be +\catcode191=13 \def^^bf{?`} % 191, '277, "bf +\catcode192=13 \def^^c0{\`A} % 192, '300, "c0 +\@ifundefined{@grave@A@grave@}{\def^^c0{\`A}}{\let^^c0=\@grave@A@grave@} +\catcode193=13 \def^^c1{\'A} % 193, '301, "c1 +\@ifundefined{@acute@A@acute@}{\def^^c1{\'A}}{\let^^c1=\@acute@A@acute@} +\catcode194=13 \def^^c2{\^A} % 194, '302, "c2 +\@ifundefined{@circflx@A@circflx@}{\def^^c2{\^A}}{\let^^c2=\@circflx@A@circflx@} +\catcode195=13 \def^^c3{\~A} % 195, '303, "c3 +\@ifundefined{@tileda@A@tilda@}{\def^^c3{\~A}}{\let^^c3=\@tileda@A@tilda@} +\catcode196=13 \def^^c4{\"A} % 196, '304, "c4 +\@ifundefined{@Umlaut@A@Umlaut@}{\def^^c4{\"A}}{\let^^c4=\@Umlaut@A@Umlaut@} +\catcode197=13 \def^^c5{\AA{}} % 197, '305, "c5 +\@ifundefined{@A@A@}{\def^^c5{\AA{}}}{\let^^c5=\@A@A@} +\catcode198=13 \def^^c6{\AE{}} % 198, '306, "c6 +\@ifundefined{@A@E@}{\def^^c6{\AE{}}}{\let^^c6=\@A@E@} +\catcode199=13 \def^^c7{\c{C}} % 199, '307, "c7 +\@ifundefined{@cedilla@C@cedilla}{\def^^c7{\c{C}}}{\let^^c7=\@cedilla@C@cedilla} +\catcode200=13 \def^^c8{\`E} % 200, '310, "c8 +\@ifundefined{@grave@E@grave@}{\def^^c8{\`E}}{\let^^c8=\@grave@E@grave@} +\catcode201=13 \def^^c9{\'E} % 201, '311, "c9 +\@ifundefined{@acute@E@acute@}{\def^^c9{\'E}}{\let^^c9=\@acute@E@acute@} +\catcode202=13 \def^^ca{\^E} % 202, '312, "ca +\@ifundefined{@circflx@E@circflx@}{\def^^ca{\^E}}{\let^^ca=\@circflx@E@circflx@} +\catcode203=13 \def^^cb{{\"E}} % 203, '313, "cb +\@ifundefined{@Umlaut@E@Umlaut@}{\def^^cb{\"E}}{\let^^cb=\@Umlaut@E@Umlaut@} +\catcode204=13 \def^^cc{\`I} % 204, '314, "cc +\@ifundefined{@grave@I@grave@}{\def^^cc{\`I}}{\let^^cc=\@grave@I@grave@} +\catcode205=13 \def^^cd{\'I} % 205, '315, "cd +\@ifundefined{@acute@I@acute@}{\def^^cd{\'I}}{\let^^cd=\@acute@I@acute@} +\catcode206=13 \def^^ce{\^I} % 206, '316, "ce +\@ifundefined{@circflx@I@circflx@}{\def^^ce{\^I}}{\let^^ce=\@circflx@I@circflx@} +\catcode207=13 \def^^cf{{\"I}} % 207, '317, "cf +\@ifundefined{@Umlaut@I@Umlaut@}{\def^^cf{\"I}}{\let^^cf=\@Umlaut@I@Umlaut@} +\catcode208=13 \def^^d0{\rlap{\raise0.3ex\hbox{--}}D} % 208, '320, "d0 +\@ifundefined{@Eth@}{}{\let^^d0=\@Eth@} +\catcode209=13 \def^^d1{�} % 209, '321, "d1 +\@ifundefined{@tileda@N@tilda@}{\def^^d1{\~N}}{\let^^d1\@tileda@N@tilda@} +\catcode210=13 \def^^d2{\`O} % 210, '322, "d2 +\@ifundefined{@grave@O@grave@}{\def^^d2{\`O}}{\let^^d2=\@grave@O@grave@} +\catcode211=13 \def^^d3{\'O} % 211, '323, "d3 +\@ifundefined{@acute@O@acute@}{\def^^d3{\'O}}{\let^^d3\@acute@O@acute@} +\catcode212=13 \def^^d4{\^O} % 212, '324, "d4 +\@ifundefined{@circflx@O@circflx@}{\def^^d4{\^O}}{\let^^d4=\@circflx@O@circflx@} +\catcode213=13 \def^^d5{\~O} % 213, '325, "d5 +\@ifundefined{@tileda@O@tilda@}{\def^^d5{\~O}}{\let^^d5\@tileda@O@tilda@} +\catcode214=13 \def^^d6{\"O} % 214, '326, "d6 +\@ifundefined{@Umlaut@O@Umlaut@}{\def^^d6{\"O}}{\let^^d6=\@Umlaut@O@Umlaut@} +\catcode215=13 \def^^d7{$\times$}% 215, '327, "d7 +\catcode216=13 \def^^d8{\O{}} % 216, '330, "d8 +\@ifundefined{@OOO@}{\def^^d8{\O{}}}{\let^^d8=\@OOO@} +\catcode217=13 \def^^d9{\`U} % 217, '331, "d9 +\@ifundefined{@grave@U@grave@}{\def^^d9{\`U}}{\let^^d9=\@grave@U@grave@} +\catcode218=13 \def^^da{\'U} % 218, '332, "da +\@ifundefined{@acute@U@acute@}{\def^^da{\'U}}{\let^^da=\@acute@U@acute@} +\catcode219=13 \def^^db{\^U} % 219, '333, "db +\@ifundefined{@circflx@U@circflx@}{\def^^db{\^U}}{\let^^db=\@circflx@U@circflx@} +\catcode220=13 \def^^dc{\"U} % 220, '334, "dc +\@ifundefined{@Umlaut@U@Umlaut@}{\def^^dc{\"U}}{\let^^dc=\@Umlaut@U@Umlaut@} +\catcode221=13 \def^^dd{{\'Y}} % 221, '335, "dd +\@ifundefined{@acute@Y@acute@}{\def^^dd{\'Y}}{\let^^dd=\@acute@Y@acute@} +\catcode222=13 \def^^de{\lower 0.7ex \hbox{l}\hskip-1ex\relax b} % 222, '336, "de +\@ifundefined{@Thorn@}{}{\let^^de=\@Thorn@} +\catcode223=13 \def^^df{\ss{}} % 223, '337, "df +\@ifundefined{@sss@}{\def^^df{\ss{}}}{\let^^df=\@sss@} +\catcode224=13 \def^^e0{\`a} % 224, '340, "e0 +\@ifundefined{@grave@a@grave@}{\def^^e0{\`a}}{\let^^e0=\@grave@a@grave@} +\catcode225=13 \def^^e1{\'a} % 225, '341, "e1 +\@ifundefined{@acute@a@acute@}{\def^^e1{\'a}}{\let^^e1=\@acute@a@acute@} +\catcode226=13 \def^^e2{\^a} % 226, '342, "e2 +\@ifundefined{@circflx@a@circflx@}{\def^^e2{\^a}}{\let^^e2=\@circflx@a@circflx@} +\catcode227=13 \def^^e3{\~a} % 227, '343, "e3 +\@ifundefined{@tileda@a@tilda@}{\def^^e3{\~a}}{\let^^e3=\@tileda@a@tilda@} +\catcode228=13 \def^^e4{\"a} % 228, '344, "e4 +\@ifundefined{@Umlaut@a@Umlaut@}{\def^^e4{\"a}}{\let^^e4=\@Umlaut@a@Umlaut@} +\catcode229=13 \def^^e5{\aa{}} % 229, '345, "e5 +\@ifundefined{@a@a@}{\def^^e5{\aa{}}}{\let^^e5=\@a@a@} +\catcode230=13 \def^^e6{\ae{}} % 230, '346, "e6 +\@ifundefined{@a@e@}{\def^^e6{\ae{}}}{\let^^e6=\@a@e@} +\catcode231=13 \def^^e7{\c{c}} % 231, '347, "e7 +\@ifundefined{@cedilla@c@cedilla}{\def^^e7{\c{c}}}{\let^^e7=\@cedilla@c@cedilla} +\catcode232=13 \def^^e8{\`e} % 232, '350, "e8 +\@ifundefined{@grave@e@grave@}{\def^^e8{\`e}}{\let^^e8=\@grave@e@grave@} +\catcode233=13 \def^^e9{\'e} % 233, '351, "e9 +\@ifundefined{@acute@e@acute@}{\def^^e9{\'e}}{\let^^e9=\@acute@e@acute@} +\catcode234=13 \def^^ea{\^e} % 234, '352, "ea +\@ifundefined{@circflx@e@circflx@}{\def^^ea{\^e}}{\let^^ea=\@circflx@e@circflx@} +\catcode235=13 \def^^eb{\"e} % 235, '353, "eb +\@ifundefined{@Umlaut@e@Umlaut@}{\def^^eb{\"e}}{\let^^eb=\@Umlaut@e@Umlaut@} +\catcode236=13 \def^^ec{\`{\i}} % 236, '354, "ec +\@ifundefined{@grave@i@grave@}{\def^^ec{\`{\i}}}{\let^^ec=\@grave@i@grave@} +\catcode237=13 \def^^ed{\'{\i}} % 237, '355, "ed +\@ifundefined{@acute@i@acute@}{\def^^ed{\'{\i}}}{\let^^ed=\@acute@i@acute@} +\catcode238=13 \def^^ee{\^{\i}} % 238, '356, "ee +\@ifundefined{@circflx@i@circflx@}{\def^^ee{\^{\i}}}{\let^^ee=\@circflx@i@circflx@} +\catcode239=13 \def^^ef{\"{\i}} % 239, '357, "ef +\@ifundefined{@Umlaut@i@Umlaut@}{\def^^ef{\"{\i}}}{\let^^ef=\@Umlaut@i@Umlaut@} +\catcode240=13 \def^^f0{$\partial$} % 240, '360, "f0 +\@ifundefined{@eth@}{\def^^f0{$\partial$}}{\let^^f0=\@eth@} +\catcode241=13 \def^^f1{\~n} % 241, '361, "f1 +\@ifundefined{@tileda@n@tilda@}{\def^^f1{\~n}}{\let^^f1\@tileda@n@tilda@} +\catcode242=13 \def^^f2{\`o} % 242, '362, "f2 +\@ifundefined{@grave@o@grave@}{\def^^f2{\`o}}{\let^^f2=\@grave@o@grave@} +\catcode243=13 \def^^f3{\'o} % 243, '363, "f3 +\@ifundefined{@acute@o@acute@}{\def^^f3{\'o}}{\let^^f3\@acute@o@acute@} +\catcode244=13 \def^^f4{\^o} % 244, '364, "f4 +\@ifundefined{@circflx@o@circflx@}{\def^^f4{\^o}}{\let^^f4=\@circflx@o@circflx@} +\catcode245=13 \def^^f5{\~o} % 245, '365, "f5 +\@ifundefined{@tileda@o@tilda@}{\def^^f5{\~o}}{\let^^f5\@tileda@o@tilda@} +\catcode246=13 \def^^f6{\"o} % 246, '366, "f6 +\@ifundefined{@Umlaut@o@Umlaut@}{\def^^f6{\"o}}{\let^^f6=\@Umlaut@o@Umlaut@} +\catcode247=13 \def^^f7{$\div$} % 247, '367, "f7 +\catcode248=13 \def^^f8{\o{}} % 248, '370, "f8 +\@ifundefined{@ooo@}{\def^^f8{\o{}}}{\let^^f8=\@ooo@} +\catcode249=13 \def^^f9{\`u} % 249, '371, "f9 +\@ifundefined{@grave@u@grave@}{\def^^f9{\`u}}{\let^^f9=\@grave@u@grave@} +\catcode250=13 \def^^fa{\'u} % 250, '372, "fa +\@ifundefined{@acute@u@acute@}{\def^^fa{\'u}}{\let^^fa=\@acute@u@acute@} +\catcode251=13 \def^^fb{\^u} % 251, '373, "fb +\@ifundefined{@circflx@u@circflx@}{\def^^fb{\^u}}{\let^^fb=\@circflx@u@circflx@} +\catcode252=13 \def^^fc{\"u} % 252, '374, "fc +\@ifundefined{@Umlaut@u@Umlaut@}{\def^^fc{\"u}}{\let^^fc=\@Umlaut@u@Umlaut@} +\catcode253=13 \def^^fd{\'y} % 253, '375, "fd +\@ifundefined{@acute@y@acute@}{\def^^fd{\'y}}{\let^^fd=\@acute@y@acute@} +\catcode254=13 \def^^fe{\lower 0.8ex\hbox{l}\hskip-1ex\relax b} % 254, '376, "fe +\@ifundefined{@thorn@}{}{\let^^fe=\@thorn@} +\catcode255=13 \def^^ff{\"y} % 255, '377, "ff +\@ifundefined{@Umlaut@y@Umlaut@}{\def^^ff{\"y}}{\let^^ff=\@Umlaut@y@Umlaut@} +\catcode `\@ = \the \atcode +\endinput +% End of iso-latin-1.tex diff --git a/manual/styles/multicols.sty b/manual/styles/multicols.sty new file mode 100644 index 0000000000..2d94548855 --- /dev/null +++ b/manual/styles/multicols.sty @@ -0,0 +1,176 @@ +% Save file as: MULTICOLS.STY Source: FILESERV@SHSU.BITNET +% multicols.sty version 1.0 +% Allows for multiple column typesetting +% From TUGboat, voulme 10 (1989), No. 3 +% +% Frank Mittelback +% Electronic Data Systems +% (Deutschland) GmbH +% Eisenstrasse 56 +% D-6090 Russelsheim +% Federal Republic of Germany +% Bitnet: pzf5hz@drueds2 +% +% Variables: +% \premulticols - If the space left on the page is less than this, a new +% page is started before the multiple columns. Otherwise, a \vskip +% of \multicolsep is added. +% \postmulticols - analogous to \premulticols +% \columnseprule - the width of the rule separating the columns. +% +% Commands: +% \raggedcolumns - don't align bottom lines of columns +% \flushcolumns - align bottom lines (default) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\@ifundefined{mult@cols}{}{\endinput} + +\def\multicols#1{\col@number#1\relax + \ifnum\col@number<\@ne + \@warning{Using '\number\col@number' columns doesn't seem a good idea.^^J + I therefore use two columns instead}% + \col@number\tw@ \fi + \@ifnextchar[\mult@cols{\mult@cols[]}} + +\def\mult@cols[#1]{\@ifnextchar[% + {\mult@@cols{#1}}% + {\mult@@cols{#1}[\premulticols]}} + +\def\mult@@cols#1[#2]{% + \enough@room#2% + #1\par\addvspace\multicolsep + \begingroup + \prepare@multicols\ignorespaces} + +\def\enough@room#1{\par \penalty\z@ + \page@free \pagegoal + \advance \page@free -\pagetotal + \ifdim \page@free <#1\newpage \fi} + +\def\prepare@multicols{% + \output{\global\setbox\partial@page + \vbox{\unvbox\@cclv}}\eject + \vbadness9999 \hbadness5000 + \tolerance\multicoltolerance + \doublecol@number\col@number + \multiply\doublecol@number\tw@ + \advance\baselineskip\multicolbaselineskip + \advance\@colroom-\ht\partial@page + \vsize\col@number\@colroom + \advance\vsize\c@collectmore\baselineskip + \hsize\columnwidth \advance\hsize\columnsep + \advance\hsize-\col@number\columnsep + \divide\hsize\col@number + \linewidth\hsize + \output{\multi@columnout}% + \multiply\count\footins\col@number + \multiply\skip \footins\col@number + \reinsert@footnotes} + +\def\endmulticols{\par\penalty\z@ + \output{\balance@columns}\eject + \endgroup \reinsert@footnotes + \global\c@unbalance\z@ + \enough@room\postmulticols + \addvspace\multicolsep} + +\newcount\c@unbalance \c@unbalance = 0 +\newcount\c@collectmore \c@collectmore = 0 +\newcount\col@number +\newcount\doublecol@number +\newcount\multicoltolerance \multicoltolerance = 9999 +\newdimen\page@free +\newdimen\premulticols \premulticols = 50pt +\newdimen\postmulticols \postmulticols = 20pt +\newskip\multicolsep \multicolsep = 12pt plus 4pt minus 3pt +\newskip\multicolbaselineskip \multicolbaselineskip=0pt +\newbox\partial@page + +\def\process@cols#1#2{\count@#1\relax + \loop #2% + \advance\count@\tw@ + \ifnum\count@<\doublecol@number + \repeat} + +\def\page@sofar{\unvbox\partial@page + \process@cols\z@{\wd\count@\hsize}% + \hbox to\textwidth{% + \process@cols\tw@{\box\count@ + \hss\vrule\@width\columnseprule\hss}% + \box\z@}} + +\def\reinsert@footnotes{\ifvoid\footins\else + \insert\footins{\unvbox\footins}\fi} + +\def\multi@columnout{% + \ifnum\outputpenalty <-\@Mi + \speci@ls \else + \splittopskip\topskip + \splitmaxdepth\maxdepth + \dimen@\@colroom + \divide\skip\footins\col@number + \ifvoid\footins \else + \advance\dimen@-\skip\footins + \advance\dimen@-\ht\footins \fi + \process@cols\tw@{\setbox\count@ + \vsplit\@cclv to\dimen@}% + \setbox\z@\vsplit\@cclv to\dimen@ + \ifvoid\@cclv \else + \unvbox\@cclv + \penalty\outputpenalty + \fi + \setbox\@cclv\vbox{\page@sofar}% + \@makecol\@outputpage + \global\@colroom\@colht + \process@deferreds + \global\vsize\col@number\@colroom + \global\advance\vsize + \c@collectmore\baselineskip + \multiply\skip\footins\col@number\fi} + +\def\speci@ls{% + \typeout{floats and marginpars not allowed inside `multicols' environment}% + \unvbox\@cclv\reinsert@footnotes + \gdef\@currlist{}} + +\def\process@deferreds{% + \@floatplacement + \begingroup + \let\@tempb\@deferlist + \gdef\@deferlist{}% + \let\@elt\@scolelt + \@tempb \endgroup} + +\newif\ifshr@nking + +\def\raggedcolumns{% + \@bsphack\shr@nkingtrue\@esphack} +\def\flushcolumns{% + \@bsphack\shr@nkingfale\@esphack} + +\def\balance@columns{% + \splittopskip\topskip + \splitmaxdepth\maxdepth + \setbox\z@\vbox{\unvbox\@cclv}\dimen@\ht\z@ + \advance\dimen@\col@number\topskip + \advance\dimen@-\col@number\baselineskip + \divide\dimen@\col@number + \advance\dimen@\c@unbalance\baselineskip + {\vbadness\@M \loop + {\process@cols\@ne{\global\setbox\count@\box\voidb@x}}% + \global\setbox\@ne\copy\z@ + {\process@cols\thr@@{\global\setbox\count@\vsplit\@ne to\dimen@}}% + \ifshr@nking \global\setbox\thr@@\vbox{\unvbox\thr@@}% + \fi + \ifdim\ht\@ne >\ht\thr@@ + \global\advance\dimen@\p@ + \repeat}% + \dimen@\ht\thr@@ + \process@cols\z@{\@tempcnta\count@ + \advance\@tempcnta\@ne + \setbox\count@\vtop to\dimen@ + {\unvbox\@tempcnta + \ifshr@nking\vfill\fi}}% + \global\vsize\@colroom + \global\advance\vsize\ht\partial@page + \page@sofar} diff --git a/manual/styles/multind.sty b/manual/styles/multind.sty new file mode 100644 index 0000000000..ef91c28df0 --- /dev/null +++ b/manual/styles/multind.sty @@ -0,0 +1,65 @@ +% indexes document style option for producing multiple indexes +% for use with the modified bbok style, CHbook.sty +% Written by F.W. Long, Version 1.1, 12 August 1991. + +% Modified by F.W. Long, Version 1.1a, 29 August 1991 +% to get the index heading correctly spaced. + +% Modified by F.W. Long, Version 1.1b, 31 August 1991 +% to remove the abbreviation \ix (which should be in the document, not here). + +% Modified \makeindex and \index commands to allow multiple indexes +% in both cases the first parameter is the index name. +% They now work more like \@starttoc and \addcontentsline. +% \index is no longer defined inside \makeindex but determines +% whether the appropriate file is defined before writing to it. + +\def\makeindex#1{\begingroup + \makeatletter + \if@filesw \expandafter\newwrite\csname #1@idxfile\endcsname + \expandafter\immediate\openout \csname #1@idxfile\endcsname #1.idx\relax + \typeout{Writing index file #1.idx }\fi \endgroup} + +\def\index#1{\@bsphack\begingroup + \def\protect##1{\string##1\space}\@sanitize + \@wrindex{#1}} + +% \@wrindex now checks that the appropriate file is defined. + +\def\@wrindex#1#2{\let\thepage\relax + \xdef\@gtempa{\@ifundefined{#1@idxfile}{}{\expandafter + \write\csname #1@idxfile\endcsname{\string + \indexentry{#2}{\thepage}}}}\endgroup\@gtempa + \if@nobreak \ifvmode\nobreak\fi\fi\@esphack} + +% Modified \printindex command to allow multiple indexes. +% This now takes over much of the work of \theindex. +% Again, the first parameter is the index name. +% The second parameter is the index title (as printed). + +\newif\if@restonecol +\def\printindex#1#2{\@restonecoltrue\if@twocolumn\@restonecolfalse\fi + \columnseprule \z@ \columnsep 35pt + \newpage \twocolumn[{\Large\bf #2 \vskip4ex}] + \markright{\uppercase{#2}} + \addcontentsline{toc}{section}{#2} + \@input{#1.ind}} + +% The following index commands are taken from book.sty. +% \theindex is modified to not start a chapter. + +\def\theindex{\parindent\z@ + \parskip\z@ plus .3pt\relax\let\item\@idxitem} +\def\@idxitem{\par\hangindent 40pt} +\def\subitem{\par\hangindent 40pt \hspace*{20pt}} +\def\subsubitem{\par\hangindent 40pt \hspace*{30pt}} +\def\endtheindex{\if@restonecol\onecolumn\else\clearpage\fi} +\def\indexspace{\par \vskip 10pt plus 5pt minus 3pt\relax} + +% the command \ix allows an abbreviation for the general index + +%\def\ix#1{#1\index{general}{#1}} + +% define the \see command from makeidx.sty + +\def\see#1#2{{\em see\/} #1} diff --git a/manual/styles/ocamldoc.hva b/manual/styles/ocamldoc.hva new file mode 100644 index 0000000000..58b7bb1219 --- /dev/null +++ b/manual/styles/ocamldoc.hva @@ -0,0 +1,20 @@ +\usepackage{alltt} +\newenvironment{ocamldoccode}{\begin{alltt}}{\end{alltt}} +\newenvironment{ocamldocdescription}{\begin{quote}}{\end{quote}} +\newenvironment{ocamldoccomment}{\begin{quote}}{\end{quote}} + + +\newenvironment{ocamldocindent}{\list{}{}\item\relax}{\endlist} +\newenvironment{ocamldocsigend} + {\noindent\quad\texttt{sig}\ocamldocindent} + {\endocamldocindent + \noindent\quad\texttt{end}\medskip} +\newenvironment{ocamldocobjectend} + {\noindent\quad\texttt{object}\ocamldocindent} + {\endocamldocindent + \noindent\quad\texttt{end}\medskip} + +\newcommand{\moduleref}[1]{\ifhtml\ahref{libref/#1.html}{\texttt{#1}}\fi} + +# For processing .tex generated by ocamldoc (for text manual) +\newcommand{\ocamldocvspace}[1]{\vspace{#1}} \ No newline at end of file diff --git a/manual/styles/ocamldoc.sty b/manual/styles/ocamldoc.sty new file mode 100644 index 0000000000..b176c9b141 --- /dev/null +++ b/manual/styles/ocamldoc.sty @@ -0,0 +1,75 @@ + +%% Support macros for LaTeX documentation generated by ocamldoc. +%% This file is in the public domain; do what you want with it. + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{ocamldoc} + [2001/12/04 v1.0 ocamldoc support] + +\newenvironment{ocamldoccode}{% + \bgroup + \leftskip\@totalleftmargin + \rightskip\z@skip + \parindent\z@ + \parfillskip\@flushglue + \parskip\z@skip + %\noindent + \@@par\smallskip + \@tempswafalse + \def\par{% + \if@tempswa + \leavevmode\null\@@par\penalty\interlinepenalty + \else + \@tempswatrue + \ifhmode\@@par\penalty\interlinepenalty\fi + \fi} + \obeylines + \verbatim@font + \let\org@prime~% + \@noligs + \let\org@dospecials\dospecials + \g@remfrom@specials{\\} + \g@remfrom@specials{\{} + \g@remfrom@specials{\}} + \let\do\@makeother + \dospecials + \let\dospecials\org@dospecials + \frenchspacing\@vobeyspaces + \everypar \expandafter{\the\everypar \unpenalty}} +{\egroup\par} + +\def\g@remfrom@specials#1{% + \def\@new@specials{} + \def\@remove##1{% + \ifx##1#1\else + \g@addto@macro\@new@specials{\do ##1}\fi} + \let\do\@remove\dospecials + \let\dospecials\@new@specials + } + +\newenvironment{ocamldocdescription} +{\list{}{\rightmargin0pt \topsep0pt}\raggedright\item\noindent\relax\ignorespaces} +{\endlist\medskip} + +\newenvironment{ocamldoccomment} +{\list{}{\leftmargin 2\leftmargini \rightmargin0pt \topsep0pt}\raggedright\item\noindent\relax} +{\endlist} + +\let \ocamldocparagraph \paragraph +\def \paragraph #1{\ocamldocparagraph {#1}\noindent} +\let \ocamldocsubparagraph \subparagraph +\def \subparagraph #1{\ocamldocsubparagraph {#1}\noindent} + +\let\ocamldocvspace\vspace + +\newenvironment{ocamldocindent}{\list{}{}\item\relax}{\endlist} +\newenvironment{ocamldocsigend} + {\noindent\quad\texttt{sig}\ocamldocindent} + {\endocamldocindent\vskip -\lastskip + \noindent\quad\texttt{end}\medskip} +\newenvironment{ocamldocobjectend} + {\noindent\quad\texttt{object}\ocamldocindent} + {\endocamldocindent\vskip -\lastskip + \noindent\quad\texttt{end}\medskip} + +\endinput diff --git a/manual/styles/plaintext.sty b/manual/styles/plaintext.sty new file mode 100644 index 0000000000..2d1b366ce5 --- /dev/null +++ b/manual/styles/plaintext.sty @@ -0,0 +1,268 @@ +% Plain text style file. + +\typeout{Style option Plaintext} + +% Version from John Pavel's dvidoc.sty, March 1987 +% Heavily hacked by Xavier Leroy, June 1993. + +% Redefine all fonts to be the "doc" pseudo-font, with fixed spacing. +% Since rm, tt and mi have different character encodings, we keep +% several copies of the doc font, with different names, so that dvi2txt +% can select the right encoding according to the name. Also, we use +% different names for boldface and italics, so that dvi2txt can select +% the right style whenever possible. + +\def\sl{\rm} +\def\sc{\rm} + +\def\vpt{} +\def\vipt{} +\def\viipt{} +\def\viiipt{} +\def\ixpt{} +\def\xipt{} +\def\xiipt{} +\def\xivpt{} +\def\xviipt{} +\def\xxpt{} +\def\xxvpt{} + +%%% for i in fiv six sev egt nin ten elv twl frtn svnt twty twfv; do +%%% echo "\\font\\${i}rm = docrm" +%%% echo "\\font\\${i}mi = docmi" +%%% echo "\\font\\${i}sy = cmsy10" +%%% echo "\\font\\${i}it = docit" +%%% echo "\\font\\${i}bf = docbf" +%%% echo "\\font\\${i}tt = doctt" +%%% echo "\\font\\${i}sf = docrm" +%%% done + +\font\fivrm = docrm +\font\fivmi = docmi +\font\fivsy = cmsy10 +\font\fivit = docit +\font\fivbf = docbf +\font\fivtt = doctt +\font\fivsf = docrm +\font\sixrm = docrm +\font\sixmi = docmi +\font\sixsy = cmsy10 +\font\sixit = docit +\font\sixbf = docbf +\font\sixtt = doctt +\font\sixsf = docrm +\font\sevrm = docrm +\font\sevmi = docmi +\font\sevsy = cmsy10 +\font\sevit = docit +\font\sevbf = docbf +\font\sevtt = doctt +\font\sevsf = docrm +\font\egtrm = docrm +\font\egtmi = docmi +\font\egtsy = cmsy10 +\font\egtit = docit +\font\egtbf = docbf +\font\egttt = doctt +\font\egtsf = docrm +\font\ninrm = docrm +\font\ninmi = docmi +\font\ninsy = cmsy10 +\font\ninit = docit +\font\ninbf = docbf +\font\nintt = doctt +\font\ninsf = docrm +\font\tenrm = docrm +\font\tenmi = docmi +\font\tensy = cmsy10 +\font\tenit = docit +\font\tenbf = docbf +\font\tentt = doctt +\font\tensf = docrm +\font\elvrm = docrm +\font\elvmi = docmi +\font\elvsy = cmsy10 +\font\elvit = docit +\font\elvbf = docbf +\font\elvtt = doctt +\font\elvsf = docrm +\font\twlrm = docrm +\font\twlmi = docmi +\font\twlsy = cmsy10 +\font\twlit = docit +\font\twlbf = docbf +\font\twltt = doctt +\font\twlsf = docrm +\font\frtnrm = docrm +\font\frtnmi = docmi +\font\frtnsy = cmsy10 +\font\frtnit = docit +\font\frtnbf = docbf +\font\frtntt = doctt +\font\frtnsf = docrm +\font\svtnrm = docrm +\font\svtnmi = docmi +\font\svtnsy = cmsy10 +\font\svtnit = docit +\font\svtnbf = docbf +\font\svtntt = doctt +\font\svtnsf = docrm +\font\twtyrm = docrm +\font\twtymi = docmi +\font\twtysy = cmsy10 +\font\twtyit = docit +\font\twtybf = docbf +\font\twtytt = doctt +\font\twtysf = docrm +\font\twfvrm = docrm +\font\twfvmi = docmi +\font\twfvsy = cmsy10 +\font\twfvit = docit +\font\twfvbf = docbf +\font\twfvtt = doctt +\font\twfvsf = docrm + +\rm + +% Dimensions + +\hsize 78 em % 78 characters per line so fit any screen +\textwidth 78 em +\raggedright % Do not try to align on the right +\parindent=2em % Two blanks for paragraph indentation +\def\enspace{\kern 1em} \def\enskip{\hskip 1em\relax} + +% Vertical skips may best be multiples of \baselineskip +\baselineskip=12pt % 6 lines per inch +\normalbaselineskip=\baselineskip +\vsize 58\baselineskip % 58 lines per page +\textheight 58\baselineskip +\voffset=0pt +\parskip=0pt +\smallskipamount=0pt +\medskipamount= \baselineskip +\bigskipamount=2\baselineskip +\raggedbottom % do not try to align the page bottom + +% By default itemize is done with bullets, which don't look good. + +\def\labelitemi{-} +\def\labelitemii{-} +\def\labelitemiii{-} +\def\labelitemiv{-} + +% Fix up table of contents. Default latex uses fractional spacing between +% the section number and title. This comes out as no space in the doc file +% so we add a space to numberline, and expand tempdima by one em to allow +% for it. Also, go out of math mode for the dot in the leader. Dots in +% math mode turn out to be colons! +% +\def\@dottedtocline#1#2#3#4#5{\ifnum #1>\c@tocdepth \else + \vskip \z@ plus .2pt + {\hangindent #2\relax \rightskip \@tocrmarg \parfillskip -\rightskip + \parindent #2\relax\@afterindenttrue + \interlinepenalty\@M + \leavevmode + \@tempdima #3\relax + \addtolength\@tempdima{1em} + #4\nobreak\leaders\hbox to 2em{\hss.\hss}\hfill \nobreak \hbox to\@pnumwidth{\hfil\rm #5}\par}\fi} +\def\numberline#1{\advance\hangindent\@tempdima \hbox to\@tempdima{#1\hfil}\ } +% +% Can't really do superscripts, so do footnotes with [] +% +\def\@makefnmark{\hbox{(\@thefnmark)}} +\long\def\@makefntext#1{\parindent 1em\noindent + \hbox to 3em{\hss\@thefnmark.}\ #1} +\skip\footins 24pt plus 4pt minus 2pt +\def\footnoterule{\kern-12\p@ +\hbox to .4\columnwidth{\leaders\hbox{-}\hfill}} +% +% \arrayrulewidth 1em \doublerulesep 1em +% +% Some fairly obvious hacks. No odd/even pages in doc files. Can't do the +% fancy TeX symbols. +% +\oddsidemargin 0pt \evensidemargin 0pt +\def\TeX{TeX} +\def\LaTeX{LaTeX} +\def\SliTeX{SliTeX} +\def\BibTeX{BibTeX} +% +% special versions of stuff from xxx10.sty, since only one font size +% +\def\@normalsize{\@setsize\normalsize{12pt}\xpt\@xpt +\abovedisplayskip 12pt +\belowdisplayskip 12pt +\abovedisplayshortskip 12pt +\belowdisplayshortskip 12pt +\let\@listi\@listI} % Setting of \@listi added 9 Jun 87 +\let\small\@normalsize +\let\footnotesize\@normalsize +\normalsize +\footnotesep 12pt +\labelsep 10pt +\def\@listI{\leftmargin\leftmargini \parsep 12pt% +\topsep 12pt% +\partopsep 0pt% +\itemsep 0pt} +\let\@listi\@listI +\let\@listii\@listI +\let\@listiii\@listI +\let\@listiv\@listI +\let\@listv\@listI +\let\@listvi\@listI +\@listI + +% We had sort of random numbers of blank lines around section numbers. +% Turns out they used various fractional spacing. Rather than depend +% upon the definition of startsection, just wrap something around it +% that normalizes the arguments to 12pt. Negative args have special +% meanings. +\let\@oldstartsec\@startsection +\def\@startsection#1#2#3#4#5#6{ + \@tempskipa #4\relax + \@tempskipb #5\relax + \ifdim \@tempskipa <\z@ \@tempskipa -12pt \else \@tempskipa 12pt \fi + \ifdim \@tempskipb >\z@ \@tempskipb 12pt \fi +\@oldstartsec{#1}{#2}{#3}{\@tempskipa}{\@tempskipb}{#6} +} + +% To get even spacing in the table of contents + +\def\@pnumwidth{3em} + +\def\l@part#1#2{\addpenalty{-\@highpenalty}% + \addvspace{12pt}% space above part line + \begingroup + \@tempdima 3em + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + {\large \bf + \leavevmode + #1\hfil \hbox to\@pnumwidth{\hss #2}}\par + \nobreak + \global\@nobreaktrue + \everypar{\global\@nobreakfalse\everypar{}}%% suggested by + + \endgroup} + +\def\l@chapter#1#2{\addpenalty{-\@highpenalty}% + \vskip 12pt + \@tempdima 2em + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \bf + \leavevmode + \advance\leftskip\@tempdima + \hskip -\leftskip + #1\nobreak\hfil \nobreak\hbox to\@pnumwidth{\hss #2}\par + \penalty\@highpenalty + \endgroup} + +\def\l@section{\@dottedtocline{1}{2em}{3em}} +\def\l@subsection{\@dottedtocline{2}{4em}{3em}} +\def\l@subsubsection{\@dottedtocline{3}{7em}{4em}} +\def\l@paragraph{\@dottedtocline{4}{10em}{5em}} +\def\l@subparagraph{\@dottedtocline{5}{12em}{6em}} + diff --git a/manual/styles/scroll.sty b/manual/styles/scroll.sty new file mode 100644 index 0000000000..a344b03dce --- /dev/null +++ b/manual/styles/scroll.sty @@ -0,0 +1,5 @@ +% Modification to plaintext.sty to suppress page headings +% and make pages contiguous when processed with dvi2txt + +\pagestyle{empty} +\advance\voffset by -2\baselineskip diff --git a/manual/styles/syntaxdef.hva b/manual/styles/syntaxdef.hva new file mode 100644 index 0000000000..39dbff5fc1 --- /dev/null +++ b/manual/styles/syntaxdef.hva @@ -0,0 +1,157 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Hevea code for syntax definitions of the ocaml manual % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Important commands +% \token, for typesetting grammar terminals +% \nonterm, for typesetting grammar non-terminals +% +% Beware: \nonterm introduces either a local anchor or a local reference +% -Anchors are introduced when \nonterm occurs in the first column of +% syntax definitions (environment 'syntax') +% - References are introduced everywhere else +% +% For pure typesetting effect without links (eg. to typeset 'e' as 'expr') +% use the \nt command (eg. \nt{e}). +% In syntax definitions, the tool 'transf' translates @word@ into \nt{word}. +% +% Warnings are produced +% - For references to non-defined non terminals +% - For multiple definitions of the same non-terminal +% Warnings can be avoided for a given non-terminal 'expr' by issuing +% the command \stx@silent{'expr'} +% +%It is also possible to alias a nonterminal: +%\stx@alias{name}{othername} +%will make reference to 'name' point to the definition of non-terminal +%'othername' +\newif\ifspace +\def\addspace{\ifspace\;\spacefalse\fi} +\ifhtml +\newcommand{\token}[1]{\texttt{\blue#1}} +\else +\newcommand{\token}[1]{\texttt{#1}} +\fi +%%% warnings +\def\stx@warning#1#2{\@ifundefined{stx@#1@silent}{\hva@warn{#2}}{}} +\def\stx@silent#1{\def\csname stx@#1@silent\endcsname{}} +%%% Do not warn about those +%initial example +\stx@silent{like}\stx@silent{that}% +%Not defined +\stx@silent{regular-char}% +\stx@silent{regular-string-char}% +%\stx@silent{regular-char-str}% +\stx@silent{lowercase-ident}% +\stx@silent{capitalized-ident}% +\stx@silent{space}% +\stx@silent{tab}% +\stx@silent{newline}% +%Used in many places +\stx@silent{prefix}% +\stx@silent{name}% +\stx@silent{xname}% +%Not defined +\stx@silent{external-declaration}% +\stx@silent{unit-name}% +%%Redefined in exten.etex +\stx@silent{parameter}% +\stx@silent{pattern}% +\stx@silent{constr-decl}% +\stx@silent{type-param}% +\stx@silent{let-binding}% +\stx@silent{expr}% +\stx@silent{typexpr}% +\stx@silent{module-expr}% +\stx@silent{type-representation}% +\stx@silent{definition}% +\stx@silent{specification}% +\stx@silent{type-equation}% +\stx@silent{class-field}% +\stx@silent{mod-constraint}% +\stx@silent{module-type}% +\stx@silent{constant}% +%%Redefined in names.etex +\stx@silent{label-name}% +%%Not really defined in lexyacc.etex +\stx@silent{character-set}% +\stx@silent{symbol}% +%%Not defined in debugger.etex +\stx@silent{integer} +%%Not defined in ocamldoc.etex +\stx@silent{string} +\stx@silent{id} +\stx@silent{Exc} +\stx@silent{URL} +%%%%%%%%%%%%% +%% Aliases %% +%%%%%%%%%%%%% +\newcommand{\stx@alias}[2]{\def\csname stx@#1@alias\endcsname{#2}} +\stx@alias{typ}{typexpr}% +\stx@alias{met}{method-name}% +\stx@alias{tag}{tag-name}% +\stx@alias{lab}{label-name}% +\stx@alias{C}{constr-name} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%special anchor +\newstyle{a.syntax:link}{color:maroon;text-decoration:underline} +\newstyle{a.syntax:visited}{color:maroon;text-decoration:underline} +\newstyle{a.syntax:hover}{color:black;text-decoration:none;background-color:\#FF6060} +%compatibility for hevea-1.1?/heeva-2.?? +\ifu\@tr@url +\providecommand{\@tr@url}[1]{#1}\def\stx@id{NAME}\else +\def\stx@id{id}\fi +\newcommand{\@syntaxlocref}[2] +{\@aelement{href="\@print{#}\@tr@url{#1}" class="syntax"}{#2}} +\newcommand{\@syntaxaname}[2] +{\@aelement{\stx@id="#1" class="syntax"}{#2}} +%%Refer to anchor, internal : +%#1 -> anchor #2 -> visible tag +\def\@ref@anchor#1#2{% +\@ifundefined{stx@#1@exists} +{\stx@warning{#1}{Undefined non-terminal: '#1'}#2} +{\@syntaxlocref{#1}{#2}}} +%%Refer to anchor +\def\ref@anchor#1{% +\ifu\csname stx@#1@alias\endcsname +\@ref@anchor{#1}{#1}\else +\@ref@anchor{\csname stx@#1@alias\endcsname}{#1}\fi} +\def\stx@exists#1{\def\csname stx@#1@exists\endcsname{}} +%%Define anachor +\def\def@anchor#1{% +\@ifundefined{stx@#1} +{{\@nostyle\@auxdowrite{\string\stx@exists\{#1\}}}% +\gdef\csname stx@#1\endcsname{}\@syntaxaname{#1}{#1}} +{\@ifundefined{stx@#1@silent} +{\hva@warn{Redefinition of non-terminal '#1'}#1} +{\ref@anchor{#1}}}} +%%%Change \@anchor and initial definition, for html only, of course! +\ifhtml +\def\set@name{\let\@anchor\def@anchor} +\let\@anchor\ref@anchor +\else +\def\set@name{} +\def\@anchor{} +\fi +%%%Format non-terminal +\def\nt#1{\textit{\maroon#1}} +%%%Link for non-terminal and format +\def\nonterm#1{\addspace\nt{\@anchor{#1}}\spacetrue} +\def\brepet{\addspace\{} +\def\erepet{\}} +\def\boption{\addspace[} +\def\eoption{]} +\def\brepets{\addspace\{} +\def\erepets{\}^+} +\def\bparen{\addspace(} +\def\eparen{)} +\def\orelse{\mid \spacefalse} +\def\is{ & ::= & \spacefalse } +\def\alt{ \\ & \mid & \spacefalse } +\def\sep{ \\ \\ \spacefalse } +\def\cutline{} +\def\emptystring{\epsilon} +\def\syntax{$$\begin{array}{>{\set@name}rcl}\spacefalse} +\def\endsyntax{\end{array}$$} +\def\syntaxleft{$\begin{array}{>{\set@name}rcl}\spacefalse} +\def\endsyntaxleft{\end{array}$} +\def\synt#1{$\spacefalse#1$} diff --git a/manual/styles/syntaxdef.sty b/manual/styles/syntaxdef.sty new file mode 100644 index 0000000000..1db6f5bf61 --- /dev/null +++ b/manual/styles/syntaxdef.sty @@ -0,0 +1,26 @@ +\newif\ifspace +\def\addspace{\ifspace \; \spacefalse \fi} +\def\token#1{\addspace\hbox{\tt #1} \spacetrue} +\def\nonterm#1{\addspace\nt{#1} \spacetrue} +\def\nt#1{\hbox{\sl #1\/}} +\def\brepet{\addspace\{} +\def\erepet{\}} +\def\boption{\addspace[} +\def\eoption{]} +\def\brepets{\addspace\{} +\def\erepets{\}^+} +\def\bparen{\addspace(} +\def\eparen{)} +\def\orelse{\mid \spacefalse} +\def\is{ & ::= & \spacefalse } +\def\alt{ \\ & \mid & \spacefalse } +\def\cutline{ \\ & & \spacefalse } +\def\sep{ \\[2mm] \spacefalse } +\def\emptystring{\epsilon} +\def\syntax{$$\begin{array}{rrl}\spacefalse} +\def\endsyntax{\end{array}$$} +\def\syntaxleft{$\begin{array}{rrl}\spacefalse} +\def\endsyntaxleft{\end{array}$} +\let\oldldots=\ldots +\def\ldots{\spacefalse\oldldots} +\def\synt#1{$\spacefalse#1$} diff --git a/manual/styles/syntaxdeftxt.sty b/manual/styles/syntaxdeftxt.sty new file mode 100644 index 0000000000..370b6580d4 --- /dev/null +++ b/manual/styles/syntaxdeftxt.sty @@ -0,0 +1,22 @@ +\newif\ifspace +\def\addspace{\ifspace\ \spacefalse\fi} +\def\token#1{\addspace\hbox{\tt #1}\spacetrue\ignorespaces} +%%% \def\nonterm#1{\addspace\hbox{\tt <#1>}\spacetrue\ignorespaces} +\def\nonterm#1{\addspace\hbox{\it #1}\spacetrue\ignorespaces} +\def\brepet{\addspace\hbox to1em{$\{$\hfil}\ignorespaces} +\def\erepet{\hbox to1em{$\}$\hfil}\ignorespaces} +\def\boption{\addspace[\ignorespaces} +\def\eoption{]\ignorespaces} +\def\brepets{\brepet\ignorespaces} +\def\erepets{\erepet+\ignorespaces} +\def\bparen{\addspace(\ignorespaces} +\def\eparen{)\ignorespaces} +\def\orelse{~\hbox to1em{$|$\hfil}~\spacefalse\ignorespaces} +\def\is{& ::= & \spacefalse\ignorespaces} +\def\alt{\\ & \hbox to1em{$|$\hfil} & \spacefalse } +\def\sep{\\[\baselineskip] \spacefalse} +\def\emptystring{nothing} +\def\syntax{\begin{center}\begin{tabular}{rrl}\spacefalse\ignorespaces} +\def\endsyntax{\end{tabular}\end{center}} +\def\ldots{\spacefalse...\ignorespaces} +\def\synt#1{$\spacefalse#1$} diff --git a/manual/tools/.gitignore b/manual/tools/.gitignore new file mode 100644 index 0000000000..db7f8368b1 --- /dev/null +++ b/manual/tools/.gitignore @@ -0,0 +1,12 @@ +transf.ml +texquote2 +htmltransf.ml +transf +htmlgen +htmlquote +latexscan.ml +dvi2txt +caml-tex2 +*.dSYM +*.cm[io] +*.o diff --git a/manual/tools/.ignore b/manual/tools/.ignore new file mode 100644 index 0000000000..12c72e4a58 --- /dev/null +++ b/manual/tools/.ignore @@ -0,0 +1,11 @@ +transf.ml +texquote2 +htmltransf.ml +transf +htmlgen +htmlquote +latexscan.ml +dvi2txt +caml-tex2 +*.dSYM +*.cm[io] diff --git a/manual/tools/Makefile b/manual/tools/Makefile new file mode 100644 index 0000000000..a06a98670e --- /dev/null +++ b/manual/tools/Makefile @@ -0,0 +1,53 @@ +TOPDIR=../.. +COMPFLAGS=-I $(OTOPDIR)/otherlibs/str -I $(OTOPDIR)/otherlibs/unix +include $(TOPDIR)/Makefile.tools + +CFLAGS=-g -O + +all: texquote2 transf htmlquote htmlgen dvi2txt caml-tex2 + +dvi2txt: + cd dvi_to_txt; ${MAKE} + +transf: transf.cmo htmltransf.cmo transfmain.cmo + $(OCAMLC) -o transf -g transf.cmo htmltransf.cmo transfmain.cmo + +transf.ml: transf.mll + $(OCAMLLEX) transf.mll + +htmltransf.ml: htmltransf.mll + $(OCAMLLEX) htmltransf.mll + +htmlgen: latexmacros.cmo latexscan.cmo latexmain.cmo + $(OCAMLC) -o htmlgen -g latexmacros.cmo latexscan.cmo latexmain.cmo + +latexscan.ml: latexscan.mll + ocamllex latexscan.mll + +caml-tex2: caml_tex2.cmo + $(OCAMLC) -o caml-tex2 str.cma unix.cma caml_tex2.cmo + +.SUFFIXES: +.SUFFIXES: .ml .cmo .mli .cmi .c + +.ml.cmo: + $(OCAMLC) -c $< + +.mli.cmi: + $(OCAMLC) -c $< + +.c: + $(CC) $(CFLAGS) -o $@ $< + +clean: + rm -f transf.ml latexscan.ml htmltransf.ml + rm -f texquote2 transf htmlquote htmlgen dvi2txt + rm -f transf.ml latex.ml + rm -f *.o *.cm? *.cmxa + rm -f *~ #*# + cd dvi_to_txt; ${MAKE} clean + +latexmacros.cmo: latexmacros.cmi +latexmain.cmo: latexscan.cmo +latexscan.cmo: latexmacros.cmi +transfmain.cmo: transf.cmo htmltransf.cmo diff --git a/manual/tools/caml-tex b/manual/tools/caml-tex new file mode 100755 index 0000000000..7eea11b563 --- /dev/null +++ b/manual/tools/caml-tex @@ -0,0 +1,131 @@ +#!/usr/bin/perl + +$camllight = "TERM=dumb ocaml"; +$camlbegin = "\\caml\n"; +$camlend = "\\endcaml\n"; +$camlin = "\\?"; +$camlout = "\\:"; +$camlblank = "\\;\n"; + +$linelen = 72; +$output = ""; +$cut_at_blanks = 0; + +while ($#ARGV >= 0) { + $_ = $ARGV[0]; + last unless (/^-/); + $linelen = $ARGV[1], shift, shift, next if (/^-n$/); + $output = $ARGV[1], shift, shift, next if (/^-o$/); + $camllight = $ARGV[1], shift, shift, next if (/^-caml$/); + $cut_at_blanks = 1, shift, next if (/^-w$/); + printf STDERR ("Unknown option '%s', ignored\n", $_); + shift; +} + +# First pass: extract the Caml phrases to evaluate + +open(ML, "> .input.ml") || die("Cannot create .input.ml : $!"); + +foreach $infile (@ARGV) { + open(IN, $infile) || die("Cannot open $infile : $!"); + while() { + if (m/^\\begin{caml_(example|example\*|eval)}\s*$/) { + while() { + last if m/^\\end{caml_(example|example\*|eval)}\s*$/; + print ML $_; + } + } + } + close(IN); +} + +close(ML); + +# Feed the phrases to a Caml toplevel + +open(TOPLEVEL, "$camllight 2>&1 < .input.ml |") || + die("Cannot start camllight : $!"); + +; ; # skip the banner +$lastread = ; +$lastread =~ s/^# //; + +# Second pass: shuffle the TeX source and the output of the toplevel + +if ($output) { + if ($output eq "-") { + open(OUT, ">&STDOUT"); + } else { + open(OUT, ">$output") || die("Cannot create $output: $!"); + } +} + +foreach $infile (@ARGV) { + open(IN, $infile) || die("Cannot open $infile: $!"); + if (! $output) { + $outfile = $infile; + $outfile =~ s/\.tex$//; + open(OUT, "> $outfile.ml.tex") || die("Cannot create $outfile.ml.tex: $!"); + } + while() { + if (m/^\\begin{caml_example(\*?)}\s*$/) { + $omit_answer = $1; # true if caml_example*, false if caml_example + print OUT $camlbegin; + $severalphrases = 0; + while() { + last if m/\\end{caml_example\*?}\s*$/; + print OUT $camlblank if ($severalphrases); + while(1) { + s/\\/\\\\/g; + print OUT $camlin, $_; + last if m/;; *$/; + $_ = ; + } + while ($lastread =~ s/^ //) { } + while($lastread) { + last if $lastread =~ s/^# //; + print STDERR $lastread; + if (! $omit_answer) { + while (length($lastread) > $linelen) { + if ($cut_at_blanks) { + $cutpos = rindex($lastread, ' ', $linelen); + if ($cutpos == -1) { $cutpos = $linelen; } else { $cutpos++; } + } else { + $cutpos = $linelen; + } + $line = substr($lastread, 0, $cutpos); + $line =~ s/\\/\\\\/g; + print OUT $camlout, $line, "\n"; + $lastread = substr($lastread, $cutpos, + length($lastread) - $cutpos); + } + $lastread =~ s/\\/\\\\/g; + print OUT $camlout, $lastread; + } + $lastread = ; + } + $severalphrases = 1; + } + print OUT $camlend; + } + elsif (m/^\\begin{caml_eval}\s*$/) { + while() { + last if m/^\\end{caml_eval}\s*$/; + if (m/;; *$/) { + while ($lastread =~ s/^ //) { } + while($lastread) { + last if $lastread =~ s/^#//; + print STDERR $lastread; + $lastread = ; + } + } + } + } + else { + print OUT $_; + } + } + close(IN); +} + +close(TOPLEVEL); diff --git a/manual/tools/caml_tex2.ml b/manual/tools/caml_tex2.ml new file mode 100644 index 0000000000..d2f6ceaea9 --- /dev/null +++ b/manual/tools/caml_tex2.ml @@ -0,0 +1,165 @@ +(* $Id$ *) + +open StdLabels +open Printf +open Str + +let camlbegin = "\\caml\n" +let camlend = "\\endcaml\n" +let camlin = "\\\\?\\1" +let camlout = "\\\\:\\1" +let camlbunderline = "\\<" +let camleunderline = "\\>" + +let camllight = ref "TERM=norepeat ocaml" +let linelen = ref 72 +let outfile = ref "" +let cut_at_blanks = ref false +let files = ref [] + +let _ = + Arg.parse ["-n", Arg.Int (fun n -> linelen := n), "line length"; + "-o", Arg.String (fun s -> outfile := s), "output"; + "-caml", Arg.String (fun s -> camllight := s), "toplevel"; + "-w", Arg.Set cut_at_blanks, "cut at blanks"] + (fun s -> files := s :: !files) + "caml-tex2: " + +let (~!) = + let memo = ref [] in + fun key -> + try List.assq key !memo + with Not_found -> + let data = Str.regexp key in + memo := (key, data) :: !memo; + data + +let caml_input, caml_output = + let cmd = !camllight ^ " 2>&1" in + try Unix.open_process cmd with _ -> failwith "Cannot start toplevel" +let () = + at_exit (fun () -> ignore (Unix.close_process (caml_input, caml_output))); + ignore (input_line caml_input); + ignore (input_line caml_input) + +let read_output () = + let input = ref (input_line caml_input) in + input := replace_first ~!"^# *" "" !input; + let underline = + if string_match ~!"Characters *\\([0-9]+\\)-\\([0-9]+\\):$" !input 0 + then + let b = int_of_string (matched_group 1 !input) + and e = int_of_string (matched_group 2 !input) in + input := input_line caml_input; + b, e + else 0, 0 + in + let output = Buffer.create 256 in + while not (string_match ~!".*\"end_of_input\"$" !input 0) do + prerr_endline !input; + Buffer.add_string output !input; + Buffer.add_char output '\n'; + input := input_line caml_input; + done; + Buffer.contents output, underline + +let escape_specials s = + let s1 = global_replace ~!"\\\\" "\\\\\\\\" s in + let s2 = global_replace ~!"'" "\\\\textquotesingle\\\\-" s1 in + let s3 = global_replace ~!"`" "\\\\textasciigrave\\\\-" s2 in + s3 + +let process_file file = + prerr_endline ("Processing " ^ file); + let ic = try open_in file with _ -> failwith "Cannot read input file" in + let oc = + try if !outfile = "-" then + stdout + else if !outfile = "" then + open_out (replace_first ~!"\\.tex$" "" file ^ ".ml.tex") + else + open_out_gen [Open_wronly; Open_creat; Open_append; Open_text] + 0x666 !outfile + with _ -> failwith "Cannot open output file" in + try while true do + let input = ref (input_line ic) in + if string_match ~!"\\\\begin{caml_example\\(\\*?\\)}[ \t]*$" + !input 0 + then begin + let omit_answer = matched_group 1 !input = "*" in + output_string oc camlbegin; + let first = ref true in + let read_phrase () = + let phrase = Buffer.create 256 in + while + let input = input_line ic in + if string_match ~!"\\\\end{caml_example\\*?}[ \t]*$" + input 0 + then raise End_of_file; + if Buffer.length phrase > 0 then Buffer.add_char phrase '\n'; + Buffer.add_string phrase input; + not (string_match ~!".*;;[ \t]*$" input 0) + do + () + done; + Buffer.contents phrase + in + try while true do + let phrase = read_phrase () in + fprintf caml_output "%s\n" phrase; + flush caml_output; + output_string caml_output "\"end_of_input\";;\n"; + flush caml_output; + let output, (b, e) = read_output () in + let phrase = + if b < e then begin + let start = String.sub phrase ~pos:0 ~len:b + and underlined = String.sub phrase ~pos:b ~len:(e-b) + and rest = + String.sub phrase ~pos:e ~len:(String.length phrase - e) + in + String.concat "" + [escape_specials start; "\\<"; + escape_specials underlined; "\\>"; + escape_specials rest] + end else + escape_specials phrase in + (* Special characters may also appear in output strings -Didier *) + let output = escape_specials output in + let phrase = global_replace ~!"^\\(.\\)" camlin phrase + and output = global_replace ~!"^\\(.\\)" camlout output in + if not !first then output_string oc "\\;\n"; + fprintf oc "%s\n" phrase; + if not omit_answer then fprintf oc "%s" output; + flush oc; + first := false + done + with End_of_file -> output_string oc camlend + end + else if string_match ~!"\\\\begin{caml_eval}[ \t]*$" !input 0 + then begin + while input := input_line ic; + not (string_match ~!"\\\\end{caml_eval}[ \t]*$" !input 0) + do + fprintf caml_output "%s\n" !input; + if string_match ~!".*;;[ \t]*$" !input 0 then begin + flush caml_output; + output_string caml_output "\"end_of_input\";;\n"; + flush caml_output; + ignore (read_output ()) + end + done + end else begin + fprintf oc "%s\n" !input; + flush oc + end + done with + End_of_file -> close_in ic; close_out oc + +let _ = + if !outfile <> "-" && !outfile <> "" then begin + try close_out (open_out !outfile) + with _ -> failwith "Cannot open output file" + end; + List.iter process_file (List.rev !files) + diff --git a/manual/tools/dvi_to_txt/Makefile b/manual/tools/dvi_to_txt/Makefile new file mode 100644 index 0000000000..852996a991 --- /dev/null +++ b/manual/tools/dvi_to_txt/Makefile @@ -0,0 +1,8 @@ +OBJS=io.o interp.o output.o main.o print.o print_rtf.o print_styl.o +CFLAGS=-g + +../dvi2txt: $(OBJS) + $(CC) $(CFLAGS) -o ../dvi2txt $(OBJS) + +clean: + rm -f ../dvi2txt *.o *~ #*# diff --git a/manual/tools/dvi_to_txt/dvi.h b/manual/tools/dvi_to_txt/dvi.h new file mode 100644 index 0000000000..8dfb25dcbe --- /dev/null +++ b/manual/tools/dvi_to_txt/dvi.h @@ -0,0 +1,8 @@ +enum { + SET_CHAR_0=0, SET_CHAR_127=127, SET1=128, SET2, SET3, SET4, SET_RULE, + PUT1, PUT2, PUT3, PUT4, PUT_RULE, NOP, BOP, EOP, PUSH, POP, RIGHT1, + RIGHT2, RIGHT3, RIGHT4, W0, W1, W2, W3, W4, X0, X1, X2, X3, X4, DOWN1, + DOWN2, DOWN3, DOWN4, Y0, Y1, Y2, Y3, Y4, Z0, Z1, Z2, Z3, Z4, + FNT_NUM_0=171, FNT_NUM_63=234, FNT1=235, FNT2, FNT3, FNT4, XXX1, XXX2, + XXX3, XXX4, FNT_DEF1, FNT_DEF2, FNT_DEF3, FNT_DEF4, PRE, POST, POST_POST +}; diff --git a/manual/tools/dvi_to_txt/interp.c b/manual/tools/dvi_to_txt/interp.c new file mode 100644 index 0000000000..e50aed36c0 --- /dev/null +++ b/manual/tools/dvi_to_txt/interp.c @@ -0,0 +1,305 @@ +#include +#include +#include +#include +#include "io.h" +#include "dvi.h" +#include "output.h" + +#define SEEK_CUR 1 + +int h, v, w, x, y, z, sp; +int currfont; +int encoding; +int style; + +#define FONT_NAME_SIZE 31 +#define NUM_FONTS 256 + +struct { + char name[FONT_NAME_SIZE+1]; + int encoding; + int style; +} font[NUM_FONTS]; + +#define TYPEWRITER 0 +#define ROMAN 1 +#define MATH_ITALIC 2 +#define MATH_SYMBOL 3 +#define MATH_EXTENSION 4 +#define LINE_SEGMENTS 5 +#define CIRCLE_SEGMENTS 6 +#define LATEX_SYMBOLS 7 + +char * transcode[] = { +/* 0.......+.......1.......+.......2.......+.......3.......+.......4.......+.......5.......+.......6.......+.......7.......+....... */ +/* TYPEWRITER */ + "GDTLXPSUPYO##################### !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~#", +/* ROMAN */ + "GDTLXPSUPYO***** 0'!\"#$%&'()*+,-./0123456789:;!=??@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\"]^.`abcdefghijklmnopqrstuvwxyz--\"~#", +/* MATH_ITALIC */ + "GDTLXPSUPYOabgdezhtiklmnxpystupxyoeuorsp----`'><0123456789.,*dABCDEFGHIJKLMNOPQRSTUVWXYZ#####labcdefghijklmnopqrstuvwxyzij###", +/* MATH_SYMBOL */ + "-.x*/###+-x/.ooo==##<><>==##<><><>||####<>||####'#####/|###0RIT##ABCDEFGHIJKLMNOPQRSTUVWXYZ###########{}<>||||\\|################", +/* MATH_EXTENSION */ + "()[]||||{}<>||##()[]||||{}<>||##()[]||||{}<>||##########################################################[]||||{}################", +/* LINE_SEGMENTS */ + "/||||| _ / / _/ // _ / / __// / _ / \\||||| \\ \\ \\ _\\ \\\\ _ \\ \\ __\\\\ \\ _ \\ ", +/* CIRCLE_SEGMENTS */ + " ", +/* LATEX_SYMBOLS */ + " <<>> U#O0 ~~[] " +}; + +#define STACK_SIZE 100 + +struct { int sh, sv, sw, sx, sy, sz; } stack[STACK_SIZE]; + +struct known_font_struct { + char * prefix; + int encoding, style; +} known_fonts[] = { + "docrm", ROMAN, PLAIN, + "doctt", TYPEWRITER, MONOSPACED, + "docit", ROMAN, ITALICS, + "docbf", ROMAN, BOLD, + "docmi", MATH_ITALIC, PLAIN, + "cmsy", MATH_SYMBOL, PLAIN, + "cmex", MATH_EXTENSION, PLAIN, + "line", LINE_SEGMENTS, PLAIN, + "lcircle", CIRCLE_SEGMENTS, PLAIN, + "lasy", LATEX_SYMBOLS, PLAIN +}; + +void fontdef(input, fontnum) + FILE * input; + int fontnum; +{ + int a, l, i; + + assert(fontnum >= 0 && fontnum < NUM_FONTS); + fseek(input, 12, SEEK_CUR); /* skip c, s and d parameters */ + a = get8u(input); + l = get8u(input); + assert(l < FONT_NAME_SIZE); + fseek(input, a, SEEK_CUR); /* skip the "area" part */ + fread(font[fontnum].name, 1, l, input); /* read the font name */ + font[fontnum].name[l] = 0; + for (i = 0; + i < sizeof(known_fonts) / sizeof(struct known_font_struct); + i++) { + if (strncmp(font[fontnum].name, known_fonts[i].prefix, + strlen(known_fonts[i].prefix)) == 0) { + font[fontnum].encoding = known_fonts[i].encoding; + font[fontnum].style = known_fonts[i].style; + return; + } + } + fprintf(stderr, "Warning: unknown font `%s'\n", font[fontnum].name); + font[fontnum].encoding = ROMAN; + font[fontnum].style = PLAIN; +} + +void setfont(fontnum) + int fontnum; +{ + currfont = fontnum; + encoding = font[fontnum].encoding; + style = font[fontnum].style; +} + +int outchar(c) + int c; +{ + if (c < 0 || c > 127) + out(h, v, '#', PLAIN); + else + out(h, v, transcode[encoding][c], style); + return scalex; +} + +void outrule(height, width) + int height, width; +{ + char c; + int dx, dy; + + if (height <= 0 || width <= 0) return; + c = height >= width ? '|' : '-'; + dy = 0; + do { + dx = 0; + do { + out(h + dx, v - dy, c, PLAIN); + dx += scalex; + } while (dx <= width); + dy += scaley; + } while (dy < height); +} + +void interprete(input) + FILE * input; +{ + int c, n, height, width, mag; + + sp = 0; + c = get8u(input); + n = get8u(input); + if (c != PRE || n != 2) { + fprintf(stderr, "File does not start with DVI preamble.\n"); + exit(2); + } + (void) get32s(input); + (void) get32s(input); + mag = get32s(input); + scalex = SCALEX * mag / 1000; + scaley = SCALEY * mag / 1000; + n = get8u(input); + fseek(input, n, SEEK_CUR); /* skip comment */ + + begin_document(); + + while (1) { + c = get8u(input); + if (c >= SET_CHAR_0 && c <= SET_CHAR_127) + h += outchar(c); + else if (c >= FNT_NUM_0 && c <= FNT_NUM_63) + setfont(c - FNT_NUM_0); + else switch(c) { + case SET1: + h += outchar(get8u(input)); break; + case SET2: + h += outchar(get16u(input)); break; + case SET3: + h += outchar(get24u(input)); break; + case SET4: + h += outchar(get32s(input)); break; + case SET_RULE: + height = get32s(input); + width = get32s(input); + outrule(height, width); + h += width; + break; + case PUT1: + (void) outchar(get8u(input)); break; + case PUT2: + (void) outchar(get16u(input)); break; + case PUT3: + (void) outchar(get24u(input)); break; + case PUT4: + (void) outchar(get32s(input)); break; + case PUT_RULE: + height = get32s(input); + width = get32s(input); + outrule(height, width); + break; + case NOP: + break; + case BOP: + clear_page(); + h = v = w = x = y = z = 0; + sp = 0; + fseek(input, 44, SEEK_CUR); /* skip c0...c9 and ptr to previous page */ + break; + case EOP: + output_page(); + break; + case PUSH: + assert(sp < STACK_SIZE); + stack[sp].sh = h; stack[sp].sv = v; stack[sp].sw = w; + stack[sp].sx = x; stack[sp].sy = y; stack[sp].sz = z; + sp++; + break; + case POP: + assert(sp > 0); + sp--; + h = stack[sp].sh; v = stack[sp].sv; w = stack[sp].sw; + x = stack[sp].sx; y = stack[sp].sy; z = stack[sp].sz; + break; + case RIGHT1: + h += get8s(input); break; + case RIGHT2: + h += get16s(input); break; + case RIGHT3: + h += get24s(input); break; + case RIGHT4: + h += get32s(input); break; + case W0: + h += w; break; + case W1: + w = get8s(input); h += w; break; + case W2: + w = get16s(input); h += w; break; + case W3: + w = get24s(input); h += w; break; + case W4: + w = get32s(input); h += w; break; + case X0: + h += x; break; + case X1: + x = get8s(input); h += x; break; + case X2: + x = get16s(input); h += x; break; + case X3: + x = get24s(input); h += x; break; + case X4: + x = get32s(input); h += x; break; + case DOWN1: + v += get8s(input); break; + case DOWN2: + v += get16s(input); break; + case DOWN3: + v += get24s(input); break; + case DOWN4: + v += get32s(input); break; + case Y0: + v += y; break; + case Y1: + y = get8s(input); v += y; break; + case Y2: + y = get16s(input); v += y; break; + case Y3: + y = get24s(input); v += y; break; + case Y4: + y = get32s(input); v += y; break; + case Z0: + v += z; break; + case Z1: + z = get8s(input); v += z; break; + case Z2: + z = get16s(input); v += z; break; + case Z3: + z = get24s(input); v += z; break; + case Z4: + z = get32s(input); v += z; break; + case FNT1: + setfont(get8u(input)); break; + case FNT2: + setfont(get16u(input)); break; + case FNT3: + setfont(get24u(input)); break; + case FNT4: + setfont(get32s(input)); break; + case XXX1: + n = get8u(input); fseek(input, n, SEEK_CUR); break; + case XXX2: + n = get16u(input); fseek(input, n, SEEK_CUR); break; + case XXX3: + n = get24u(input); fseek(input, n, SEEK_CUR); break; + case XXX4: + n = get32s(input); fseek(input, n, SEEK_CUR); break; + case FNT_DEF1: + fontdef(input, get8u(input)); break; + case FNT_DEF2: + fontdef(input, get16u(input)); break; + case FNT_DEF3: + fontdef(input, get24u(input)); break; + case FNT_DEF4: + fontdef(input, get32s(input)); break; + case POST: + end_document(); return; + default: + assert(0); + } + } +} diff --git a/manual/tools/dvi_to_txt/io.c b/manual/tools/dvi_to_txt/io.c new file mode 100644 index 0000000000..5dfe1ccc55 --- /dev/null +++ b/manual/tools/dvi_to_txt/io.c @@ -0,0 +1,43 @@ +#include +#include "io.h" + +int get16u(input) + FILE * input; +{ + int b1 = getc(input); + int b2 = getc(input); + return (b1 << 8) + b2; +} +int get16s(input) + FILE * input; +{ + int b1 = (schar) getc(input); + int b2 = getc(input); + return (b1 << 8) + b2; +} +int get24u(input) + FILE * input; +{ + int b1 = getc(input); + int b2 = getc(input); + int b3 = getc(input); + return (b1 << 16) + (b2 << 8) + b3; +} +int get24s(input) + FILE * input; +{ + int b1 = (schar) getc(input); + int b2 = getc(input); + int b3 = getc(input); + return (b1 << 16) + (b2 << 8) + b3; +} +int get32s(input) + FILE * input; +{ + int b1 = (schar) getc(input); + int b2 = getc(input); + int b3 = getc(input); + int b4 = getc(input); + return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4; +} + diff --git a/manual/tools/dvi_to_txt/io.h b/manual/tools/dvi_to_txt/io.h new file mode 100644 index 0000000000..f9a800d40c --- /dev/null +++ b/manual/tools/dvi_to_txt/io.h @@ -0,0 +1,10 @@ +#ifdef __STDC__ +typedef signed char schar; +#else +typedef char schar; +#endif + +#define get8u(input) getc(input) +#define get8s(input) (schar) getc(input) + +int get16u(), get16s(), get24u(), get24s(), get32u(), get32s(); diff --git a/manual/tools/dvi_to_txt/main.c b/manual/tools/dvi_to_txt/main.c new file mode 100644 index 0000000000..0fb03c4341 --- /dev/null +++ b/manual/tools/dvi_to_txt/main.c @@ -0,0 +1,47 @@ +#include +#include "output.h" + +void interprete(FILE *input); + +char * input_name; + +int main(argc, argv) + int argc; + char ** argv; +{ + FILE * f; + int i; + + output_device = OUTPUT_PLAIN; + standout_tt = 0; + for (i = 1; i < argc && argv[i][0] == '-'; i++) { + switch(argv[i][1]) { + case 'p': + output_device = OUTPUT_PRINTER; break; + case 'r': + output_device = OUTPUT_RTF; break; + case 's': + output_device = OUTPUT_STYL; break; + case 't': + standout_tt = 1; break; + default: + fprintf(stderr, "Unknown option `%s', ignored\n", argv[i]); + } + } + if (i >= argc) { + input_name = "unknown.dvi"; + interprete(stdin); + } else { + for (/*nothing*/; i < argc; i++) { + f = fopen(argv[i], "r"); + if (f == NULL) { + perror(argv[i]); + continue; + } + input_name = argv[i]; + interprete(f); + fclose(f); + } + } + return 0; +} diff --git a/manual/tools/dvi_to_txt/output.c b/manual/tools/dvi_to_txt/output.c new file mode 100644 index 0000000000..fc79ed8066 --- /dev/null +++ b/manual/tools/dvi_to_txt/output.c @@ -0,0 +1,209 @@ +#include +#include +#include +#include "output.h" + +void null(), print_FF(), plain_line(), printer_line(); +void begin_rtf_document(), end_rtf_document(), end_rtf_page(), rtf_line(); +void begin_styl_page(), end_styl_page(), styl_line(); + +struct output_device { + void (*begin_document)(); + void (*end_document)(); + void (*begin_page)(); + void (*end_page)(); + void (*line)(); +} device[] = { + null, null, null, print_FF, plain_line, + null, null, null, print_FF, printer_line, + begin_rtf_document, end_rtf_document, null, end_rtf_page, rtf_line, + null, null, begin_styl_page, end_styl_page, styl_line +}; + +#define SIZEX 160 + +struct line { + int ypos; + int len; + char * contents; + char * styles; + struct line * next_in_bucket; +}; + +#define NBUCKETS 101 + +struct line * screenlines[NBUCKETS]; + +int numlines; + +char * xmalloc(size) + int size; +{ + char * res = (char *) malloc(size); + if (res == NULL) { + fprintf(stderr, "Out of memory\n"); + exit(2); + } + return res; +} + +char * xrealloc(ptr, size) + char * ptr; + int size; +{ + char * res = (char *) realloc(ptr, size); + if (res == NULL) { + fprintf(stderr, "Out of memory\n"); + exit(2); + } + return res; +} + +void begin_document() +{ + device[output_device].begin_document(); +} + +void end_document() +{ + device[output_device].end_document(); +} + +void clear_page() +{ + int i; + + for (i = 0; i < NBUCKETS; i++) screenlines[i] = NULL; + numlines = 0; +} + +void out(x, y, c, style) + int x, y; + char c; + char style; +{ + unsigned int h; + struct line * line; + + h = ((unsigned int) y) % NBUCKETS; + line = screenlines[h]; + while (line != NULL && line->ypos != y) line = line->next_in_bucket; + if (line == NULL) { + line = (struct line *) xmalloc(sizeof(struct line)); + line->ypos = y; + line->len = 80; + line->contents = (char *) xmalloc(line->len); + memset(line->contents, ' ', line->len); + line->styles = (char *) xmalloc(line->len); + memset(line->styles, PLAIN, line->len); + line->next_in_bucket = screenlines[h]; + screenlines[h] = line; + numlines++; + } + x = x / scalex; + if (x < 0) return; + while (x >= line->len) { + int newlen = 2 * line->len; + line->contents = (char *) xrealloc(line->contents, newlen); + memset(line->contents + line->len, ' ', newlen - line->len); + line->styles = (char *) xrealloc(line->styles, newlen); + memset(line->styles + line->len, PLAIN, newlen - line->len); + line->len = newlen; + } + line->contents[x] = c; + line->styles[x] = style; +} + +static void free_bucket(l) + struct line * l; +{ + if (l != NULL) { + free(l->contents); + free(l->styles); + free_bucket(l->next_in_bucket); + free(l); + } +} + +static void free_buckets() +{ + int i; + for (i = 0; i < NBUCKETS; i++) free_bucket(screenlines[i]); +} + +static int compare_lines(l1, l2) + struct line ** l1, ** l2; +{ + return (**l1).ypos - (**l2).ypos; +} + +void output_page() +{ + struct line ** lines; + struct line * l; + int i, j, k, y; + char * p, * q, * style_p, * style_q, * s; + + device[output_device].begin_page(); + + /* First, sort the lines by y coordinate */ + lines = (struct line **) malloc(numlines * sizeof(struct line *)); + if (lines == NULL) { + printf("*** Out of memory ***\n\014"); + free_buckets(); + return; + } + j = 0; + for (i = 0; i < NBUCKETS; i++) + for (l = screenlines[i]; l != NULL; l = l->next_in_bucket) + lines[j++] = l; + qsort(lines, numlines, sizeof(struct line *), compare_lines); + + /* Output the lines */ + + y = 0; + for (i = 0; i < numlines; i++) { + /* Emit blank lines to reach the current line ypos */ + while (lines[i]->ypos - y >= 3 * scaley / 2) { + device[output_device].line(NULL, NULL, 0); + y += scaley; + } + /* If next line is close to current line, attempt to merge them */ + while (i + 1 < numlines && + lines[i+1]->ypos - lines[i]->ypos < scaley) { + p = lines[i]->contents; + q = lines[i+1]->contents; + style_p = lines[i]->styles; + style_q = lines[i+1]->styles; + for (j = lines[i]->len; j < lines[i+1]->len; j++) + if (q[j] != ' ') goto cannot_merge; + for (j = lines[i+1]->len; j < lines[i]->len; j++) + if (p[j] != ' ') goto cannot_merge; + k = lines[i]->len; + if (k > lines[i+1]->len) k = lines[i+1]->len; + for (j = 0; j < k; j++) + if (p[j] != ' ' && q[j] != ' ') goto cannot_merge; + /* Seems OK, do the merging */ + for (j = 0; j < k; j++) + if (p[j] != ' ') { + q[j] = p[j]; + style_q[j] = style_p[j]; + } + /* Now consider next line */ + i++; + } + cannot_merge: + /* Now print the current line */ + p = lines[i]->contents; + q = p + lines[i]->len; + while (q >= p && *--q == ' ') /*nothing*/; + device[output_device].line(p, lines[i]->styles, q-p+1); + /* Go on with next line */ + y = lines[i]->ypos; + } + + device[output_device].end_page(); + free(lines); + free_buckets(); +} + diff --git a/manual/tools/dvi_to_txt/output.h b/manual/tools/dvi_to_txt/output.h new file mode 100644 index 0000000000..43ce317b35 --- /dev/null +++ b/manual/tools/dvi_to_txt/output.h @@ -0,0 +1,24 @@ +#define SCALEX 404685 +#define SCALEY 786432 + +int scalex; +int scaley; + +#define PLAIN 0 +#define ITALICS 1 +#define BOLD 2 +#define MONOSPACED 3 + +void begin_document(); +void end_document(); +void clear_page(); +void output_page(); +void out(); + +int output_device; +int standout_tt; + +#define OUTPUT_PLAIN 0 +#define OUTPUT_PRINTER 1 +#define OUTPUT_RTF 2 +#define OUTPUT_STYL 3 diff --git a/manual/tools/dvi_to_txt/print.c b/manual/tools/dvi_to_txt/print.c new file mode 100644 index 0000000000..d0f02cc349 --- /dev/null +++ b/manual/tools/dvi_to_txt/print.c @@ -0,0 +1,41 @@ +#include +#include "output.h" + +/* Low-level output functions */ + +void null() +{ +} + +void print_FF() +{ + putchar('\014'); +} + +void plain_line(txt, style, len) + char * txt, * style; + int len; +{ + fwrite(txt, 1, len, stdout); + putchar('\n'); +} + +void printer_line(txt, style, len) + char * txt, * style; + int len; +{ + for (/*nothing*/; len > 0; len--, txt++, style++) { + putchar(*txt); + switch(*style) { + case ITALICS: + putchar('\b'); putchar('_'); break; + case BOLD: + putchar('\b'); putchar(*txt); break; + case MONOSPACED: + if (standout_tt) { putchar('\b'); putchar(*txt); } + break; + } + } + putchar('\n'); +} + diff --git a/manual/tools/dvi_to_txt/print_rtf.c b/manual/tools/dvi_to_txt/print_rtf.c new file mode 100644 index 0000000000..c12c67a321 --- /dev/null +++ b/manual/tools/dvi_to_txt/print_rtf.c @@ -0,0 +1,80 @@ +#include +#include "output.h" + +/* Rich Text Format */ + +void begin_rtf_document() +{ + printf("{\\rtf1\\ansi\\deff0\n"); + printf("{\\fonttbl{\\f0\\fmodern Courier;}}\n"); + printf("\\f0\\fs20\n"); +} + +void end_rtf_document() +{ + printf("}\n"); +} + +void end_rtf_page() +{ + printf("\\page\n"); +} + +void rtf_line(txt, style, len) + char * txt, * style; + int len; +{ + int currstyle; + + for (currstyle = PLAIN; len > 0; len--, txt++, style++) { + if (*txt != ' ') { + switch(*style) { + case PLAIN: + if (currstyle != PLAIN) { + putchar('}'); + currstyle = PLAIN; + } + break; + case ITALICS: + if (currstyle != ITALICS) { + if (currstyle != PLAIN) putchar('}'); + printf("{\\i "); + currstyle = ITALICS; + } + break; + case BOLD: + if (currstyle != BOLD) { + if (currstyle != PLAIN) putchar('}'); + printf("{\\b "); + currstyle = BOLD; + } + break; + case MONOSPACED: + if (standout_tt) { + if (currstyle != BOLD) { + if (currstyle != PLAIN) putchar('}'); + printf("{\\b "); + currstyle = BOLD; + } + } else { + if (currstyle != PLAIN) { + putchar('}'); + currstyle = PLAIN; + } + } + break; + } + } + switch(*txt) { + case '\\': + case '{': + case '}': + putchar('\\'); putchar(*txt); break; + default: + putchar(*txt); break; + } + } + if (currstyle != PLAIN) putchar('}'); + printf("\\par\n"); +} + diff --git a/manual/tools/dvi_to_txt/print_styl.c b/manual/tools/dvi_to_txt/print_styl.c new file mode 100644 index 0000000000..39135f23b7 --- /dev/null +++ b/manual/tools/dvi_to_txt/print_styl.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include "output.h" + +/* Macintosh STYL tables */ + +extern char * input_name; + +static FILE * text; +static FILE * styl; +static int partnum = 0; +static int currstyle; +static int currstart; +static int currpos; + +static void output_current_style() +{ + int style_code; + + switch(currstyle) { + case PLAIN: + style_code = 0; break; + case ITALICS: + style_code = 2; break; + case BOLD: + style_code = 1 + 32; break; /* bold condensed */ + case MONOSPACED: + style_code = standout_tt ? 1 + 32 : 0; break; + } + fprintf(styl, "%d %d Monaco %d 9 0 0 0\n", currstart, currpos, style_code); +} + + +static void output_style_change(newstyle) + int newstyle; +{ + if (!standout_tt && (newstyle == PLAIN && currstyle == MONOSPACED || + newstyle == MONOSPACED && currstyle == PLAIN)) { + currstyle = newstyle; + return; + } + output_current_style(); + currstyle = newstyle; + currstart = currpos; +} + +void begin_styl_page() +{ + char name[1024], buffer[1024]; + int n; + + strcpy(name, input_name); + n = strlen(name); + if (n >= 4 && strcmp(name + n - 4, ".dvi") == 0) name[n - 4] = 0; + partnum++; + sprintf(buffer, "%s.%03d.txt", name, partnum); + text = fopen(buffer, "w"); + if (text == NULL) { perror(buffer); exit(2); } + sprintf(buffer, "%s.%03d.stl", name, partnum); + styl = fopen(buffer, "w"); + if (styl == NULL) { perror(buffer); exit(2); } + currstyle = PLAIN; + currstart = 0; + currpos = 0; +} + +void end_styl_page() +{ + output_current_style(); + fclose(text); + fclose(styl); +} + +void styl_line(txt, style, len) + char * txt, * style; + int len; +{ + for (/*nothing*/; len > 0; len--, txt++, style++, currpos++) { + putc(*txt, text); + if (*txt != ' ' && *style != currstyle) { + output_style_change(*style); + } + } + putc('\n', text); + currpos++; +} + + + diff --git a/manual/tools/fix_index.sh b/manual/tools/fix_index.sh new file mode 100755 index 0000000000..d2402b40c6 --- /dev/null +++ b/manual/tools/fix_index.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +# usage: fix_index.sh .idx + +# This script works around a hyperref bug: hyperref does not handle +# quotes in \index arguments properly. +# +# Symptom: +# When \index{-pipe-pipe@\verb`("|"|)`} appears in your .tex, the hyperref +# package mangles it and produces this line in your .idx: +# \indexentry{(-pipe-pipe)@\verb`("|hyperindexformat{\"}}{292} +# instead of the expected: +# \indexentry{(-pipe-pipe)@\verb`("|"|)`|hyperpage}{292} +# +# This is because it fails to handle quoted characters correctly. +# +# The workaround: +# Look for the buggy line in the given .idx file and change it. + +# Note: this bug will happen every time you have a | (pipe) character +# in an index entry (properly quoted with a " (double-quote) before it). +# We fix only the one case that appears in the OCaml documentation. +# We do not attempt a general solution because hyperref erases part +# of the argument, so we cannot recover the correct string from its +# output. + +# Note 2013-06-19: +# The above was for the || operator in the stdlib's Pervasives module. +# Now we have the same problem with the |> operator that was added +# to the same module in commit 13739, hence the second special case. + +usage(){ + echo "usage: fix_index.sh .idx" >&2 + exit 2 +} + +case $# in + 1) ;; + *) usage;; +esac + +ed "$1" <<'EOF' +/-pipe-pipe/s/verb`("|hyperindexformat{\\"}/verb`("|"|)`|hyperpage/ +/-pipe-gt/s/verb`("|hyperindexformat{\\>)`}/verb`("|>)`|hyperpage/ +w +q +EOF + +case $? in + 0) echo "fix_index.sh: fixed $1 successfully.";; + *) echo "fix_index.sh: some error occurred."; exit 0;; +esac diff --git a/manual/tools/format-intf b/manual/tools/format-intf new file mode 100755 index 0000000000..0228ecc18e --- /dev/null +++ b/manual/tools/format-intf @@ -0,0 +1,153 @@ +#!/usr/bin/perl + +$sep = "\246"; + +$html = 0; +if ($ARGV[0] eq "-html") { + $html = 1; + shift; +} + +# Skip initial junk + +while(($_ = <>) && ! m/^\(\* Module \[(.*)\]:/) { } +m/^\(\* Module \[(.*)\]:/; +$modname = $1; +chop; +s/^\(\* *//; +s/ *\*\) *$//; +s/\[/{\\tt /g; +s/\]/}/g; +print "\\section{$_}\n\n"; +$label = $modname; $label =~ s/[^A-Za-z0-9]//g; +print "\\label{s:$label}\n"; +print "\\index{$modname (module)@\\verb~$modname~ (module)}%\n\n"; +s/{\\tt //g; +s/}//g; +s/_//g; +print "\\pdfsection{$_}\n\n"; + +$incomment = 0; +$inverbatim = 0; + +line: +while(<>) { + chop; + last line if /^\s*\(\*--/; + if (s/^\(\*- //) { + s/ *\*\)$//; + } + if (m/^\s*\(\*\*\*\s*(.*)\*\)\s*$/) { + if ($inverbatim) { + do end_verbatim(); + } + print "\\subsection*{", $1, "}\n"; + next line; + } + if (m/^\s*\(\*\*\s*(.*)\*\)\s*$/) { + if ($inverbatim) { + do end_verbatim(); + } + print "\\subsubsection*{", $1, "}\n"; + next line; + } + if (s/^\s*\(\*//) { + if ($inverbatim) { + do end_verbatim(); + } + print "\\begin{comment}\n"; + $incomment = 1; + } + if ($incomment) { + $endcomment = s/\*\)\s*$//; + if (m/^\s*\[\s*$/) { + print "\\begin{restoreindent}\n" unless $html; + print "\\begin{verbatim}\n"; + while (($_ = <>) && ! m/^\s*\]\s*$/) { + print $_; + } + print "\\end{verbatim}\n"; + print "\\end{restoreindent}\n" unless $html; + } else { + if (s/^-//) { + print "\\\\"; + print "[\\smallskipamount]" unless $html; + } + s/^\s*//; + $count = 0; + foreach $part (split(/(\\?[\[\]])/, $_)) { + if ($part eq "[") { + print ($count == 0 ? "\\verb$sep" : "["); + $count++; + } elsif ($part eq "]") { + $count--; + print ($count == 0 ? "$sep" : "]"); + } elsif ($part =~ m/^\\([\[\]])$/) { + print $1; + } else { + print $part; + } + } + } + if ($endcomment) { + print "\n\\end{comment}"; + $incomment = 0; + $inverbatim = 0; + } + } else { + next line if /^$/; + if (! $inverbatim) { + print "\\begin{verbatim}\n"; + $inverbatim = 1; + } + s/^external /val /; + s/ = ("[^"]*"\s*)+$//; + next line if /^\s*$/; + s/^val \( ([^ )]+) \)/val (\1)/; + { + do indexentry($1, " (operator)"), last + if (m/^val \(([^)]*)\)/); + do indexentry($1, ""), last + if (m/^val ([a-zA-Z0-9_']*)/); + do indexentry($1, " (type)"), last + if (m/^type\s.*([a-zA-Z0-9_']*)\s*=/); + do indexentry($1, " (exception)"), last + if (m/^exception ([a-zA-Z0-9_']*)/); + do indexentry($1, " (module type)"), last + if (m/^module type ([a-zA-Z0-9_']*)/); + do indexentry($1, " (functor)"), last + if (m/^module ([a-zA-Z0-9_']*)\s*\(/); + do indexentry($1, " (module)"), last + if (m/^module ([a-zA-Z0-9_']*)/); + } + print $_; + } + print "\n"; +} +do end_verbatim() if $inverbatim; +print "\\end{comment}\n" if $incomment; + +sub indexentry { + local ($_, $comment) = @_; + return if m/^$/ || m/^[a-zA-Z]$/; + s/([@|!])/"$1/g; + if (! m|`|) { + $s = "`"; + } elsif (! m|~|) { + $s = "~"; + } elsif (! m/\|/) { + $s = "|"; + } else { + die("Can't find quote character for $_"); + } + push (@index, "\\index{$_$comment@\\verb$s$_$s$comment}"); +} + +sub end_verbatim { + print "\\end{verbatim}\n"; + foreach $idx (@index) { + print $idx, "%\n"; + } + undef(@index); + $inverbatim = 0; +} diff --git a/manual/tools/htmlcut b/manual/tools/htmlcut new file mode 100755 index 0000000000..be079abb2b --- /dev/null +++ b/manual/tools/htmlcut @@ -0,0 +1,111 @@ +#!/usr/local/bin/perl +# Split an HTML file into smaller nodes. +# Split at

    headers and also at some

    headers. + +$h0 = "H0"; +$h1 = "H1"; +$h2 = "H2"; + +# Parse options + +option: +while(1) { + $_ = $ARGV[0]; + if (/^-([0-9]+)$/) { + $split2[$1] = 1; + } + elsif (/^-article/) { + $h0 = "H1"; + $h1 = "H2"; + $h2 = "H3"; + } + else { + last option; + } + shift(@ARGV); +} + +$infile = $ARGV[0]; + +# Find URL's for the links + +$level0 = 0; +$level1 = 0; +$uselabel = 1; +open(INPUT, $infile); +while() { + if (m|^<$h0>(.*)|o) { + $level0++; + $currfile = "node" . ($level1 + 1) . ".html"; + $lblnum = $level0; + $uselabel = 0; + } + if (m|^<$h1>(.*)|o) { + $level1++; + $level2 = 0; + $currfile = "node$level1.html"; + $lblnum = $level1; + $uselabel = 1; + } + if (m|^<$h2>(.*)|o) { + $level2++; + if ($split2[$level1]) { $currfile = "node$level1.$level2.html"; } + $lblnum = "$level1.$level2"; + } + s||do set_url($1)|ige; +} + +sub set_url { + local ($lbl) = @_; + if ($uselabel) { + $url{$lbl} = "$currfile#$lbl"; + } else { + $url{$lbl} = $currfile; + } + $label{$lbl} = $lblnum; +} + +# Cut the file + +$level1 = 0; +open(INPUT, $infile); +while() { + if (m|^<$h0>(.*)|o) { + if ($level2 > 0) { print FILE1 "\n"; } + select(STDOUT); + if ($level1 >= 1) { print ""; } + print "<$h2>$1\n"; + if ($level1 >= 1) { print "
      "; } + next; + } + if (m|^<$h1>(.*)|o) { + if ($level2 > 0) { print FILE1 "
    \n"; } + $level1++; + $level2 = 0; + select(STDOUT); + if ($level1 == 1) { print "