123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2024 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* 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). *)(* *)(**************************************************************************)openSexprmoduletypeCONTEXT=sigtypet(** context *)typev(** domain abstract value *)valadd_dependency:t->parent:Expr.t->Expr.t->unitvalfind_dependency:t->Expr.t->BvSet.tvaladd:t->Expr.t->v->unitvalfind:t->Expr.t->vendmoduletypeS=sigtypettypevvaleval:t->Expr.t->vvalrefine:t->Expr.t->v->unitendmoduleMake(D:Domains.S)(C:CONTEXTwithtypev:=D.t):Swithtypet=C.tandtypev:=D.t=structtypet=C.topenDletunary(f:Term.unaryTerm.operator)~sizex=matchfwith|Not->lognot~sizex|Minus->uminus~sizex|Sextn->sextn~sizex|Uextn->uextn~sizex|Restrict{hi;lo}->restrict~hi~lo~sizexletbinary(f:Term.binaryTerm.operator)=matchfwith|Plus->add|Minus->sub|Mul->mul|Udiv->udiv|Umod->umod|Sdiv->sdiv|Smod->smod|Or->logor|And->logand|Xor->logxor|Eq->equal|Diff->diff|Ule->ule|Ult->ult|Uge->uge|Ugt->ugt|Sle->sle|Slt->slt|Sge->sge|Sgt->sgt|Lsl->shift_left|Lsr->shift_right|Asr->shift_right_signed|Rol->rotate_left|Ror->rotate_right|Concat->assertfalseletrecevalctx(e:Expr.t)=tryC.findctxewithNot_found->letd=matchewith|Cstbv->constant~size:(Bitvector.size_ofbv)(Bitvector.value_ofbv)|Var{size;_}->topsize|Load{len;_}->top(lenlsl3)|Unary{f;x;_}->C.add_dependencyctxx~parent:e;unaryf~size:(Expr.sizeofx)(evalctxx)|Binary{f=Concat;x;y;_}->C.add_dependencyctxx~parent:e;C.add_dependencyctxy~parent:e;append~size1:(Expr.sizeofx)(evalctxx)~size2:(Expr.sizeofy)(evalctxy)|Binary{f;x;y;_}->C.add_dependencyctxx~parent:e;C.add_dependencyctxy~parent:e;(binaryf)~size:(Expr.sizeofx)(evalctxx)(evalctxy)|Ite{c;t;e=r;_}->C.add_dependencyctxc~parent:e;C.add_dependencyctxt~parent:e;C.add_dependencyctxr~parent:e;letc'=evalctxcinifincluded~size:1c'onethenevalctxtelseifincluded~size:1c'zerothenevalctxrelseunion~size:(Expr.sizeoft)(evalctxt)(evalctxr)inC.addctxed;dletunary_feedback(f:Term.unaryTerm.operator)xd=matchfwith|Not->lognot_feedbackxd|Minus->uminus_feedbackxd|Sextn->sext_feedbacknxd|Uextn->uext_feedbacknxd|Restrict{hi;lo}->restrict_feedback~hi~loxdletbinary_feedback(f:Term.binaryTerm.operator)=matchfwith|Plus->add_feedback|Minus->sub_feedback|Mul->mul_feedback|Udiv->udiv_feedback|Umod->umod_feedback|Sdiv->sdiv_feedback|Smod->smod_feedback|Or->logor_feedback|And->logand_feedback|Xor->logxor_feedback|Eq->equal_feedback|Diff->diff_feedback|Ule->ule_feedback|Ult->ult_feedback|Uge->uge_feedback|Ugt->ugt_feedback|Sle->sle_feedback|Slt->slt_feedback|Sge->sge_feedback|Sgt->sgt_feedback|Lsl->shift_left_feedback|Lsr->shift_right_feedback|Asr->shift_right_signed_feedback|Rol->rotate_left_feedback|Ror->rotate_right_feedback|Concat->assertfalseletrefine=letrecloop_uptodoctxlocked=ifBvSet.is_emptytodothen()elselete=BvSet.choosetodoinlettodo=BvSet.removeetodoinifBvSet.memelockedthenloop_uptodoctxlockedelse(* let locked = BvSet.add e locked in *)leto=C.findctxeinletn=matchewith|Cst_|Var_|Load_->assertfalse|Unary{f;x;_}->unaryf~size:(Expr.sizeofx)(C.findctxx)|Binary{f=Concat;x;y;_}->append~size1:(Expr.sizeofx)(C.findctxx)~size2:(Expr.sizeofy)(C.findctxy)|Binary{f;x;y;_}->binaryf~size:(Expr.sizeofx)(C.findctxx)(C.findctxy)|Ite{c;t;e=r;_}->letc'=C.findctxcinifincluded~size:1c'onethenC.findctxtelseifincluded~size:1c'zerothenC.findctxrelseunion~size:(Expr.sizeoft)(C.findctxt)(C.findctxr)inifincluded~size:(Expr.sizeofe)onthenloop_uptodoctxlockedelselettodo=tryBvSet.union(C.find_dependencyctxe)todowithNot_found->todoinC.addctxen;loop_uptodoctxlockedinletrecloop_downtodoctxdirtylocked=ifQueue.is_emptytodothenloop_updirtyctxlockedelselet(e:Expr.t),(d:t)=Queue.poptodoinletsize=Expr.sizeofeinleto=C.findctxeinifincluded~sizeodthenloop_downtodoctxdirtylockedelseletn=inter~sizeodinletlocked=BvSet.addelockedinC.addctxen;letdirty=tryBvSet.union(C.find_dependencyctxe)dirtywithNot_found->dirtyin(matchewith|Cst_|Var_|Load_->()|Unary{f;x;_}->letx'=unary_feedbackf~size:(Expr.sizeofx)(C.findctxx)ninQueue.add(x,x')todo|Binary{f=Concat;x;y;_}->letx',y'=append_feedback~size1:(Expr.sizeofx)(C.findctxx)~size2:(Expr.sizeofy)(C.findctxy)ninQueue.add(x,x')todo;Queue.add(y,y')todo|Binary{f;x;y;_}->letx',y'=(binary_feedbackf)~size:(Expr.sizeofx)(C.findctxx)(C.findctxy)ninQueue.add(x,x')todo;Queue.add(y,y')todo|Ite{c;t;e;_}->letc'=C.findctxcinifincluded~size:1c'onethenQueue.add(t,n)todoelseifincluded~size:1c'zerothenQueue.add(e,n)todoelseifdisjoint~size(C.findctxt)nthenQueue.add(c,zero)todoelseifdisjoint~size(C.findctxe)nthenQueue.add(c,one)todo);loop_downtodoctxdirtylockedinfunctxed->lettodo=Queue.create()inQueue.add(e,d)todo;loop_downtodoctxBvSet.emptyBvSet.emptyend