123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175(****************************************************************************)(* *)(* 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/>. *)(* *)(****************************************************************************)openMopsaopenUniversal.AstopenStubs.AstopenAstopenTop(** Compute symbolic boundaries of a quantified offset. *)(* FIXME: works only for linear expressions *)letrecboundoffsetquants:expr*expr=matchekind@@get_orig_exproffsetwith|E_constant_->offset,offset|E_var(v,_)whenis_forall_quantified_varvquants->find_quantified_var_intervalvquants|E_var_->offset,offset|E_unop(O_minus,e)->letl,u=boundequantsin{offsetwithekind=E_unop(O_minus,u)},{offsetwithekind=E_unop(O_minus,l)}|E_binop(O_plus,e1,e2)->letl1,u1=bounde1quantsinletl2,u2=bounde2quantsin{offsetwithekind=E_binop(O_plus,l1,l2)},{offsetwithekind=E_binop(O_plus,u1,u2)}|E_binop(O_minus,e1,e2)->letl1,u1=bounde1quantsinletl2,u2=bounde2quantsin{offsetwithekind=E_binop(O_minus,l1,u2)},{offsetwithekind=E_binop(O_minus,u1,l2)}|E_binop(O_mult,e,({ekind=E_constant(C_intc)}asconst))|E_binop(O_mult,({ekind=E_constant(C_intc)}asconst),e)->letl,u=boundequantsinifZ.geqcZ.zerothen{offsetwithekind=E_binop(O_mult,l,{constwithekind=E_constant(C_intc)})},{offsetwithekind=E_binop(O_mult,u,{constwithekind=E_constant(C_intc)})}else{offsetwithekind=E_binop(O_mult,u,{constwithekind=E_constant(C_intc)})},{offsetwithekind=E_binop(O_mult,l,{constwithekind=E_constant(C_intc)})}|E_c_cast(e,xplct)->letl,u=boundequantsin{offsetwithekind=E_c_cast(l,xplct)},{offsetwithekind=E_c_cast(u,xplct)}|_->panic_atoffset.erange"can not compute symbolic bounds of non-linear expression %a"pp_exproffset(** [is_aligned o n man flow] checks whether the value of an
expression [o] is aligned w.r.t. size sz *)letis_alignedeszmanflow=(sz=Z.one)||(is_c_expr_equals_zeZ.zeroflow)||(man.evaleflow~translate:"Universal"|>Cases.for_all_result(funeeflow->letopenUniversal.Numeric.Commoninleti,c=ask_and_reduceman.ask(mk_int_congr_interval_queryee)flowinmatchiwith|Bot.Nb(I.B.Finitea,I.B.Finiteb)whena=b&&Z.remasz=Z.zero->true|_->Universal.Numeric.Common.C.included_botc(Bot.Nb(sz,Z.zero))))(** Compute symbolic boundaries of offset / den *)letbound_div(offset:expr)(den:Z.t)quantsmanflow:(expr*expr)with_top=letrecdoitoffsetden=letrange=erangeoffsetinmatchekind@@get_orig_exproffsetwith|E_constant(C_intc)whenZ.remcden=Z.zero->letr=ifden=Z.onethenoffsetelseifc=Z.zerothenoffsetelsedivoffset(mk_zdenrange)rangeinr,r|E_var(v,_)whenis_forall_quantified_varvquants->ifden=Z.onethenfind_quantified_var_intervalvquantselseraiseFound_TOP|E_var(v,_)->ifnot(is_alignedoffsetdenmanflow)thenraiseFound_TOP;letr=ifden=Z.onethenoffsetelsedivoffset(mk_zdenrange)rangeinr,r|E_unop(O_minus,e)->letl,u=doitedenin{offsetwithekind=E_unop(O_minus,u)},{offsetwithekind=E_unop(O_minus,l)}|E_binop(O_plus,e1,e2)->letl1,u1=doite1deninletl2,u2=doite2denin{offsetwithekind=E_binop(O_plus,l1,l2)},{offsetwithekind=E_binop(O_plus,u1,u2)}|E_binop(O_minus,e1,e2)->letl1,u1=doite1deninletl2,u2=doite2denin{offsetwithekind=E_binop(O_minus,l1,u2)},{offsetwithekind=E_binop(O_minus,u1,l2)}|E_binop(O_mult,e1,e2)->lete1,c,e2=matche1,e2with|{ekind=E_constant(C_intc)},_->e1,c,e2|_,{ekind=E_constant(C_intc)}->e2,c,e1|_->raiseFound_TOPinletgcd=Z.gcdcdeninletc,den=Z.divcgcd,Z.divdengcdinletl,u=doite2deninifc=Z.onethenl,uelseifc>=Z.zerothen{offsetwithekind=E_binop(O_mult,l,{e1withekind=E_constant(C_intc)})},{offsetwithekind=E_binop(O_mult,u,{e1withekind=E_constant(C_intc)})}else{offsetwithekind=E_binop(O_mult,u,{e1withekind=E_constant(C_intc)})},{offsetwithekind=E_binop(O_mult,l,{e1withekind=E_constant(C_intc)})}|E_binop(O_div,e,({ekind=E_constant(C_intc)}))->doite(Z.muldenc)|E_c_cast(e,xplct)->letl,u=doitedenin{offsetwithekind=E_c_cast(l,xplct)},{offsetwithekind=E_c_cast(u,xplct)}|_->(*
panic_at offset.erange
"can not compute symbolic bounds of non-linear expression %a / %a"
pp_expr offset Z.pp_print den
*)raiseFound_TOPinretop(doitoffset)den(*
let bound_div offset den man flow =
Format.printf "bound_div %a / %a@." pp_expr offset Z.pp_print den;
let l,u = bound_div offset den man flow in
Format.printf " [%a,@. %a]@." pp_expr l pp_expr u;
l, u
*)