Caml1999I031a[#Tmc'rewriteZ@&Lambda&lambda@@@&lambda@@@@@@.lambda/tmc.mliQ [ [Q [ y@@B@@%#Tmc0chorWZ9(Warnings0zdͦkUe$%Types0lm?ƈ.Type_immediacy0dV^25b)̓ԆSj%Subst0BYw>*Su}Ck-Stdlib__Uchar0*Ujmyc6]]W.Stdlib__String0I3UK# +Stdlib__Set0.z9FX+Stdlib__Seq05"g1<)b+Stdlib__Map0kZ,ҷ'V.Stdlib__Lexing01'jh,-k4,Stdlib__Lazy0C 4 "$p1tU/Stdlib__Hashtbl04$*uկdD.Stdlib__Format0{hXsHW#ȼ.Stdlib__Either0&]XF.Stdlib__Digest0aI]2t*x4%".Stdlib__Buffer0K ɦb+Z8)#KH"&Stdlib0yӶ~*%Shape0H[DTċwToe@Q)Primitive0յ_9|br$Path0L%SsN|#Ɣj)Parsetree0`ⰧkRE+Outcometree0gCtr [] | x :: xs -> let y = f x in y :: map f xs |} becomes (expressed in almost-source-form; the translation is in fact at the Lambda-level) {| let rec map f = function | [] -> [] | x :: xs -> let y = f x in let dst = y :: Placeholder in map_dps dst 1 f xs; dst and map_dps dst offset f = function | [] -> dst.offset <- [] | x :: xs -> let y = f x in let dst' = y :: Placeholder in dst.offset <- dst'; map_dps dst 1 f fx |} In this example, the expression (y :: map f xs) had a call in non-tail-position, and it gets rewritten into tail-calls. TMC handles all such cases where the continuation of the call (what needs to be done after the return) is a "construction", the creation of a (possibly nested) data block. The code transformation generates two versions of the input function, the "direct" version with the same type and behavior as the original one (here just [map]), and the "destination-passing-style" version (here [map_dps]). Any call to the original function from outside the let..rec declaration gets transformed into a call into the direct version, which will itself call the destination-passing-style versions on recursive calls that may benefit from it (they are in tail-position modulo constructors). Because of this inherent code duplication, the transformation may not always improve performance. In this implementation, TMC is opt-in, we only transform functions that the user has annotated with an attribute to request the transformation. BXRRCM J L@@@@@@Aࠐ&Lambda&LambdaPO N SQO N Y@@A0ONNOOOOO@N @AUO N N@@S@'rewriteY_Q [ _`Q [ f@б@г&lambdajQ [ ikQ [ o@@ @@@ j@@г*&lambdawQ [ sxQ [ y@@ @@@ k*@@@@@ l-@@@Q [ [ @@B@ @@3@,@@0@6. @A@ H************************************************************************A@@A@L@ H BMMBM@ H OCaml CC@ H DD3@ J Frédéric Bour E44E4@ H Gabriel Scherer, projet Partout, INRIA Saclay FF@ I Basile Clément, projet Cambium, INRIA Paris GG@ H HHj@ H Copyright 2020 Institut National de Recherche en Informatique et IkkIk@ H en Automatique. JJ@ H KKQ@ H All rights reserved. This file is distributed under the terms of LRRLR@ H the GNU Lesser General Public License version 2.1, with the MM@ H special exception on linking described in the file LICENSE. NN8@ H O99O9@ H************************************************************************PP@ x* Tail-modulo-cons optimization. {b Warning:} this module is unstable and part of {{!Compiler_libs}compiler-libs}.  * TMC (Tail Modulo Cons) is a code transformation that rewrites transformed functions in destination-passing-style, in such a way that certain calls that were not in tail position in the original program become tail-calls in the transformed program. As a classic example, the following program {| let[@tail_mod_cons] rec map f = function | [] -> [] | x :: xs -> let y = f x in y :: map f xs |} becomes (expressed in almost-source-form; the translation is in fact at the Lambda-level) {| let rec map f = function | [] -> [] | x :: xs -> let y = f x in let dst = y :: Placeholder in map_dps dst 1 f xs; dst and map_dps dst offset f = function | [] -> dst.offset <- [] | x :: xs -> let y = f x in let dst' = y :: Placeholder in dst.offset <- dst'; map_dps dst 1 f fx |} In this example, the expression (y :: map f xs) had a call in non-tail-position, and it gets rewritten into tail-calls. TMC handles all such cases where the continuation of the call (what needs to be done after the return) is a "construction", the creation of a (possibly nested) data block. The code transformation generates two versions of the input function, the "direct" version with the same type and behavior as the original one (here just [map]), and the "destination-passing-style" version (here [map_dps]). Any call to the original function from outside the let..rec declaration gets transformed into a call into the direct version, which will itself call the destination-passing-style versions on recursive calls that may benefit from it (they are in tail-position modulo constructors). Because of this inherent code duplication, the transformation may not always improve performance. In this implementation, TMC is opt-in, we only transform functions that the user has annotated with an attribute to request the transformation. @-./boot/ocamlc"-g)-nostdlib"-I$boot*-use-prims2runtime/primitives0-strict-sequence*-principal(-absname"-w>+a-4-9-40-41-42-44-45-48-66-70+-warn-error"+a*-bin-annot,-safe-string/-strict-formats"-I%utils"-I'parsing"-I&typing"-I(bytecomp"-I,file_formats"-I&lambda"-I*middle_end"-I2middle_end/closure"-I2middle_end/flambda"-I=middle_end/flambda/base_types"-I'asmcomp"-I&driver"-I(toplevel"-c 3/home/barsac/ci/builds/workspace/step-by-step-build - @0ZRgLfC*0-,,-----@+@@(Asttypes0'$O~75Build_path_prefix_map0xөvĠ8CamlinternalFormatBasics0cEXy*Su}Ck0chorWZ9.Type_immediacy0dV^25b)̓ԆSj%Types0lm?ƈ(Warnings0zdͦkUe$@0chorWZ9AA@ji@@@@@@@@@@@@@@@@@P@