Skip to content

Commit 3eddfd5

Browse files
committed
function calls
1 parent 9772501 commit 3eddfd5

File tree

1 file changed

+107
-94
lines changed

1 file changed

+107
-94
lines changed

src/cprover/state_encoding.cpp

Lines changed: 107 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ class state_encodingt
5757
const goto_functionst &,
5858
goto_programt::const_targett,
5959
encoding_targett &);
60+
void function_call_symbol(
61+
const goto_functionst &,
62+
goto_programt::const_targett,
63+
encoding_targett &);
6064

6165
loct first_loc;
6266
using incomingt = std::map<loct, std::vector<loct>>;
@@ -354,121 +358,130 @@ static exprt simplifying_not(exprt src)
354358
return not_exprt(src);
355359
}
356360

357-
void state_encodingt::function_call(
361+
void state_encodingt::function_call_symbol(
358362
const goto_functionst &goto_functions,
359363
goto_programt::const_targett loc,
360364
encoding_targett &dest)
361365
{
362-
// Function pointer?
363366
const auto &function = loc->call_function();
364-
if(function.id() == ID_dereference)
367+
auto identifier = to_symbol_expr(function).get_identifier();
368+
369+
// malloc is special-cased
370+
if(identifier == "malloc")
365371
{
366-
// TBD.
367-
throw incorrect_goto_program_exceptiont(
368-
"can't do function pointers", loc->source_location());
372+
auto state = state_expr();
373+
PRECONDITION(loc->call_arguments().size() == 1);
374+
auto size_evaluated = evaluate_expr(loc, state, loc->call_arguments()[0]);
375+
376+
auto lhs_address = address_rec(loc, state, loc->call_lhs());
377+
exprt new_state = ternary_exprt(
378+
ID_allocate, state, lhs_address, size_evaluated, state_typet());
379+
dest << forall_states_expr(
380+
loc, function_application_exprt(out_state_expr(loc), {new_state}));
381+
return;
369382
}
370-
else if(function.id() == ID_symbol)
371-
{
372-
auto identifier = to_symbol_expr(function).get_identifier();
373383

374-
// malloc is special-cased
375-
if(identifier == "malloc")
376-
{
377-
auto state = state_expr();
378-
PRECONDITION(loc->call_arguments().size() == 1);
379-
auto size_evaluated = evaluate_expr(loc, state, loc->call_arguments()[0]);
384+
// Do we have a function body?
385+
auto f = goto_functions.function_map.find(identifier);
386+
if(f == goto_functions.function_map.end())
387+
DATA_INVARIANT(false, "failed find function in function_map");
380388

381-
auto lhs_address = address_rec(loc, state, loc->call_lhs());
382-
exprt new_state = ternary_exprt(
383-
ID_allocate, state, lhs_address, size_evaluated, state_typet());
384-
dest << forall_states_expr(
385-
loc, function_application_exprt(out_state_expr(loc), {new_state}));
389+
if(!f->second.body_available())
390+
{
391+
// no function body -- do LHS assignment nondeterministically, if any
392+
if(loc->call_lhs().is_not_nil())
393+
{
394+
auto rhs = side_effect_expr_nondett(
395+
loc->call_lhs().type(), loc->source_location());
396+
dest << assignment_constraint(loc, loc->call_lhs(), std::move(rhs));
386397
}
387398
else
388399
{
389-
// Do we have a function body?
390-
auto f = goto_functions.function_map.find(identifier);
391-
if(f == goto_functions.function_map.end())
392-
DATA_INVARIANT(false, "failed find function in function_map");
393-
if(f->second.body_available())
394-
{
395-
// Evaluate the arguments of the call in the 'in state'
396-
multi_ary_exprt arguments_evaluated(ID_tuple, {}, typet(ID_tuple));
397-
arguments_evaluated.reserve_operands(loc->call_arguments().size());
400+
// This is a SKIP.
401+
dest << equal_exprt(out_state_expr(loc), in_state_expr(loc));
402+
}
403+
}
398404

399-
const auto in_state = in_state_expr(loc);
405+
// Evaluate the arguments of the call in the 'in state'
406+
multi_ary_exprt arguments_evaluated(ID_tuple, {}, typet(ID_tuple));
407+
arguments_evaluated.reserve_operands(loc->call_arguments().size());
400408

401-
for(auto &argument : loc->call_arguments())
402-
arguments_evaluated.add_to_operands(
403-
evaluate_expr(loc, in_state, argument));
409+
const auto in_state = in_state_expr(loc);
404410

405-
auto function_entry_state = state_expr_with_suffix(loc, "Entry");
411+
for(auto &argument : loc->call_arguments())
412+
arguments_evaluated.add_to_operands(
413+
evaluate_expr(loc, in_state, argument));
406414

407-
dest << forall_states_expr(
408-
loc,
409-
function_application_exprt(function_entry_state, {state_expr()}));
410-
411-
// Function return state (suffix PostReturn).
412-
// This is the state after exiting the function but prior to
413-
// assigning the LHS of the function call.
414-
auto return_state = state_expr_with_suffix(loc, "PostReturn");
415-
416-
/*
417-
constraints.push_back(
418-
multi_ary_exprt(
419-
ID_goto_contract,
420-
{loc->call_function(), in_state, return_state, arguments_evaluated},
421-
bool_typet()));
422-
*/
423-
424-
// assign the return value, if any
425-
if(loc->call_lhs().is_not_nil())
426-
{
427-
exprt equality_rhs = return_state;
415+
auto function_entry_state = state_expr_with_suffix(loc, "Entry");
428416

429-
/*
430-
auto &return_type = loc->call_lhs().type();
431-
auto rhs_evaluated =
432-
evaluate_expr(
433-
loc,
434-
return_state,
435-
symbol_exprt("return_value", return_type));
417+
dest << forall_states_expr(
418+
loc,
419+
function_application_exprt(function_entry_state, {state_expr()}));
436420

437-
multi_ary_exprt designator(ID_designator, { loc->call_lhs() }, typet());
421+
// Function return state (suffix PostReturn).
422+
// This is the state after exiting the function but prior to
423+
// assigning the LHS of the function call.
424+
auto return_state = state_expr_with_suffix(loc, "PostReturn");
438425

439-
auto lhs = out_state_expr(source);
426+
/*
427+
constraints.push_back(
428+
multi_ary_exprt(
429+
ID_goto_contract,
430+
{loc->call_function(), in_state, return_state, arguments_evaluated},
431+
bool_typet()));
432+
*/
440433

441-
auto rhs = update_exprt(
442-
return_state,
443-
designator,
444-
rhs_evaluated);
434+
// assign the return value, if any
435+
if(loc->call_lhs().is_not_nil())
436+
{
437+
exprt equality_rhs = return_state;
445438

446-
// 'out state' equality
447-
constraints.push_back(equal_exprt(lhs, rhs));
448-
*/
449-
}
450-
else
451-
{
452-
// 'out state' equality
453-
dest << equal_exprt(out_state_expr(loc), return_state);
454-
}
455-
}
456-
else
457-
{
458-
// no function body -- do LHS assignment nondeterministically, if any
459-
if(loc->call_lhs().is_not_nil())
460-
{
461-
auto rhs = side_effect_expr_nondett(
462-
loc->call_lhs().type(), loc->source_location());
463-
dest << assignment_constraint(loc, loc->call_lhs(), std::move(rhs));
464-
}
465-
else
466-
{
467-
// This is a SKIP.
468-
dest << equal_exprt(out_state_expr(loc), in_state_expr(loc));
469-
}
470-
}
471-
}
439+
/*
440+
auto &return_type = loc->call_lhs().type();
441+
auto rhs_evaluated =
442+
evaluate_expr(
443+
loc,
444+
return_state,
445+
symbol_exprt("return_value", return_type));
446+
447+
multi_ary_exprt designator(ID_designator, { loc->call_lhs() }, typet());
448+
449+
auto lhs = out_state_expr(source);
450+
451+
auto rhs = update_exprt(
452+
return_state,
453+
designator,
454+
rhs_evaluated);
455+
456+
// 'out state' equality
457+
constraints.push_back(equal_exprt(lhs, rhs));
458+
*/
459+
}
460+
/*
461+
else
462+
{
463+
// 'out state' equality
464+
dest << equal_exprt(out_state_expr(loc), return_state);
465+
}
466+
*/
467+
}
468+
469+
void state_encodingt::function_call(
470+
const goto_functionst &goto_functions,
471+
goto_programt::const_targett loc,
472+
encoding_targett &dest)
473+
{
474+
// Function pointer?
475+
const auto &function = loc->call_function();
476+
if(function.id() == ID_dereference)
477+
{
478+
// TBD.
479+
throw incorrect_goto_program_exceptiont(
480+
"can't do function pointers", loc->source_location());
481+
}
482+
else if(function.id() == ID_symbol)
483+
{
484+
function_call_symbol(goto_functions, loc, dest);
472485
}
473486
else
474487
{

0 commit comments

Comments
 (0)