1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575(* 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.
*)open!StdlibopenCodeopenInstrletdebug_parser=Debug.find"parser"letdebug_sourcemap=Debug.find"sourcemap"typebytecode=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:sigtypetvalnames:t->boolvaltoplevel:t->boolvalenabled:t->boolvalis_empty:t->boolvaldbg_section_needed:t->boolvalpropagate:Code.Var.tlist->Code.Var.tlist->unitvalfind:t->Code.Addr.t->(int*string*Ident.t)list*Env.summaryvalfind_loc:t->?after:bool->int->Parse_info.toptionvalfind_source:t->string->stringoptionvalmem:t->Code.Addr.t->boolvalread:t->crcs:(string*stringoption)list->includes:stringlist->in_channel->unitvalread_event_list:t->crcs:(string*stringoption)list->includes:stringlist->orig:int->in_channel->unitvalcreate:toplevel:bool->bool->tvalfold:t->(Code.Addr.t->Instruct.debug_event->'a->'a)->'a->'avalpaths:t->units:StringSet.t->StringSet.tend=structopenInstructtypeml_unit={module_name:string;fname:string;crc:stringoption;paths:stringlist;source:stringoption}moduleString_table=Hashtbl.Make(String)moduleInt_table=Hashtbl.Make(Int)typet={events_by_pc:(debug_event*ml_unit)Int_table.t;units:(string*string,ml_unit)Hashtbl.t;pos_fname_to_source:stringString_table.t;toplevel:bool;names:bool;enabled:bool}letnamest=t.nameslettoplevelt=t.toplevelletenabledt=t.enabledletdbg_section_neededt=t.names||t.toplevel||t.enabledletrelocate_eventorigev=ev.ev_pos<-(orig+ev.ev_pos)/4letcreate~toplevelenabled=letnames=enabled||Config.Flag.pretty()in{events_by_pc=Int_table.create17;units=Hashtbl.create17;pos_fname_to_source=String_table.create17;names;toplevel;enabled}letis_emptyt=Int_table.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=letrewrite_pathpath=ifFilename.is_relativepaththenpathelsematchBuild_path_prefix_map.get_build_path_prefix_map()with|Somemap->Build_path_prefix_map.rewrite(Build_path_prefix_map.flipmap)path|None->pathinletread_pathsic:stringlist=List.map(input_valueic)~f:rewrite_pathinfun{events_by_pc;units;pos_fname_to_source;toplevel=_;names;enabled}~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)inletsource=matchsourcewith|None->None|Somesource->Some(Fs.absolute_pathsource)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}in(matchpos_fname,sourcewith|"_none_",_|_,None->()|pos_fname,Somesource->String_table.addpos_fname_to_sourcepos_fnamesource);Hashtbl.addunits(ev_module,pos_fname)u;uinrelocate_eventorigev;ifenabled||namesthenInt_table.addevents_by_pcev.ev_pos(ev,unit);())letfind_source{pos_fname_to_source;_}pos_fname=matchString_table.find_allpos_fname_to_sourcepos_fnamewith|[x]->Somex|[]|_::_::_->Noneletreadt~crcs~includesic=letlen=input_binary_inticinfor_i=0tolen-1doletorig=input_binary_inticinread_event_listt~crcs~includes~origicdoneletfind{events_by_pc;_}pc=tryletev,_=Int_table.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;_}=Int_table.memevents_by_pcletfind_loc{events_by_pc;_}?(after=false)pc=tryletbefore,(ev,unit)=tryfalse,Int_table.findevents_by_pcpcwithNot_found->((true,tryInt_table.findevents_by_pc(pc+1)withNot_found->(tryInt_table.findevents_by_pc(pc+2)withNot_found->Int_table.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.t_of_position~srcpos)withNot_found->Noneletrecpropagatel1l2=matchl1,l2with|v1::r1,v2::r2->Var.propagate_namev1v2;propagater1r2|_->()letfoldtfacc=Int_table.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.t->bytecode->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=letdebug_data=ifDebug.enableddebug_datathendebug_dataelseDebug.create~toplevel:falsefalseinletblocks=Addr.Set.emptyinletlen=String.lengthcode/4inletblocks=addblocks0inletblocks=addblocksleninscandebug_datablockscode0lenend(* Parse constants *)moduleConstants:sigvalparse:Obj.t->Code.constantvalinlined:Code.constant->boolend=struct(* In order to check that two custom objects share the same kind, we
compare their identifier. The identifier is currently extracted
from the marshaled value. *)letident_of_customx=(* Make sure tags are equal to custom_tag.
Note that in javascript [0l] and [0n] are not encoded as custom blocks. *)ifObj.tagx<>Obj.custom_tagthenNoneelsetryletbin=Marshal.to_stringx[]inmatchChar.codebin.[20]with|0x12|0x18|0x19->letlast=String.index_frombin21'\000'inletname=String.subbin~pos:21~len:(last-21)inSomename|_->assertfalsewith_->assertfalseletsame_identxy=matchywith|Somey->String.equalxy|None->falseletident_32=ident_of_custom(Obj.repr0l)letident_64=ident_of_custom(Obj.repr0L)letident_native=ident_of_custom(Obj.repr0n)letrecparsex=ifObj.is_blockxthenlettag=Obj.tagxiniftag=Obj.string_tagthenString(Obj.magicx:string)elseiftag=Obj.double_tagthenFloat(Obj.magicx:float)elseiftag=Obj.double_array_tagthenFloat_array(Array.init(Obj.sizex)~f:(funi->Obj.double_fieldxi))elseiftag=Obj.custom_tagthenmatchident_of_customxwith|Somenamewhensame_identnameident_32->Int(Obj.magicx:int32)|Somenamewhensame_identnameident_native->leti:nativeint=Obj.magicxinInt(Int32.of_nativeint_warning_on_overflowi)|Somenamewhensame_identnameident_64->Int64(Obj.magicx:int64)|Somename->failwith(Printf.sprintf"parse_bytecode: Don't know what to do with custom block (%s)"name)|None->assertfalseelseiftag<Obj.no_scan_tagthenTuple(tag,Array.init(Obj.sizex)~f:(funi->parse(Obj.fieldxi)),Unknown)elseassertfalseelseleti:int=Obj.magicxinInt(Int32.of_int_warning_on_overflowi)letinlined=function|String_|IString_->false|Float_->true|Float_array_->false|Int64_->false|Tuple_->false|Int_->trueendletconsti=Constant(Inti)(* 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:Code.constantarray;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_fnameinParse_info.t_of_position~srcposletrecname_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=ifDebug.namesdebugthenletl,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=g.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=ref1letnew_closure_repr=matchOcaml_version.vwith|`V4_02|`V4_03|`V4_04|`V4_06|`V4_07|`V4_08|`V4_09|`V4_10|`V4_11->false|`V4_12->truetypecompile_info={blocks:Blocks.u;code:string;limit:int;debug:Debug.t}letreccompile_blockblocksdebug_datacodepcstate=ifnot(Addr.Set.mempc!tagged_blocks)then(letlimit=Blocks.nextblockspcinassert(limit>pc);letstring_of_addraddr=matchDebug.find_locdebug_dataaddrwith|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=debug_data}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_blockblocksdebug_datacodepc'state'|Cond(_,(pc1,_),(pc2,_))->compile_blockblocksdebug_datacodepc1state';compile_blockblocksdebug_datacodepc2state'|Switch(_,l1,l2)->Array.iterl1~f:(fun(pc',_)->compile_blockblocksdebug_datacodepc'state');Array.iterl2~f:(fun(pc',_)->compile_blockblocksdebug_datacodepc'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=(* See interp.c *)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=List.mapvals~f:(funx->State.Varx)inletenv=letcode=State.Dummyinletclosure_info=State.Dummyinifnew_closure_reprthencode::closure_info::envelsecode::envinletenv=Array.of_listenvinifdebug_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)->letcode=State.Varxinletclosure_info=State.Dummyinifnew_closure_reprthenenv:=code::closure_info::!envelseenv:=code::!env;ifi>0thenletinfix_tag=State.Dummyinenv:=infix_tag::!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|_->1inletoffset=ifnew_closure_reprtheni*3elsei*2inletstate'=State.start_functionstateenvoffsetinletparams,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(Option.is_noneg.vars.(i));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,[||],Unknown))::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,[||],NotArray))::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,[||],Unknown))::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,[||],NotArray))::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,Unknown))::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|],NotArray))::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|],NotArray))::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|],NotArray))::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,Unknown))::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(x,(pc+offset+1,args),(pc+2,args)),state|BRANCHIFNOT->letoffset=getscode(pc+1)inletx=State.accustateinletargs=State.stack_varsstateininstrs,Cond(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=(* See interp.c *)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))inifString.equal(Primitive.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_varsstateinlety=Var.fresh()in(Let(y,Prim(Eq,[Pc(Intn);Pvx]))::instrs,Cond(y,(pc+offset+2,args),(pc+3,args)),state)|BNEQ->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateinlety=Var.fresh()in(Let(y,Prim(Eq,[Pc(Intn);Pvx]))::instrs,Cond(y,(pc+3,args),(pc+offset+2,args)),state)|BLTINT->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateinlety=Var.fresh()in(Let(y,Prim(Lt,[Pc(Intn);Pvx]))::instrs,Cond(y,(pc+offset+2,args),(pc+3,args)),state)|BLEINT->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateinlety=Var.fresh()in(Let(y,Prim(Le,[Pc(Intn);Pvx]))::instrs,Cond(y,(pc+offset+2,args),(pc+3,args)),state)|BGTINT->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateinlety=Var.fresh()in(Let(y,Prim(Le,[Pc(Intn);Pvx]))::instrs,Cond(y,(pc+3,args),(pc+offset+2,args)),state)|BGEINT->letn=gets32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateinlety=Var.fresh()in(Let(y,Prim(Lt,[Pc(Intn);Pvx]))::instrs,Cond(y,(pc+3,args),(pc+offset+2,args)),state)|BULTINT->letn=getu32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateinlety=Var.fresh()in(Let(y,Prim(Ult,[Pc(Intn);Pvx]))::instrs,Cond(y,(pc+offset+2,args),(pc+3,args)),state)|BUGEINT->letn=getu32code(pc+1)inletoffset=getscode(pc+2)inletx=State.accustateinletargs=State.stack_varsstateinlety=Var.fresh()in(Let(y,Prim(Ult,[Pc(Intn);Pvx]))::instrs,Cond(y,(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(Addr.Set.is_emptyconts);letbranch=Pushtrap(cont1,x,cont2,conts')inAddr.Map.addpc{blockwithbranch}blocks|_->assertfalse)mapblocks(****)typeone={code:Code.program;cmis:StringSet.t;debug:Debug.t}letparse_bytecodecodeglobalsdebug_data=letstate=State.initialglobalsinCode.Var.reset();letblocks=Blocks.analysedebug_datacodeinletblocks=(* Disabled. [pc] might not be an appropriate place to split blocks *)iffalse&&Debug.enableddebug_datathenDebug.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_trapsblocksin{start=0;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|],NotArray))::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->ifString.equalnnamethen(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_tableletfrom_exe?(includes=[])?(toplevel=false)?exported_unit?(dynlink=false)?(debug=false)ic=letdebug_data=Debug.create~topleveldebuginlettoc=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_valueicinletinit_data=Array.map~f:Constants.parseinit_datainignore(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->(matchexported_unitwith|Somel->List.mems~set:l|None->true)inletcrcs=List.filter~f:(fun(unit,_crc)->keepunit)orig_crcsinletsymbols=Ocaml_compiler.Symtable.GlobalMap.filter_global_map(funid->keep(Ident.nameid))orig_symbolsin(ifnot(Debug.dbg_section_neededdebug_data)then()elsetryignore(seek_sectiontocic"DBUG");Debug.readdebug_data~crcs~includesicwithNot_found->ifDebug.enableddebug_data||Debug.topleveldebug_datathenwarn"Warning: Program not linked with -g, original variable names and locations \
not available.@.");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_bytecodecodeglobalsdebug_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,Constantglobals.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.emptyinletcmis=matchexported_unitwith|None->cmis|Somel->iftoplevel&&Config.Flag.include_cmis()thenList.fold_leftl~init:cmis~f:(funaccs->StringSet.addsacc)elsecmisinletcode=prependpbodyinCode.invariantcode;{code;cmis;debug=debug_data}(* As input: list of primitives + size of global table *)letfrom_bytesprimitives(code:bytecode)=letdebug_data=Debug.create~toplevel:falsefalseinletglobals=make_globals0[||]primitivesinletp=parse_bytecodecodeglobalsdebug_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:Code.constantlist;mutablestep2_started:bool;names:(string,int)Hashtbl.t;primitives:(string,int)Hashtbl.t}letcreate()=letconstants=[]in{pos=List.lengthconstants;constants;step2_started=false;names=Hashtbl.create17;primitives=Hashtbl.create17}(* We currently rely on constants to be relocated before globals. *)letstep1tcompunitcode=ift.step2_startedthenassertfalse;letopenCmo_formatinList.itercompunit.cu_primitives~f:(funname->Hashtbl.addt.primitivesname(Hashtbl.lengtht.primitives));letslot_for_literalsc=t.constants<-Ocaml_compiler.constant_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=t.step2_started<-true;letopenCmo_formatinletnextid=letname=Ident.nameidintryHashtbl.findt.namesnamewithNot_found->letpos=t.posint.pos<-succt.pos;Hashtbl.addt.namesnamepos;posinletslot_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=Array.of_list(List.revt.constants)letmake_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_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_bytecodecodeglobalsdebug_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=globals.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.emptyin{code=prependprogbody;cmis;debug=debug_data}letfrom_cmo?(includes=[])?(toplevel=false)?(debug=false)compunitic=letdebug_data=Debug.create~topleveldebuginseek_iniccompunit.Cmo_format.cu_pos;letcode=Bytes.createcompunit.Cmo_format.cu_codesizeinreally_inputiccode0compunit.Cmo_format.cu_codesize;if(not(Debug.dbg_section_neededdebug_data))||compunit.Cmo_format.cu_debug=0then()else(seek_iniccompunit.Cmo_format.cu_debug;Debug.read_event_listdebug_data~crcs:[]~includes~orig:0ic);letp=from_compilation_units~toplevel~includes~debug_data[compunit,code]inCode.invariantp.code;pletfrom_cma?(includes=[])?(toplevel=false)?(debug=false)libic=letdebug_data=Debug.create~topleveldebuginletorig=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;if(not(Debug.dbg_section_neededdebug_data))||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)inletp=from_compilation_units~toplevel~includes~debug_dataunitsinCode.invariantp.code;pletfrom_channelic=letformat=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_number.equalmagicMagic_number.current_cmo)thenraiseMagic_number.(Bad_magic_versionmagic);letcompunit_pos=input_binary_inticinseek_iniccompunit_pos;letcompunit:Cmo_format.compilation_unit=input_valueicin`Cmocompunit|`Cma->ifConfig.Flag.check_magic()&¬(Magic_number.equalmagicMagic_number.current_cma)thenraiseMagic_number.(Bad_magic_versionmagic);letpos_toc=input_binary_inticin(* Go to table of contents *)seek_inicpos_toc;letlib:Cmo_format.library=input_valueicin`Cmalib|_->raiseMagic_number.(Bad_magic_number(to_stringmagic)))|`Postmagic->(matchMagic_number.kindmagicwith|`Exe->ifConfig.Flag.check_magic()&¬(Magic_number.equalmagicMagic_number.current_exe)thenraiseMagic_number.(Bad_magic_versionmagic);`Exe|_->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,Constant(IStringname));Let(v_index,Constant(Int(Int32.of_int(-index))));Let(exn,Block(248,[|v_name;v_index|],NotArray));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}in{start=0;blocks=Addr.Map.singleton0block;free_pc=1}