123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148(** {{!EqConstrSys} constraint system} signatures. *)openBatteriesmoduletypeSysVar=sigtypetvalis_write_only:t->boolendmoduletypeVarType=sigincludeHashtbl.HashedTypeincludeSysVarwithtypet:=tvalpretty_trace:unit->t->GoblintCil.Pretty.docvalcompare:t->t->intvalprintXml:'aBatInnerIO.output->t->unitvalvar_id:t->stringvalnode:t->MyCFG.nodevalrelift:t->t(* needed only for incremental+hashcons to re-hashcons contexts after loading *)end(** Combined variables so that we can also use the more common [EqConstrSys]
that uses only one kind of a variable. *)moduleVar2(LV:VarType)(GV:VarType):VarTypewithtypet=[`LofLV.t|`GofGV.t]=structtypet=[`LofLV.t|`GofGV.t][@@derivingeq,ord,hash]letrelift=function|`Lx->`L(LV.reliftx)|`Gx->`G(GV.reliftx)letpretty_trace()=function|`La->GoblintCil.Pretty.dprintf"L:%a"LV.pretty_tracea|`Ga->GoblintCil.Pretty.dprintf"G:%a"GV.pretty_tracealetprintXmlf=function|`La->LV.printXmlfa|`Ga->GV.printXmlfaletvar_id=function|`La->LV.var_ida|`Ga->GV.var_idaletnode=function|`La->LV.nodea|`Ga->GV.nodealetis_write_only=function|`La->LV.is_write_onlya|`Ga->GV.is_write_onlyaend(** Abstract incremental change to constraint system.
@param 'v constrain system variable type *)type'vsys_change_info={obsolete:'vlist;(** Variables to destabilize. *)delete:'vlist;(** Variables to delete. *)reluctant:'vlist;(** Variables to solve reluctantly. *)restart:'vlist;(** Variables to restart. *)}(** A side-effecting system. *)moduletypeEqConstrSys=sigtypev(* variables *)typed(* values *)(** Variables must be hashable, comparable, etc. *)moduleVar:VarTypewithtypet=v(** Values must form a lattice. *)moduleDom:Lattice.Swithtypet=d(** The system in functional form. *)valsystem:v->((v->d)->(v->d->unit)->d)option(** Compute incremental constraint system change from old solution. *)valsys_change:(v->d)->vsys_change_info(** List of unknowns that should be queried again when the argument unknown has shrunk to bot, to eagerly trigger (analysis-time!) abstract garbage collection idependently of reach-based pruning at the end.
@see <https://arxiv.org/abs/2504.06026> Stemmler, F., Schwarz, M., Erhard, J., Tilscher, S., Seidl, H. Taking out the Toxic Trash: Recovering Precision in Mixed Flow-Sensitive Static Analyses *)valpostmortem:v->vlistend(** A side-effecting system that supports [demand] calls *)moduletypeDemandEqConstrSys=sigincludeEqConstrSysvalsystem:v->((v->d)->(v->d->unit)->(v->unit)->d)optionend(** A side-effecting system with globals. *)moduletypeGlobConstrSys=sigmoduleLVar:VarTypemoduleGVar:VarTypemoduleD:Lattice.SmoduleG:Lattice.Svalsystem:LVar.t->((LVar.t->D.t)->(LVar.t->D.t->unit)->(GVar.t->G.t)->(GVar.t->G.t->unit)->D.t)optionvaliter_vars:(LVar.t->D.t)->(GVar.t->G.t)->VarQuery.t->LVar.tVarQuery.f->GVar.tVarQuery.f->unitvalsys_change:(LVar.t->D.t)->(GVar.t->G.t)->[`LofLVar.t|`GofGVar.t]sys_change_infovalpostmortem:LVar.t->LVar.tlistend(** A side-effecting system with globals that supports [demand] calls *)moduletypeDemandGlobConstrSys=sigmoduleLVar:VarTypemoduleGVar:VarTypemoduleD:Lattice.SmoduleG:Lattice.Svalsystem:LVar.t->((LVar.t->D.t)->(LVar.t->D.t->unit)->(LVar.t->unit)->(GVar.t->G.t)->(GVar.t->G.t->unit)->D.t)optionvaliter_vars:(LVar.t->D.t)->(GVar.t->G.t)->VarQuery.t->LVar.tVarQuery.f->GVar.tVarQuery.f->unitvalsys_change:(LVar.t->D.t)->(GVar.t->G.t)->[`LofLVar.t|`GofGVar.t]sys_change_infovalpostmortem:LVar.t->LVar.tlistend(** {!DemandEqConstrSys} where [current_var] indicates the variable whose right-hand side is currently being evaluated. *)moduleCurrentVarDemandEqConstrSys(S:DemandEqConstrSys)=structletcurrent_var=refNonemoduleS=structincludeSletsystemx=Option.map(funf->letf'getsetdemand=letold_current_var=!current_varincurrent_var:=Somex;Fun.protect~finally:(fun()->current_var:=old_current_var)(fun()->fgetsetdemand)inf')(S.systemx)endend