CBMC
replace_calls.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Replace calls
4 
5 Author: Daniel Poetzl
6 
7 \*******************************************************************/
8 
13 
14 #include "replace_calls.h"
15 
16 #include <util/exception_utils.h>
17 #include <util/invariant.h>
18 #include <util/namespace.h>
19 #include <util/string_utils.h>
20 
23 
30  goto_modelt &goto_model,
31  const replacement_listt &replacement_list) const
32 {
33  replacement_mapt replacement_map = parse_replacement_list(replacement_list);
34  (*this)(goto_model, replacement_map);
35 }
36 
42  goto_modelt &goto_model,
43  const replacement_mapt &replacement_map) const
44 {
45  const namespacet ns(goto_model.symbol_table);
46  goto_functionst &goto_functions = goto_model.goto_functions;
47 
48  check_replacement_map(replacement_map, goto_functions, ns);
49 
50  for(auto &p : goto_functions.function_map)
51  {
52  goto_functionst::goto_functiont &goto_function = p.second;
53  goto_programt &goto_program = goto_function.body;
54 
55  (*this)(goto_program, goto_functions, ns, replacement_map);
56  }
57 }
58 
60  goto_programt &goto_program,
61  const goto_functionst &goto_functions,
62  const namespacet &ns,
63  const replacement_mapt &replacement_map) const
64 {
65  Forall_goto_program_instructions(it, goto_program)
66  {
67  goto_programt::instructiont &ins = *it;
68 
69  if(!ins.is_function_call())
70  continue;
71 
72  const exprt &function = ins.call_function();
73 
74  PRECONDITION(function.id() == ID_symbol);
75 
76  const symbol_exprt &se = to_symbol_expr(function);
77  const irep_idt &id = se.get_identifier();
78 
79  auto f_it1 = goto_functions.function_map.find(id);
80 
82  f_it1 != goto_functions.function_map.end(),
83  "Called functions need to be present");
84 
85  replacement_mapt::const_iterator r_it = replacement_map.find(id);
86 
87  if(r_it == replacement_map.end())
88  continue;
89 
90  const irep_idt &new_id = r_it->second;
91 
92  auto f_it2 = goto_functions.function_map.find(new_id);
93  PRECONDITION(f_it2 != goto_functions.function_map.end());
94 
95  // check that returns have not been removed
96  if(to_code_type(function.type()).return_type().id() != ID_empty)
97  {
98  goto_programt::const_targett next_it = std::next(it);
99  if(next_it != goto_program.instructions.end() && next_it->is_assign())
100  {
101  const exprt &rhs = next_it->assign_rhs();
102 
103  INVARIANT(
104  rhs != return_value_symbol(id, ns),
105  "returns must not be removed before replacing calls");
106  }
107  }
108 
109  // Finally modify the call
110  ins.call_function().type() = ns.lookup(f_it2->first).type;
112  }
113 }
114 
116  const replacement_listt &replacement_list) const
117 {
118  replacement_mapt replacement_map;
119 
120  for(const std::string &s : replacement_list)
121  {
122  std::string original;
123  std::string replacement;
124 
125  split_string(s, ':', original, replacement, true);
126 
127  const auto r =
128  replacement_map.insert(std::make_pair(original, replacement));
129 
130  if(!r.second)
131  {
133  "conflicting replacement for function " + original, "--replace-calls");
134  }
135  }
136 
137  return replacement_map;
138 }
139 
141  const replacement_mapt &replacement_map,
142  const goto_functionst &goto_functions,
143  const namespacet &ns) const
144 {
145  for(const auto &p : replacement_map)
146  {
147  if(replacement_map.find(p.second) != replacement_map.end())
149  "function " + id2string(p.second) +
150  " cannot both be replaced and be a replacement",
151  "--replace-calls");
152 
153  auto it2 = goto_functions.function_map.find(p.second);
154 
155  if(it2 == goto_functions.function_map.end())
157  "replacement function " + id2string(p.second) + " needs to be present",
158  "--replace-calls");
159 
160  auto it1 = goto_functions.function_map.find(p.first);
161  if(it1 != goto_functions.function_map.end())
162  {
163  if(ns.lookup(it1->first).type != ns.lookup(it2->first).type)
165  "functions " + id2string(p.first) + " and " + id2string(p.second) +
166  " are not type-compatible",
167  "--replace-calls");
168  }
169  }
170 }
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
typet & type()
Return the type of the expression.
Definition: expr.h:84
A collection of goto functions.
function_mapt function_map
::goto_functiont goto_functiont
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
This class represents an instruction in the GOTO intermediate representation.
Definition: goto_program.h:181
const exprt & call_function() const
Get the function that is called for FUNCTION_CALL.
Definition: goto_program.h:272
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:622
instructionst::const_iterator const_targett
Definition: goto_program.h:615
Thrown when users pass incorrect command line arguments, for example passing no files to analysis or ...
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
std::list< std::string > replacement_listt
Definition: replace_calls.h:29
replacement_mapt parse_replacement_list(const replacement_listt &replacement_list) const
void check_replacement_map(const replacement_mapt &replacement_map, const goto_functionst &goto_functions, const namespacet &ns) const
std::map< irep_idt, irep_idt > replacement_mapt
Definition: replace_calls.h:30
void operator()(goto_modelt &goto_model, const replacement_listt &replacement_list) const
Replace function calls with calls to other functions.
Expression to hold a symbol (variable)
Definition: std_expr.h:131
void set_identifier(const irep_idt &identifier)
Definition: std_expr.h:155
const irep_idt & get_identifier() const
Definition: std_expr.h:160
Symbol Table + CFG.
#define Forall_goto_program_instructions(it, program)
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
static int8_t r
Definition: irep_hash.h:60
symbol_exprt return_value_symbol(const irep_idt &identifier, const namespacet &ns)
produces the symbol that is used to store the return value of the function with the given identifier
Replace function returns by assignments to global variables.
Replace calls to given functions with calls to other given functions.
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:534
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:788
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)