123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2017-2019 The MOPSA Project. *)(* *)(* 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, either version 3 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, see <http://www.gnu.org/licenses/>. *)(* *)(****************************************************************************)(** Extensible type of expressions. *)openMopsa_utilsopenLocationopenTypopenProgramopenOperatoropenConstantopenVaropenAddropenFormatopenSemantictypeexpr_kind=..typeexpr={ekind:expr_kind;etyp:typ;erange:Location.range;etrans:exprSemanticMap.t;ehistory:exprlist;}letekind(e:expr)=e.ekindletetyp(e:expr)=e.etypleterange(e:expr)=e.erangeletetrans(e:expr)=e.etransletehistory(e:expr)=e.ehistorytypeexpr_kind+=|E_varofvar*modeoption|E_constantofconstant|E_unopofoperator*expr|E_binopofoperator*expr*expr|E_addrofaddr*modeoption|E_alloc_addrofaddr_kind*modeletexpr_compare_chain=TypeExt.mk_compare_chain(fune1e2->matchekinde1,ekinde2with|E_var(v1,m1),E_var(v2,m2)->Compare.compose[(fun()->compare_varv1v2);(fun()->Compare.optioncompare_modem1m2)]|E_constantc1,E_constantc2->compare_constantc1c2|E_alloc_addr(ak1,m1),E_alloc_addr(ak2,m2)->Compare.compose[(fun()->compare_addr_kindak1ak2);(fun()->compare_modem1m2);]|E_addr(a1,om1),E_addr(a2,om2)->Compare.compose[(fun()->compare_addra1a2);(fun()->Compare.optioncompare_modeom1om2);]|_->Stdlib.compare(ekinde1)(ekinde2))letexpr_pp_chain=TypeExt.mk_print_chain(funfmtexpr->matchekindexprwith|E_constantc->pp_constantfmtc|E_var(v,None)->pp_varfmtv|E_var(v,SomeSTRONG)->Format.fprintffmt"strong(%a)"pp_varv|E_var(v,SomeWEAK)->Format.fprintffmt"weak(%a)"pp_varv|E_alloc_addr(akind,mode)->fprintffmt"alloc(%a, %a)"pp_addr_kindakindpp_modemode|E_addr(addr,None)->fprintffmt"%a"pp_addraddr|E_addr(addr,SomeSTRONG)->fprintffmt"strong(%a)"pp_addraddr|E_addr(addr,SomeWEAK)->fprintffmt"weak(%a)"pp_addraddr|_->failwith"Pp: Unknown expression")letregister_exprinfo=TypeExt.registerinfoexpr_compare_chainexpr_pp_chainletregister_expr_comparecmp=TypeExt.register_comparecmpexpr_compare_chainletregister_expr_pppp=TypeExt.register_printppexpr_pp_chainletcompare_expre1e2=TypeExt.compareexpr_compare_chaine1e2letpp_exprfmte=Var.force_print_uniq_with_uidfalse(fun()->TypeExt.printexpr_pp_chainfmte)letadd_expr_translationsemanticte={ewithetrans=SemanticMap.addsemanticte.etrans}letget_expr_translationse=e.etransletget_expr_translationsemantice=ifis_any_semanticsemantictheneelsetrySemanticMap.findsemantice.etranswithNot_found->(* XXX We assume that an expression is translated to itself if no
translation exists. This is a temporary fix for situations where
domains don't add appropriate entires in the translation table. *)eletget_expr_historye=e.ehistoryletget_orig_expre=matche.ehistorywith|[]->e|_->ListExt.laste.ehistoryletfind_expr_ancestorfe=letreciter=function|[]->raiseNot_found|hd::tl->iffhdthenhdelseitertlinitere.ehistorylet()=register_expr{compare=(funnexte1e2->matchekinde1,ekinde2with|E_unop(op1,e1),E_unop(op2,e2)->Compare.compose[(fun()->compare_operatorop1op2);(fun()->compare_expre1e2);]|E_binop(op1,e1,e1'),E_binop(op2,e2,e2')->Compare.compose[(fun()->compare_operatorop1op2);(fun()->compare_expre1e2);(fun()->compare_expre1'e2');]|_->nexte1e2);print=(funnextfmte->matchekindewith|E_unop(O_cast,ee)->fprintffmt"cast(%a, %a)"pp_type.etyppp_expree|E_unop(op,e)->fprintffmt"%a(%a)"pp_operatoroppp_expre|E_binop(op,e1,e2)->fprintffmt"(%a %a %a)"pp_expre1pp_operatoroppp_expre2|_->nextfmte);}(** Utility functions *)letmk_expr?(etyp=T_any)?(etrans=SemanticMap.empty)?(ehistory=[])ekinderange={ekind;etyp;erange;etrans;ehistory}letmk_varv?(mode=None)erange=mk_expr~etyp:v.vtyp(E_var(v,mode))erangeletweaken_var_exprv=matchekindvwith|E_var(vv,SomeWEAK)->v|E_var(vv,None)whenvv.vmode=WEAK->v|E_var(vv,_)->{vwithekind=E_var(vv,SomeWEAK)}|_->assertfalseletstrongify_var_exprv=matchekindvwith|E_var(vv,SomeSTRONG)->v|E_var(vv,None)whenvv.vmode=STRONG->v|E_var(vv,_)->{vwithekind=E_var(vv,SomeSTRONG)}|_->assertfalseletvar_mode(v:var)(omode:modeoption):mode=matchomodewith|None->v.vmode|Somem->mletmk_addraddr?(etyp=T_addr)?(mode=None)range=mk_expr~etyp(E_addr(addr,mode))rangeletmk_alloc_addr?(mode=STRONG)addr_kindrange=mk_expr(E_alloc_addr(addr_kind,mode))~etyp:T_addrrangeletweaken_addr_expre=matchekindewith|E_addr({addr_mode=WEAK},_)->e|E_addr(addr,om)->{ewithekind=E_addr({addrwithaddr_mode=WEAK},om)}|_->assertfalseletstrongify_addr_expre=matchekindewith|E_addr({addr_mode=STRONG},_)->e|E_addr(addr,om)->{ewithekind=E_addr({addrwithaddr_mode=STRONG},om)}|_->assertfalseletmk_binop?(etyp=T_any)leftoprighterange=mk_expr(E_binop(op,left,right))~etyperangeletmk_unop?(etyp=T_any)opoperanderange=mk_expr(E_unop(op,operand))~etyperangeletmk_constant?(etyp=T_any)c=mk_expr~etyp(E_constantc)letmk_toptyprange=mk_constant(C_toptyp)~etyp:typrangeletmk_noterange=mk_unopO_log_note~etyp:e.etyprangeletrecnegate_exprexp=matchekindexpwith|E_unop(O_log_not,ee)->ee|E_binop(op,e1,e2)whenis_logic_opop->mk_binop(negate_expre1)(negate_logic_opop)(negate_expre2)~etyp:exp.etypexp.erange|E_binop(op,e1,e2)whenis_comparison_opop->mk_binope1(negate_comparison_opop)e2~etyp:exp.etypexp.erange|_->mk_notexpexp.erangemoduleExprSet=SetExt.Make(structtypet=exprletcompare=compare_exprend)moduleExprMap=MapExt.Make(structtypet=exprletcompare=compare_exprend)