@@ -11,6 +11,7 @@ Author: Diffblue Ltd.
1111#include < goto-programs/goto_convert.h>
1212#include < goto-programs/goto_model.h>
1313#include < util/allocate_objects.h>
14+ #include < util/arith_tools.h>
1415#include < util/exception_utils.h>
1516#include < util/std_code.h>
1617#include < util/std_expr.h>
@@ -19,10 +20,31 @@ Author: Diffblue Ltd.
1920#include " function_harness_generator_options.h"
2021#include " goto_harness_parse_options.h"
2122
23+ // / This contains implementation details of
24+ // / function call harness generator to avoid
25+ // / leaking them out into the header.
26+ /* NOLINTNEXTLINE(readability/identifier_spacing) */
2227struct function_call_harness_generatort ::implt
2328{
2429 ui_message_handlert *message_handler;
2530 irep_idt function;
31+ irep_idt harness_function_name;
32+ symbol_tablet *symbol_table;
33+ goto_functionst *goto_functions;
34+
35+ // / \see goto_harness_generatort::generate
36+ void generate (goto_modelt &goto_model, const irep_idt &harness_function_name);
37+ // / Non-deterministically initialise the parameters of the entry function
38+ // / and insert function call to the passed code block.
39+ void setup_parameters_and_call_entry_function (code_blockt &function_body);
40+ // / Return a reference to the entry function or throw if it doesn't exist.
41+ const symbolt &lookup_function_to_call ();
42+ // / Generate initialisation code for one lvalue inside block.
43+ void generate_initialisation_code_for (code_blockt &block, const exprt &lhs);
44+ // / Throw if the harness function already exists in the symbol table.
45+ void ensure_harness_does_not_already_exist ();
46+ // / Update the goto-model with the new harness function.
47+ void add_harness_function_to_goto_model (code_blockt function_body);
2648};
2749
2850function_call_harness_generatort::function_call_harness_generatort (
@@ -53,82 +75,124 @@ void function_call_harness_generatort::generate(
5375 goto_modelt &goto_model,
5476 const irep_idt &harness_function_name)
5577{
56- auto const &function = p_impl->function ;
57- auto &symbol_table = goto_model.symbol_table ;
58- auto function_found = symbol_table.lookup (function);
59- auto harness_function_found = symbol_table.lookup (harness_function_name);
78+ p_impl->generate (goto_model, harness_function_name);
79+ }
6080
61- if (function_found == nullptr )
81+ void function_call_harness_generatort::implt::
82+ setup_parameters_and_call_entry_function (code_blockt &function_body)
83+ {
84+ const auto &function_to_call = lookup_function_to_call ();
85+ const auto &function_type = to_code_type (function_to_call.type );
86+ const auto ¶meters = function_type.parameters ();
87+
88+ code_function_callt::operandst arguments{};
89+
90+ auto allocate_objects = allocate_objectst{function_to_call.mode ,
91+ function_to_call.location ,
92+ " __goto_harness" ,
93+ *symbol_table};
94+ for (const auto ¶meter : parameters)
6295 {
63- throw invalid_command_line_argument_exceptiont{
64- " function that should be harnessed is not found " + id2string (function),
65- " -- " FUNCTION_HARNESS_GENERATOR_FUNCTION_OPT} ;
96+ auto argument = allocate_objects. allocate_automatic_local_object (
97+ parameter. type (), parameter. get_base_name ());
98+ arguments. push_back (argument) ;
6699 }
67-
68- if (harness_function_found != nullptr )
100+ allocate_objects. declare_created_symbols (function_body);
101+ for ( auto const &argument : arguments )
69102 {
70- throw invalid_command_line_argument_exceptiont{
71- " harness function already in the symbol table " +
72- id2string (harness_function_name),
73- " --" GOTO_HARNESS_GENERATOR_HARNESS_FUNCTION_NAME_OPT};
103+ generate_initialisation_code_for (function_body, argument);
74104 }
105+ code_function_callt function_call{function_to_call.symbol_expr (),
106+ std::move (arguments)};
107+ function_call.add_source_location () = function_to_call.location ;
75108
76- auto allocate_objects = allocate_objectst{function_found->mode ,
77- function_found->location ,
78- " __goto_harness" ,
79- symbol_table};
109+ function_body.add (std::move (function_call));
110+ }
111+
112+ void function_call_harness_generatort::implt::generate (
113+ goto_modelt &goto_model,
114+ const irep_idt &harness_function_name)
115+ {
116+ symbol_table = &goto_model.symbol_table ;
117+ goto_functions = &goto_model.goto_functions ;
118+ this ->harness_function_name = harness_function_name;
119+ ensure_harness_does_not_already_exist ();
80120
81121 // create body for the function
82122 code_blockt function_body{};
83123
84- const auto &function_type = to_code_type (function_found->type );
85- const auto ¶meters = function_type.parameters ();
124+ setup_parameters_and_call_entry_function (function_body);
125+ add_harness_function_to_goto_model (std::move (function_body));
126+ }
86127
87- code_function_callt::operandst arguments{};
88- arguments.reserve (parameters.size ());
128+ void function_call_harness_generatort::implt::generate_initialisation_code_for (
129+ code_blockt &block,
130+ const exprt &lhs)
131+ {
132+ block.add (code_assignt{lhs, side_effect_expr_nondett{lhs.type ()}});
133+ }
89134
90- for (const auto ¶meter : parameters)
135+ void function_call_harness_generatort::validate_options ()
136+ {
137+ if (p_impl->function == ID_empty)
138+ throw invalid_command_line_argument_exceptiont{
139+ " required parameter entry function not set" ,
140+ " --" FUNCTION_HARNESS_GENERATOR_FUNCTION_OPT};
141+ }
142+
143+ const symbolt &
144+ function_call_harness_generatort::implt::lookup_function_to_call ()
145+ {
146+ auto function_found = symbol_table->lookup (function);
147+
148+ if (function_found == nullptr )
91149 {
92- auto argument = allocate_objects. allocate_automatic_local_object (
93- parameter. type (), parameter. get_base_name ());
94- arguments. push_back ( std::move (argument)) ;
150+ throw invalid_command_line_argument_exceptiont{
151+ " function that should be harnessed is not found " + id2string (function),
152+ " -- " FUNCTION_HARNESS_GENERATOR_FUNCTION_OPT} ;
95153 }
96154
97- code_function_callt function_call{function_found->symbol_expr (),
98- std::move (arguments)};
99- function_call.add_source_location () = function_found->location ;
155+ return *function_found;
156+ }
100157
101- function_body.add (std::move (function_call));
158+ void function_call_harness_generatort::implt::
159+ ensure_harness_does_not_already_exist ()
160+ {
161+ if (symbol_table->lookup (harness_function_name))
162+ {
163+ throw invalid_command_line_argument_exceptiont{
164+ " harness function already exists in the symbol table" ,
165+ " --" GOTO_HARNESS_GENERATOR_HARNESS_FUNCTION_NAME_OPT};
166+ }
167+ }
168+
169+ void function_call_harness_generatort::implt::
170+ add_harness_function_to_goto_model (code_blockt function_body)
171+ {
172+ const auto &function_to_call = lookup_function_to_call ();
102173
103174 // create the function symbol
104175 symbolt harness_function_symbol{};
105176 harness_function_symbol.name = harness_function_symbol.base_name =
106177 harness_function_symbol.pretty_name = harness_function_name;
107178
108179 harness_function_symbol.is_lvalue = true ;
109- harness_function_symbol.mode = function_found-> mode ;
180+ harness_function_symbol.mode = function_to_call. mode ;
110181 harness_function_symbol.type = code_typet{{}, empty_typet{}};
111- harness_function_symbol.value = function_body;
182+ harness_function_symbol.value = std::move ( function_body) ;
112183
113- symbol_table. insert (harness_function_symbol);
184+ symbol_table-> insert (harness_function_symbol);
114185
115- goto_model.goto_functions .function_map [harness_function_name].type =
116- to_code_type (harness_function_symbol.type );
117- auto &body =
118- goto_model.goto_functions .function_map [harness_function_name].body ;
186+ auto const &generated_harness =
187+ symbol_table->lookup_ref (harness_function_name);
188+ goto_functions->function_map [harness_function_name].type =
189+ to_code_type (generated_harness.type );
190+ auto &body = goto_functions->function_map [harness_function_name].body ;
119191 goto_convert (
120- static_cast <const codet &>(harness_function_symbol .value ),
121- goto_model. symbol_table ,
192+ static_cast <const codet &>(generated_harness .value ),
193+ * symbol_table,
122194 body,
123- *p_impl-> message_handler ,
124- function_found-> mode );
195+ *message_handler,
196+ function_to_call. mode );
125197 body.add (goto_programt::make_end_function ());
126198}
127-
128- void function_call_harness_generatort::validate_options ()
129- {
130- if (p_impl->function == ID_empty)
131- throw invalid_command_line_argument_exceptiont{
132- " required parameter entry function not set" ,
133- " --" FUNCTION_HARNESS_GENERATOR_FUNCTION_OPT};
134- }
0 commit comments