12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788openUtilsopenProgtypekeep={vars:Sv.t;funs:Sf.t}letwith_varkx={kwithvars=Sv.addxk.vars}letwith_funkf={kwithfuns=Sf.addfk.funs}letinspect_gvark{gs;gv}=matchgswithSlocal->k|Sglob->with_vark(L.unlocgv)letrecinspect_ek=function|Pconst_|Pbool_|Parr_init_->k|Pvarx->inspect_gvarkx|Pget(_,_,_,x,e)|Psub(_,_,_,x,e)->inspect_gvar(inspect_eke)x|Pload(_,_,e)|Papp1(_,e)->inspect_eke|Papp2(_,e1,e2)->inspect_e(inspect_eke1)e2|PappN(_,es)->inspect_eskes|Pif(_,e1,e2,e3)->inspect_e(inspect_e(inspect_eke1)e2)e3andinspect_eskes=List.fold_leftinspect_ekesletrecinspect_ak=function|Pexpre->inspect_eke|PappN_safety(_,es)->inspect_eskes|Pis_var_init_x->k|Pis_mem_init(e1,e2)->inspect_esk[e1;e2]|Pand(e1,e2)->inspect_a(inspect_ake1)e2letinspect_as=List.fold_left(funk(_,a)->inspect_aka)letinspect_lvk=function|Lnone_|Lvar_->k|Lmem(_,_,_,e)|Laset(_,_,_,_,e)|Lasub(_,_,_,_,e)->inspect_ekeletinspect_lvskxs=List.fold_leftinspect_lvkxsletrecinspect_stmtkstmt=List.fold_leftinspect_instrkstmtandinspect_instrki=inspect_instr_rki.i_descandinspect_instr_rk=function|Cassgn(x,_,_,e)->inspect_lv(inspect_eke)x|Copn(xs,_,_,es)|Csyscall(xs,_,es)->inspect_lvs(inspect_eskes)xs|Cassert(_,e)->inspect_ake|Cif(g,a,b)|Cwhile(_,a,g,_,b)->inspect_stmt(inspect_stmt(inspect_ekg)a)b|Cfor(_,(_,e1,e2),s)->inspect_stmt(inspect_esk[e1;e2])s|Ccall(xs,fn,es)->with_fun(inspect_lvs(inspect_eskes)xs)fnletinspect_funkfd=letk=matchfd.f_contractwith|None->k|Somefc->inspect_as(inspect_askfc.f_pre)fc.f_postininspect_stmtkfd.f_bodyletslicefs(gd,fds)=letfuns=List.fold_left(funsn->matchList.find(funfd->String.equalnfd.f_name.fn_name)fdswith|exceptionNot_found->warningAlwaysL.i_dummy"slicing: function ā%sā not found"n;s|fd->Sf.addfd.f_names)Sf.emptyfsinletk=List.fold_left(funkfd->ifSf.memfd.f_namek.funstheninspect_funkfdelsek){vars=Sv.empty;funs}fdsin(* Keep only global variables that are referenced *)letgd=List.filter(fun(x,_)->Sv.memxk.vars)gdin(* Keep only functions that are referenced *)letfds=List.filter(funfd->Sf.memfd.f_namek.funs)fdsin(* Turn export functions that are not in the fs list into inline functions *)letfds=List.map(funfd->ifList.memfd.f_name.fn_namefs||not(FInfo.is_exportfd.f_cc)thenfdelse{fdwithf_cc=Internal})fdsin(gd,fds)