123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114(****************************************************************************)(* *)(* 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/>. *)(* *)(****************************************************************************)(** Reduction operator for computing the most precise interval in a
post-condition and inform the intervals domain about it.
*)openMopsaopenSig.Reduction.SimplifiedopenAstmoduleReduction=structletname="universal.numeric.reductions.intervals_rel"letdebugfmt=Debug.debug~channel:namefmtmoduleI=Values.Intervals.Integer.ValuemoduleR=Relational.Domain(** Get a list of variables related numerically to [v] *)letget_related_varsvmanctxa=man.ask(R.Q_related_varsv)ctxa(** Get the list of modified variables *)letget_modified_varsstmtmanctxa=matchskindstmtwith|S_assign({ekind=E_var(v,_)},_)->[v]|S_assumee->(* In case of a filter, we search for the relations of the
variables present in the expression *)letvars=Visitor.expr_varseinList.fold_left(funaccv->get_related_varsvmanctxa@acc)varsvars|>List.sort_uniqcompare_var|_->[](** Reduction operator *)(* TODO:
- factor with universal.numeric.packing.intervals_static_scope.ml
- float reduction
*)letreducestmtmanctx(pre:'a)(post:'a):'a=let(moduleCR:Relational.Instances.RELATIONAL)=!Relational.Instances_choices.numeric_domainin(* Get the modified variables *)letvars=get_modified_varsstmtmanctxpre|>List.filter(funv->is_int_type(vtypv))in(* Refine the interval of each variable *)List.fold_left(funpostvar->(* Get the interval of var in the box domain *)letitv=man.get_valueI.idvarpostin(* Get the interval in the relational domain *)letitv'=CR.bound_varvar(man.get_envCR.idpost)in(* Combine data *)letitv''=I.meetitvitv'inlet()=debug"%a %a %a %a %a"pp_varvarpp_typ(vtypvar)(formatI.print)itv(formatI.print)itv'(formatI.print)itv''in(* Check if box is less precise *)letpost=ifnot(I.subsetitvitv')thenman.set_valueI.idvaritv''postelsepostin(* Check if rel is less precise *)ifnot(I.subsetitv'itv)thenletrange=stmt.srangeinletev=mk_varvarrangeinmatchitv''with|Bot.BOT->man.set_envCR.idCR.bottompost|Bot.Nb_->letol,oh=I.bounds_optitv''inletassumespost=letoenv=CR.assumes(funq->man.askqctxpost)(man.get_envCR.idpost)inOptionExt.apply(funenv->man.set_envCR.idenvpost)postoenvinletpost=OptionExt.apply(funl->assume(mk_assume(mk_binop~etyp:T_bool(mk_constant~etyp:T_int(C_intl)range)O_leevrange)range)post)postolinletpost=OptionExt.apply(funh->assume(mk_assume(mk_binop~etyp:T_boolevO_le(mk_constant~etyp:T_int(C_inth)range)range)range)post)postohinpostelsepost)postvarsendlet()=register_simplified_reduction(moduleReduction)