123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163(**************************************************************************)(* *)(* This file is part of the Frama-C's MetACSL plug-in. *)(* *)(* Copyright (C) 2018-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) *)(* *)(**************************************************************************)openCil_typesopenMeta_utilsopenMeta_parseopenMeta_optionstypeunpacked_metaproperty={ump_emitter:Emitter.t;ump_property:Kernel_function.t->?stmt:stmt->(string*replaced_kind)list->predicate;ump_ip:Property.t;ump_counter:intref;ump_admit:bool;ump_assert:bool;}letname_of_meta_acsl_termt=matcht.term_nodewith|TConstLStrs->s|_->failwith"Invalid meta term"letget_mp_ipmp=letvis=object(_)inheritVisitor.frama_c_inplacevalmutablefound=Nonemethodget()=Option.getfoundmethod!vannotation=function|Dextended({ext_name="meta";ext_kind=Ext_terms[t]}asext,_,_)whenname_of_meta_acsl_termt=mp.mp_name->found<-Some(Property.ip_of_extendedProperty.ELGlobext);Cil.SkipChildren|_->Cil.DoChildrenendinignore(Visitor.visitFramacFileSameGlobals(vis:>Visitor.frama_c_visitor)(Ast.get()));vis#get()letname_mp_predflagspredump_counter=letpred=ifflags.prefix_metathen{predwithpred_name="meta"::pred.pred_name}elsepredinifflags.number_assertionsthen((* Number the instantiation *)ump_counter:=!ump_counter+1;{predwithpred_name=("_"^(string_of_int!ump_counter))::pred.pred_name})elsepredletunpack_mpflagsmpadmit=letump_emitter=Emitter.createmp.mp_name~correctness:[]~tuning:[][Emitter.Code_annot]inletump_ip=get_mp_ipmpinletump_counter=ref0in(* Wrapped property *)letump_propertykf?stmtal=letpred=mp.mp_propertykfalinletpred=matchstmtwith|None->pred|Somestmt->Meta_simplify.remove_alpha_conflictspredkfstmtinletpred=ifflags.simplthenMeta_simplify.simplifypredelsepredinpredinletump_assert=matchmp.mp_translationwith|MtNone->assertfalse|MtAssert->true|MtCheck->false|MtDefault->flags.default_to_assertin{ump_emitter;ump_property;ump_ip;ump_counter;ump_admit=admit;ump_assert}(* Returns an assoc list associating each context to a
* hash table mapping each function to a list of
* MP names to process for that context and for that function.
* The order is the same as in the original file
*
* Also returns a hash table mapping a MP name to an unpacked MP
*)letdispatchflagsmps=letall_mp=Hashtbl.create10inletctxts=[Weak_invariant;Strong_invariant;Writing;Reading;Calling;Precond;Postcond;Conditional_invariant]inlettables=List.map(functx->ctx,Str_Hashtbl.create5)ctxtsinList.iter(funmp->lettable=List.assocmp.mp_contexttablesinlettargets=Meta_deduce.compute_targetmp.mp_targetinifflags.list_targetsthenSelf.feedback"Targets of %s: %a"mp.mp_nameStrSet.prettytargets;letadmit=matchmp.mp_proof_methodwith|MmLocal->false|MmAxiom->true|MmDeduction->letip=get_mp_ipmpinMeta_deduce.deduceflagsmpipmpsinifmp.mp_translation<>MtNonethen(StrSet.iter(funtarget->add_to_hash_listStr_Hashtbl.(find_opt,replace)tabletargetmp.mp_name)targets;Hashtbl.addall_mpmp.mp_name(unpack_mpflagsmpadmit));)mps;(* Reverse lists in tables to maintain the correct order *)List.iter(fun(_,table)->Str_Hashtbl.iter(funkv->Str_Hashtbl.replacetablek(List.revv))table)tables;tables,all_mpmoduleUmpHash=structtypet=unpacked_metapropertyletequalab=Emitter.equala.ump_emitterb.ump_emitterlethashp=Emitter.hashp.ump_emitterendmoduleUmpHashtbl=Hashtbl.Make(UmpHash)(* Associates a list of deps (IPs) to an UMP *)letdependencies=UmpHashtbl.create10(* Call each time an instantiation of a prop is done *)letadd_dependencyumpips=List.iter(add_to_hash_listUmpHashtbl.(find_opt,replace)dependenciesump)ips(* Call once at the end to actually register dependencies between props and
* their instanciations *)letfinalize_dependencies()=letkeys=UmpHashtbl.to_seq_keysdependenciesinletadd_oneprop=letdeps=find_hash_listUmpHashtbl.find_optdependenciespropin(* If the MP is admitted, every instance *is* true *)ifprop.ump_admitthenList.iter(funinst->Property_status.emitprop.ump_emitter~hyps:[]instProperty_status.True)depselse((* The MP is true if every instance is true *)Property_status.emitprop.ump_emitter~hyps:depsprop.ump_ipProperty_status.True)inSeq.iteradd_onekeys