123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401(**************************************************************************)(* This file is part of the Codex semantics library. *)(* *)(* Copyright (C) 2013-2025 *)(* 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 LICENSE). *)(* *)(**************************************************************************)(* TODO: The identifier for unimplemented should be an argument here too. *)(* ALso this should be renamed to unimplemented. *)moduleDummy_Enum_Lattice=Lattices.Unimplemented.Enum_Lattice(structletloc=__LOC__end)openUnits(* Used to create dummy types to fill the signatures, even when the
abstract domain does not support the type. *)moduleBoolean=structmoduleBoolean_Backward=structlet(||)___=assertfalselet(&&)___=assertfalseletnot__=assertfalseletassume_cond_store_result=assertfalseendmoduleBoolean_Forward=structlet(||)__=assertfalselet(&&)__=assertfalseletnot_=assertfalseletassume_cond_store=assertfalselettrue__=assertfalseletfalse__=assertfalseletunknown?level_=assertfalseendendmoduleInteger=structmoduleInteger_Forward=structletone_=assertfalseletzero_=assertfalseletile_=assertfalseletieq_=assertfalseletisub_=assertfalseleticonst_=assertfalseletassume_=assertfalseletiunknown_=assertfalseletixor_=assertfalseletior_=assertfalseletiand_=assertfalseletishr_=assertfalseletishl_=assertfalseletimod_=assertfalseletidiv_=assertfalseletimul_=assertfalseletiadd_=assertfalseletitimes_=assertfalseendendmoduleBinary=structmoduleBinary_Forward=structletbeq~size__=assertfalseletbiule~size__=assertfalseletbisle~size__=assertfalseletbitimes~size__=assertfalseletbiadd~size~flags__=assertfalseletbisub~size~flags__=assertfalseletbimul~size~flags__=assertfalseletbxor~size__=assertfalseletband~size__=assertfalseletbor~size__=assertfalseletnondet~sizel=assertfalseletassume~size_cond_store=assertfalseletbsext~size~oldsize_=assertfalseletbuext~size~oldsize_=assertfalseletbofbool~size_=assertfalseletbchoose~size__=assertfalseletbashr~size__=assertfalseletblshr~size__=assertfalseletbshl~size~flags__=assertfalseletbisdiv~size__=assertfalseletbiudiv~size__=assertfalseletbconcat~size1~size2b1b2=assertfalseletbismod~size__=assertfalseletbiumod~size__=assertfalseletbextract~size~index~oldsize_=assertfalseletvalid~size_=assertfalseletvalid_ptr_arith~size_=assertfalseletbunknown~size_=assertfalseletbaddr~size_=assertfalseletbiconst~size_=assertfalseletbuninit~size_=assertfalseletbshift~size~offset~max_=assertfalseletbindex~size_=assertfalseendmoduleBinary_Backward=structletbeq___=assertfalseletbiule___=assertfalseletbisle___=assertfalseletbitimes___=assertfalseletbiadd___=assertfalseletbimul~size___=assertfalseletbxor~size___=assertfalseletband~size___=assertfalseletbor~size___=assertfalseletassume~size_cond_store_result=assertfalseletbsext~size__=assertfalseletbuext~size__=assertfalseletbashr~size___=assertfalseletblshr~size___=assertfalseletbshl~size~flags___=assertfalseletbisdiv___=assertfalseletbconcat~size1~size2b1b2result=assertfalseletbismod___=assertfalseletbextract~size~index~oldsize__=assertfalseletvalid~size__=assertfalseletbshift~size_=assertfalseletbindex~size_=assertfalseendendmoduleEnum=structmoduleEnum_Forward=structletcaseof~case:__=assertfalseletenum_const~case:_=assertfalseendend(* A commodity to start implementing domains; start from here, then complete things as needed. *)moduleDomain:Sig.BASE=structletname()="assert false"letunique_id()=Sig.Fresh_id.fresh@@name();;moduleTypes=structtypebinary=unittypeenum=unittypeinteger=unittypeboolean=unitendincludeTypes(**************** Root context ****************)[@@@ocaml.warning"-69"]typemu_context={mu_ctx:context;(* Context corresponding to this mu_context *)mu_parent_ctx:context;(* Parent of the current context. *)}androot_context={root_ctx:context;(* Context corresponding to this root_context *)}andcontext_=|Mu_contextofmu_context|Root_contextofroot_contextandcontext={ctx:context_;level:int;};;[@@@ocaml.warning"+69"]letroot_context()=letrecroot_ctx={root_ctx=ctx;}andctx={ctx=Root_contextroot_ctx;level=0;}inctx;;letcontext_pretty_=assertfalse(**************** Fixpoint computation ****************)letmu_context_fixpoint_step3ctx~arg_body=assertfalseletmu_context_upcastctx=assertfalseletmu_context_openparent_ctx=letrecmu_ctx={mu_ctx=ctx;mu_parent_ctx=parent_ctx}andctx={ctx=Mu_contextmu_ctx;level=parent_ctx.level+1;}inctxmoduleSerialize=structmoduleT=Types(* A lazy version of serialization functions. *)type'ain_tuple=|InEmpty:unitin_tuple|InInteger:T.integer*T.integer*'ain_tuple->(T.integer*'a)in_tuple|InBoolean:T.boolean*T.boolean*'ain_tuple->(T.boolean*'a)in_tuple|InEnum:T.enum*T.enum*'ain_tuple->(T.enum*'a)in_tuple|InBinary:In_bits.t*T.binary*T.binary*'ain_tuple->(T.binary*'a)in_tupletype'ain_acc=bool*'ain_tupletype'aout_tuple=|OutEmpty:unitout_tuple|OutInteger:T.integer*'aout_tuple->(T.integer*'a)out_tuple|OutBoolean:T.boolean*'aout_tuple->(T.boolean*'a)out_tuple|OutEnum:T.enum*'aout_tuple->(T.enum*'a)out_tuple|OutBinary:int*T.binary*'aout_tuple->(T.binary*'a)out_tupletypeempty_tuple=unitletempty_tuple()=InEmptyletpush_integersabtup=InInteger(a,b,tup)letpush_booleansabtup=InBoolean(a,b,tup)letpush_binaries~sizeabtup=InBinary(size,a,b,tup)letpush_enumerationabtup=InEnum(a,b,tup)[@@@warning"-8"]letpop_integer(OutInteger(x,tup))=x,tupletpop_boolean(OutBoolean(x,tup))=x,tupletpop_binary(OutBinary(_,x,tup))=x,tupletpop_enumeration(OutEnum(x,tup))=x,tup[@@@warning"+8"]moduleContext=structtypet=contextletlevelx=x.levelletcopyx=xletassign_=assertfalsetypenonrec'ain_tuple='ain_tupletypenonrec'aout_tuple='aout_tupletypenonrec'ain_acc='ain_acctypenonrecempty_tuple=empty_tupleletempty_tuple=empty_tupletype('a,'b)result=Result:bool*'somein_tuple*(t->'someout_tuple->'a*'bout_tuple)->('a,'b)resultendopenContext(* On pourrait vouloir fournir ces fonctions a la place de celles
que j'utilise (push_int,pop_int). Mais elles sont peut-etre moins pratiques pour le
produit de domaines? *)letserialize_integer:widens:bool->'any->T.integer->'any->T.integer->'ain_acc->(T.integer,'a)result=fun~widens_a_b(included,old)->lettup=push_integersaboldinResult(included,tup,fun_ctxx->pop_integerx);;letserialize_enum:'any->T.enum->'any->T.enum->'ain_acc->(T.enum,'a)result=fun_a_b(inc,old)->lettup=push_enumerationaboldinResult(inc,tup,fun_ctxx->pop_enumerationx);;letserialize_boolean:'any->T.boolean->'any->T.boolean->'ain_acc->(T.boolean,'a)result=fun_a_b(included,old)->(* Instead of using a default implementation, we should be
immediately serializing to the domain below for instance. *)(* Codex_log.warning "avoid using the default implementation of serialize_* functions"; *)lettup=push_booleansaboldinResult(included,tup,fun_ctxx->pop_booleanx);;letserialize_binary:widens:bool->size:In_bits.t->'any->T.binary->'any->T.binary->'ain_acc->(T.binary,'a)result=fun~widens~size_a_b(inc,old)->lettup=push_binaries~sizeaboldinResult(inc,tup,fun_ctxx->pop_binaryx);;lettyped_nondet2_=assertfalseletnondet_same_context_=assertfalselettyped_fixpoint_step_=assertfalseletwidened_fixpoint_step~widening_id~previous~next_=assertfalseendincludeSerializemoduleBoolean_Forward=Boolean.Boolean_ForwardmoduleInteger_Forward=Integer.Integer_ForwardmoduleBinary_Forward=Binary.Binary_ForwardmoduleEnum_Forward=Enum.Enum_ForwardmoduleBinary=Datatype_sig.UnitmoduleEnum=Datatype_sig.UnitmoduleInteger=Datatype_sig.UnitmoduleBoolean=Datatype_sig.Unitletbinary_is_bottom~sizectx=assertfalseletboolean_is_bottomctx=assertfalse(**************** Pretty printing ****************)letbinary_pretty~sizectxfmt=assertfalseletboolean_prettyctxfmt=assertfalseletinteger_pretty_=assertfalseletenum_pretty_=assertfalse(**************** Tuple fonctions ****************)lettuple_bottom_=assertfalseletnew_tuple_nondet2_=assertfalselettyped_fixpoint_step~iteration:_~init:_~arg:_~body:_=assertfalselettuple_pretty_=assertfalseletassumectxbool=assertfalseletimperative_assumectxbool=assertfalse(**************** Queries ****************)moduleQuery=structletreachable_=assertfalseletboolean_=assertfalseletbinary~size_=assertfalseletinteger_=assertfalseletconvert_to_ival_=assertfalseletconvert_to_quadrivalent_=assertfalseletbinary_to_ival~signed~size_=assertfalseletbinary_to_known_bits~size_=assertfalseletbinary_is_empty~size_=assertfalseletbinary_fold_crop~sizebin~inf~supfacc=assertfalseletis_singleton_int_=assertfalseletbinary_is_singleton~size_=assertfalsemoduleBoolean_Lattice=Lattices.QuadrivalentmoduleInteger_Lattice=Lattices.UnitmoduleBinary_Lattice=Lattices.Unimplemented.Bitvector_Lattice(structtypet=unitletloc=__LOC__end)letenum_=assertfalseletis_singleton_enum_=assertfalseletenum_to_values_=assertfalsemoduleEnum_Lattice=Dummy_Enum_Latticeendletbinary_is_empty~size_=assertfalseletinteger_is_empty_=assertfalseletboolean_is_empty_=assertfalseletbuiltin_=assertfalseletbinary_empty~size_=assertfalseletinteger_empty_=assertfalseletboolean_empty_=assertfalseletenum_empty_=assertfalseletbinary_unknown~size_=assertfalseletinteger_unknown_=assertfalseletboolean_unknown_=assertfalseletenum_unknown~enumsize:__=assertfalse(* Assume. *)letassume_binary~size__=assertfalseletassume_boolean_ctx__=assertfalseletassume_integer_ctx__=assertfalseletreachable_=assertfalseletsatisfiable_=assertfalseletunknown_condition_?level=assertfalseletunknown_choice_?level=assertfalse(* type binary_set = binary *)typechoice=unittypecondition=unitletunion_=assertfalseletchoose_binary~size_=assertfalseletbinary_unknown_typed~size:__=assertfalseletquery_boolean=Query.booleanend