20
20
#include < util/std_types.h>
21
21
22
22
#include < goto-programs/goto_convert_functions.h>
23
+ #include < goto-programs/goto_inline.h>
23
24
#include < goto-programs/goto_model.h>
24
25
25
26
#include < ansi-c/c_expr.h>
26
27
#include < linking/static_lifetime_init.h>
27
28
29
+ #include " utils.h"
30
+
28
31
dfcc_utilst::dfcc_utilst (goto_modelt &goto_model, messaget &log)
29
32
: goto_model(goto_model), log(log), message_handler(log.get_message_handler())
30
33
{
@@ -48,7 +51,7 @@ const symbolt &dfcc_utilst::create_symbol(
48
51
const irep_idt &module,
49
52
bool is_parameter)
50
53
{
51
- log .debug () << " dfcc_utilst: create_symbol(" << prefix << " ::" << base_name
54
+ log .debug () << " dfcc_utilst:: create_symbol(" << prefix << " ::" << base_name
52
55
<< " )" << messaget::eom;
53
56
54
57
symbolt &symbol = get_fresh_aux_symbol (
@@ -70,7 +73,7 @@ const symbolt &dfcc_utilst::create_static_symbol(
70
73
const irep_idt &module,
71
74
const exprt &initial_value)
72
75
{
73
- log .debug () << " dfcc_utilst: create_static_symbol(" << prefix
76
+ log .debug () << " dfcc_utilst:: create_static_symbol(" << prefix
74
77
<< " ::" << base_name << " )" << messaget::eom;
75
78
76
79
symbolt &symbol = get_fresh_aux_symbol (
@@ -115,7 +118,7 @@ const symbolt &dfcc_utilst::add_parameter(
115
118
const std::string &base_name,
116
119
const typet &type)
117
120
{
118
- log .debug () << " dfcc_utilst: add_parameter(" << function_id << " , "
121
+ log .debug () << " dfcc_utilst:: add_parameter(" << function_id << " , "
119
122
<< base_name << " )" << messaget::eom;
120
123
121
124
symbolt &function_symbol = get_function_symbol (function_id);
@@ -144,14 +147,14 @@ const symbolt &dfcc_utilst::clone_and_rename_function(
144
147
std::function<const typet(const typet &)> &trans_ret_type,
145
148
std::function<const source_locationt(const source_locationt &)> &trans_loc)
146
149
{
147
- log .debug () << " dfcc_utilst: clone_and_rename_function(" << function_id << " )"
150
+ log .debug () << " dfcc_utilst:: clone_and_rename_function(" << function_id << " )"
148
151
<< messaget::eom;
149
152
const symbolt &old_function_symbol = get_function_symbol (function_id);
150
153
code_typet old_code_type = to_code_type (old_function_symbol.type );
151
154
152
155
irep_idt new_function_id = trans_fun (function_id);
153
156
154
- log .debug () << " dfcc_utilst: clone_and_rename_function: function "
157
+ log .debug () << " dfcc_utilst:: clone_and_rename_function: function "
155
158
<< function_id << " ->" << new_function_id << messaget::eom;
156
159
157
160
code_typet::parameterst new_params;
@@ -180,7 +183,7 @@ const symbolt &dfcc_utilst::clone_and_rename_function(
180
183
181
184
if (!goto_model.symbol_table .add (new_function_symbol))
182
185
{
183
- log .error () << " dfcc_utilst: clone_and_rename_function: renamed function "
186
+ log .error () << " dfcc_utilst:: clone_and_rename_function: renamed function "
184
187
<< function_id << " -> " << new_function_id << " already exists"
185
188
<< messaget::eom;
186
189
exit (0 );
@@ -225,7 +228,7 @@ void dfcc_utilst::clone_parameters(
225
228
new_params.push_back (new_param);
226
229
227
230
// build symbol
228
- log .debug () << " dfcc_utilst: clone_parameters: param " << old_base_name
231
+ log .debug () << " dfcc_utilst:: clone_parameters: param " << old_base_name
229
232
<< " ->" << new_param_id << messaget::eom;
230
233
parameter_symbolt new_param_symbol;
231
234
new_param_symbol.base_name = new_base_name;
@@ -237,7 +240,7 @@ void dfcc_utilst::clone_parameters(
237
240
new_param_symbol.location = location;
238
241
if (!goto_model.symbol_table .add (new_param_symbol))
239
242
{
240
- log .error () << " dfcc_utilst: clone_parameters: renamed parameter "
243
+ log .error () << " dfcc_utilst:: clone_parameters: renamed parameter "
241
244
<< old_param.get_identifier () << " -> "
242
245
<< new_param.get_identifier () << " already exists"
243
246
<< messaget::eom;
@@ -248,12 +251,11 @@ void dfcc_utilst::clone_parameters(
248
251
249
252
const symbolt &dfcc_utilst::clone_and_rename_function (
250
253
const irep_idt &function_id,
251
- const std::string &suffix ,
254
+ const irep_idt &new_function_id ,
252
255
optionalt<typet> new_return_type = {})
253
256
{
254
257
std::function<const irep_idt (const irep_idt &)> trans_fun =
255
- [&](const irep_idt &old_name)
256
- { return id2string (old_name) + " ::" + suffix; };
258
+ [&](const irep_idt &old_name) { return new_function_id; };
257
259
258
260
std::function<const irep_idt (const irep_idt &)> trans_param =
259
261
[&](const irep_idt &old_name) { return old_name; };
@@ -279,7 +281,7 @@ void dfcc_utilst::wrap_function(
279
281
auto old_function = goto_functions.function_map .find (function_id);
280
282
INVARIANT (
281
283
old_function != goto_functions.function_map .end (),
282
- " dfcc_utilst: function to wrap " + id2string (function_id) +
284
+ " dfcc_utilst::wrap_function: function to wrap " + id2string (function_id) +
283
285
" must exist in the program" );
284
286
285
287
// Register the wrapped function under the new name
@@ -290,7 +292,8 @@ void dfcc_utilst::wrap_function(
290
292
INVARIANT (
291
293
goto_functions.function_map .find (wrapped_function_id) !=
292
294
goto_functions.function_map .end (),
293
- " dfcc_utilst: wrapped function " + id2string (wrapped_function_id) +
295
+ " dfcc_utilst::wrap_function: wrapped function " +
296
+ id2string (wrapped_function_id) +
294
297
" shall exist in function_map at this point" );
295
298
296
299
// Remove previous entry
@@ -300,7 +303,8 @@ void dfcc_utilst::wrap_function(
300
303
INVARIANT (
301
304
goto_functions.function_map .find (function_id) ==
302
305
goto_functions.function_map .end (),
303
- " dfcc_utilst: the original function " + id2string (function_id) +
306
+ " dfcc_utilst::wrap_function: the original function " +
307
+ id2string (function_id) +
304
308
" shall not exist in function_map anymore at this point" );
305
309
306
310
// Add new symbol for the wrapped function in the symbol table
@@ -316,8 +320,8 @@ void dfcc_utilst::wrap_function(
316
320
const auto wrapped_found = symbol_table.insert (std::move (wrapped_sym));
317
321
INVARIANT (
318
322
wrapped_found.second ,
319
- " dfcc_utilst: wrapped function symbol " + id2string (wrapped_function_id) +
320
- " already exists in the symbol table" );
323
+ " dfcc_utilst::wrap_function: wrapped function symbol " +
324
+ id2string (wrapped_function_id) + " already exists in the symbol table" );
321
325
322
326
// Re-insert a symbol for `function_id` which is now the wrapper function
323
327
symbolt wrapper_sym;
@@ -347,17 +351,17 @@ void dfcc_utilst::wrap_function(
347
351
// Remove original symbol from the symbol_table
348
352
if (!goto_model.symbol_table .remove (function_id))
349
353
{
350
- log .error () << " dfcc_utilst: could not remove " << function_id
351
- << " from the symbol table" << messaget::eom;
354
+ log .error () << " dfcc_utilst::wrap_function: could not remove "
355
+ << function_id << " from the symbol table" << messaget::eom;
352
356
exit (0 );
353
357
}
354
358
355
359
// Insert update symbol in the symbol_table
356
360
const auto wrapper_sym_found = symbol_table.insert (std::move (wrapper_sym));
357
361
INVARIANT (
358
362
wrapper_sym_found.second ,
359
- " dfcc_utilst: could not insert symbol " + id2string (function_id) +
360
- " in the symbol table" );
363
+ " dfcc_utilst::wrap_function: could not insert symbol " +
364
+ id2string (function_id) + " in the symbol table" );
361
365
362
366
// Insert wrapper function in the function_map
363
367
goto_functiont &wrapper_fun = goto_functions.function_map [function_id];
@@ -372,14 +376,15 @@ const exprt dfcc_utilst::make_null_check_expr(const exprt &ptr)
372
376
373
377
exprt dfcc_utilst::make_sizeof_expr (const exprt &expr)
374
378
{
375
- log .debug () << " dfcc_utilst : make_sizeof_expr(" << format (expr) << " )"
379
+ log .debug () << " dfcc_utilst:: make_sizeof_expr(" << format (expr) << " )"
376
380
<< messaget::eom;
377
381
const auto &size =
378
382
size_of_expr (expr.type (), namespacet (goto_model.symbol_table ));
379
383
380
384
PRECONDITION_WITH_DIAGNOSTICS (
381
385
size.has_value (),
382
- " dfcc_utilst: no definite size for lvalue target:\n " + expr.pretty ());
386
+ " dfcc_utilst::make_sizeof_expr: no definite size for lvalue target:\n " +
387
+ expr.pretty ());
383
388
384
389
return typecast_exprt::conditional_cast (size.value (), size_type ());
385
390
}
@@ -389,4 +394,32 @@ exprt dfcc_utilst::make_map_start_address(const exprt &expr)
389
394
return typecast_exprt::conditional_cast (
390
395
address_of_exprt (index_exprt (expr, from_integer (0 , c_index_type ()))),
391
396
pointer_type (bool_typet ()));
392
- }
397
+ }
398
+
399
+ void dfcc_utilst::inline_and_check_loop_freeness (const irep_idt &function_id)
400
+ {
401
+ auto &goto_function = goto_model.goto_functions .function_map .at (function_id);
402
+
403
+ PRECONDITION_WITH_DIAGNOSTICS (
404
+ goto_function.body_available (),
405
+ " dfcc_utilst::inline_and_check_loop_freeness: function " +
406
+ id2string (function_id) + " must have a body" );
407
+
408
+ inlining_decoratort decorated (log .get_message_handler ());
409
+ namespacet ns{goto_model.symbol_table };
410
+ goto_function_inline (
411
+ goto_model.goto_functions , function_id, ns, log .get_message_handler ());
412
+
413
+ PRECONDITION_WITH_DIAGNOSTICS (
414
+ decorated.get_recursive_function_warnings_count () == 0 ,
415
+ " dfcc_utilst::inline_and_check_loop_freeness: function " +
416
+ id2string (function_id) + " must not contain recursive function calls" );
417
+
418
+ PRECONDITION_WITH_DIAGNOSTICS (
419
+ is_loop_free (goto_function.body , ns, log ),
420
+ " dfcc_utilst::inline_and_check_loop_freeness: function " +
421
+ id2string (function_id) + " must not contain loops" );
422
+
423
+ // restore internal invariants
424
+ goto_model.goto_functions .update ();
425
+ }
0 commit comments