@@ -11,6 +11,7 @@ Author: Diffblue Ltd.
11
11
#include < goto-programs/goto_convert.h>
12
12
#include < goto-programs/goto_model.h>
13
13
#include < util/allocate_objects.h>
14
+ #include < util/arith_tools.h>
14
15
#include < util/exception_utils.h>
15
16
#include < util/std_code.h>
16
17
#include < util/std_expr.h>
@@ -19,10 +20,31 @@ Author: Diffblue Ltd.
19
20
#include " function_harness_generator_options.h"
20
21
#include " goto_harness_parse_options.h"
21
22
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) */
22
27
struct function_call_harness_generatort ::implt
23
28
{
24
29
ui_message_handlert *message_handler;
25
30
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);
26
48
};
27
49
28
50
function_call_harness_generatort::function_call_harness_generatort (
@@ -53,82 +75,124 @@ void function_call_harness_generatort::generate(
53
75
goto_modelt &goto_model,
54
76
const irep_idt &harness_function_name)
55
77
{
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
+ }
60
80
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)
62
95
{
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) ;
66
99
}
67
-
68
- if (harness_function_found != nullptr )
100
+ allocate_objects. declare_created_symbols (function_body);
101
+ for ( auto const &argument : arguments )
69
102
{
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);
74
104
}
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 ;
75
108
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 ();
80
120
81
121
// create body for the function
82
122
code_blockt function_body{};
83
123
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
+ }
86
127
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
+ }
89
134
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 )
91
149
{
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} ;
95
153
}
96
154
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
+ }
100
157
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 ();
102
173
103
174
// create the function symbol
104
175
symbolt harness_function_symbol{};
105
176
harness_function_symbol.name = harness_function_symbol.base_name =
106
177
harness_function_symbol.pretty_name = harness_function_name;
107
178
108
179
harness_function_symbol.is_lvalue = true ;
109
- harness_function_symbol.mode = function_found-> mode ;
180
+ harness_function_symbol.mode = function_to_call. mode ;
110
181
harness_function_symbol.type = code_typet{{}, empty_typet{}};
111
- harness_function_symbol.value = function_body;
182
+ harness_function_symbol.value = std::move ( function_body) ;
112
183
113
- symbol_table. insert (harness_function_symbol);
184
+ symbol_table-> insert (harness_function_symbol);
114
185
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 ;
119
191
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,
122
194
body,
123
- *p_impl-> message_handler ,
124
- function_found-> mode );
195
+ *message_handler,
196
+ function_to_call. mode );
125
197
body.add (goto_programt::make_end_function ());
126
198
}
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