123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358(**************************************************************************)(* 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). *)(* *)(**************************************************************************)includeSmtbackend_smtlib_sigmoduleMake(P:PARAM_S)=structtypet=unit->unittypelogic=ttypecommand=ttypesatisfiable=Sat|Unsat|Unknown;;letpr_inti()=P.print@@string_of_intiletar0str()=P.print"(";P.printstr;P.print")";;letar1str(a:t)()=P.print"(";P.printstr;P.print" ";a();P.print")";;letar2str(a:t)(b:t)()=P.print"(";P.printstr;P.print" ";a();P.print" ";b();P.print")";;letar3str(a:t)(b:t)(c:t)()=P.print"(";P.printstr;P.print" ";a();P.print" ";b();P.print" ";c();P.print")";;letar_listl()=P.print"(";(matchlwith|[]->()|a::b->a();b|>List.iter(funx->P.print" ";(x())));P.print")";;letread_sat()=(* P.print "\n"; *)(* P.flush(); *)letinput=matchinput_lineP.incwith|exceptionEnd_of_file->Codex_log.fatal"Could not read the solver answer. Is z3 installed?"|input->inputinmatchinputwith|"sat"->Sat|"unsat"->Unsat|"unknown"->Codex_log.warning"Non-timeout unknown";Unknown|"timeout"->Unknown|_->failwith("input line "^input)letcheck_sat()=ar0"check-sat"();P.print"\n";P.flush();read_sat();;letset_optionstring=P.print"(set-option ";P.printstring;P.print")\n";;letget_assignment()=ar0"get-assignment"();P.print"\n";P.flush();;letqf_uf()=P.print"QF_UF"letqf_lia()=P.print"QF_LIA"letqf_nia()=P.print"QF_NIA"letqf_lra()=P.print"QF_LRA"letqf_auflia()=P.print"QF_AUFLIA"letauflia()=P.print"AUFLIA"letauflira()=P.print"AUFLIRA"letaufnira()=P.print"AUFNIRA"letlra()=P.print"LRA"letqf_idl()=P.print"QF_IDL"letqf_rdl()=P.print"QF_RDL"letqf_ufidl()=P.print"QF_UFIDL"letqf_bv()=P.print"QF_BV"letqf_ax()=P.print"QF_AX"letqf_abv()=P.print"QF_ABV"letqf_aubv()=P.print"QF_AUBV"lethorn()=P.print"HORN"letsortstr=(fun()->P.printstr)letbool=sort"Bool"letint=sort"Int"letgensym_ctr=ref0;;letgensym?name:(name="x")()=letcount=!gensym_ctrinincrgensym_ctr;name^(string_of_intcount);;(* When given, the name should alredy be uniquified. Not always true for prevous versions. *)let_gensym_?name()=matchnamewith|None->incrgensym_ctr;"x"^(string_of_int!gensym_ctr)|Some"nondet"->incrgensym_ctr;"x"^(string_of_int!gensym_ctr)|Some"var"->incrgensym_ctr;"x"^(string_of_int!gensym_ctr)|Some"mu"->incrgensym_ctr;"x"^(string_of_int!gensym_ctr)|Somename->nameletdeclare_var?namesort=letname=gensym()inletpr_name()=P.printnamein(* let command () = *)P.print"(declare-fun ";P.printname;P.print" () ";sort();P.print")\n";(* command, *)pr_name;;letdefine_var?namesortvalue=letname=gensym()inletpr_name()=P.printnamein(* let command () = *)P.print"(define-fun ";P.printname;P.print" () ";sort();P.print" ";value();P.print")\n";(* command, *)pr_name;;letlet_?name(v:unit->unit)(f:(unit->unit)->(unit->unit)):(unit->unit)=fun()->letname=gensym()inletprname=fun()->P.printnameinP.print"(let ((";P.printname;P.print" ";v();P.print")) ";fprname();P.print")";;letquantifstr?name(sort:unit->unit)(f:(unit->unit)->(unit->unit))=fun()->letname=gensym()inletprname=fun()->P.printnameinP.print"(";P.printstr;P.print"((";P.printname;P.print" ";sort();P.print")) ";fprname();P.print")";;letforall=quantif"forall";;letexists=quantif"exists";;letassert_cond=let()=ar1"assert"cond()inP.print"\n";;letset_logiclog=ar1"set-logic"log();P.print"\n";;let(||)=ar2"or";;let(&&)=ar2"and";;let(=>)=ar2"=>";;letnot=ar1"not";;lettrue_()=P.print"true";;letfalse_()=P.print"false";;letarray=ar2"Array"letselect=ar2"select";;letstore=ar3"store";;(**************** bitvectors ****************)letbitvecint=ar1"_ BitVec"(pr_intint);;(* let bvlit int = *)letbvult=ar2"bvult"letbvlshr=ar2"bvlshr"letbvshl=ar2"bvshl"letbvurem=ar2"bvurem"letbvudiv=ar2"bvudiv"letbvmul=ar2"bvmul"letbvadd=ar2"bvadd"letbvor=ar2"bvor"letbvand=ar2"bvand"letbvneg=ar1"bvneg"letbvnot=ar1"bvnot"letconcat=ar2"concat"letbvlit~sizek()=letx=ifZ.geqkZ.zerothenkelseZ.(+)k@@Z.shift_leftZ.onesizein(* If we can use hexadecimal *)if(sizeland3)==0thenbeginletu=Z.format"%x"xinletleading_zeroes=(sizelsr2)-(String.lengthu)inP.print"#x";for_=0toleading_zeroes-1doP.print"0"done;P.printuendelsebegin(* We use binary *)letu=Z.format"%b"xinletleading_zeroes=size-(String.lengthu)inP.print"#b";for_=0toleading_zeroes-1doP.print"0"done;P.printuend;;(* Only works when Integer is provided with Zarith. *)letbvlit~size(k:Z.t)()=bvlit~size(Obj.magick)();;(* Does not output the right number of zeroes. *)(* let bvlit64 = make_bvlit (Printf.sprintf "%Lx") *)letbvxor=ar2"bvxor"letbvsdiv=ar2"bvsdiv"letbvsrem=ar2"bvsrem"letbvule=ar2"bvule"letbvslt=ar2"bvslt"letbvsle=ar2"bvsle"letbvashr=ar2"bvashr"letbvsmod=ar2"bvsmod"letzero_extendi=ar1@@"(_ zero_extend "^(string_of_inti)^")"letsign_extendi=ar1@@"(_ sign_extend "^(string_of_inti)^")"letextract~first~last=ar1@@"(_ extract "^(string_of_intlast)^" "^(string_of_intfirst)^")"(* Muz. *)(* type relation = value t list -> value t *)typerelation=(unit->unit)list->unit->unitletdeclare_rel?namesorts=letname=gensym?name()inletpr_namelist()=matchlistwith|[]->P.printname|_->P.print("("^name);List.iter(funx->P.print" ";x())list;P.print")"inP.print"(declare-rel ";P.printname;P.print" ";ar_listsorts();P.print")\n";pr_name,name;;(* let query rel list = P.print "(query"; ar_list (rel::list) (); P.print ")\n";; *)letquerybool=P.print"(query ";bool();P.print")\n";P.flush();read_sat()letquery2string=P.print"(query ";P.printstring;P.print")\n";P.flush();read_sat()letfactconclusion=P.print"(rule ";conclusion();P.print")\n";;letrulepremicesconclusion=ifpremices==[]thenfactconclusionelsebeginP.print"(rule (=> (and ";List.iter(funx->P.print"\n ";x())premices;P.print")\n ";conclusion();P.print"))\n"end;;letand_list=function|[]->true_|[x]->x|l->beginfun()->P.print"(and ";List.iter(funx->P.print" ";x())l;P.print")"end;;letor_list=function|[]->false_|[x]->x|l->beginfun()->P.print"(or ";List.iter(funx->P.print" ";x())l;P.print")"end;;letdeclare_muz_var?namesort=letname=gensym?name()inletpr_name()=P.printnamein(* let command () = *)P.print"(declare-var ";P.printname;P.print" ";sort();P.print")\n";(* command, *)pr_name;;(**************** Ints ****************)letnumeralx()=P.print@@string_of_intx;;letnumeralzx()=P.print@@Z.to_stringx;;let(<)=ar2"<"let(<=)=ar2"<="let(=)=ar2"="letmodu=ar2"mod"letdiv=ar2"div"let(+)=ar2"+"let(-)=ar2"-"let(*)=ar2"*"letneg=ar1"-"endmoduleMake_Typed(P:PARAM_S):TYPED_S=structincludeMake(P)typebitvectortype('a,'b)arraytype'asort=ttype'avalue=tendmoduleMake_Untyped(P:PARAM_S):UNTYPED_S=structincludeMake(P)typesort=ttypevalue=tendmoduleMake_Untyped_Muz(P:PARAM_S):UNTYPED_MUZ=structincludeMake(P)typesort=ttypevalue=tendletwith_z3?(executable="z3")(f:(moduleUNTYPED_MUZ)->'a)=letexecutable="z3"in(* Note: careful with functions that pass the env, as the PATH may
be modified, which is problematic on Nix. *)let(pout,pin)=Unix.open_process(executable^" -T:"^(Codex_config.smt_timeout()|>string_of_int)^" -in")inletmoduleSMT=Make_Untyped_Muz(structletprintstr=(* Duplicate the output for debugging *)ifCodex_config.print_smt_input()thenStdlib.print_stringstr;Stdlib.output_stringpinstr;;letinc=poutletflush()=Stdlib.flushpinend)inf(moduleSMT:UNTYPED_MUZ);;