123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* 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 licenses/LGPLv2.1). *)(* *)(**************************************************************************)openDive_typesmoduleGraph=Dive_graphmoduleNodeRef=Datatype.Pair_with_collections(Node_kind)(Callstack)(structletmodule_name="Build.NodeRef"end)moduleIndex=Datatype.Int.HashtblmoduleNodeTable=FCHashtbl.Make(NodeRef)moduleNodeSet=Graph.Node.SetmoduleBaseSet=Cil_datatype.Varinfo.Settypeelement=Nodeofnode|Edgeof(node*dependency*node)typet={mutablegraph:Graph.t;mutablevertex_table:nodeIndex.t;(* node_key -> node *)mutablenode_table:nodeNodeTable.t;(* node_kind * callstack -> node *)mutableunfolded_bases:BaseSet.t;mutablehidden_bases:BaseSet.t;mutablemax_dep_fetch_count:int;mutableroots:NodeSet.t;mutableupdate_hook:element->unit;mutableremove_hook:element->unit;mutableclear_hook:unit->unit;}(* --- initialization --- *)letno_hook=fun_->()letcreate()={graph=Graph.create();vertex_table=Index.create13;node_table=NodeTable.create13;unfolded_bases=BaseSet.empty;hidden_bases=BaseSet.empty;max_dep_fetch_count=10;roots=NodeSet.empty;update_hook=no_hook;remove_hook=no_hook;clear_hook=no_hook;}letclearcontext=context.graph<-Graph.create();context.vertex_table<-Index.create13;context.node_table<-NodeTable.create13;context.max_dep_fetch_count<-10;context.roots<-NodeSet.empty;context.clear_hook()(* Hooks *)letset_update_hookcontextf=context.update_hook<-fletset_remove_hookcontextf=context.remove_hook<-fletset_clear_hookcontextf=context.clear_hook<-fletnotify_node_updatecontextnode=context.update_hook(Nodenode)(* --- Accessors --- *)letget_graphcontext=context.graphletfind_nodecontextnode_key=Index.findcontext.vertex_tablenode_keyletget_max_dep_fetch_countcontext=context.max_dep_fetch_count(* --- Roots --- *)letget_rootscontext=NodeSet.elementscontext.rootsletupdate_rootscontextnew_roots=letold_roots=context.rootsincontext.roots<-new_roots;letunsetn=n.node_is_root<-false;context.update_hook(Noden);andsetn=n.node_is_root<-true;context.update_hook(Noden);inNodeSet.iterunsetold_roots;NodeSet.itersetnew_rootsletset_unique_rootcontextroot=update_rootscontext(NodeSet.singletonroot)letadd_rootcontextroot=update_rootscontext(NodeSet.addrootcontext.roots)letremove_rootcontextroot=update_rootscontext(NodeSet.removerootcontext.roots)(* --- Folding --- *)letis_foldedcontextvi=not(BaseSet.memvicontext.unfolded_bases)letfoldcontextvi=context.unfolded_bases<-BaseSet.removevicontext.unfolded_basesletunfoldcontextvi=context.unfolded_bases<-BaseSet.addvicontext.unfolded_bases(* --- Base hiding --- *)letis_hiddencontextnode_kind=matchNode_kind.get_basenode_kindwith|SomeviwhenBaseSet.memvicontext.hidden_bases->true|_->falseletshowcontextvi=context.hidden_bases<-BaseSet.addvicontext.hidden_baseslethidecontextvi=context.hidden_bases<-BaseSet.addvicontext.hidden_bases(* --- Building --- *)letadd_nodecontext~node_kind~node_locality=letnode_ref=(node_kind,node_locality.loc_callstack)inletadd_new_=letnode=Graph.create_nodecontext.graph~node_kind~node_localityinnode.node_hidden<-is_hiddencontextnode.node_kind;Index.addcontext.vertex_tablenode.node_keynode;context.update_hook(Nodenode);nodeinNodeTable.memocontext.node_tablenode_refadd_newletremove_nodecontextnode=letnode_ref=(node.node_kind,node.node_locality.loc_callstack)inletgraph=context.graphinGraph.iter_succ(funn->n.node_writes_computation<-NotDone)graphnode;Graph.iter_pred(funn->n.node_reads_computation<-NotDone)graphnode;Graph.iter_succ_e(fune->context.remove_hook(Edgee))graphnode;Graph.iter_pred_e(fune->context.remove_hook(Edgee))graphnode;Graph.remove_nodecontext.graphnode;Index.removecontext.vertex_tablenode.node_key;NodeTable.removecontext.node_tablenode_ref;context.remove_hook(Nodenode)letadd_depcontext~origin~kindsrcdest=letedge=Graph.create_dependencycontext.graph~origin~kindsrcdestincontext.update_hook(Edgeedge)letremove_depcontextedge=Graph.remove_dependencycontext.graphedge;context.remove_hook(Edgeedge)letremove_node_depscontextnode=Graph.iter_pred_e(remove_depcontext)context.graphnodeletupdate_node_valuescontextnode~typ~cvalue~taint=Graph.update_node_valuesnode~typ~cvalue~taint;notify_node_updatecontextnodeletset_node_writescontextnodewrites=node.node_writes<-List.sort_uniqStudia.Writes.comparewrites;notify_node_updatecontextnode