@@ -47,7 +47,10 @@ mathematical_function_typet state_predicate_type()
4747class state_encodingt
4848{
4949public:
50- void operator ()(const goto_functiont &, encoding_targett &);
50+ void operator ()(
51+ const goto_functionst &,
52+ const goto_functiont &,
53+ encoding_targett &);
5154
5255protected:
5356 using loct = goto_programt::const_targett;
@@ -245,6 +248,7 @@ void state_encodingt::setup_incoming(const goto_functiont &goto_function)
245248}
246249
247250void state_encodingt::operator ()(
251+ const goto_functionst &goto_functions,
248252 const goto_functiont &goto_function,
249253 encoding_targett &dest)
250254{
@@ -353,63 +357,103 @@ void state_encodingt::operator()(
353357 }
354358 else if (loc->is_function_call ())
355359 {
356- // Evaluate the arguments of the call in the 'in state'
357- multi_ary_exprt arguments_evaluated (ID_tuple, {}, typet (ID_tuple));
358- arguments_evaluated.reserve_operands (loc->call_arguments ().size ());
359-
360- const auto in_state = in_state_expr (loc);
361-
362- for (auto &argument : loc->call_arguments ())
363- arguments_evaluated.add_to_operands (evaluate_expr (loc, in_state, argument));
364-
365- auto function_entry_state = state_expr_with_suffix (loc, " Entry" );
366-
367- dest << forall_states_expr (loc,
368- function_application_exprt (function_entry_state, {state_expr ()}));
369-
370- // Function return state (suffix PostReturn).
371- // This is the state after exiting the function but prior to
372- // assigning the LHS of the function call.
373- auto return_state = state_expr_with_suffix (loc, " PostReturn" );
374-
375- /*
376- constraints.push_back(
377- multi_ary_exprt(
378- ID_goto_contract,
379- {loc->call_function(), in_state, return_state, arguments_evaluated},
380- bool_typet()));
381- */
382-
383- // assign the return value, if any
384- if (loc->call_lhs ().is_not_nil ())
360+ // Function pointer?
361+ const auto &function = loc->call_function ();
362+ if (function.id () == ID_dereference)
385363 {
386- exprt equality_rhs = return_state;
387-
388- /*
389- auto &return_type = loc->call_lhs().type();
390- auto rhs_evaluated =
391- evaluate_expr(
392- loc,
393- return_state,
394- symbol_exprt("return_value", return_type));
364+ // TBD.
365+ PRECONDITION (false );
366+ }
367+ else if (function.id () == ID_symbol)
368+ {
369+ // Do we have a function body?
370+ auto identifier = to_symbol_expr (function).get_identifier ();
371+ auto f = goto_functions.function_map .find (identifier);
372+ if (f == goto_functions.function_map .end ())
373+ DATA_INVARIANT (false , " failed find function in function_map" );
374+ if (f->second .body_available ())
375+ {
376+ // Evaluate the arguments of the call in the 'in state'
377+ multi_ary_exprt arguments_evaluated (ID_tuple, {}, typet (ID_tuple));
378+ arguments_evaluated.reserve_operands (loc->call_arguments ().size ());
395379
396- multi_ary_exprt designator(ID_designator, { loc->call_lhs() }, typet() );
380+ const auto in_state = in_state_expr (loc );
397381
398- auto lhs = out_state_expr(source);
382+ for (auto &argument : loc->call_arguments ())
383+ arguments_evaluated.add_to_operands (
384+ evaluate_expr (loc, in_state, argument));
399385
400- auto rhs = update_exprt(
401- return_state,
402- designator,
403- rhs_evaluated);
386+ auto function_entry_state = state_expr_with_suffix (loc, " Entry" );
404387
405- // 'out state' equality
406- constraints.push_back(equal_exprt(lhs, rhs));
407- */
388+ dest << forall_states_expr (
389+ loc,
390+ function_application_exprt (function_entry_state, {state_expr ()}));
391+
392+ // Function return state (suffix PostReturn).
393+ // This is the state after exiting the function but prior to
394+ // assigning the LHS of the function call.
395+ auto return_state = state_expr_with_suffix (loc, " PostReturn" );
396+
397+ /*
398+ constraints.push_back(
399+ multi_ary_exprt(
400+ ID_goto_contract,
401+ {loc->call_function(), in_state, return_state, arguments_evaluated},
402+ bool_typet()));
403+ */
404+
405+ // assign the return value, if any
406+ if (loc->call_lhs ().is_not_nil ())
407+ {
408+ exprt equality_rhs = return_state;
409+
410+ /*
411+ auto &return_type = loc->call_lhs().type();
412+ auto rhs_evaluated =
413+ evaluate_expr(
414+ loc,
415+ return_state,
416+ symbol_exprt("return_value", return_type));
417+
418+ multi_ary_exprt designator(ID_designator, { loc->call_lhs() }, typet());
419+
420+ auto lhs = out_state_expr(source);
421+
422+ auto rhs = update_exprt(
423+ return_state,
424+ designator,
425+ rhs_evaluated);
426+
427+ // 'out state' equality
428+ constraints.push_back(equal_exprt(lhs, rhs));
429+ */
430+ }
431+ else
432+ {
433+ // 'out state' equality
434+ dest << equal_exprt (out_state_expr (loc), return_state);
435+ }
436+ }
437+ else
438+ {
439+ // no function body -- do LHS assignment nondeterministically, if any
440+ if (loc->call_lhs ().is_not_nil ())
441+ {
442+ auto rhs = side_effect_expr_nondett (
443+ loc->call_lhs ().type (), loc->source_location ());
444+ dest << assignment_constraint (loc, loc->call_lhs (), std::move (rhs));
445+ }
446+ else
447+ {
448+ // This is a SKIP.
449+ dest << equal_exprt (out_state_expr (loc), in_state_expr (loc));
450+ }
451+ }
408452 }
409453 else
410454 {
411- // 'out state' equality
412- dest << equal_exprt ( out_state_expr (loc), return_state );
455+ DATA_INVARIANT (
456+ false , " got function that's neither a symbol nor a function pointer " );
413457 }
414458 }
415459 else if (loc->is_set_return_value ())
@@ -433,7 +477,7 @@ void state_encoding(
433477 goto_functionst::entry_point ());
434478 PRECONDITION (f_entry != goto_model.goto_functions .function_map .end ());
435479
436- state_encodingt{}(f_entry->second , dest);
480+ state_encodingt{}(goto_model. goto_functions , f_entry->second , dest);
437481 }
438482 else
439483 {
@@ -445,7 +489,7 @@ void state_encoding(
445489 if (f->second .body_available ())
446490 {
447491 dest.annotation (" function " + id2string (f->first ));
448- state_encodingt{}(f->second , dest);
492+ state_encodingt{}(goto_model. goto_functions , f->second , dest);
449493 }
450494 }
451495 }
0 commit comments