123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180(**************************************************************************)(* 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). *)(* *)(**************************************************************************)(**************** Standard abstractions for integers. ****************)(* All these abstractions rely on pairs of Z. *)moduleZPair=structtypet=Z.t*Z.tletcompare(a1,b1)(a2,b2)=letres=Z.comparea1a2inifres==0thenZ.compareb1b2elseres;;letequal(a1,b1)(a2,b2)=Z.equala1a2&&Z.equalb1b2lethash(a,b)=Hashing.hash2(Z.hasha)(Z.hashb);;endmoduleInterval=struct(* Min, max pair. Note that we can only represent finite sets. *)includeZPair;;letjoin(min1,max1)(min2,max2)=(Z.minmin1min2,Z.maxmax1max2);;letinter(min1,max1)(min2,max2)=(Z.maxmin1min2,Z.minmax1max2);;(* Any element where max is smaller than min is bottom, and this is
the canonical one. *)letbottom()=Z.one,Z.zeroletincludes(min1,max1)(min2,max2)=Z.leqmin1min2&&Z.geqmax1max2;;letprettyfmt(a,b)=Format.fprintffmt"[%s..%s]"(Z.to_stringa)(Z.to_stringb)endmoduleKnown_Bits=struct(* First bitvector = 0 where the bits must be 0, 1 otherwise.
Second bitvector = 1 where the bits must be 1, 0 otherwise. *)includeZPairletbottom()=(Z.zero,Z.minus_one);;letis_bottom(x0,x1)=letopenZinnot@@Z.equalZ.zero@@~!x0landx1;;lettop()=(Z.minus_one,Z.zero);;typebitvalue=One|Zero|Unknown(* Note: 0 is the least significant bit. *)lettestbit(x0,x1)index=ifZ.testbitx0indexthenifZ.testbitx1index(* First bit is 1. *)thenOneelseUnknownelseZero;;letprettyfmt(x0,x1)=ifis_bottom(x0,x1)thenFormat.fprintffmt"<bottom>"elseletsize=Z.numbitsx0infori=(size-1)downto0domatchtestbit(x0,x1)iwith|Zero->Format.fprintffmt"0"|One->Format.fprintffmt"1"|Unknown->Format.fprintffmt"?"done;;letreads=letn=(String.lengths)-1inletrecloopnbit(x0,x1)=ifn<0then(x0,x1)elsematchs.[n]with|'0'->loop(n-1)(Z.(lsl)bit1)(x0,x1)|'1'->loop(n-1)(Z.(lsl)bit1)(Z.(lor)x0bit,Z.(lor)x1bit)|'?'->loop(n-1)(Z.(lsl)bit1)(Z.(lor)x0bit,x1)|_->failwith"Wrong input"inloopnZ.one(Z.zero,Z.zero);;letsingletonx=(x,x);;(* Intersection: keep the bits known by one side. *)letinter0=Z.(land)letinter1=Z.(lor)letinter(x0,x1)(y0,y1)=(inter0x0y0,inter1x1y1);;letjoin0=Z.(lor)letjoin1=Z.(land)letjoin(x0,x1)(y0,y1)=(join0x0y0,join1x1y1)letequal(x0,x1)(y0,y1)=Z.equalx0y0&&Z.equalx1y1;;letis_includedxy=equaly(joinxy);;letincludesxy=is_includedyx(* A widening operator from a paper by Antoine Miné. *)letwiden~size~previous:(prev0,prev1)(new0,new1)=letres0=lett=join0prev0new0inifZ.equalprev0tthenprev0elseZ.minus_oneinletres1=lett=join1prev1new1inifZ.equalprev1tthenprev1elseZ.zeroin(res0,res1);;letincludes_or_widen~size~previous_=assertfalseendmoduleCongruence=struct(* Represents a set q * Z + r, where q is the first element, and r the second.
- If q is negative, this represents bottom.
- If q is 0, this represents a singleton.
- If q is >0, then 0 <= r < q. *)(* Note: we could have another abstraction representing truncated
division. *)includeZPairletbottom()=(Z.minus_one,Z.minus_one)lettop()=Z.one,Z.zero(* 1 * Z + 0 = R *)letsingletonx=Z.zero,xendmoduleInteger_Set=structmoduleZSet=Set.Make(Z)letequal=ZSet.equalletcompare=ZSet.comparelethash_=assertfalseletprettyfmtx=Format.fprintffmt"@[<hv>";x|>ZSet.iter(funx->Format.fprintffmt"%s@ "(Z.to_stringx));Format.fprintffmt"@]";;typet=ZSet.tletbottom()=ZSet.empty(* let top = assert false *)letjoin=ZSet.unionletinter=ZSet.interletsingleton=ZSet.singletonend