123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433(* Js_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
* Copyright (C) 2010 Jérôme Vouillon
* Laboratoire PPS - CNRS Université Paris Diderot
*
* This program 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, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)openStdlibopenCodeopenInstrletdebug_parser=Debug.find"parser"letdebug_sourcemap=Debug.find"sourcemap"typecode=stringletpredefined_exceptions=[0,"Out_of_memory";1,"Sys_error";2,"Failure";3,"Invalid_argument";4,"End_of_file";5,"Division_by_zero";6,"Not_found";7,"Match_failure";8,"Stack_overflow";9,"Sys_blocked_io";10,"Assert_failure";11,"Undefined_recursive_module"](* Read and manipulate debug section *)moduleDebug:sigtypedatavalis_empty:data->boolvalpropagate:Code.Var.tlist->Code.Var.tlist->unitvalfind:data->Code.Addr.t->(int*string*Ident.t)list*Env.summaryvalfind_loc:data->?after:bool->int->Parse_info.toptionvalfind_source:data->string->stringoptionvalmem:data->Code.Addr.t->boolvalread:data->crcs:(string*stringoption)list->includes:stringlist->in_channel->unitvalread_event_list:data->crcs:(string*stringoption)list->includes:stringlist->orig:int->in_channel->unitvalcreate:unit->datavalfold:data->(Code.Addr.t->Instruct.debug_event->'a->'a)->'a->'avalpaths:data->units:StringSet.t->StringSet.tend=structopenInstructtypeml_unit={module_name:string;fname:string;crc:stringoption;paths:stringlist;source:stringoption}typedata={events_by_pc:(int,debug_event*ml_unit)Hashtbl.t;units:(string*string,ml_unit)Hashtbl.t}letrelocate_eventorigev=ev.ev_pos<-(orig+ev.ev_pos)/4letcreate()={events_by_pc=Hashtbl.create17;units=Hashtbl.create17}letis_emptyt=Hashtbl.lengtht.events_by_pc=0letfind_ml_in_pathspathsname=letuname=String.uncapitalize_asciinameintrySome(Fs.find_in_pathpaths(uname^".ml"))withNot_found->(trySome(Fs.find_in_pathpaths(name^".ml"))withNot_found->None)letread_event_list=letread_pathsic:stringlist=input_valueicinfun{events_by_pc;units}~crcs~includes~origic->letcrcs=lett=Hashtbl.create17inList.itercrcs~f:(fun(m,crc)->Hashtbl.addtmcrc);tinletevl:debug_eventlist=input_valueicinletpaths=read_pathsic@includesinList.iterevl~f:(fun({ev_module;ev_loc={Location.loc_start={Lexing.pos_fname;_};_};_}asev)->letunit=tryHashtbl.findunits(ev_module,pos_fname)withNot_found->letcrc=tryHashtbl.findcrcsev_modulewithNot_found->Noneinletsource=trySome(Fs.find_in_pathpathspos_fname)withNot_found->(trySome(Fs.find_in_pathpaths(Filename.basenamepos_fname))withNot_found->find_ml_in_pathspathsev_module)inifdebug_sourcemap()thenFormat.eprintf"module:%s - source:%s - name:%s\n%!"ev_module(matchsourcewith|None->"NONE"|Somex->x)pos_fname;letu={module_name=ev_module;fname=pos_fname;crc;source;paths}inHashtbl.addunits(ev_module,pos_fname)u;uinrelocate_eventorigev;Hashtbl.addevents_by_pcev.ev_pos(ev,unit);())letfind_source{units;_}pos_fname=letset=Hashtbl.fold(fun(_m,p)unitacc->ifp=pos_fnamethenmatchunit.sourcewith|None->acc|Somesrc->StringSet.addsrcaccelseacc)unitsStringSet.emptyinifStringSet.cardinalset=1thenSome(StringSet.chooseset)elseNoneletreadt~crcs~includesic=letlen=input_binary_inticinfor_i=0tolen-1doletorig=input_binary_inticinread_event_listt~crcs~includes~origicdoneletfind{events_by_pc;_}pc=tryletev,_=Hashtbl.findevents_by_pcpcin(Ocaml_compiler.Ident.table_contentsev.ev_stacksizeev.ev_compenv.ce_stack,ev.ev_typenv)withNot_found->[],Env.Env_emptyletmem{events_by_pc;_}=Hashtbl.memevents_by_pcletfind_loc{events_by_pc;_}?(after=false)pc=tryletbefore,(ev,unit)=tryfalse,Hashtbl.findevents_by_pcpcwithNot_found->((true,tryHashtbl.findevents_by_pc(pc+1)withNot_found->(tryHashtbl.findevents_by_pc(pc+2)withNot_found->Hashtbl.findevents_by_pc(pc+3))))inletloc=ev.ev_locinifloc.Location.loc_ghostthenNoneelseletpos=ifafterthenloc.Location.loc_endelseifbeforethenloc.Location.loc_startelsematchev.ev_kindwith|Event_after_->loc.Location.loc_end|_->loc.Location.loc_startinletsrc=unit.sourceinSome{Parse_info.name=Somepos.Lexing.pos_fname;src;line=pos.Lexing.pos_lnum-1;col=pos.Lexing.pos_cnum-pos.Lexing.pos_bol;idx=0;fol=None}withNot_found->Noneletrecpropagatel1l2=matchl1,l2with|v1::r1,v2::r2->Var.propagate_namev1v2;propagater1r2|_->()letfoldtfacc=Hashtbl.fold(funk(e,_u)acc->fkeacc)t.events_by_pcaccletpathst~units=letpaths=Hashtbl.fold(fun_uacc->ifStringSet.memu.module_nameunitsthenu.paths::accelseacc)t.units[]inStringSet.of_list(List.concatpaths)end(* Block analysis *)(* Detect each block *)moduleBlocks:sigtypetvalanalyse:Debug.data->code->tvaladd:t->int->ttypeuvalfinish_analysis:t->uvalnext:u->int->intvalis_empty:u->boolend=structtypet=Addr.Set.ttypeu=intarrayletaddblockspc=Addr.Set.addpcblocksletrecscandebugblockscodepclen=ifpc<lenthenmatch(get_instr_exncodepc).kindwith|KNullary->scandebugblockscode(pc+1)len|KUnary->scandebugblockscode(pc+2)len|KBinary->scandebugblockscode(pc+3)len|KNullaryCall->letblocks=ifDebug.memdebug(pc+1)thenAddr.Set.addpcblockselseblocksinscandebugblockscode(pc+1)len|KUnaryCall->letblocks=ifDebug.memdebug(pc+2)thenAddr.Set.addpcblockselseblocksinscandebugblockscode(pc+2)len|KBinaryCall->letblocks=ifDebug.memdebug(pc+3)thenAddr.Set.addpcblockselseblocksinscandebugblockscode(pc+3)len|KJump->letoffset=getscode(pc+1)inletblocks=Addr.Set.add(pc+offset+1)blocksinscandebugblockscode(pc+2)len|KCond_jump->letoffset=getscode(pc+1)inletblocks=Addr.Set.add(pc+offset+1)blocksinscandebugblockscode(pc+2)len|KCmp_jump->letoffset=getscode(pc+2)inletblocks=Addr.Set.add(pc+offset+2)blocksinscandebugblockscode(pc+3)len|KSwitch->letsz=getucode(pc+1)inletblocks=refblocksinfori=0to(szland0xffff)+(szlsr16)-1doletoffset=getscode(pc+2+i)inblocks:=Addr.Set.add(pc+offset+2)!blocksdone;scandebug!blockscode(pc+2+(szland0xffff)+(szlsr16))len|KClosurerec->letnfuncs=getucode(pc+1)inscandebugblockscode(pc+nfuncs+3)len|KClosure->scandebugblockscode(pc+3)len|KStopn->scandebugblockscode(pc+n+1)len|K_will_not_happen->assertfalseelse(assert(pc=len);blocks)letfinish_analysisblocks=Array.of_list(Addr.Set.elementsblocks)(* invariant: a.(i) <= x < a.(j) *)letrecfindaijx=assert(i<j);ifi+1=jthena.(j)elseletk=(i+j)/2inifa.(k)<=xthenfindakjxelsefindaikxletnextblockspc=findblocks0(Array.lengthblocks-1)pcletis_emptyx=Array.lengthx<=1letanalysedebug_datacode=letblocks=Addr.Set.emptyinletlen=String.lengthcode/4inletblocks=addblocks0inletblocks=addblocksleninscandebug_datablockscode0lenend(* Parse constants *)moduleConstants:sigvalparse:Obj.t->Code.constantvalinlined:Obj.t->boolend=structletsame_customxy=Obj.fieldx0==Obj.field(Obj.repry)0letwarn_overflowii32=warn"Warning: integer overflow: integer %s truncated to 0x%lx (%ld); the generated \
code might be incorrect.@."ii32i32letrecparsex=ifObj.is_blockxthenlettag=Obj.tagxiniftag=Obj.string_tagthenString(Obj.magicx:string)elseiftag=Obj.double_tagthenFloat(Obj.magicx:float)elseiftag=Obj.double_array_tagthenFloat_array(Obj.magicx:floatarray)elseiftag=Obj.custom_tag&&same_customx0lthenInt(Obj.magicx:int32)elseiftag=Obj.custom_tag&&same_customx0nthen(leti:nativeint=Obj.magicxinleti32=Nativeint.to_int32iinleti'=Nativeint.of_int32i32inifi'<>ithenwarn_overflow(Printf.sprintf"0x%nx (%nd)"ii)i32;Inti32)elseiftag=Obj.custom_tag&&same_customx0LthenInt64(Obj.magicx:int64)elseiftag<Obj.no_scan_tagthenTuple(tag,Array.init(Obj.sizex)~f:(funi->parse(Obj.fieldxi)))elseassertfalseelseleti:int=Obj.magicxinleti32=Int32.of_intiinleti'=Int32.to_inti32inifi'<>ithenwarn_overflow(Printf.sprintf"0x%x (%d)"ii)i32;Inti32letinlinedx=(not(Obj.is_blockx))||lettag=Obj.tagxintag=Obj.double_tag||(tag=Obj.custom_tag&&(same_customx0l||same_customx0n))end(* Globals *)typeglobals={mutablevars:Var.toptionarray;mutableis_const:boolarray;mutableis_exported:boolarray;mutablenamed_value:stringoptionarray;mutableoverride:(Var.t->Code.instrlist->Var.t*Code.instrlist)optionarray;constants:Obj.tarray;primitives:stringarray}letmake_globalssizeconstantsprimitives={vars=Array.makesizeNone;is_const=Array.makesizefalse;is_exported=Array.makesizefalse;named_value=Array.makesizeNone;override=Array.makesizeNone;constants;primitives}letresize_arrayalendef=letb=Array.makelendefinArray.blit~src:a~src_pos:0~dst:b~dst_pos:0~len:(Array.lengtha);bletresize_globalsgsize=g.vars<-resize_arrayg.varssizeNone;g.is_const<-resize_arrayg.is_constsizefalse;g.is_exported<-resize_arrayg.is_exportedsizetrue;g.named_value<-resize_arrayg.named_valuesizeNone;g.override<-resize_arrayg.overridesizeNone(* State of the VM *)moduleState=structtypeelt=|VarofVar.t|Dummyletelt_to_vare=matchewith|Varx->x|_->assertfalseletprint_eltfv=matchvwith|Varx->Format.fprintff"%a"Var.printx|Dummy->Format.fprintff"???"typehandler={var:Var.t;addr:Addr.t;stack_len:int;block_pc:Addr.t}typet={accu:elt;stack:eltlist;env:eltarray;env_offset:int;handlers:handlerlist;globals:globals;current_pc:Addr.t}letfresh_varstate=letx=Var.fresh()inx,{statewithaccu=Varx}letglobalsst=st.globalsletsize_globalsstsize=ifsize>Array.lengthst.globals.varsthenresize_globalsst.globalssizeletreclist_startnl=ifn=0then[]elsematchlwith|[]->assertfalse|v::r->v::list_start(n-1)rletrecst_popnst=ifn=0thenstelsematchstwith|[]->assertfalse|_::r->st_pop(n-1)rletpushst={stwithstack=st.accu::st.stack}letpopnst={stwithstack=st_popnst.stack}letaccnst={stwithaccu=List.nthst.stackn}letenv_accnst={stwithaccu=st.env.(st.env_offset+n)}letaccust=elt_to_varst.acculetstack_varsst=List.fold_left(st.accu::st.stack)~init:[]~f:(funle->matchewith|Varx->x::l|Dummy->l)letset_accustx={stwithaccu=Varx}letclear_accust={stwithaccu=Dummy}letpeeknst=elt_to_var(List.nthst.stackn)letgrabnst=List.map(list_startnst.stack)~f:elt_to_var,popnstletrecst_assignsnx=matchswith|[]->assertfalse|y::rem->ifn=0thenx::remelsey::st_assignrem(n-1)xletassignstn={stwithstack=st_assignst.stacknst.accu}letstart_functionstateenvoffset={statewithaccu=Dummy;stack=[];env;env_offset=offset;handlers=[]}letstart_blockcurrent_pcstate=letstack=List.fold_rightstate.stack~init:[]~f:(funestack->matchewith|Dummy->Dummy::stack|Varx->lety=Var.forkxinVary::stack)inletstate={statewithstack;current_pc}inmatchstate.accuwith|Dummy->state|Varx->lety,state=fresh_varstateinVar.propagate_namexy;stateletpush_handlerstatexaddr={statewithhandlers={block_pc=state.current_pc;var=x;addr;stack_len=List.lengthstate.stack}::state.handlers}letpop_handlerstate={statewithhandlers=List.tlstate.handlers}letaddr_of_current_handlerstate=matchstate.handlerswith|[]->assertfalse|x::_->x.block_pcletcurrent_handlerstate=matchstate.handlerswith|[]->None|{var;addr;stack_len;_}::_->letstate={statewithaccu=Varvar;stack=st_pop(List.lengthstate.stack-stack_len)state.stack}inSome(var,(addr,stack_varsstate))letinitialg={accu=Dummy;stack=[];env=[||];env_offset=0;handlers=[];globals=g;current_pc=-1}letrecprint_stackfl=matchlwith|[]->()|v::r->Format.fprintff"%a %a"print_eltvprint_stackrletprint_envfe=Array.iterie~f:(funiv->ifi>0thenFormat.fprintff" ";Format.fprintff"%a"print_eltv)letprintst=Format.eprintf"{ %a | %a | (%d) %a }@."print_eltst.accuprint_stackst.stackst.env_offsetprint_envst.envletpi_of_locdebuglocation=letpos=location.Location.loc_startinletsrc=Debug.find_sourcedebugpos.Lexing.pos_fnamein{Parse_info.name=Somepos.Lexing.pos_fname;src;line=pos.Lexing.pos_lnum-1;col=pos.Lexing.pos_cnum-pos.Lexing.pos_bol;idx=0;fol=None}letrecname_recdebugilssummary=matchl,swith|[],_->()|(j,nm,ident)::lrem,Varv::sremwheni=j->(matchOcaml_compiler.find_loc_in_summaryidentsummarywith|None->()|Someloc->Var.locv(pi_of_locdebugloc));Var.namevnm;name_recdebug(i+1)lremsremsummary|(j,_,_)::_,_::sremwheni<j->name_recdebug(i+1)lsremsummary|_->assertfalseletname_varsstdebugpc=letl,summary=Debug.finddebugpcinname_recdebug0lst.stacksummaryletrecmake_stackistate=ifi=0then[],stateelseletx,state=fresh_varstateinletparams,state=make_stack(predi)(pushstate)inifdebug_parser()thenifi>1thenFormat.printf", ";ifdebug_parser()thenFormat.printf"%a"Var.printx;x::params,stateendletprimitive_namestatei=letg=State.globalsstateinassert(i>=0&&i<=Array.lengthg.primitives);letprim=g.primitives.(i)inPrimitive.add_externalprim;primletaccess_globalgi=matchg.vars.(i)with|Somex->x|None->g.is_const.(i)<-true;letx=Var.fresh()ing.vars.(i)<-Somex;xletregister_global?(force=false)girem=ifforce||g.is_exported.(i)thenletargs=matchg.named_value.(i)with|None->[]|Somename->Code.Var.name(access_globalgi)name;[Pc(IStringname)]inLet(Var.fresh(),Prim(Extern"caml_register_global",Pc(Int(Int32.of_inti))::Pv(access_globalgi)::args))::remelseremletget_globalstateinstrsi=State.size_globalsstate(i+1);letg=State.globalsstateinmatchg.vars.(i)with|Somex->ifdebug_parser()thenFormat.printf"(global access %a)@."Var.printx;x,State.set_accustatex,instrs|None->ifi<Array.lengthg.constants&&Constants.inlinedg.constants.(i)thenletx,state=State.fresh_varstateinletcst=Constants.parseg.constants.(i)inx,state,Let(x,Constantcst)::instrselse(g.is_const.(i)<-true;letx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = CONST(%d)@."Var.printxi;g.vars.(i)<-Somex;x,state,instrs)lettagged_blocks=refAddr.Set.emptyletcompiled_blocks=refAddr.Map.emptyletmethod_cache_id=ref1typecompile_info={blocks:Blocks.u;code:string;limit:int;debug:Debug.data}letreccompile_blockblocksdebugcodepcstate=ifnot(Addr.Set.mempc!tagged_blocks)then(letlimit=Blocks.nextblockspcinassert(limit>pc);letstring_of_addraddr=matchDebug.find_locdebugaddrwith|None->string_of_intaddr|Someloc->(matchloc.Parse_info.srcwith|None->string_of_intaddr|Somefile->Printf.sprintf"%s:%d:%d-%d"fileloc.Parse_info.lineloc.Parse_info.col(addr+2))inifdebug_parser()thenFormat.eprintf"Compiling from %s to %d@."(string_of_addrpc)(limit-1);letstate=State.start_blockpcstateintagged_blocks:=Addr.Set.addpc!tagged_blocks;letinstr,last,state'=compile{blocks;code;limit;debug}pcstate[]inassert(not(Addr.Map.mempc!compiled_blocks));compiled_blocks:=Addr.Map.addpc(state,List.revinstr,last)!compiled_blocks;matchlastwith|Branch(pc',_)|Poptrap((pc',_),_)->compile_blockblocksdebugcodepc'state'|Cond(_,_,(pc1,_),(pc2,_))->compile_blockblocksdebugcodepc1state';compile_blockblocksdebugcodepc2state'|Switch(_,l1,l2)->Array.iterl1~f:(fun(pc',_)->compile_blockblocksdebugcodepc'state');Array.iterl2~f:(fun(pc',_)->compile_blockblocksdebugcodepc'state')|Pushtrap_|Raise_|Return_|Stop->())andcompileinfospcstateinstrs=ifdebug_parser()thenState.printstate;assert(pc<=infos.limit);ifpc=infos.limitthenif(* stop if we reach end_of_code (ie when compiling cmo) *)pc=String.lengthinfos.code/4then(ifdebug_parser()thenFormat.eprintf"Stop@.";instrs,Stop,state)else(State.name_varsstateinfos.debugpc;letstack=State.stack_varsstateinifdebug_parser()thenFormat.eprintf"Branch %d (%a) @."pcprint_var_liststack;instrs,Branch(pc,stack),state)else(ifdebug_parser()thenFormat.eprintf"%4d "pc;State.name_varsstateinfos.debugpc;letcode=infos.codeinletinstr=get_instr_exncodepcinifdebug_parser()thenFormat.eprintf"%08x %s@."instr.opcodeinstr.name;matchinstr.Instr.codewith|ACC0->compileinfos(pc+1)(State.acc0state)instrs|ACC1->compileinfos(pc+1)(State.acc1state)instrs|ACC2->compileinfos(pc+1)(State.acc2state)instrs|ACC3->compileinfos(pc+1)(State.acc3state)instrs|ACC4->compileinfos(pc+1)(State.acc4state)instrs|ACC5->compileinfos(pc+1)(State.acc5state)instrs|ACC6->compileinfos(pc+1)(State.acc6state)instrs|ACC7->compileinfos(pc+1)(State.acc7state)instrs|ACC->letn=getucode(pc+1)incompileinfos(pc+2)(State.accnstate)instrs|PUSH->compileinfos(pc+1)(State.pushstate)instrs|PUSHACC0->compileinfos(pc+1)(State.acc0(State.pushstate))instrs|PUSHACC1->compileinfos(pc+1)(State.acc1(State.pushstate))instrs|PUSHACC2->compileinfos(pc+1)(State.acc2(State.pushstate))instrs|PUSHACC3->compileinfos(pc+1)(State.acc3(State.pushstate))instrs|PUSHACC4->compileinfos(pc+1)(State.acc4(State.pushstate))instrs|PUSHACC5->compileinfos(pc+1)(State.acc5(State.pushstate))instrs|PUSHACC6->compileinfos(pc+1)(State.acc6(State.pushstate))instrs|PUSHACC7->compileinfos(pc+1)(State.acc7(State.pushstate))instrs|PUSHACC->letn=getucode(pc+1)incompileinfos(pc+2)(State.accn(State.pushstate))instrs|POP->letn=getucode(pc+1)incompileinfos(pc+2)(State.popnstate)instrs|ASSIGN->letn=getucode(pc+1)inletstate=State.assignstateninletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;(* We switch to a different block as this may have
changed the exception handler continuation *)compile_blockinfos.blocksinfos.debugcode(pc+2)state;Let(x,Const0l)::instrs,Branch(pc+2,State.stack_varsstate),state|ENVACC1->compileinfos(pc+1)(State.env_acc1state)instrs|ENVACC2->compileinfos(pc+1)(State.env_acc2state)instrs|ENVACC3->compileinfos(pc+1)(State.env_acc3state)instrs|ENVACC4->compileinfos(pc+1)(State.env_acc4state)instrs|ENVACC->letn=getucode(pc+1)incompileinfos(pc+2)(State.env_accnstate)instrs|PUSHENVACC1->compileinfos(pc+1)(State.env_acc1(State.pushstate))instrs|PUSHENVACC2->compileinfos(pc+1)(State.env_acc2(State.pushstate))instrs|PUSHENVACC3->compileinfos(pc+1)(State.env_acc3(State.pushstate))instrs|PUSHENVACC4->compileinfos(pc+1)(State.env_acc4(State.pushstate))instrs|PUSHENVACC->letn=getucode(pc+1)incompileinfos(pc+2)(State.env_accn(State.pushstate))instrs|PUSH_RETADDR->compileinfos(pc+2){statewithState.stack=State.Dummy::State.Dummy::State.Dummy::state.State.stack}instrs|APPLY->letn=getucode(pc+1)inletf=State.accustateinletx,state=State.fresh_varstateinletargs,state=State.grabnstateinifdebug_parser()then(Format.printf"%a = %a("Var.printxVar.printf;fori=0ton-1doifi>0thenFormat.printf", ";Format.printf"%a"Var.print(List.nthargsi)done;Format.printf")@.");compileinfos(pc+2)(State.pop3state)(Let(x,Apply(f,args,false))::instrs)|APPLY1->letf=State.accustateinletx,state=State.fresh_varstateinlety=State.peek0stateinifdebug_parser()thenFormat.printf"%a = %a(%a)@."Var.printxVar.printfVar.printy;compileinfos(pc+1)(State.pop1state)(Let(x,Apply(f,[y],false))::instrs)|APPLY2->letf=State.accustateinletx,state=State.fresh_varstateinlety=State.peek0stateinletz=State.peek1stateinifdebug_parser()thenFormat.printf"%a = %a(%a, %a)@."Var.printxVar.printfVar.printyVar.printz;compileinfos(pc+1)(State.pop2state)(Let(x,Apply(f,[y;z],false))::instrs)|APPLY3->letf=State.accustateinletx,state=State.fresh_varstateinlety=State.peek0stateinletz=State.peek1stateinlett=State.peek2stateinifdebug_parser()thenFormat.printf"%a = %a(%a, %a, %a)@."Var.printxVar.printfVar.printyVar.printzVar.printt;compileinfos(pc+1)(State.pop3state)(Let(x,Apply(f,[y;z;t],false))::instrs)|APPTERM->letn=getucode(pc+1)inletf=State.accustateinletl,state=State.grabnstateinifdebug_parser()then(Format.printf"return %a("Var.printf;fori=0ton-1doifi>0thenFormat.printf", ";Format.printf"%a"Var.print(List.nthli)done;Format.printf")@.");letx,state=State.fresh_varstateinLet(x,Apply(f,l,false))::instrs,Returnx,state|APPTERM1->letf=State.accustateinletx=State.peek0stateinifdebug_parser()thenFormat.printf"return %a(%a)@."Var.printfVar.printx;lety,state=State.fresh_varstateinLet(y,Apply(f,[x],false))::instrs,Returny,state|APPTERM2->letf=State.accustateinletx=State.peek0stateinlety=State.peek1stateinifdebug_parser()thenFormat.printf"return %a(%a, %a)@."Var.printfVar.printxVar.printy;letz,state=State.fresh_varstateinLet(z,Apply(f,[x;y],false))::instrs,Returnz,state|APPTERM3->letf=State.accustateinletx=State.peek0stateinlety=State.peek1stateinletz=State.peek2stateinifdebug_parser()thenFormat.printf"return %a(%a, %a, %a)@."Var.printfVar.printxVar.printyVar.printz;lett,state=State.fresh_varstateinLet(t,Apply(f,[x;y;z],false))::instrs,Returnt,state|RETURN->letx=State.accustateinifdebug_parser()thenFormat.printf"return %a@."Var.printx;instrs,Returnx,state|RESTART->assertfalse|GRAB->compileinfos(pc+2)stateinstrs|CLOSURE->letnvars=getucode(pc+1)inletaddr=pc+getscode(pc+2)+2inletstate=ifnvars>0thenState.pushstateelsestateinletvals,state=State.grabnvarsstateinletx,state=State.fresh_varstateinletenv=Array.of_list(State.Dummy::List.mapvals~f:(funx->State.Varx))inifdebug_parser()thenFormat.printf"fun %a ("Var.printx;letnparams=match(get_instr_exncodeaddr).Instr.codewith|GRAB->getucode(addr+1)+1|_->1inletstate'=State.start_functionstateenv0inletparams,state'=State.make_stacknparamsstate'inifdebug_parser()thenFormat.printf") {@.";letstate'=State.clear_accustate'incompile_blockinfos.blocksinfos.debugcodeaddrstate';ifdebug_parser()thenFormat.printf"}@.";letargs=State.stack_varsstate'inletstate'',_,_=Addr.Map.findaddr!compiled_blocksinDebug.propagate(State.stack_varsstate'')args;compileinfos(pc+3)state(Let(x,Closure(List.revparams,(addr,args)))::instrs)|CLOSUREREC->letnfuncs=getucode(pc+1)inletnvars=getucode(pc+2)inletstate=ifnvars>0thenState.pushstateelsestateinletvals,state=State.grabnvarsstateinletstate=refstateinletvars=ref[]infori=0tonfuncs-1doletx,st=State.fresh_var!stateinvars:=(i,x)::!vars;state:=State.pushstdone;letenv=ref(List.mapvals~f:(funx->State.Varx))inList.iter!vars~f:(fun(i,x)->env:=State.Varx::!env;ifi>0thenenv:=State.Dummy::!env);letenv=Array.of_list!envinletstate=!stateinletinstrs=List.fold_left(List.rev!vars)~init:instrs~f:(funinstr(i,x)->letaddr=pc+3+getscode(pc+3+i)inifdebug_parser()thenFormat.printf"fun %a ("Var.printx;letnparams=match(get_instr_exncodeaddr).Instr.codewith|GRAB->getucode(addr+1)+1|_->1inletstate'=State.start_functionstateenv(i*2)inletparams,state'=State.make_stacknparamsstate'inifdebug_parser()thenFormat.printf") {@.";letstate'=State.clear_accustate'incompile_blockinfos.blocksinfos.debugcodeaddrstate';ifdebug_parser()thenFormat.printf"}@.";letargs=State.stack_varsstate'inletstate'',_,_=Addr.Map.findaddr!compiled_blocksinDebug.propagate(State.stack_varsstate'')args;Let(x,Closure(List.revparams,(addr,args)))::instr)incompileinfos(pc+3+nfuncs)(State.acc(nfuncs-1)state)instrs|OFFSETCLOSUREM2->compileinfos(pc+1)(State.env_acc(-2)state)instrs|OFFSETCLOSURE0->compileinfos(pc+1)(State.env_acc0state)instrs|OFFSETCLOSURE2->compileinfos(pc+1)(State.env_acc2state)instrs|OFFSETCLOSURE->letn=getscode(pc+1)incompileinfos(pc+2)(State.env_accnstate)instrs|PUSHOFFSETCLOSUREM2->letstate=State.pushstateincompileinfos(pc+1)(State.env_acc(-2)state)instrs|PUSHOFFSETCLOSURE0->letstate=State.pushstateincompileinfos(pc+1)(State.env_acc0state)instrs|PUSHOFFSETCLOSURE2->letstate=State.pushstateincompileinfos(pc+1)(State.env_acc2state)instrs|PUSHOFFSETCLOSURE->letstate=State.pushstateinletn=getscode(pc+1)incompileinfos(pc+2)(State.env_accnstate)instrs|GETGLOBAL->leti=getucode(pc+1)inlet_,state,instrs=get_globalstateinstrsiincompileinfos(pc+2)stateinstrs|PUSHGETGLOBAL->letstate=State.pushstateinleti=getucode(pc+1)inlet_,state,instrs=get_globalstateinstrsiincompileinfos(pc+2)stateinstrs|GETGLOBALFIELD->leti=getucode(pc+1)inletx,state,instrs=get_globalstateinstrsiinletj=getucode(pc+2)inlety,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[%d]@."Var.printyVar.printxj;compileinfos(pc+3)state(Let(y,Field(x,j))::instrs)|PUSHGETGLOBALFIELD->letstate=State.pushstateinleti=getucode(pc+1)inletx,state,instrs=get_globalstateinstrsiinletj=getucode(pc+2)inlety,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[%d]@."Var.printyVar.printxj;compileinfos(pc+3)state(Let(y,Field(x,j))::instrs)|SETGLOBAL->leti=getucode(pc+1)inState.size_globalsstate(i+1);lety=State.accustateinletg=State.globalsstateinassert(g.vars.(i)=None);ifdebug_parser()thenFormat.printf"(global %d) = %a@."iVar.printy;letinstrs=matchg.override.(i)with|Somef->letv,instrs=fyinstrsing.vars.(i)<-Somev;instrs|None->g.vars.(i)<-Somey;instrsinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;letinstrs=register_globalgiinstrsincompileinfos(pc+2)state(Let(x,Const0l)::instrs)|ATOM0->letx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = ATOM(0)@."Var.printx;compileinfos(pc+1)state(Let(x,Block(0,[||]))::instrs)|ATOM->leti=getucode(pc+1)inletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = ATOM(%d)@."Var.printxi;compileinfos(pc+2)state(Let(x,Block(i,[||]))::instrs)|PUSHATOM0->letstate=State.pushstateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = ATOM(0)@."Var.printx;compileinfos(pc+1)state(Let(x,Block(0,[||]))::instrs)|PUSHATOM->letstate=State.pushstateinleti=getucode(pc+1)inletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = ATOM(%d)@."Var.printxi;compileinfos(pc+2)state(Let(x,Block(i,[||]))::instrs)|MAKEBLOCK->letsize=getucode(pc+1)inlettag=getucode(pc+2)inletstate=State.pushstateinletx,state=State.fresh_varstateinletcontents,state=State.grabsizestateinifdebug_parser()then(Format.printf"%a = { "Var.printx;fori=0tosize-1doFormat.printf"%d = %a; "iVar.print(List.nthcontentsi)done;Format.printf"}@.");compileinfos(pc+3)state(Let(x,Block(tag,Array.of_listcontents))::instrs)|MAKEBLOCK1->lettag=getucode(pc+1)inlety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = { 0 = %a; }@."Var.printxVar.printy;compileinfos(pc+2)state(Let(x,Block(tag,[|y|]))::instrs)|MAKEBLOCK2->lettag=getucode(pc+1)inlety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = { 0 = %a; 1 = %a; }@."Var.printxVar.printyVar.printz;compileinfos(pc+2)(State.pop1state)(Let(x,Block(tag,[|y;z|]))::instrs)|MAKEBLOCK3->lettag=getucode(pc+1)inlety=State.accustateinletz=State.peek0stateinlett=State.peek1stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = { 0 = %a; 1 = %a; 2 = %a }@."Var.printxVar.printyVar.printzVar.printt;compileinfos(pc+2)(State.pop2state)(Let(x,Block(tag,[|y;z;t|]))::instrs)|MAKEFLOATBLOCK->letsize=getucode(pc+1)inletstate=State.pushstateinletx,state=State.fresh_varstateinletcontents,state=State.grabsizestateinifdebug_parser()then(Format.printf"%a = { "Var.printx;fori=0tosize-1doFormat.printf"%d = %a; "iVar.print(List.nthcontentsi)done;Format.printf"}@.");compileinfos(pc+2)state(Let(x,Block(254,Array.of_listcontents))::instrs)|GETFIELD0->lety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[0]@."Var.printxVar.printy;compileinfos(pc+1)state(Let(x,Field(y,0))::instrs)|GETFIELD1->lety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[1]@."Var.printxVar.printy;compileinfos(pc+1)state(Let(x,Field(y,1))::instrs)|GETFIELD2->lety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[2]@."Var.printxVar.printy;compileinfos(pc+1)state(Let(x,Field(y,2))::instrs)|GETFIELD3->lety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[3]@."Var.printxVar.printy;compileinfos(pc+1)state(Let(x,Field(y,3))::instrs)|GETFIELD->lety=State.accustateinletn=getucode(pc+1)inletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[%d]@."Var.printxVar.printyn;compileinfos(pc+2)state(Let(x,Field(y,n))::instrs)|GETFLOATFIELD->lety=State.accustateinletn=getucode(pc+1)inletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[%d]@."Var.printxVar.printyn;compileinfos(pc+2)state(Let(x,Field(y,n))::instrs)|SETFIELD0->lety=State.accustateinletz=State.peek0stateinifdebug_parser()thenFormat.printf"%a[0] = %a@."Var.printyVar.printz;letx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;compileinfos(pc+1)(State.pop1state)(Let(x,Const0l)::Set_field(y,0,z)::instrs)|SETFIELD1->lety=State.accustateinletz=State.peek0stateinifdebug_parser()thenFormat.printf"%a[1] = %a@."Var.printyVar.printz;letx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;compileinfos(pc+1)(State.pop1state)(Let(x,Const0l)::Set_field(y,1,z)::instrs)|SETFIELD2->lety=State.accustateinletz=State.peek0stateinifdebug_parser()thenFormat.printf"%a[2] = %a@."Var.printyVar.printz;letx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;compileinfos(pc+1)(State.pop1state)(Let(x,Const0l)::Set_field(y,2,z)::instrs)|SETFIELD3->lety=State.accustateinletz=State.peek0stateinifdebug_parser()thenFormat.printf"%a[3] = %a@."Var.printyVar.printz;letx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;compileinfos(pc+1)(State.pop1state)(Let(x,Const0l)::Set_field(y,3,z)::instrs)|SETFIELD->lety=State.accustateinletz=State.peek0stateinletn=getucode(pc+1)inifdebug_parser()thenFormat.printf"%a[%d] = %a@."Var.printynVar.printz;letx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;compileinfos(pc+2)(State.pop1state)(Let(x,Const0l)::Set_field(y,n,z)::instrs)|SETFLOATFIELD->lety=State.accustateinletz=State.peek0stateinletn=getucode(pc+1)inifdebug_parser()thenFormat.printf"%a[%d] = %a@."Var.printynVar.printz;letx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;compileinfos(pc+2)(State.pop1state)(Let(x,Const0l)::Set_field(y,n,z)::instrs)|VECTLENGTH->lety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a.length@."Var.printxVar.printy;compileinfos(pc+1)state(Let(x,Prim(Vectlength,[Pvy]))::instrs)|GETVECTITEM->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[%a]@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Array_get,[Pvy;Pvz]))::instrs)|SETVECTITEM->ifdebug_parser()thenFormat.printf"%a[%a] = %a@."Var.print(State.accustate)Var.print(State.peek0state)Var.print(State.peek1state);letinstrs=Array_set(State.accustate,State.peek0state,State.peek1state)::instrsinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;compileinfos(pc+1)(State.pop2state)(Let(x,Const0l)::instrs)|GETSTRINGCHAR->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[%a]@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"caml_string_unsafe_get",[Pvy;Pvz]))::instrs)|GETBYTESCHAR->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a[%a]@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"caml_bytes_unsafe_get",[Pvy;Pvz]))::instrs)|SETBYTESCHAR->ifdebug_parser()thenFormat.printf"%a[%a] = %a@."Var.print(State.accustate)Var.print(State.peek0state)Var.print(State.peek1state);letx=State.accustateinlety=State.peek0stateinletz=State.peek1stateinlett,state=State.fresh_varstateinletinstrs=Let(t,Prim(Extern"caml_bytes_unsafe_set",[Pvx;Pvy;Pvz]))::instrsinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = 0@."Var.printx;compileinfos(pc+1)(State.pop2state)(Let(x,Const0l)::instrs)|BRANCH->letoffset=getscode(pc+1)inifdebug_parser()thenFormat.printf"... (branch)@.";instrs,Branch(pc+offset+1,State.stack_varsstate),state|BRANCHIF->letoffset=getscode(pc+1)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(IsTrue,x,(pc+offset+1,args),(pc+2,args)),state|BRANCHIFNOT->letoffset=getscode(pc+1)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(IsTrue,x,(pc+2,args),(pc+offset+1,args)),state|SWITCH->ifdebug_parser()thenFormat.printf"switch ...@.";letsz=getucode(pc+1)inletx=State.accustateinletargs=State.stack_varsstateinletl=szland0xFFFFinletit=Array.init(szland0XFFFF)~f:(funi->pc+2+getscode(pc+2+i),args)inletbt=Array.init(szlsr16)~f:(funi->pc+2+getscode(pc+2+l+i),args)ininstrs,Switch(x,it,bt),state|BOOLNOT->lety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = !%a@."Var.printxVar.printy;compileinfos(pc+1)state(Let(x,Prim(Not,[Pvy]))::instrs)|PUSHTRAP->letaddr=pc+1+getscode(pc+1)inletx,state'=State.fresh_varstateincompile_blockinfos.blocksinfos.debugcodeaddrstate';compile_blockinfos.blocksinfos.debugcode(pc+2){(State.push_handlerstatexaddr)withState.stack=State.Dummy::State.Dummy::State.Dummy::State.Dummy::state.State.stack};(instrs,Pushtrap((pc+2,State.stack_varsstate),x,(addr,State.stack_varsstate'),Addr.Set.empty),state)|POPTRAP->letaddr=pc+1inlethandler_addr=State.addr_of_current_handlerstateincompile_blockinfos.blocksinfos.debugcodeaddr(State.pop4(State.pop_handlerstate));instrs,Poptrap((addr,State.stack_varsstate),handler_addr),state|RERAISE|RAISE_NOTRACE|RAISE->letkind=matchinstr.Instr.codewith|RERAISE->`Reraise|RAISE_NOTRACE->`Notrace|RAISE->`Normal|_->assertfalseinifdebug_parser()thenFormat.printf"throw(%a)@."Var.print(State.accustate);instrs,Raise(State.accustate,kind),state|CHECK_SIGNALS->compileinfos(pc+1)stateinstrs|C_CALL1->letprim=primitive_namestate(getucode(pc+1))inifPrimitive.resolveprim="%identity"then(* This is a no-op *)compileinfos(pc+2)stateinstrselselety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = ccall \"%s\" (%a)@."Var.printxprimVar.printy;compileinfos(pc+2)state(Let(x,Prim(Externprim,[Pvy]))::instrs)|C_CALL2->letprim=primitive_namestate(getucode(pc+1))inlety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = ccall \"%s\" (%a, %a)@."Var.printxprimVar.printyVar.printz;compileinfos(pc+2)(State.pop1state)(Let(x,Prim(Externprim,[Pvy;Pvz]))::instrs)|C_CALL3->letprim=primitive_namestate(getucode(pc+1))inlety=State.accustateinletz=State.peek0stateinlett=State.peek1stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = ccall \"%s\" (%a, %a, %a)@."Var.printxprimVar.printyVar.printzVar.printt;compileinfos(pc+2)(State.pop2state)(Let(x,Prim(Externprim,[Pvy;Pvz;Pvt]))::instrs)|C_CALL4->letnargs=4inletprim=primitive_namestate(getucode(pc+1))inletstate=State.pushstateinletx,state=State.fresh_varstateinletargs,state=State.grabnargsstateinifdebug_parser()then(Format.printf"%a = ccal \"%s\" ("Var.printxprim;fori=0tonargs-1doifi>0thenFormat.printf", ";Format.printf"%a"Var.print(List.nthargsi)done;Format.printf")@.");compileinfos(pc+2)state(Let(x,Prim(Externprim,List.mapargs~f:(funx->Pvx)))::instrs)|C_CALL5->letnargs=5inletprim=primitive_namestate(getucode(pc+1))inletstate=State.pushstateinletx,state=State.fresh_varstateinletargs,state=State.grabnargsstateinifdebug_parser()then(Format.printf"%a = ccal \"%s\" ("Var.printxprim;fori=0tonargs-1doifi>0thenFormat.printf", ";Format.printf"%a"Var.print(List.nthargsi)done;Format.printf")@.");compileinfos(pc+2)state(Let(x,Prim(Externprim,List.mapargs~f:(funx->Pvx)))::instrs)|C_CALLN->letnargs=getucode(pc+1)inletprim=primitive_namestate(getucode(pc+2))inletstate=State.pushstateinletx,state=State.fresh_varstateinletargs,state=State.grabnargsstateinifdebug_parser()then(Format.printf"%a = ccal \"%s\" ("Var.printxprim;fori=0tonargs-1doifi>0thenFormat.printf", ";Format.printf"%a"Var.print(List.nthargsi)done;Format.printf")@.");compileinfos(pc+3)state(Let(x,Prim(Externprim,List.mapargs~f:(funx->Pvx)))::instrs)|(CONST0|CONST1|CONST2|CONST3)ascc->letx,state=State.fresh_varstateinletn=matchccwith|CONST0->0l|CONST1->1l|CONST2->2l|CONST3->3l|_->assertfalseinifdebug_parser()thenFormat.printf"%a = %ld@."Var.printxn;compileinfos(pc+1)state(Let(x,Constn)::instrs)|CONSTINT->letn=gets32code(pc+1)inletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %ld@."Var.printxn;compileinfos(pc+2)state(Let(x,Constn)::instrs)|(PUSHCONST0|PUSHCONST1|PUSHCONST2|PUSHCONST3)ascc->letstate=State.pushstateinletx,state=State.fresh_varstateinletn=matchccwith|PUSHCONST0->0l|PUSHCONST1->1l|PUSHCONST2->2l|PUSHCONST3->3l|_->assertfalseinifdebug_parser()thenFormat.printf"%a = %ld@."Var.printxn;compileinfos(pc+1)state(Let(x,Constn)::instrs)|PUSHCONSTINT->letstate=State.pushstateinletn=gets32code(pc+1)inletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %ld@."Var.printxn;compileinfos(pc+2)state(Let(x,Constn)::instrs)|NEGINT->lety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = -%a@."Var.printxVar.printy;compileinfos(pc+1)state(Let(x,Prim(Extern"%int_neg",[Pvy]))::instrs)|ADDINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a + %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_add",[Pvy;Pvz]))::instrs)|SUBINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a - %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_sub",[Pvy;Pvz]))::instrs)|MULINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a * %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_mul",[Pvy;Pvz]))::instrs)|DIVINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a / %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_div",[Pvy;Pvz]))::instrs)|MODINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a %% %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_mod",[Pvy;Pvz]))::instrs)|ANDINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a & %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_and",[Pvy;Pvz]))::instrs)|ORINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a | %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_or",[Pvy;Pvz]))::instrs)|XORINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a ^ %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_xor",[Pvy;Pvz]))::instrs)|LSLINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a << %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_lsl",[Pvy;Pvz]))::instrs)|LSRINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a >>> %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_lsr",[Pvy;Pvz]))::instrs)|ASRINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a >> %a@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Extern"%int_asr",[Pvy;Pvz]))::instrs)|EQ->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = mk_bool(%a == %a)@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Eq,[Pvy;Pvz]))::instrs)|NEQ->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = mk_bool(%a != %a)@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Neq,[Pvy;Pvz]))::instrs)|LTINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = mk_bool(%a < %a)@."Var.printxVar.printyVar.print(State.peek0state);compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Lt,[Pvy;Pvz]))::instrs)|LEINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = mk_bool(%a <= %a)@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Le,[Pvy;Pvz]))::instrs)|GTINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = mk_bool(%a > %a)@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Lt,[Pvz;Pvy]))::instrs)|GEINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = mk_bool(%a >= %a)@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Le,[Pvz;Pvy]))::instrs)|OFFSETINT->letn=gets32code(pc+1)inlety=State.accustateinletz,state=State.fresh_varstateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %a + %ld@."Var.printxVar.printyn;compileinfos(pc+2)state(Let(x,Prim(Extern"%int_add",[Pvy;Pvz]))::Let(z,Constn)::instrs)|OFFSETREF->letn=getscode(pc+1)inletx=State.accustateinifdebug_parser()thenFormat.printf"%a += %d@."Var.printxn;letinstrs=Offset_ref(x,n)::instrsinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"x = 0@.";compileinfos(pc+2)state(Let(x,Const0l)::instrs)|ISINT->lety=State.accustateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = !%a@."Var.printxVar.printy;compileinfos(pc+1)state(Let(x,Prim(IsInt,[Pvy]))::instrs)|BEQ->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(CEqn,x,(pc+offset+2,args),(pc+3,args)),state|BNEQ->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(CEqn,x,(pc+3,args),(pc+offset+2,args)),state|BLTINT->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(CLtn,x,(pc+offset+2,args),(pc+3,args)),state|BLEINT->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(CLen,x,(pc+offset+2,args),(pc+3,args)),state|BGTINT->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(CLen,x,(pc+3,args),(pc+offset+2,args)),state|BGEINT->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(CLtn,x,(pc+3,args),(pc+offset+2,args)),state|BULTINT->letn=getu32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(CUltn,x,(pc+offset+2,args),(pc+3,args)),state|BUGEINT->letn=getu32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(CUltn,x,(pc+3,args),(pc+offset+2,args)),state|ULTINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = mk_bool(%a <= %a) (unsigned)@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Ult,[Pvy;Pvz]))::instrs)|UGEINT->lety=State.accustateinletz=State.peek0stateinletx,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = mk_bool(%a >= %a)@."Var.printxVar.printyVar.printz;compileinfos(pc+1)(State.pop1state)(Let(x,Prim(Ult,[Pvz;Pvy]))::instrs)|GETPUBMET->letn=gets32code(pc+1)inletcache=!method_cache_idinincrmethod_cache_id;letobj=State.accustateinletstate=State.pushstateinlettag,state=State.fresh_varstateinletm,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = %ld@."Var.printtagn;ifdebug_parser()thenFormat.printf"%a = caml_get_public_method(%a, %a)@."Var.printmVar.printobjVar.printtag;compileinfos(pc+3)state(Let(m,Prim(Extern"caml_get_public_method",[Pvobj;Pvtag;Pc(Int(Int32.of_intcache))]))::Let(tag,Constn)::instrs)|GETDYNMET->lettag=State.accustateinletobj=State.peek0stateinletm,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = caml_get_public_method(%a, %a)@."Var.printmVar.printobjVar.printtag;compileinfos(pc+1)state(Let(m,Prim(Extern"caml_get_public_method",[Pvobj;Pvtag;Pc(Int0l)]))::instrs)|GETMETHOD->letlab=State.accustateinletobj=State.peek0stateinletmeths,state=State.fresh_varstateinletm,state=State.fresh_varstateinifdebug_parser()thenFormat.printf"%a = lookup(%a, %a)@."Var.printmVar.printobjVar.printlab;compileinfos(pc+1)state(Let(m,Prim(Array_get,[Pvmeths;Pvlab]))::Let(meths,Field(obj,0))::instrs)|STOP->instrs,Stop,state|EVENT|BREAK|FIRST_UNIMPLEMENTED_OP->assertfalse)(****)letmatch_exn_traps(blocks:'aAddr.Map.t)=letmap=Addr.Map.fold(fun_blockmap->matchblock.branchwith|Poptrap((cont,_),addr_push)->letset=tryAddr.Set.addcont(Addr.Map.findaddr_pushmap)withNot_found->Addr.Set.singletoncontinAddr.Map.addaddr_pushsetmap|_->map)blocksAddr.Map.emptyinAddr.Map.fold(funpcconts'blocks->matchAddr.Map.findpcblockswith|{branch=Pushtrap(cont1,x,cont2,conts);_}asblock->assert(conts=Addr.Set.empty);letbranch=Pushtrap(cont1,x,cont2,conts')inAddr.Map.addpc{blockwithbranch}blocks|_->assertfalse)mapblocks(****)letparse_bytecode~debugcodeglobalsdebug_data=letstate=State.initialglobalsinCode.Var.reset();letblocks=Blocks.analyse(ifdebug=`Fullthendebug_dataelseDebug.create())codeinletblocks=(* Disabled. [pc] might not be an appropriate place to split blocks *)iffalse&&debug=`FullthenDebug.folddebug_data(funpc_blocks->Blocks.addblockspc)blockselseblocksinletblocks'=Blocks.finish_analysisblocksinifnot(Blocks.is_emptyblocks')thencompile_blockblocks'debug_datacode0state;letblocks=Addr.Map.mapi(fun_(state,instr,last)->{params=State.stack_varsstate;handler=State.current_handlerstate;body=instr;branch=last})!compiled_blocksincompiled_blocks:=Addr.Map.empty;tagged_blocks:=Addr.Set.empty;letfree_pc=String.lengthcode/4inletblocks=match_exn_trapsblocksin0,blocks,free_pc(* HACK - override module *)letoverride_global=letjsmodulenamefunc=Prim(Extern"%overrideMod",[Pc(Stringname);Pc(Stringfunc)])in[("CamlinternalMod",fun_originstrs->letx=Var.fresh_n"internalMod"inletinit_mod=Var.fresh_n"init_mod"inletupdate_mod=Var.fresh_n"update_mod"in(x,Let(x,Block(0,[|init_mod;update_mod|]))::Let(init_mod,jsmodule"CamlinternalMod""init_mod")::Let(update_mod,jsmodule"CamlinternalMod""update_mod")::instrs))](* HACK END *)letseek_sectiontocicname=letrecseek_seccurr_ofs=function|[]->raiseNot_found|(n,len)::rem->ifn=namethen(seek_inic(curr_ofs-len);len)elseseek_sec(curr_ofs-len)reminseek_sec(in_channel_lengthic-16-(8*List.lengthtoc))tocletread_tocic=letpos_trailer=in_channel_lengthic-16inseek_inicpos_trailer;letnum_sections=input_binary_inticinseek_inic(pos_trailer-(8*num_sections));letsection_table=ref[]infor_i=1tonum_sectionsdoletname=really_input_stringic4inletlen=input_binary_inticinsection_table:=(name,len)::!section_tabledone;!section_tableletexe_from_channel~includes?(toplevel=false)?(expunge=fun_->`Keep)?(dynlink=false)~debug~debug_dataic=lettoc=read_tocicinletprim_size=seek_sectiontocic"PRIM"inletprim=really_input_stringicprim_sizeinletprimitive_table=Array.of_list(String.split_char~sep:'\000'prim)inletcode_size=seek_sectiontocic"CODE"inletcode=really_input_stringiccode_sizeinignore(seek_sectiontocic"DATA");letinit_data:Obj.tarray=input_valueicinignore(seek_sectiontocic"SYMB");letorig_symbols:Ocaml_compiler.Symtable.GlobalMap.t=input_valueicinignore(seek_sectiontocic"CRCS");letorig_crcs:(string*Digest.toption)list=input_valueicinletkeeps=lett=Hashtbl.create17inList.iter~f:(fun(_,s)->Hashtbl.addts())predefined_exceptions;List.iter~f:(funs->Hashtbl.addts())["Outcometree";"Topdirs";"Toploop"];tinletkeeps=tryHashtbl.findkeepss;truewithNot_found->(matchexpungeswith|`Keep->true|`Skip->false)inletcrcs=List.filter~f:(fun(unit,_crc)->keepunit)orig_crcsinletsymbols=Ocaml_compiler.Symtable.GlobalMap.filter_global_map(funid->keep(Ident.nameid))orig_symbolsin(ifdebug=`Nothen()elsetryignore(seek_sectiontocic"DBUG");Debug.readdebug_data~crcs~includesicwithNot_found->(matchdebugwith|`No->assertfalse|`Names->()|`Full->warn"Warning: Program not linked with -g, original variable names and locations \
not availalbe.@."));letglobals=make_globals(Array.lengthinit_data)init_dataprimitive_tablein(* Initialize module override mechanism *)List.iteroverride_global~f:(fun(name,v)->tryletnn=Ident.create_persistentnameinleti=Ocaml_compiler.Symtable.GlobalMap.findnnorig_symbolsinglobals.override.(i)<-Somev;ifdebug_parser()thenFormat.eprintf"overriding global %s@."namewithNot_found->());iftoplevel||dynlinkthen(* export globals *)Ocaml_compiler.Symtable.GlobalMap.iter(funidn->globals.named_value.(n)<-Some(Ident.nameid);globals.is_exported.(n)<-true)symbols(* @vouillon: *)(* we should then use the -linkall option to build the toplevel. *)(* The OCaml compiler can generate code using this primitive but *)(* does not use it itself. This is the only primitive in this case. *)(* Ideally, Js_of_ocaml should parse the .mli files for primitives as *)(* well as marking this primitive as potentially used. But *)(* the -linkall option is probably good enough. *)(* Primitive.mark_used "caml_string_greaterthan" *);letp=parse_bytecode~debugcodeglobalsdebug_datain(* register predefined exception *)letbody=List.fold_leftpredefined_exceptions~init:[]~f:(funbody(i,name)->globals.named_value.(i)<-Somename;letbody=register_global~force:trueglobalsibodyinglobals.is_exported.(i)<-false;body)inletbody=Array.fold_right_iglobals.constants~init:body~f:(funi_l->matchglobals.vars.(i)with|Somexwhenglobals.is_const.(i)->letl=register_globalglobalsilinLet(x,Constant(Constants.parseglobals.constants.(i)))::l|_->l)inletbody=iftoplevelthen(* Include linking information *)lettoc=["SYMB",Obj.reprsymbols;"CRCS",Obj.reprcrcs;"PRIM",Obj.reprprim]inletgdata=Var.fresh()inletinfos=["toc",Constants.parse(Obj.reprtoc);"prim_count",Int(Int32.of_int(Array.lengthglobals.primitives))]inletbody=List.fold_leftinfos~init:body~f:(funrem(name,const)->letc=Var.fresh()inLet(c,Constantconst)::Let(Var.fresh(),Prim(Extern"caml_js_set",[Pvgdata;Pc(Stringname);Pvc]))::rem)inLet(gdata,Prim(Extern"caml_get_global_data",[]))::bodyelsebodyin(* List interface files *)letis_module=letis_ident_char=function|'A'..'Z'|'a'..'z'|'_'|'\''|'0'..'9'->true|_->falseinletis_uppercase=function|'A'..'Z'->true|_->falseinfunname->tryifString.lengthname=0thenraiseExit;ifnot(is_uppercasename.[0])thenraiseExit;fori=1toString.lengthname-1doifnot(is_ident_charname.[i])thenraiseExitdone;truewithExit->falseinletcmis=letexception_ids=List.fold_leftpredefined_exceptions~init:(-1)~f:(funacc(i,_)->maxacci)iniftoplevel&&Config.Flag.include_cmis()thenOcaml_compiler.Symtable.GlobalMap.fold(funidnumacc->ifnum>exception_ids&&Ident.globalid&&is_module(Ident.nameid)thenStringSet.add(Ident.nameid)accelseacc)symbolsStringSet.emptyelseStringSet.emptyinprependpbody,cmis,debug_data(* As input: list of primitives + size of global table *)letfrom_bytesprimitives(code:code)=letglobals=make_globals0[||]primitivesinletdebug_data=Debug.create()inletp=parse_bytecode~debug:`Nocodeglobalsdebug_datainletgdata=Var.fresh()inletbody=Array.fold_right_iglobals.vars~init:[]~f:(funivarl->matchvarwith|Somexwhenglobals.is_const.(i)->Let(x,Field(gdata,i))::l|_->l)inletbody=Let(gdata,Prim(Extern"caml_get_global_data",[]))::bodyinprependpbody,debug_dataletfrom_stringprimitives(code:string)=from_bytesprimitivescodemoduleReloc=structletgen_patch_intbuffposn=Bytes.setbuff(pos+0)(Char.unsafe_chrn);Bytes.setbuff(pos+1)(Char.unsafe_chr(nasr8));Bytes.setbuff(pos+2)(Char.unsafe_chr(nasr16));Bytes.setbuff(pos+3)(Char.unsafe_chr(nasr24))typet={mutablepos:int;mutableconstants:Obj.tlist;names:(string,int)Hashtbl.t;primitives:(string,int)Hashtbl.t}letcreate()=letconstants=[]in{pos=List.lengthconstants;constants;names=Hashtbl.create17;primitives=Hashtbl.create17}letstep1tcompunitcode=letopenCmo_formatinList.itercompunit.cu_primitives~f:(funname->Hashtbl.addt.primitivesname(Hashtbl.lengtht.primitives));letslot_for_literalsc=t.constants<-Ocaml_compiler.obj_of_constsc::t.constants;letpos=t.posint.pos<-succt.pos;posinletnum_of_primname=tryHashtbl.findt.primitivesnamewithNot_found->leti=Hashtbl.lengtht.primitivesinHashtbl.addt.primitivesnamei;iinList.itercompunit.cu_reloc~f:(function|Reloc_literalsc,pos->gen_patch_intcodepos(slot_for_literalsc)|Reloc_primitivename,pos->gen_patch_intcodepos(num_of_primname)|_->())letstep2tcompunitcode=letopenCmo_formatinletnextid=letname=Ident.nameidintryHashtbl.findt.namesnamewithNot_found->letx=t.posint.pos<-succt.pos;Hashtbl.addt.namesnamex;xinletslot_for_getglobalid=nextidinletslot_for_setglobalid=nextidinList.itercompunit.cu_reloc~f:(function|Reloc_getglobalid,pos->gen_patch_intcodepos(slot_for_getglobalid)|Reloc_setglobalid,pos->gen_patch_intcodepos(slot_for_setglobalid)|_->())letprimitivest=letl=Hashtbl.lengtht.primitivesinleta=Array.makel""inHashtbl.iter(funnamei->a.(i)<-name)t.primitives;aletconstantst=letlen=List.lengtht.constantsinleta=Array.makelen(Obj.repr0)inList.iterit.constants~f:(funio->a.(len-1-i)<-o);(* WARNING: [Obj.t array] is dangerous.
Make sure we don't end up with an unboxed float array. *)assert(Obj.tag(Obj.repra)=0);aletmake_globalst=letprimitives=primitivestinletconstants=constantstinletglobals=make_globals(Array.lengthconstants)constantsprimitivesinresize_globalsglobalst.pos;Hashtbl.iter(funnamei->globals.named_value.(i)<-Somename)t.names;(* Initialize module override mechanism *)List.iteroverride_global~f:(fun(name,v)->tryleti=Hashtbl.findt.namesnameinglobals.override.(i)<-Somev;ifdebug_parser()thenFormat.eprintf"overriding global %s@."namewithNot_found->());globalsendletfrom_compilation_units~includes:_~toplevel~debug~debug_datal=letreloc=Reloc.create()inList.iterl~f:(fun(compunit,code)->Reloc.step1reloccompunitcode);List.iterl~f:(fun(compunit,code)->Reloc.step2reloccompunitcode);letglobals=Reloc.make_globalsrelocinletcode=letl=List.mapl~f:(fun(_,c)->Bytes.to_stringc)inString.concat~sep:""linletprog=parse_bytecode~debugcodeglobalsdebug_datainletgdata=Var.fresh_n"global_data"inletbody=Array.fold_right_iglobals.vars~init:[]~f:(funivarl->matchvarwith|Somexwhenglobals.is_const.(i)->(matchglobals.named_value.(i)with|None->letl=register_globalglobalsilinletcst=Constants.parseglobals.constants.(i)in(matchcst,Code.Var.get_namexwith|(Stringstr|IStringstr),None->Code.Var.namex(Printf.sprintf"cst_%s"str)|_->());Let(x,Constantcst)::l|Somename->Var.namexname;Let(x,Prim(Extern"caml_js_get",[Pvgdata;Pc(IStringname)]))::l)|_->l)inletbody=Let(gdata,Prim(Extern"caml_get_global_data",[]))::bodyinletcmis=iftoplevel&&Config.Flag.include_cmis()thenList.fold_leftl~init:StringSet.empty~f:(funacc(compunit,_)->StringSet.addcompunit.Cmo_format.cu_nameacc)elseStringSet.emptyinprependprogbody,cmis,debug_dataletfrom_channel?(includes=[])?(toplevel=false)?expunge?(dynlink=false)?(debug=`No)ic=letdebug_data=Debug.create()inletformat=tryletheader=really_input_stringicMagic_number.sizein`Pre(Magic_number.of_stringheader)with_->letpos_magic=in_channel_lengthic-Magic_number.sizeinseek_inicpos_magic;letheader=really_input_stringicMagic_number.sizein`Post(Magic_number.of_stringheader)inmatchformatwith|`Premagic->(matchMagic_number.kindmagicwith|`Cmo->ifConfig.Flag.check_magic()&&magic<>Magic_number.current_cmothenraiseMagic_number.(Bad_magic_versionmagic);letcompunit_pos=input_binary_inticinseek_iniccompunit_pos;letcompunit:Cmo_format.compilation_unit=input_valueicinseek_iniccompunit.Cmo_format.cu_pos;letcode=Bytes.createcompunit.Cmo_format.cu_codesizeinreally_inputiccode0compunit.Cmo_format.cu_codesize;ifdebug=`No||compunit.Cmo_format.cu_debug=0then()else(seek_iniccompunit.Cmo_format.cu_debug;Debug.read_event_listdebug_data~crcs:[]~includes~orig:0ic);leta,b,c=from_compilation_units~toplevel~includes~debug~debug_data[compunit,code]ina,b,c,false|`Cma->ifConfig.Flag.check_magic()&&magic<>Magic_number.current_cmathenraiseMagic_number.(Bad_magic_versionmagic);letpos_toc=input_binary_inticin(* Go to table of contents *)seek_inicpos_toc;letlib:Cmo_format.library=input_valueicinletorig=ref0inletunits=List.maplib.Cmo_format.lib_units~f:(funcompunit->seek_iniccompunit.Cmo_format.cu_pos;letcode=Bytes.createcompunit.Cmo_format.cu_codesizeinreally_inputiccode0compunit.Cmo_format.cu_codesize;ifdebug=`No||compunit.Cmo_format.cu_debug=0then()else(seek_iniccompunit.Cmo_format.cu_debug;Debug.read_event_listdebug_data~crcs:[]~includes~orig:!origic);orig:=!orig+compunit.Cmo_format.cu_codesize;compunit,code)inleta,b,c=from_compilation_units~toplevel~includes~debug~debug_dataunitsina,b,c,false|_->raiseMagic_number.(Bad_magic_number(to_stringmagic)))|`Postmagic->(matchMagic_number.kindmagicwith|`Exe->ifConfig.Flag.check_magic()&&magic<>Magic_number.current_exethenraiseMagic_number.(Bad_magic_versionmagic);leta,b,c=exe_from_channel~includes~toplevel?expunge~dynlink~debug~debug_dataicinCode.invarianta;a,b,c,true|_->raiseMagic_number.(Bad_magic_number(to_stringmagic)))letpredefined_exceptions()=letbody=letopenCodeinList.mappredefined_exceptions~f:(fun(index,name)->letexn=Var.fresh()inletv_name=Var.fresh()inletv_name_js=Var.fresh()inletv_index=Var.fresh()in[Let(v_name,Constant(Stringname));Let(v_name_js,Prim(Extern"caml_js_from_string",[Pc(IStringname)]));Let(v_index,Constant(Int(Int32.of_int(-index))));Let(exn,Block(248,[|v_name;v_index|]));Let(Var.fresh(),Prim(Extern"caml_register_global",[Pc(Int(Int32.of_intindex));Pvexn;Pvv_name_js]))])|>List.concatinletblock={params=[];handler=None;body;branch=Stop}in0,Addr.Map.singleton0block,1