CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
goto_inline.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Function Inlining
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include "goto_inline.h"
13
14#include <util/std_expr.h>
15
16#include "goto_inline_class.h"
17#include "goto_model.h"
18
27 goto_modelt &goto_model,
28 message_handlert &message_handler,
29 bool adjust_function)
30{
31 const namespacet ns(goto_model.symbol_table);
33 goto_model.goto_functions,
34 ns,
35 message_handler,
36 adjust_function);
37}
38
48 goto_functionst &goto_functions,
49 const namespacet &ns,
50 message_handlert &message_handler,
51 bool adjust_function)
52{
54 goto_functions,
55 ns,
56 message_handler,
57 adjust_function);
58
60
61 // find entry point
62 goto_functionst::function_mapt::iterator it=
63 goto_functions.function_map.find(goto_functionst::entry_point());
64
65 if(it==goto_functions.function_map.end())
66 return;
67
68 goto_functiont &entry_function = it->second;
70 entry_function.body_available(),
71 "body of entry point function must be available");
72
73 // gather all calls
74 // we use non-transitive inlining to avoid the goto program
75 // copying that goto_inlinet would do otherwise
77
78 for(auto &gf_entry : goto_functions.function_map)
79 {
80 goto_functiont &goto_function = gf_entry.second;
81
82 if(!goto_function.body_available())
83 continue;
84
86
87 goto_programt &goto_program=goto_function.body;
88
90 {
91 if(!i_it->is_function_call())
92 continue;
93
94 call_list.push_back(goto_inlinet::callt(i_it, false));
95 }
96 }
97
98 goto_inline.goto_inline(
100
101 // clean up
102 for(auto &gf_entry : goto_functions.function_map)
103 {
105 {
106 goto_functiont &goto_function = gf_entry.second;
107 goto_function.body.clear();
108 }
109 }
110}
111
123 goto_modelt &goto_model,
124 message_handlert &message_handler,
125 unsigned smallfunc_limit,
126 bool adjust_function)
127{
128 const namespacet ns(goto_model.symbol_table);
130 goto_model.goto_functions,
131 ns,
132 message_handler,
134 adjust_function);
135}
136
150 goto_functionst &goto_functions,
151 const namespacet &ns,
152 message_handlert &message_handler,
153 unsigned smallfunc_limit,
154 bool adjust_function)
155{
157 goto_functions,
158 ns,
159 message_handler,
160 adjust_function);
161
163
164 // gather all calls
166
167 for(auto &gf_entry : goto_functions.function_map)
168 {
169 goto_functiont &goto_function = gf_entry.second;
170
171 if(!goto_function.body_available())
172 continue;
173
174 if(gf_entry.first == goto_functions.entry_point())
175 {
176 // Don't inline any function calls made from the _start function.
177 // This is so that the convention of __CPROVER_start
178 // calling __CPROVER_initialize is maintained, so these can be
179 // augmented / replaced by later passes.
180 continue;
181 }
182
183 goto_programt &goto_program=goto_function.body;
184
186
188 {
189 if(!i_it->is_function_call())
190 continue;
191
192 exprt lhs;
194 exprt::operandst arguments;
195 goto_inlinet::get_call(i_it, lhs, function_expr, arguments);
196
197 if(function_expr.id()!=ID_symbol)
198 // Can't handle pointers to functions
199 continue;
200
201 const symbol_exprt &symbol_expr=to_symbol_expr(function_expr);
202 const irep_idt id=symbol_expr.get_identifier();
203
204 goto_functionst::function_mapt::const_iterator called_it =
205 goto_functions.function_map.find(id);
206
207 if(called_it == goto_functions.function_map.end())
208 // Function not loaded, can't check size
209 continue;
210
211 // called function
212 const goto_functiont &called_function = called_it->second;
213
214 if(!called_function.body_available())
215 // The bodies of functions that don't have bodies can't be inlined.
216 continue;
217
218 if(
219 to_code_type(ns.lookup(id).type).get_inlined() ||
220 called_function.body.instructions.size() <= smallfunc_limit)
221 {
222 PRECONDITION(i_it->is_function_call());
223
224 call_list.push_back(goto_inlinet::callt(i_it, false));
225 }
226 }
227 }
228
229 goto_inline.goto_inline(inline_map, false);
230}
231
240 goto_modelt &goto_model,
241 const irep_idt function,
242 message_handlert &message_handler,
243 bool adjust_function,
244 bool caching)
245{
246 const namespacet ns(goto_model.symbol_table);
248 goto_model.goto_functions,
249 function,
250 ns,
251 message_handler,
252 adjust_function,
253 caching);
254}
255
265 goto_functionst &goto_functions,
266 const irep_idt function,
267 const namespacet &ns,
268 message_handlert &message_handler,
269 bool adjust_function,
270 bool caching)
271{
273 goto_functions,
274 ns,
275 message_handler,
276 adjust_function,
277 caching);
278
279 goto_functionst::function_mapt::iterator f_it=
280 goto_functions.function_map.find(function);
281
282 if(f_it==goto_functions.function_map.end())
283 return;
284
285 goto_functionst::goto_functiont &goto_function=f_it->second;
286
287 if(!goto_function.body_available())
288 return;
289
290 // gather all calls
292
294
295 goto_programt &goto_program=goto_function.body;
296
298 {
299 if(!i_it->is_function_call())
300 continue;
301
302 call_list.push_back(goto_inlinet::callt(i_it, true));
303 }
304
305 goto_inline.goto_inline(function, goto_function, inline_map, true);
306}
307
309 goto_modelt &goto_model,
310 const irep_idt function,
311 message_handlert &message_handler,
312 bool adjust_function,
313 bool caching)
314{
315 const namespacet ns(goto_model.symbol_table);
316
318 goto_model.goto_functions,
319 ns,
320 message_handler,
321 adjust_function,
322 caching);
323
324 goto_functionst::function_mapt::iterator f_it=
325 goto_model.goto_functions.function_map.find(function);
326
327 if(f_it==goto_model.goto_functions.function_map.end())
328 return jsont();
329
330 goto_functionst::goto_functiont &goto_function=f_it->second;
331
332 if(!goto_function.body_available())
333 return jsont();
334
335 // gather all calls
337
338 // create empty call list
340
341 goto_programt &goto_program=goto_function.body;
342
344 {
345 if(!i_it->is_function_call())
346 continue;
347
348 call_list.push_back(goto_inlinet::callt(i_it, true));
349 }
350
351 goto_inline.goto_inline(function, goto_function, inline_map, true);
352 goto_model.goto_functions.update();
354
355 return goto_inline.output_inline_log_json();
356}
357
367 goto_functionst &goto_functions,
368 goto_programt &goto_program,
369 const namespacet &ns,
370 message_handlert &message_handler,
371 bool adjust_function,
372 bool caching)
373{
375 goto_functions, ns, message_handler, adjust_function, caching);
376
377 // gather all calls found in the program
379
381 {
382 if(!i_it->is_function_call())
383 continue;
384
385 call_list.push_back(goto_inlinet::callt(i_it, true));
386 }
387
388 goto_inline.goto_inline(call_list, goto_program, true);
389}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
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
std::vector< exprt > operandst
Definition expr.h:58
A collection of goto functions.
function_mapt function_map
::goto_functiont goto_functiont
static irep_idt entry_point()
Get the identifier of the entry point to a goto model.
A goto function, consisting of function body (see body) and parameter identifiers (see parameter_iden...
goto_programt body
bool body_available() const
std::list< callt > call_listt
static void get_call(goto_programt::const_targett target, exprt &lhs, exprt &function, exprt::operandst &arguments)
std::pair< goto_programt::targett, bool > callt
std::map< irep_idt, call_listt > inline_mapt
symbol_tablet symbol_table
Symbol table.
Definition goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition goto_model.h:34
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
void clear()
Clear the goto program.
Definition json.h:27
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Expression to hold a symbol (variable)
Definition std_expr.h:131
const irep_idt & get_identifier() const
Definition std_expr.h:160
void goto_program_inline(goto_functionst &goto_functions, goto_programt &goto_program, const namespacet &ns, message_handlert &message_handler, bool adjust_function, bool caching)
Transitively inline all function calls found in a particular program.
void goto_inline(goto_modelt &goto_model, message_handlert &message_handler, bool adjust_function)
Inline every function call into the entry_point() function.
void goto_function_inline(goto_modelt &goto_model, const irep_idt function, message_handlert &message_handler, bool adjust_function, bool caching)
Transitively inline all function calls made from a particular function.
void goto_partial_inline(goto_modelt &goto_model, message_handlert &message_handler, unsigned smallfunc_limit, bool adjust_function)
Inline all function calls to functions either marked as "inlined" or smaller than smallfunc_limit (by...
jsont goto_function_inline_and_log(goto_modelt &goto_model, const irep_idt function, message_handlert &message_handler, bool adjust_function, bool caching)
Function Inlining This gives a number of different interfaces to the function inlining functionality ...
Function Inlining This is a class that encapsulates the state and functionality needed to do inline m...
Symbol Table + CFG.
#define Forall_goto_program_instructions(it, program)
#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
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
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788