123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122(**************************************************************************)(* *)(* This file is part of WP plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat a l'energie atomique et aux energies *)(* alternatives) *)(* *)(* 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, version 2.1. *)(* *)(* It 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. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)openLang(* -------------------------------------------------------------------------- *)(* --- Helpers --- *)(* -------------------------------------------------------------------------- *)letpositivee=F.p_leqF.e_zeroe(* 0 <= n *)letpowerk=F.e_bigint(Integer.two_power_of_intk)letlookup_inte=letopenQed.LogicinmatchF.reprewith|Kintz->(trySome(Integer.to_int_exnz)withZ.Overflow->None)|_->Noneletreclookup_bitteste=matchF.reprewith|Note->lookup_bitteste|Fun(f,[n;ek])whenList.memqfCint.f_bits->beginmatchlookup_intekwith|Somekwhen0<=k&&k<128->Some(n,k)|_->Noneend|_->None(* -------------------------------------------------------------------------- *)(* --- Bit-Test Range --- *)(* -------------------------------------------------------------------------- *)classbittestrange=objectinheritTactical.make~id:"Wp.bittestrange"~title:"Bit-Test Range"~descr:"Tighten Bounds with respect to bits"~params:[]methodselect_feedbackselection=lete=Tactical.selectedselectioninmatchlookup_bittestewith|Some(n,k)->letbit=Cint.bit_testnkinletbit_set=F.p_boolbitinletbit_clear=F.p_notbit_setinletpos=positiveninletpk=powerkinletpk1=power(succk)inletg_inf=F.p_hyps[pos](F.p_leqpkn)inletg_sup=F.p_hyps[pos;F.p_ltnpk1](F.p_ltnpk)inletname_inf=Printf.sprintf"Bit #%d (inf)"kinletname_sup=Printf.sprintf"Bit #%d (sup)"kinletat=Tactical.atselectioninTactical.Applicable(Tactical.insert?at[name_inf,F.p_andbit_setg_inf;name_sup,F.p_andbit_clearg_sup;])|None->Tactical.Not_applicableendlettactical=Tactical.export(newbittestrange)letstrategy=Strategy.maketactical~arguments:[](* -------------------------------------------------------------------------- *)(* --- Auto Bitrange --- *)(* -------------------------------------------------------------------------- *)letreclookuppushstepe=matchF.reprewith|Andes->List.iter(lookuppushstep)es|Ores->List.iter(lookuppushstep)es|Imply(hs,p)->List.iter(lookuppushstep)(p::hs)|_->beginmatchlookup_bittestewith|None->()|Some_->push@@strategy~priority:0.3(Tactical.Inside(step,e))endclassautobittestrange:Strategy.heuristic=objectmethodid="wp:bittestrange"methodtitle="Auto Bit-Test Range"methoddescr="Apply Bit-Test Range on bit-tests"methodsearchpush(seq:Conditions.sequent)=Conditions.iter(funstep->letp=Conditions.headstep|>F.e_propinlookuppush(Tactical.Stepstep)p)(fstseq);letp=sndseqinlookuppush(Tactical.Goalp)(F.e_propp)endlet()=Strategy.register(newautobittestrange)