123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156(**************************************************************************)(* 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). *)(* *)(**************************************************************************)typear1_format={prefix:string;suffix:string}typear2_format={prefix:string;middle:string;suffix:string}typear3_format={prefix:string;middle1:string;middle2:string;suffix:string}(* TODO: arn. *)typeexpr=|Ar0of{s:string}|Ar1of{format:ar1_format;arg:expr}|Ar2of{format:ar2_format;arg1:expr;arg2:expr}|Ar3of{format:ar3_format;arg1:expr;arg2:expr;arg3:expr}|Iteof{cond:expr;then_expr:expr;else_expr:expr}typeexpr_path=intlistletrecequal_expre1e2=matche1,e2with|_whene1==e2->true|Ar0{s=s1},Ar0{s=s2}->s1=s2|Ar1{format=format1;arg=arg1},Ar1{format=format2;arg=arg2}->(format1==format2||format1=format2)&&equal_exprarg1arg2|Ar2{format=formata;arg1=arg1a;arg2=arg2a},Ar2{format=formatb;arg1=arg1b;arg2=arg2b}->(formata==formatb||formata=formatb)&&equal_exprarg1aarg1b&&equal_exprarg2aarg2b|Ar3{format=formata;arg1=arg1a;arg2=arg2a;arg3=arg3a},Ar3{format=formatb;arg1=arg1b;arg2=arg2b;arg3=arg3b}->(formata==formatb||formata=formatb)&&equal_exprarg1aarg1b&&equal_exprarg2aarg2b&&equal_exprarg3aarg3b|Ite{cond=c1;then_expr=t1;else_expr=e1},Ite{cond=c2;then_expr=t2;else_expr=e2}->equal_exprc1c2&&equal_exprt1t2&&equal_exprc1c2|_->falseletarity=function|Ar0_->0|Ar1_->1|Ar2_->2|Ar3_->3|Ite_->3letisdeepexpr=matchexprwith|Ar0{s}->String.containss' '|Ar1{format;arg}->true|Ar2_->true|Ar3_->true|Ite_->trueletrecstring_of_expr_impldisplay_parexpr=(ifdisplay_parthen"("else"")^(matchexprwith|Ar0{s}->s|Ar1{format={prefix;suffix};arg}->prefix^(string_of_expr_impl(isdeeparg)arg)^suffix|Ar2{format={prefix;middle;suffix};arg1;arg2}->prefix^(string_of_expr_impl(isdeeparg1)arg1)^middle^(string_of_expr_impl(isdeeparg2)arg2)^suffix|Ar3{format={prefix;middle1;middle2;suffix};arg1;arg2;arg3}->prefix^(string_of_expr_impl(isdeeparg1)arg1)^middle1^(string_of_expr_impl(isdeeparg2)arg2)^middle2^(string_of_expr_impl(isdeeparg2)arg3)^suffix|Ite{cond:expr;then_expr:expr;else_expr:expr}->string_of_expr_impl(isdeepcond)cond^" ? "^string_of_expr_impl(isdeepthen_expr)then_expr^" : "^string_of_expr_impl(isdeepelse_expr)else_expr)^(ifdisplay_parthen")"else"")letstring_of_exprexpr=string_of_expr_implfalseexprmoduleHashcons=struct(* TODO: We could be hash-consing the format too. *)moduleExprH=Weak.Make(structtypet=exprletequal=equal_exprlethash=Hashtbl.hashend)letexpr_h=ExprH.create17letrechashconsx=tryExprH.findexpr_hxwithNot_found->beginletx=matchxwith|Ar0{s}->x|Ar1{format;arg}->Ar1{format;arg=hashconsarg}|Ar2{format;arg1;arg2}->Ar2{format;arg1=hashconsarg1;arg2=hashconsarg2}|Ar3{format;arg1;arg2;arg3}->Ar3{format;arg1=hashconsarg1;arg2=hashconsarg2;arg3=hashconsarg3}|Ite{cond;then_expr;else_expr}->Ite{cond=hashconscond;then_expr=hashconsthen_expr;else_expr=hashconselse_expr}inExprH.addexpr_hx;xendendlethashcons=Hashcons.hashconsmoduleLocation_identifier=structtypepath=|Nameofstring|Int64ofint64|Inside:{locid:'bt;idx:int}->pathand'akind=|Address|Expression|DbaInstruction(* | Instruction *)(* | Symbol *)(* | Function *)(* | Type *)and'at='akind*pathtypeany=Any:'at->any[@@unboxed]letequal_kind:typeab.akind->bkind->bool=funab->assert(Obj.is_int@@Obj.repra);assert(Obj.is_int@@Obj.reprb);Int.equal(Obj.magica)(Obj.magicb)letrecequal:typeab.at->bt->bool=fun(ka,pa)(kb,pb)->equal_kindkakb&&equal_pathpapbandequal_pathab=matcha,bwith|Namesa,Namesb->String.equalsasb|Int64ia,Int64ib->Int64.equaliaib|Inside{locid=locida;idx=idxa},Inside{locid=locidb;idx=idxb}->idxa=idxb&&equallocidalocidb|Name_,(Int64_|Inside_)|(Int64_|Inside_),Name_->false|Int64_,Inside_|Inside_,Int64_->falselethash=Hashtbl.hashendtype'alocated='a*'aLocation_identifier.t