CBMC
dependence_graph.h
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Field-Sensitive Program Dependence Analysis, Litvak et al.,
4  FSE 2010
5 
6 Author: Michael Tautschnig
7 
8 Date: August 2013
9 
10 \*******************************************************************/
11 
14 
15 #ifndef CPROVER_ANALYSES_DEPENDENCE_GRAPH_H
16 #define CPROVER_ANALYSES_DEPENDENCE_GRAPH_H
17 
18 #include <util/graph.h>
19 #include <util/threeval.h>
20 
21 #include "ai.h"
22 #include "cfg_dominators.h"
23 #include "reaching_definitions.h"
24 
25 class dependence_grapht;
26 
27 class dep_edget
28 {
29 public:
30  enum class kindt { NONE, CTRL, DATA, BOTH };
31 
32  void add(kindt _kind)
33  {
34  switch(kind)
35  {
36  case kindt::NONE:
37  kind=_kind;
38  break;
39  case kindt::DATA:
40  case kindt::CTRL:
41  if(kind!=_kind)
43  break;
44  case kindt::BOTH:
45  break;
46  }
47  }
48 
49  kindt get() const
50  {
51  return kind;
52  }
53 
54 protected:
56 };
57 
58 struct dep_nodet:public graph_nodet<dep_edget>
59 {
62 
64 };
65 
67 {
68 public:
70 
72  : has_values(false), node_id(id), has_changed(false)
73  {
74  }
75 
76  bool merge(const dep_graph_domaint &src, trace_ptrt from, trace_ptrt to);
77 
78  void transform(
79  const irep_idt &function_from,
80  trace_ptrt trace_from,
81  const irep_idt &function_to,
82  trace_ptrt trace_to,
83  ai_baset &ai,
84  const namespacet &ns) final override;
85 
86  void output(
87  std::ostream &out,
88  const ai_baset &ai,
89  const namespacet &ns) const final override;
90 
92  const ai_baset &ai,
93  const namespacet &ns) const override;
94 
95  void make_top() final override
96  {
97  DATA_INVARIANT(node_id!=std::numeric_limits<node_indext>::max(),
98  "node_id must not be valid");
99 
100  has_values=tvt(true);
101  control_deps.clear();
102  control_dep_candidates.clear();
103  data_deps.clear();
104  }
105 
106  void make_bottom() final override
107  {
108  DATA_INVARIANT(node_id!=std::numeric_limits<node_indext>::max(),
109  "node_id must be valid");
110 
111  has_values=tvt(false);
112  control_deps.clear();
113  control_dep_candidates.clear();
114  data_deps.clear();
115 
116  has_changed = false;
117  }
118 
119  void make_entry() final override
120  {
122  node_id != std::numeric_limits<node_indext>::max(),
123  "node_id must not be valid");
124 
126  control_deps.clear();
127  control_dep_candidates.clear();
128  data_deps.clear();
129 
130  has_changed = false;
131  }
132 
133  bool is_top() const final override
134  {
135  DATA_INVARIANT(node_id!=std::numeric_limits<node_indext>::max(),
136  "node_id must be valid");
137 
139  !has_values.is_true() ||
140  (control_deps.empty() && control_dep_candidates.empty() &&
141  data_deps.empty()),
142  "If the domain is top, it must have no dependencies");
143 
144  return has_values.is_true();
145  }
146 
147  bool is_bottom() const final override
148  {
149  DATA_INVARIANT(node_id!=std::numeric_limits<node_indext>::max(),
150  "node_id must be valid");
151 
153  !has_values.is_false() ||
154  (control_deps.empty() && control_dep_candidates.empty() &&
155  data_deps.empty()),
156  "If the domain is bottom, it must have no dependencies");
157 
158  return has_values.is_false();
159  }
160 
162  {
163  assert(node_id!=std::numeric_limits<node_indext>::max());
164  return node_id;
165  }
166 
167  void populate_dep_graph(
169 
170 private:
174 
175  typedef std::set<goto_programt::const_targett> depst;
176 
177  // Set of locations with control instructions on which the instruction at this
178  // location has a control dependency on
180 
181  // Set of locations with control instructions from which there is a path in
182  // the CFG to the current location (with the locations being in the same
183  // function). The set control_deps is a subset of this set.
185 
186  // Set of locations with instructions on which the instruction at this
187  // location has a data dependency on
189 
190  friend const depst &
192  friend const depst &
194 
196  const irep_idt &function_id,
199  dependence_grapht &dep_graph);
200 
201  void data_dependencies(
203  const irep_idt &function_to,
205  dependence_grapht &dep_graph,
206  const namespacet &ns);
207 };
208 
210 
212  public ait<dep_graph_domaint>,
213  public grapht<dep_nodet>
214 {
215 public:
218 
219  typedef std::map<irep_idt, cfg_post_dominatorst> post_dominators_mapt;
220 
221  explicit dependence_grapht(const namespacet &_ns);
222 
223  void initialize(const goto_functionst &goto_functions)
224  {
225  ait<dep_graph_domaint>::initialize(goto_functions);
226  rd(goto_functions, ns);
227 
228  for(const auto &entry : goto_functions.function_map)
229  {
230  const goto_programt &goto_program = entry.second.body;
231  if(!goto_program.empty())
232  {
233  end_function_map.emplace(
234  entry.first, std::prev(goto_program.instructions.end()));
235  }
236  }
237  }
238 
239  void initialize(const irep_idt &function, const goto_programt &goto_program)
240  {
241  ait<dep_graph_domaint>::initialize(function, goto_program);
242 
243  // The dependency graph requires that all nodes are explicitly created
244  forall_goto_program_instructions(i_it, goto_program)
245  get_state(i_it).make_bottom();
246 
247  if(!goto_program.empty())
248  {
249  cfg_post_dominatorst &pd = post_dominators[function];
250  pd(goto_program);
251 
252  end_function_map.emplace(
253  function, std::prev(goto_program.instructions.end()));
254  }
255  }
256 
257  void finalize()
258  {
259  for(const auto &location_state :
260  static_cast<location_sensitive_storaget &>(*storage).internal())
261  {
262  std::static_pointer_cast<dep_graph_domaint>(location_state.second)
263  ->populate_dep_graph(*this, location_state.first);
264  }
265  }
266 
267  void add_dep(
268  dep_edget::kindt kind,
271 
273  {
274  return post_dominators;
275  }
276 
278  {
279  return rd;
280  }
281 
282 protected:
285  const namespacet &ns;
286 
289  std::map<irep_idt, goto_programt::const_targett> end_function_map;
290 };
291 
292 #endif // CPROVER_ANALYSES_DEPENDENCE_GRAPH_H
dependence_grapht::reaching_definitions
const reaching_definitions_analysist & reaching_definitions() const
Definition: dependence_graph.h:277
dependence_grapht::end_function_map
std::map< irep_idt, goto_programt::const_targett > end_function_map
Definition: dependence_graph.h:289
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
dep_graph_domaint::data_deps
depst data_deps
Definition: dependence_graph.h:188
dep_graph_domaint::node_indext
grapht< dep_nodet >::node_indext node_indext
Definition: dependence_graph.h:69
dependence_grapht::initialize
void initialize(const irep_idt &function, const goto_programt &goto_program)
Initialize all the abstract states for a single function.
Definition: dependence_graph.h:239
ai_domain_baset::make_bottom
virtual void make_bottom()=0
no states
dep_graph_domaint::transform
void transform(const irep_idt &function_from, trace_ptrt trace_from, const irep_idt &function_to, trace_ptrt trace_to, ai_baset &ai, const namespacet &ns) final override
how function calls are treated: a) there is an edge from each call site to the function head b) there...
Definition: dependence_graph.cpp:217
dep_graph_domaint::has_changed
bool has_changed
Definition: dependence_graph.h:173
dependence_grapht
Definition: dependence_graph.h:211
dependence_grapht::add_dep
void add_dep(dep_edget::kindt kind, goto_programt::const_targett from, goto_programt::const_targett to)
Definition: dependence_graph.cpp:369
dependence_grapht::dep_graph_domain_factoryt
friend dep_graph_domain_factoryt
Definition: dependence_graph.h:283
dep_graph_domaint::node_id
node_indext node_id
Definition: dependence_graph.h:172
dependence_grapht::dependence_grapht
dependence_grapht(const namespacet &_ns)
Definition: dependence_graph.cpp:362
threeval.h
grapht
A generic directed graph with a parametric node type.
Definition: graph.h:166
dependence_grapht::cfg_post_dominators
const post_dominators_mapt & cfg_post_dominators() const
Definition: dependence_graph.h:272
location_sensitive_storaget::internal
state_mapt & internal(void)
Definition: ai_storage.h:168
dep_graph_domaint::make_top
void make_top() final override
all states – the analysis doesn't use this, and domains may refuse to implement it.
Definition: dependence_graph.h:95
goto_programt::empty
bool empty() const
Is the program empty?
Definition: goto_program.h:790
ait
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition: ai.h:563
dep_graph_domaint::is_bottom
bool is_bottom() const final override
Definition: dependence_graph.h:147
dep_nodet::edget
graph_nodet< dep_edget >::edget edget
Definition: dependence_graph.h:60
dependence_grapht::finalize
void finalize()
Override this to add a cleanup or post-processing step after fixedpoint has run.
Definition: dependence_graph.h:257
dep_edget::kindt::NONE
@ NONE
dep_graph_domaint::dependence_graph_test_get_data_deps
const friend depst & dependence_graph_test_get_data_deps(const dep_graph_domaint &)
goto_functionst::function_map
function_mapt function_map
Definition: goto_functions.h:29
jsont
Definition: json.h:26
dep_graph_domain_factoryt
This ensures that all domains are constructed with the node ID that links them to the graph part of t...
Definition: dependence_graph.cpp:341
dep_graph_domaint::output
void output(std::ostream &out, const ai_baset &ai, const namespacet &ns) const final override
Definition: dependence_graph.cpp:272
ai_domain_baset::trace_ptrt
ai_history_baset::trace_ptrt trace_ptrt
Definition: ai_domain.h:74
reaching_definitions_analysist
Definition: reaching_definitions.h:354
dep_graph_domaint::make_entry
void make_entry() final override
Make this domain a reasonable entry-point state.
Definition: dependence_graph.h:119
cfg_dominators.h
dependence_grapht::dep_graph_domaint
friend dep_graph_domaint
Definition: dependence_graph.h:284
dependence_grapht::initialize
void initialize(const goto_functionst &goto_functions)
Initialize all the abstract states for a whole program.
Definition: dependence_graph.h:223
dep_graph_domaint::has_values
tvt has_values
Definition: dependence_graph.h:171
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
DATA_INVARIANT
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:510
dep_graph_domaint::control_dependencies
void control_dependencies(const irep_idt &function_id, goto_programt::const_targett from, goto_programt::const_targett to, dependence_grapht &dep_graph)
Definition: dependence_graph.cpp:52
dep_nodet::PC
goto_programt::const_targett PC
Definition: dependence_graph.h:63
dep_edget::add
void add(kindt _kind)
Definition: dependence_graph.h:32
dep_graph_domaint::make_bottom
void make_bottom() final override
no states
Definition: dependence_graph.h:106
dep_graph_domaint::dep_graph_domaint
dep_graph_domaint(node_indext id)
Definition: dependence_graph.h:71
dep_edget
Definition: dependence_graph.h:27
ait< dep_graph_domaint >::get_state
virtual statet & get_state(trace_ptrt p)
Get the state for the given history, creating it with the factory if it doesn't exist.
Definition: ai.h:517
dep_graph_domaint::get_node_id
node_indext get_node_id() const
Definition: dependence_graph.h:161
dependence_grapht::rd
reaching_definitions_analysist rd
Definition: dependence_graph.h:288
dep_edget::kindt
kindt
Definition: dependence_graph.h:30
dep_edget::get
kindt get() const
Definition: dependence_graph.h:49
dependence_grapht::post_dominators_mapt
std::map< irep_idt, cfg_post_dominatorst > post_dominators_mapt
Definition: dependence_graph.h:219
tvt::unknown
static tvt unknown()
Definition: threeval.h:33
dep_graph_domaint::depst
std::set< goto_programt::const_targett > depst
Definition: dependence_graph.h:175
reaching_definitions.h
dep_graph_domaint::control_dep_candidates
depst control_dep_candidates
Definition: dependence_graph.h:184
ai.h
tvt::is_false
bool is_false() const
Definition: threeval.h:26
dep_edget::kindt::BOTH
@ BOTH
location_sensitive_storaget
The most conventional storage; one domain per location.
Definition: ai_storage.h:152
dep_graph_domaint::is_top
bool is_top() const final override
Definition: dependence_graph.h:133
tvt
Definition: threeval.h:19
dep_graph_domaint::control_deps
depst control_deps
Definition: dependence_graph.h:179
dependence_grapht::post_dominators
post_dominators_mapt post_dominators
Definition: dependence_graph.h:287
goto_programt::instructions
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:592
ai_baset::initialize
virtual void initialize(const irep_idt &function_id, const goto_programt &goto_program)
Initialize all the abstract states for a single function.
Definition: ai.cpp:195
dep_edget::kindt::DATA
@ DATA
dep_edget::kind
kindt kind
Definition: dependence_graph.h:55
goto_functionst
A collection of goto functions.
Definition: goto_functions.h:24
dep_graph_domaint::merge
bool merge(const dep_graph_domaint &src, trace_ptrt from, trace_ptrt to)
Definition: dependence_graph.cpp:22
graph.h
graph_nodet
This class represents a node in a directed graph.
Definition: graph.h:34
dep_edget::kindt::CTRL
@ CTRL
dep_graph_domaint::dependence_graph_test_get_control_deps
const friend depst & dependence_graph_test_get_control_deps(const dep_graph_domaint &)
dep_graph_domaint::data_dependencies
void data_dependencies(goto_programt::const_targett from, const irep_idt &function_to, goto_programt::const_targett to, dependence_grapht &dep_graph, const namespacet &ns)
Definition: dependence_graph.cpp:154
ai_baset
This is the basic interface of the abstract interpreter with default implementations of the core func...
Definition: ai.h:118
dep_nodet::edgest
graph_nodet< dep_edget >::edgest edgest
Definition: dependence_graph.h:61
goto_programt
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:72
goto_programt::const_targett
instructionst::const_iterator const_targett
Definition: goto_program.h:587
dep_graph_domaint::populate_dep_graph
void populate_dep_graph(dependence_grapht &, goto_programt::const_targett) const
Definition: dependence_graph.cpp:386
dep_nodet
Definition: dependence_graph.h:58
ai_domain_baset
The interface offered by a domain, allows code to manipulate domains without knowing their exact type...
Definition: ai_domain.h:54
dep_graph_domaint::output_json
jsont output_json(const ai_baset &ai, const namespacet &ns) const override
Outputs the current value of the domain.
Definition: dependence_graph.cpp:311
dep_graph_domaint
Definition: dependence_graph.h:66
dependence_grapht::ns
const namespacet & ns
Definition: dependence_graph.h:285
forall_goto_program_instructions
#define forall_goto_program_instructions(it, program)
Definition: goto_program.h:1229
tvt::is_true
bool is_true() const
Definition: threeval.h:25
cfg_dominators_templatet
Dominator graph.
Definition: cfg_dominators.h:36