CBMC
Loading...
Searching...
No Matches
cfg.h
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Control Flow Graph
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#ifndef CPROVER_GOTO_PROGRAMS_CFG_H
13#define CPROVER_GOTO_PROGRAMS_CFG_H
14
16#include <util/graph.h>
17#include <util/std_expr.h>
18
19#include "goto_functions.h"
20
22{
23};
24
25// these are the CFG nodes
26template<class T, typename I>
27struct cfg_base_nodet:public graph_nodet<empty_edget>, public T
28{
31
33};
34
37template <class T>
39{
40public:
41 std::size_t operator()(T &&t) const
42 {
43 return std::forward<T>(identity_functort{}(t));
44 }
45};
46
48template <>
50{
51public:
52 std::size_t operator()(const goto_programt::const_targett &t) const
53 {
54 return t->location_number;
55 }
56};
57
83template<class T,
84 typename P=const goto_programt,
86class cfg_baset:public grapht< cfg_base_nodet<T, I> >
87{
89
90public:
92 typedef typename base_grapht::nodet nodet;
93
94 class entry_mapt final
95 {
96 typedef dense_integer_mapt<
98 entryt,
102
103 public:
105
106 // NOLINTNEXTLINE(readability/identifiers)
108 // NOLINTNEXTLINE(readability/identifiers)
110
111 template <typename U>
112 const_iterator find(U &&u) const { return data.find(std::forward<U>(u)); }
113
114 iterator begin() { return data.begin(); }
115 const_iterator begin() const { return data.begin(); }
116 const_iterator cbegin() const { return data.cbegin(); }
117
118 iterator end() { return data.end(); }
119 const_iterator end() const { return data.end(); }
120 const_iterator cend() const { return data.cend(); }
121
126
128 {
129 auto e=data.insert(std::make_pair(t, 0));
130
131 if(e.second)
132 e.first->second=container.add_node();
133
134 return e.first->second;
135 }
136
138 {
139 return data.at(t);
140 }
142 {
143 return data.at(t);
144 }
145
146 template <class Iter>
151 };
153
154protected:
155 virtual void compute_edges_goto(
156 const goto_programt &goto_program,
157 const goto_programt::instructiont &instruction,
159 entryt &entry);
160
162 const goto_programt &goto_program,
163 const goto_programt::instructiont &instruction,
165 entryt &entry);
166
168 const goto_programt &goto_program,
169 const goto_programt::instructiont &instruction,
171 entryt &entry);
172
174 const goto_programt &goto_program,
175 const goto_programt::instructiont &instruction,
177 entryt &entry);
178
180 const goto_functionst &goto_functions,
181 const goto_programt &goto_program,
182 const goto_programt::instructiont &instruction,
184 entryt &entry);
185
187 const goto_functionst &goto_functions,
188 const goto_programt &goto_program,
189 I PC);
190
192 const goto_functionst &goto_functions,
193 P &goto_program);
194
196 const goto_functionst &goto_functions);
197
198public:
200 {
201 }
202
203 virtual ~cfg_baset()
204 {
205 }
206
208 const goto_functionst &goto_functions)
209 {
210 std::vector<goto_programt::const_targett> possible_keys;
211 for(const auto &id_and_function : goto_functions.function_map)
212 {
213 const auto &instructions = id_and_function.second.body.instructions;
214 possible_keys.reserve(possible_keys.size() + instructions.size());
215 for(auto it = instructions.begin(); it != instructions.end(); ++it)
216 possible_keys.push_back(it);
217 }
218 entry_map.setup_for_keys(possible_keys.begin(), possible_keys.end());
219 compute_edges(goto_functions);
220 }
221
222 void operator()(P &goto_program)
223 {
224 goto_functionst goto_functions;
225 std::vector<goto_programt::const_targett> possible_keys;
226 const auto &instructions = goto_program.instructions;
227 possible_keys.reserve(instructions.size());
228 for(auto it = instructions.begin(); it != instructions.end(); ++it)
229 possible_keys.push_back(it);
230 entry_map.setup_for_keys(possible_keys.begin(), possible_keys.end());
231 compute_edges(goto_functions, goto_program);
232 }
233
243
249
252 {
253 return (*this)[get_node_index(program_point)];
254 }
255
259 const entry_mapt &entries() const
260 {
261 return entry_map;
262 }
263
264 static I get_first_node(P &program)
265 {
266 return program.instructions.begin();
267 }
268 static I get_last_node(P &program)
269 {
270 return --program.instructions.end();
271 }
272 static bool nodes_empty(P &program)
273 {
274 return program.instructions.empty();
275 }
276};
277
278template<class T,
279 typename P=const goto_programt,
281class concurrent_cfg_baset:public virtual cfg_baset<T, P, I>
282{
283protected:
285 const goto_programt &goto_program,
286 const goto_programt::instructiont &instruction,
288 typename cfg_baset<T, P, I>::entryt &entry);
289};
290
291template<class T,
292 typename P=const goto_programt,
294class procedure_local_cfg_baset:public virtual cfg_baset<T, P, I>
295{
296protected:
298 const goto_functionst &goto_functions,
299 const goto_programt &goto_program,
300 const goto_programt::instructiont &instruction,
302 typename cfg_baset<T, P, I>::entryt &entry);
303};
304
305template<class T,
306 typename P=const goto_programt,
309 public concurrent_cfg_baset<T, P, I>,
310 public procedure_local_cfg_baset<T, P, I>
311{
312};
313
314template<class T, typename P, typename I>
316 const goto_programt &goto_program,
317 const goto_programt::instructiont &instruction,
319 entryt &entry)
320{
321 if(
322 next_PC != goto_program.instructions.end() &&
323 !instruction.condition().is_true())
324 {
325 this->add_edge(entry, entry_map[next_PC]);
326 }
327
328 this->add_edge(entry, entry_map[instruction.get_target()]);
329}
330
331template<class T, typename P, typename I>
333 const goto_programt &goto_program,
334 const goto_programt::instructiont &instruction,
336 entryt &entry)
337{
338 if(next_PC!=goto_program.instructions.end())
339 this->add_edge(entry, entry_map[next_PC]);
340
341 // Not ideal, but preserves targets
342 // Ideally, the throw statements should have those as successors
343
344 for(const auto &t : instruction.targets)
345 if(t!=goto_program.instructions.end())
346 this->add_edge(entry, entry_map[t]);
347}
348
349template<class T, typename P, typename I>
351 const goto_programt &,
354 entryt &)
355{
356 // no (trivial) successors
357}
358
359template<class T, typename P, typename I>
361 const goto_programt &goto_program,
364 entryt &entry)
365{
366 if(next_PC!=goto_program.instructions.end())
367 this->add_edge(entry, entry_map[next_PC]);
368}
369
370template<class T, typename P, typename I>
372 const goto_programt &goto_program,
373 const goto_programt::instructiont &instruction,
375 typename cfg_baset<T, P, I>::entryt &entry)
376{
378 goto_program,
379 instruction,
380 next_PC,
381 entry);
382
383 this->add_edge(entry, this->entry_map[instruction.get_target()]);
384}
385
386template<class T, typename P, typename I>
388 const goto_functionst &goto_functions,
389 const goto_programt &goto_program,
390 const goto_programt::instructiont &instruction,
392 entryt &entry)
393{
394 const exprt &function = instruction.call_function();
395
396 if(function.id()!=ID_symbol)
397 return;
398
399 const irep_idt &identifier=
400 to_symbol_expr(function).get_identifier();
401
402 goto_functionst::function_mapt::const_iterator f_it=
403 goto_functions.function_map.find(identifier);
404
405 if(f_it!=goto_functions.function_map.end() &&
406 f_it->second.body_available())
407 {
408 // get the first instruction
410 f_it->second.body.instructions.begin();
411
413 f_it->second.body.instructions.end();
414
416
417 if(i_it!=e_it)
418 {
419 // nonempty function
420 this->add_edge(entry, entry_map[i_it]);
421
422 // add the last instruction as predecessor of the return location
423 if(next_PC!=goto_program.instructions.end())
424 this->add_edge(entry_map[last_it], entry_map[next_PC]);
425 }
426 else if(next_PC!=goto_program.instructions.end())
427 {
428 // empty function
429 this->add_edge(entry, entry_map[next_PC]);
430 }
431 }
432 else if(next_PC!=goto_program.instructions.end())
433 this->add_edge(entry, entry_map[next_PC]);
434}
435
436template<class T, typename P, typename I>
438 const goto_functionst &,
439 const goto_programt &goto_program,
440 const goto_programt::instructiont &instruction,
442 typename cfg_baset<T, P, I>::entryt &entry)
443{
444 const exprt &function = instruction.call_function();
445
446 if(function.id()!=ID_symbol)
447 return;
448
449 if(next_PC!=goto_program.instructions.end())
450 this->add_edge(entry, this->entry_map[next_PC]);
451}
452
453template<class T, typename P, typename I>
455 const goto_functionst &goto_functions,
456 const goto_programt &goto_program,
457 I PC)
458{
459 const goto_programt::instructiont &instruction=*PC;
460 entryt entry=entry_map[PC];
461 (*this)[entry].PC=PC;
463 next_PC++;
464
465 // compute forward edges first
466 switch(instruction.type())
467 {
468 case GOTO:
469 compute_edges_goto(goto_program, instruction, next_PC, entry);
470 break;
471
472 case CATCH:
473 compute_edges_catch(goto_program, instruction, next_PC, entry);
474 break;
475
476 case THROW:
477 compute_edges_throw(goto_program, instruction, next_PC, entry);
478 break;
479
480 case START_THREAD:
481 compute_edges_start_thread(
482 goto_program,
483 instruction,
484 next_PC,
485 entry);
486 break;
487
488 case FUNCTION_CALL:
489 compute_edges_function_call(
490 goto_functions,
491 goto_program,
492 instruction,
493 next_PC,
494 entry);
495 break;
496
497 case END_THREAD:
498 case END_FUNCTION:
499 // no successor
500 break;
501
502 case ASSUME:
503 // false guard -> no successor
504 if(instruction.condition().is_false())
505 break;
506
507 case ASSIGN:
508 case ASSERT:
509 case OTHER:
510 case SET_RETURN_VALUE:
511 case SKIP:
512 case LOCATION:
513 case ATOMIC_BEGIN:
514 case ATOMIC_END:
515 case DECL:
516 case DEAD:
517 if(next_PC!=goto_program.instructions.end())
518 this->add_edge(entry, entry_map[next_PC]);
519 break;
520
522 case INCOMPLETE_GOTO:
524 break;
525 }
526}
527
528template<class T, typename P, typename I>
530 const goto_functionst &goto_functions,
531 P &goto_program)
532{
533 for(I it=goto_program.instructions.begin();
534 it!=goto_program.instructions.end();
535 ++it)
536 compute_edges(goto_functions, goto_program, it);
537}
538
539template<class T, typename P, typename I>
541 const goto_functionst &goto_functions)
542{
543 for(const auto &gf_entry : goto_functions.function_map)
544 {
545 if(gf_entry.second.body_available())
546 compute_edges(goto_functions, gf_entry.second.body);
547 }
548}
549
550#endif // CPROVER_GOTO_PROGRAMS_CFG_H
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
ait()
Definition ai.h:565
const_iterator cend() const
Definition cfg.h:120
const_iterator find(U &&u) const
Definition cfg.h:112
grapht< cfg_base_nodet< T, I > > & container
Definition cfg.h:104
entry_mapt(grapht< cfg_base_nodet< T, I > > &_container)
Definition cfg.h:122
iterator end()
Definition cfg.h:118
dense_integer_mapt< goto_programt::const_targett, entryt, cfg_instruction_to_dense_integert< goto_programt::const_targett > > data_typet
Definition cfg.h:100
iterator begin()
Definition cfg.h:114
void setup_for_keys(Iter begin, Iter end)
Definition cfg.h:147
entryt & operator[](const goto_programt::const_targett &t)
Definition cfg.h:127
entryt & at(const goto_programt::const_targett &t)
Definition cfg.h:137
data_typet::iterator iterator
Definition cfg.h:107
data_typet data
Definition cfg.h:101
data_typet::const_iterator const_iterator
Definition cfg.h:109
const_iterator begin() const
Definition cfg.h:115
const entryt & at(const goto_programt::const_targett &t) const
Definition cfg.h:141
const_iterator cbegin() const
Definition cfg.h:116
const_iterator end() const
Definition cfg.h:119
A multi-procedural control flow graph (CFG) whose nodes store references to instructions in a GOTO pr...
Definition cfg.h:87
virtual ~cfg_baset()
Definition cfg.h:203
const entry_mapt & entries() const
Get a map from program points to their corresponding node indices.
Definition cfg.h:259
void compute_edges(const goto_functionst &goto_functions, P &goto_program)
Definition cfg.h:529
base_grapht::node_indext entryt
Definition cfg.h:91
virtual void compute_edges_catch(const goto_programt &goto_program, const goto_programt::instructiont &instruction, goto_programt::const_targett next_PC, entryt &entry)
Definition cfg.h:332
static I get_first_node(P &program)
Definition cfg.h:264
static I get_last_node(P &program)
Definition cfg.h:268
virtual void compute_edges_function_call(const goto_functionst &goto_functions, const goto_programt &goto_program, const goto_programt::instructiont &instruction, goto_programt::const_targett next_PC, entryt &entry)
Definition cfg.h:387
void compute_edges(const goto_functionst &goto_functions)
Definition cfg.h:540
virtual void compute_edges_start_thread(const goto_programt &goto_program, const goto_programt::instructiont &instruction, goto_programt::const_targett next_PC, entryt &entry)
Definition cfg.h:360
base_grapht::nodet nodet
Definition cfg.h:92
nodet & get_node(const goto_programt::const_targett &program_point)
Get the CFG graph node relating to program_point.
Definition cfg.h:245
void operator()(P &goto_program)
Definition cfg.h:222
cfg_baset()
Definition cfg.h:199
entryt get_node_index(const goto_programt::const_targett &program_point) const
Get the graph node index for program_point.
Definition cfg.h:239
entry_mapt entry_map
Definition cfg.h:152
void operator()(const goto_functionst &goto_functions)
Definition cfg.h:207
grapht< cfg_base_nodet< T, I > > base_grapht
Definition cfg.h:88
void compute_edges(const goto_functionst &goto_functions, const goto_programt &goto_program, I PC)
Definition cfg.h:454
const nodet & get_node(const goto_programt::const_targett &program_point) const
Get the CFG graph node relating to program_point.
Definition cfg.h:251
virtual void compute_edges_throw(const goto_programt &goto_program, const goto_programt::instructiont &instruction, goto_programt::const_targett next_PC, entryt &entry)
Definition cfg.h:350
virtual void compute_edges_goto(const goto_programt &goto_program, const goto_programt::instructiont &instruction, goto_programt::const_targett next_PC, entryt &entry)
Definition cfg.h:315
static bool nodes_empty(P &program)
Definition cfg.h:272
std::size_t operator()(const goto_programt::const_targett &t) const
Definition cfg.h:52
Functor to convert cfg nodes into dense integers, used by cfg_baset.
Definition cfg.h:39
std::size_t operator()(T &&t) const
Definition cfg.h:41
virtual void compute_edges_start_thread(const goto_programt &goto_program, const goto_programt::instructiont &instruction, goto_programt::const_targett next_PC, typename cfg_baset< T, P, I >::entryt &entry)
Definition cfg.h:371
A map type that is backed by a vector, which relies on the ability to (a) see the keys that might be ...
std::pair< iterator, bool > insert(const std::pair< const K, V > &pair)
void setup_for_keys(Iter first, Iter last)
Set the keys that are allowed to be used in this container.
const_iterator cbegin() const
const V & at(const K &key) const
const_iterator cend() const
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:56
A collection of goto functions.
function_mapt function_map
This class represents an instruction in the GOTO intermediate representation.
targetst targets
The list of successor instructions.
const exprt & call_function() const
Get the function that is called for FUNCTION_CALL.
const exprt & condition() const
Get the condition of gotos, assume, assert.
const_targett get_target() const
Returns the first (and only) successor for the usual case of a single target.
goto_program_instruction_typet type() const
What kind of instruction?
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
instructionst::const_iterator const_targett
This class represents a node in a directed graph.
Definition graph.h:35
std::map< node_indext, edget > edgest
Definition graph.h:40
A generic directed graph with a parametric node type.
Definition graph.h:167
nodet::node_indext node_indext
Definition graph.h:173
node_indext add_node(arguments &&... values)
Definition graph.h:180
Identity functor. When we use C++20 this can be replaced with std::identity.
const irep_idt & id() const
Definition irep.h:388
virtual void compute_edges_function_call(const goto_functionst &goto_functions, const goto_programt &goto_program, const goto_programt::instructiont &instruction, goto_programt::const_targett next_PC, typename cfg_baset< T, P, I >::entryt &entry)
Definition cfg.h:437
Dense integer map.
Goto Programs with Functions.
@ FUNCTION_CALL
@ ATOMIC_END
@ DEAD
@ LOCATION
@ END_FUNCTION
@ ASSIGN
@ ASSERT
@ SET_RETURN_VALUE
@ ATOMIC_BEGIN
@ CATCH
@ END_THREAD
@ SKIP
@ NO_INSTRUCTION_TYPE
@ START_THREAD
@ THROW
@ DECL
@ OTHER
@ GOTO
@ INCOMPLETE_GOTO
@ ASSUME
A Template Class for Graphs.
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
API to expression classes.
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
graph_nodet< empty_edget >::edgest edgest
Definition cfg.h:30
graph_nodet< empty_edget >::edget edget
Definition cfg.h:29