123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535(* ------------------------------------------------------------------------ *)openUtilsopenWsize(* ------------------------------------------------------------------------ *)includeCoreIdent(* ------------------------------------------------------------------------ *)moduleE=Exprtype'lengvar_i='len gvarL.locatedtype'lenggvar={gv:'lengvar_i;gs:E.v_scope;}type'lengexpr=|PconstofZ.t|Pboolofbool|Parr_initof'len|Pvarof'lenggvar|PgetofMemory_model.aligned*Warray_.arr_access*wsize*'lenggvar*'lengexpr|PsubofWarray_.arr_access*wsize*'len*'lenggvar*'lengexpr|PloadofMemory_model.aligned*wsize*'lengexpr|Papp1ofE.sop1*'lengexpr|Papp2ofE.sop2*'lengexpr*'lengexpr|PappNofE.opN*'lengexprlist|Pifof'lengty*'lengexpr*'lengexpr*'lengexprtype'lengexprs='lengexprlistletkind_iv=(L.unlocv).v_kindletty_iv=(L.unlocv).v_tyletis_stack_kindk=matchkwith|Stack_->true|_->falseletis_reg_kindk=matchkwith|Reg_->true|_->falseletreg_kindk=matchkwith|Reg(k,_)->k|_->assertfalseletis_reg_direct_kindk=matchkwith|Reg(_,Direct)->true|_->falseletis_reg_ptr_kindk=matchkwith|Reg(_,Pointer_)->true|_->falseletis_stk_ptr_kindk=matchkwith|Stack(Pointer_)->true|_->falseletis_ptrk=matchkwith|Stackk|Reg(_,k)->k<>Direct|_->falseletis_regxx=matchx.v_kindwith|Reg(Extra,_)->true|_->false(* ------------------------------------------------------------------------ *)type'lenglval=|LnoneofL.t*'lengty|Lvarof'lengvar_i|LmemofMemory_model.aligned*wsize*L.t*'lengexpr|LasetofMemory_model.aligned*Warray_.arr_access*wsize*'lengvar_i*'lengexpr|LasubofWarray_.arr_access*wsize*'len*'lengvar_i*'lengexpr(* Lasub(acc,sz,len,v,e) is the sub-array of v:
- [ws/8 * e; ws/8 * e + ws/8 * len[ if acc = Scale
- [ e; e + ws/8 * len[ if acc = Direct *)type'lenglvals='lenglvallisttype'lengrange=E.dir*'lengexpr*'lengexprtype('len,'info,'asm)ginstr_r=|Cassgnof'lenglval*E.assgn_tag*'lengty*'lengexpr(* turn 'asm Sopn.sopn into 'sopn? could be useful to ensure that we remove things statically *)|Copnof'lenglvals*E.assgn_tag*'asmSopn.sopn*'lengexprs|Csyscallof'lenglvals*BinNums.positiveSyscall_t.syscall_t*'lengexprs|Cifof'lengexpr*('len,'info,'asm)gstmt*('len,'info,'asm)gstmt|Cforof'lengvar_i*'lengrange*('len,'info,'asm)gstmt|CwhileofE.align*('len,'info,'asm)gstmt*'lengexpr*(IInfo.t*'info)*('len,'info,'asm)gstmt|Ccallof'lenglvals*funname*'lengexprsand('len,'info,'asm)ginstr={i_desc:('len,'info,'asm)ginstr_r;i_loc:L.i_loc;i_info:'info;i_annot:Annotations.annotations;}and('len,'info,'asm)gstmt=('len,'info,'asm)ginstrlist(* ------------------------------------------------------------------------ *)type('len,'info,'asm)gfunc={f_loc:L.t;f_annot:FInfo.f_annot;f_info:'info;f_cc:FInfo.call_conv;f_name:funname;f_tyin:'lengtylist;f_args:'lengvarlist;f_body:('len,'info,'asm)gstmt;f_tyout:'lengtylist;f_ret_info:FInfo.return_info;f_ret:'lengvar_ilist}type'lenggexpr=|GEwordof'lengexpr|GEarrayof'lengexprstype('len,'info,'asm)gmod_item=|MIfunof('len,'info,'asm)gfunc|MIparamof('lengvar*'lengexpr)|MIglobalof('lengvar*'lenggexpr)type('len,'info,'asm)gprog=('len,'info,'asm)gmod_itemlist(* first declaration occur at the end (i.e reverse order) *)(* ------------------------------------------------------------------------ *)letgkglobx={gv=x;gs=E.Sglob}letgkvarx={gv=x;gs=E.Slocal}letis_gkvarx=x.gs=E.Slocal(* ------------------------------------------------------------------------ *)(* Parametrized expression *)typepty=pexpr_gtyandpvar=pexpr_gvarandpvar_i=pexpr_gvar_iandplval=pexpr_glvalandplvals=pexpr_glvalsandpexpr=pexpr_gexprandpexpr_=PEofpexpr[@@unboxed]typerange=intgrangetypeepty=pexpr_getytype('info,'asm)pinstr_r=(pexpr_,'info,'asm)ginstr_rtype('info,'asm)pinstr=(pexpr_,'info,'asm)ginstrtype('info,'asm)pstmt=(pexpr_,'info,'asm)gstmttype('info,'asm)pfunc=(pexpr_,'info,'asm)gfunctype('info,'asm)pmod_item=(pexpr_,'info,'asm)gmod_itemtype('info,'asm)pprog=(pexpr_,'info,'asm)gprog(* ------------------------------------------------------------------------ *)modulePV=structtypet=pvarincludeGVletgequalx1x2=equal(L.unlocx1.gv)(L.unlocx2.gv)&&(x1.gs=x2.gs)endmoduleMpv:Map.Swithtypekey=pvar=Map.Make(PV)moduleSpv=Set.Make(PV)(* ------------------------------------------------------------------------ *)letrecpty_equalt1t2=matcht1,t2with|Btyb1,Btyb2->b1=b2|Arr(b1,e1),Arr(b2,e2)->(b1=b2)&&pexpr__equale1e2|_,_->falseandpexpr_equale1e2=matche1,e2with|Pconstn1,Pconstn2->Z.equaln1n2|Pboolb1,Pboolb2->b1=b2|Pvarv1,Pvarv2->PV.gequalv1v2|Pget(al1,a1,b1,v1,e1),Pget(al2,a2,b2,v2,e2)->al1=al2&&a1=a2&&b1=b2&&PV.gequalv1v2&&pexpr_equale1e2|Psub(a1,b1,l1,v1,e1),Psub(a2,b2,l2,v2,e2)->a1=a2&&b1=b2&&pexpr__equall1l2&&PV.gequalv1v2&&pexpr_equale1e2|Pload(al1,b1,e1),Pload(al2,b2,e2)->al1=al2&&b1=b2&&pexpr_equale1e2|Papp1(o1,e1),Papp1(o2,e2)->o1=o2&&pexpr_equale1e2|Papp2(o1,e11,e12),Papp2(o2,e21,e22)->o1=o2&&pexpr_equale11e21&&pexpr_equale12e22|Pif(_,e11,e12,e13),Pif(_,e21,e22,e23)->pexpr_equale11e21&&pexpr_equale12e22&&pexpr_equale13e23|_,_->falseandpexpr__equal(PEe1)(PEe2)=pexpr_equale1e2letepty_equalt1t2=matcht1,t2with|ETbool,ETbool|ETint,ETint->true|ETword(s1,sz1),ETword(s2,sz2)->s1=s2&&sz1=sz2|ETarr(b1,e1),ETarr(b2,e2)->b1=b1&&pexpr__equale1e2|_,_->falseletws_of_ety=function|ETword(_,ws)->ws|_->assertfalse(* ------------------------------------------------------------------------ *)(* Non parametrized expression *)typety=intgtytypevar=intgvartypevar_i=intgvar_itypelval=intglvaltypelvals=intglvallisttypeexpr=intgexprtypeexprs=intgexprlisttype('info,'asm)instr=(int,'info,'asm)ginstrtype('info,'asm)instr_r=(int,'info,'asm)ginstr_rtype('info,'asm)stmt=(int,'info,'asm)gstmttype('info,'asm)func=(int,'info,'asm)gfunctype('info,'asm)mod_item=(int,'info,'asm)gmod_itemtypeglobal_decl=var*Global.glob_valuetype('info,'asm)prog=global_decllist*('info,'asm)funclistmoduleSv=Set.Make(V)moduleMv=Map.Make(V)moduleHv=Hash.Make(V)letvar_of_ident(x:CoreIdent.var):var=xletident_of_var(x:var):CoreIdent.var=x(* -------------------------------------------------------------------- *)(* used variables *)letrvars_vfxs=ifis_gkvarxthenf(L.unlocx.gv)selsesletrecrvars_efs=function|Pconst_|Pbool_|Parr_init_->s|Pvarx->rvars_vfxs|Pget(_,_,_,x,e)|Psub(_,_,_,x,e)->rvars_ef(rvars_vfxs)e|Pload(_,_,e)|Papp1(_,e)->rvars_efse|Papp2(_,e1,e2)->rvars_ef(rvars_efse1)e2|PappN(_,es)->rvars_esfses|Pif(_,e,e1,e2)->rvars_ef(rvars_ef(rvars_efse)e1)e2andrvars_esfses=List.fold_left(rvars_ef)sesletrvars_lvfs=function|Lnone_->s|Lvarx->f(L.unlocx)s|Lmem(_,_,_,e)->rvars_efse|Laset(_,_,_,x,e)|Lasub(_,_,_,x,e)->rvars_ef(f(L.unlocx)s)eletrvars_lvsfslvs=List.fold_left(rvars_lvf)slvsletrecrvars_ifsi=matchi.i_descwith|Cassgn(x,_,_,e)->rvars_ef(rvars_lvfsx)e|Copn(x,_,_,e)|Csyscall(x,_,e)->rvars_esf(rvars_lvsfsx)e|Cif(e,c1,c2)->rvars_cf(rvars_cf(rvars_efse)c1)c2|Cfor(x,(_,e1,e2),c)->rvars_cf(rvars_ef(rvars_ef(f(L.unlocx)s)e1)e2)c|Cwhile(_,c,e,_,c')->rvars_cf(rvars_ef(rvars_cfsc')e)c|Ccall(x,_,e)->rvars_esf(rvars_lvsfsx)eandrvars_cfsc=List.fold_left(rvars_if)scletfold_vars_retfinitfd=List.fold_left(funax->f(L.unlocx)a)initfd.f_retletfold_vars_fcfzfc=leta=fold_vars_retfzfcinrvars_cfafc.f_bodyletvars_retfd=fold_vars_retSv.addSv.emptyfdletvars_lvzx=rvars_lvSv.addzxletvars_ee=rvars_eSv.addSv.emptyeletvars_eses=rvars_esSv.addSv.emptyesletvars_ii=rvars_iSv.addSv.emptyiletvars_cc=rvars_cSv.addSv.emptycletpvars_cc=rvars_cSpv.addSpv.emptycletparamsfc=List.fold_left(funsv->Sv.addvs)Sv.emptyfc.f_argsletvars_fcfc=lets=paramsfcinlets=List.fold_left(funsv->Sv.add(L.unlocv)s)sfc.f_retinrvars_cSv.addsfc.f_bodyletlocalsfc=lets1=paramsfcinlets2=Sv.diff(vars_fcfc)s1inSv.filterV.is_locals2letwritten_lvs=function|Lvarx|Laset(_,_,_,x,_)|Lasub(_,_,_,x,_)->Sv.add(L.unlocx)s|_->sletrecwritten_vars_i((v,f)asacc)i=matchi.i_descwith|Cassgn(x,_,_,_)->written_lvvx,f|Copn(xs,_,_,_)|Csyscall(xs,_,_)->List.fold_leftwritten_lvvxs,f|Ccall(xs,fn,_)->List.fold_leftwritten_lvvxs,Mf.modify_def[]fn(funold->i.i_loc::old)f|Cif(_,s1,s2)|Cwhile(_,s1,_,_,s2)->written_vars_stmt(written_vars_stmtaccs1)s2|Cfor(_,_,s)->written_vars_stmtaccsandwritten_vars_stmtaccs=List.fold_leftwritten_vars_iaccsletwritten_vars_fcfc=written_vars_stmt(Sv.empty,Mf.empty)fc.f_body(* -------------------------------------------------------------------- *)(* Refresh i_loc, ensure that locations are uniq *)letrecrefresh_i_loc_i(i:('info,'asm)instr):('info,'asm)instr=leti_desc=matchi.i_descwith|Cassgn_|Copn_|Csyscall_|Ccall_->i.i_desc|Cif(e,c1,c2)->Cif(e,refresh_i_loc_cc1,refresh_i_loc_cc2)|Cfor(x,r,c)->Cfor(x,r,refresh_i_loc_cc)|Cwhile(a,c1,e,((loc,annot),info),c2)->Cwhile(a,refresh_i_loc_cc1,e,((L.refresh_i_locloc,annot),info),refresh_i_loc_cc2)in{iwithi_desc;i_loc=L.refresh_i_loci.i_loc}andrefresh_i_loc_c(c:('info,'asm)stmt):('info,'asm)stmt=List.maprefresh_i_loc_icletrefresh_i_loc_f(f:('info,'asm)func):('info,'asm)func={fwithf_body=refresh_i_loc_cf.f_body}letrefresh_i_loc_p(p:('info,'asm)prog):('info,'asm)prog=fstp,List.maprefresh_i_loc_f(sndp)(* -------------------------------------------------------------------- *)(* Functions on types *)letint_of_ws=Annotations.int_of_wsletsize_of_ws=function|U8->1|U16->2|U32->4|U64->8|U128->16|U256->32letstring_of_ws=Annotations.string_of_wsletwsize_ltws1ws2=Wsize.wsize_cmpws1ws2=Datatypes.Ltletwsize_lews1ws2=Wsize.wsize_cmpws1ws2<>Datatypes.Gtletint_of_pe=function|PE1->1|PE2->2|PE4->4|PE8->8|PE16->16|PE32->32|PE64->64|PE128->128letint_of_velemve=int_of_ws(wsize_of_velemve)letis_ty_arr=function|Arr_->true|_->falseletarray_kind=function|Arr(ws,n)->ws,n|_->assertfalseletws_of_ty=function|Bty(Uws)->ws|_->assertfalseletarr_sizewsi=size_of_wsws*iletsize_oft=matchtwith|Bty(Uws)->size_of_wsws|Arr(ws',n)->arr_sizews'n|_->assertfalse(* -------------------------------------------------------------------- *)(* Functions over variables *)letis_stack_varv=is_stack_kindv.v_kindletis_reg_arrv=is_reg_direct_kindv.v_kind&&is_ty_arrv.v_tyletis_stack_arrayx=letx=L.unlocxinis_ty_arrx.v_ty&&x.v_kind=StackDirect(* -------------------------------------------------------------------- *)(* Functions over expressions *)let(++)e1e2=matche1,e2with|Pconstn1,Pconstn2->Pconst(Z.addn1n2)|_,_->Papp2(E.OaddOp_int,e1,e2)let(**)e1e2=matche1,e2with|Pconstn1,Pconstn2->Pconst(Z.muln1n2)|_,_->Papp2(E.OmulOp_int,e1,e2)letcnsti=Pconstileticnsti=cnst(Z.of_inti)letis_var=function|Pvar_->true|_->falseletaccess_offsetaawsi=matchaawith|Warray_.AAscale->size_of_wsws*i|Warray_.AAdirect->iletget_ofsaawse=matchewith|Pconsti->Some(access_offsetaaws(Z.to_inti))|_->None(* -------------------------------------------------------------------- *)(* Functions over lvalue *)letexpr_of_lval=function|Lnone_->None|Lvarx->Some(Pvar(gkvarx))|Lmem(al,ws,_,e)->Some(Pload(al,ws,e))|Laset(al,a,ws,x,e)->Some(Pget(al,a,ws,gkvarx,e))|Lasub(a,ws,l,x,e)->Some(Psub(a,ws,l,gkvarx,e))(* -------------------------------------------------------------------- *)(* Functions over instruction *)letrechas_syscall_ii=matchi.i_descwith|Csyscall_->true|Cassgn_|Copn_|Ccall_->false|Cif(_,c1,c2)|Cwhile(_,c1,_,_,c2)->has_syscallc1||has_syscallc2|Cfor(_,_,c)->has_syscallcandhas_syscallc=List.existshas_syscall_icletrechas_call_or_syscall_ii=matchi.i_descwith|Csyscall_|Ccall_->true|Cassgn_|Copn_->false|Cif(_,c1,c2)|Cwhile(_,c1,_,_,c2)->has_call_or_syscallc1||has_call_or_syscallc2|Cfor(_,_,c)->has_call_or_syscallcandhas_call_or_syscallc=List.existshas_call_or_syscall_iclethas_annota{i_annot;_}=Annotations.has_symbolai_annotletis_inlineannotcc=Annotations.has_symbol"inline"annot||cc=FInfo.Internalletrecspilled_isi=matchi.i_descwith|Copn(_,_,Sopn.Opseudo_op(Pseudo_operator.Ospill_),es)->rvars_esSv.addses|Cassgn_|Csyscall_|Ccall_|Copn_->s|Cif(_e,c1,c2)->spilled_c(spilled_csc1)c2|Cfor(_,_,c)->spilled_csc|Cwhile(_,c,_,_,c')->spilled_c(spilled_csc)c'andspilled_csc=List.fold_leftspilled_iscletspilledfc=spilled_cSv.emptyfc.f_bodyletassigns=function|Cassgn(x,_,_,_)->written_lvSv.emptyx|Copn(xs,_,_,_)|Csyscall(xs,_,_)|Ccall(xs,_,_)->List.fold_leftwritten_lvSv.emptyxs|Cif_|Cwhile_|Cfor_->Sv.empty(* -------------------------------------------------------------------- *)letreciter_instrfstmt=List.iter(iter_instr_if)stmtanditer_instr_ifgi=fgi;iter_instr_irfgi.i_descanditer_instr_irf=function|Cassgn_|Copn_|Csyscall_|Ccall_->()|Cfor(_,_,c)->iter_instrfc|Cif(_,c1,c2)|Cwhile(_,c1,_,_,c2)->iter_instrfc1;iter_instrfc2(* -------------------------------------------------------------------- *)letclamp(sz:wsize)(z:Z.t)=Z.eremz(Z.shift_leftZ.one(int_of_wssz))(* --------------------------------------------------------------------- *)type('info,'asm)sfundef=Expr.stk_fun_extra*('info,'asm)functype('info,'asm)sprog=('info,'asm)sfundeflist*Expr.sprog_extra