123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495(**************************************************************************)(* 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). *)(* *)(**************************************************************************)(* Note: this was not heavily tested or reviewed. *)let_name="Sentinel"includeSva_quadrivalentmoduleInteger_Lattice=structincludeLattices.Unimplemented.Integer_Lattice(structtypet=unitletloc=__LOC__end)endtypeinteger=Integer_Lattice.tmoduleInteger_Backward=Sva_Assert_False_Transfer_Functions.Integer_BackwardmoduleInteger_Forward=Sva_Assert_False_Transfer_Functions.Integer_ForwardmoduleBitvector_Lattice=structtypet=Bot|Zero|NonZero|SentinelTopmoduleL=Lattices.Unimplemented.Bitvector_Lattice(structtypenonrect=tletloc=__LOC__end)include(L:moduletypeofLwithtypet:=t)letbottom~size:_=Botletis_bottom~size:_=functionBot->true|_->falselettop~size:_=SentinelTopletpretty~size:_fmt=letopenFormatinfunction|Bot->pp_print_stringfmt"Bottom"|Zero->pp_print_stringfmt"Zero"|NonZero->pp_print_stringfmt"NonZero"|SentinelTop->pp_print_stringfmt"MbZero"letincludes~size:_xy=matchx,ywith|_,Bot->true|Zero,NonZero|NonZero,Zero->false|Zero,Zero|NonZero,NonZero->true|SentinelTop,_->true|_->falseletjoin~size:_xy=matchx,ywith|Bot,a|a,Bot->a|Zero,Zero ->Zero|NonZero,NonZero->NonZero|_->SentinelTopletinter~size:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,NonZero|NonZero,Zero->Bot|NonZero,_|_,NonZero->NonZero|Zero,_|_,Zero->Zero|SentinelTop,SentinelTop->SentinelToplethash=function|Bot->Hashtbl.hash0|Zero->Hashtbl.hash1|NonZero->Hashtbl.hash2|SentinelTop->Hashtbl.hash3letcomparexy=matchx,ywith|Bot,Bot->0|Bot,_->-1|_,Bot->1|Zero,Zero->0|Zero,_->-1|_,Zero->1|NonZero,NonZero->0|NonZero,SentinelTop->-1|SentinelTop,NonZero->1|SentinelTop,SentinelTop->0letequalxy=comparexy=0letwiden~size~previousx=join~sizepreviousxletincludes_or_widen~size~previousx=ifincludes~sizepreviousxthen(true,x)else(false,widen~size~previousx)letsingleton~size:_i=ifZ.equaliZ.zerothenZeroelseNonZeroletis_singleton~size_x=assertfalseletis_empty~size_x=assertfalseletfold_crop_signed~size_x~inf~sup_acc_f=assertfalseletfold_crop_unsigned~size_x~inf~sup_acc_f=assertfalseendtypebitvector=Bitvector_Lattice.tmoduleBitvector_Forward=structopenBitvector_Latticeletbiconst~size:_const=ifZ.equalconstZ.zerothenZeroelseNonZeroletbiadd~size:_~flags:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,Zero->Zero|NonZero,Zero|Zero,NonZero->NonZero|_->SentinelTopletbisub~size:_~flags:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,Zero->Zero|NonZero,Zero|Zero,NonZero->NonZero|_->SentinelTopletbimul~size:_~flagsxy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,_|_,Zero->Zero|NonZero,NonZero->NonZero|_->SentinelTopletbimul_add~size~prod~offsetx=Integer_Forward.iadd(Integer_Forward.imul(biconst~sizeprod)x)(biconst~sizeoffset)letbisdiv~size:_xy=matchx,ywith|Bot,_|_,Bot|_,Zero->Bot|Zero,_->Zero|NonZero,_->SentinelTop|SentinelTop,(NonZero|SentinelTop)->SentinelTopletbismod~size:_xy=matchx,ywith|Bot,_|_,Bot|_,Zero->Bot|Zero,_->Zero|_->SentinelTopletbiudiv=bisdivletbiumod=bismodletband~size:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,_|_,Zero->Zero|_->SentinelTopletbor~size:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,Zero->Zero|NonZero,_|_,NonZero->NonZero|_->SentinelTopletbxor~size:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,Zero->Zero|Zero,NonZero|NonZero,Zero->NonZero|_->SentinelTopletbshl~size:_~flags:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,_->Zero|NonZero,Zero->NonZero|_->SentinelTopletbashr~size:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,_->Zero|NonZero,Zero->NonZero|_->SentinelTopletblshr~size:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,_->Zero|NonZero,Zero->NonZero|_->SentinelTopletbconcat~size1:_~size2:_xy=matchx,ywith|Bot,_|_,Bot->Bot|Zero,Zero->Zero|NonZero,_|_,NonZero->NonZero|_->SentinelTopletbeq~size:_xy=matchx,ywith|Bot,_|_,Bot->Lattices.Quadrivalent.Bottom|Zero,Zero->Lattices.Quadrivalent.True|Zero,NonZero|NonZero,Zero->Lattices.Quadrivalent.False|_->Lattices.Quadrivalent.Topletbisle~size:_xy=matchx,ywith|Bot,_|_,Bot->Lattices.Quadrivalent.Bottom|_->Lattices.Quadrivalent.Topletbiule~size:_xy=matchx,ywith|Bot,_|_,Bot->Lattices.Quadrivalent.Bottom|Zero,_->Lattices.Quadrivalent.True|NonZero,Zero->Lattices.Quadrivalent.False|_->Lattices.Quadrivalent.Topletbuext~size:_~oldsize:_x=xletbsext~size:_~oldsize:_x=xletbextract~size:_~index:_~oldsize:_=function|Bot->Bot|Zero->Zero|_->SentinelTopletbofbool~size:_=letopenLattices.Quadrivalentinfunction|Bottom->Bot|False->Zero|True->NonZero|Top->SentinelTopendmoduleBitvector_Backward=structopenBitvector_Latticeletbeq~size:_xyres=matchreswith|Lattices.Quadrivalent.True->beginmatchx,ywith|Zero,SentinelTop->None,SomeZero|SentinelTop,Zero->SomeZero,None|NonZero,SentinelTop->None,SomeNonZero|SentinelTop,NonZero->SomeNonZero,None|Zero,Zero|NonZero,NonZero->None,None|SentinelTop,SentinelTop->None,None|Bot,_|_,Bot->None,None|NonZero,Zero|Zero,NonZero->assertfalseend|Lattices.Quadrivalent.False->beginmatchx,ywith|SentinelTop,Zero->SomeNonZero,None|Zero,SentinelTop->None,SomeNonZero|Zero,Zero->SomeBot,SomeBot|_->None,Noneend|_->None,Noneletbiule~size:_xyres=matchreswith|Lattices.Quadrivalent.True->beginmatchx,ywith|SentinelTop,Zero->SomeZero,None|NonZero,SentinelTop->None,SomeNonZero|_->None,Noneend|Lattices.Quadrivalent.False->beginmatchx,ywith|SentinelTop,Zero|SentinelTop,NonZero->SomeNonZero,None|_->None,Noneend|_->None,Noneletbisle~size:_xyres=matchreswith|Lattices.Quadrivalent.True->None,None|Lattices.Quadrivalent.False->beginmatchx,ywith|SentinelTop,Zero->SomeNonZero,None|Zero,SentinelTop->None,SomeNonZero|_->None,Noneend|_->None,Noneletbiadd~size:_~flags:_xy=function|Zero->beginmatchx,ywith|Zero,SentinelTop->None,SomeZero|SentinelTop,Zero->SomeZero,None|NonZero,SentinelTop->None,SomeNonZero|SentinelTop,NonZero->SomeNonZero,None|_->None,Noneend|NonZero->beginmatchx,ywith|Zero,SentinelTop->None,SomeNonZero|SentinelTop,Zero->SomeNonZero,None|_->None,Noneend|_->None,Noneletbisub~size:_~flags:_xy=function|Zero->beginmatchx,ywith|Zero,SentinelTop->None,SomeZero|SentinelTop,Zero->SomeZero,None|NonZero,SentinelTop->None,SomeNonZero|SentinelTop,NonZero->SomeNonZero,None|_->None,Noneend|NonZero->beginmatchx,ywith|Zero,SentinelTop->None,SomeNonZero|SentinelTop,Zero->SomeNonZero,None|_->None,Noneend|_->None,Noneletbimul~size:_~flags:_xy=function|Zero->beginmatchx,ywith|NonZero,SentinelTop->None,SomeZero|SentinelTop,NonZero->SomeZero,None|_->None,Noneend|NonZero->beginmatchx,ywith|SentinelTop,SentinelTop->SomeNonZero,SomeNonZero|NonZero,SentinelTop->None,SomeNonZero|SentinelTop,NonZero->SomeNonZero,None|_->None,Noneend|_->None,Noneletbimul_add~size~prod~offsetxres=letprod=Bitvector_Forward.biconst~sizeprodinletmul=Integer_Forward.imulprodxin(* We could check that the second arguments match the constants here, and
raise bottom if that is not the case... *)matchInteger_Backward.iaddmul(Bitvector_Forward.biconst~sizeoffset)|>fstwith|None->None|Somemul->Integer_Backward.imulprodx|>sndletband~size:___=function|NonZero->SomeNonZero,SomeNonZero|_->None,Noneletbor~size:_xy=function|Zero->SomeZero,SomeZero|NonZero->beginmatchx,ywith|SentinelTop,Zero->SomeNonZero,None|Zero,SentinelTop->None,SomeNonZero|_->None,Noneend|_->None,Noneletbxor~size:_xy=function|Zero->beginmatchx,ywith|Zero,SentinelTop->None,SomeZero|SentinelTop,Zero->SomeZero,None|NonZero,SentinelTop->None,SomeNonZero|SentinelTop,NonZero->SomeNonZero,None|_->None,Noneend|NonZero->beginmatchx,ywith|Zero,SentinelTop->None,SomeNonZero|SentinelTop,Zero->SomeNonZero,None|_->None,Noneend|_->None,Noneletbisdiv~size:_xy=function|Zero->SomeZero,None|NonZero->SomeNonZero,SomeNonZero|Bot->beginmatchx,ywith|Bot,_|_,Bot->None,None|_->None,SomeZeroend|_->None,Noneletbiudiv~size:_xy=function|Zero->SomeZero,None|NonZero->SomeNonZero,SomeNonZero|Bot->beginmatchx,ywith|Bot,_|_,Bot->None,None|_->None,SomeZeroend|_->None,Noneletbismod~size:_xy=function|NonZero->SomeNonZero,SomeNonZero|Bot->beginmatchx,ywith|Bot,_|_,Bot->None,None|_->None,SomeZeroend|_->None,Noneletbiumod~size:_xy=function|NonZero->SomeNonZero,SomeNonZero|Bot->beginmatchx,ywith|Bot,_|_,Bot->None,None|_->None,SomeZeroend|_->None,Noneletbashr~size:_xy=function|Zero->beginmatchx,ywith|SentinelTop,Zero->SomeZero,None|NonZero,SentinelTop->None,SomeNonZero|_->None,Noneend|NonZero->SomeNonZero,None|_->None,Noneletblshr~sizexy=bashr~sizexyletbshl~size~flagsxy=bashr~sizexyletbsext~size:_~oldsize:___=(None)letbuext~size:_~oldsize:___=(None)letbconcat~size1:_~size2:____=(None,None)letbextract~size:_~index:_~oldsize:___=(None)letbofbool~size:__bool=letopenLattices.Quadrivalentinfunction|Bot->SomeBottom|Zero->SomeFalse|NonZero->SomeTrue|SentinelTop->SomeTopendlet_binary_to_ival~signed~size=letopenBitvector_Latticeinfunction|Zero->Framac_ival.Ival.of_int0|NonZero->ifsignedthenFramac_ival.Ival.topelse(* Range is [1,2^size-1]. *)Framac_ival.Ival.inject_range(SomeZ.one)(Some(Z.sub(Z.shift_leftZ.onesize)Z.one))|SentinelTop->Framac_ival.Ival.top|Bot->Framac_ival.Ival.bottomlet_binary_is_singleton~size:_=letopenBitvector_Latticeinfunction|Zero->SomeZ.zero|_->Nonelet_binary_is_empty~size:_=letopenBitvector_Latticeinfunction|Bot->true|_->falseletis_zero=function|Bitvector_Lattice.(Bot|Zero)->true|Bitvector_Lattice.(NonZero|SentinelTop)->falseletzero=Bitvector_Lattice.Zeroletnonzero=Bitvector_Lattice.NonZerolet_binary_to_known_bits~size=letopenBitvector_Latticeinfunction|Bot->Lattices.Known_Bits.bottom~size|Zero->(Z.zero,Z.zero)|NonZero|SentinelTop->Lattices.Known_Bits.top~size