@@ -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,30 @@ 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.
22
26
struct function_call_harness_generatort ::implt
23
27
{
24
28
ui_message_handlert *message_handler;
25
29
irep_idt function;
30
+ irep_idt harness_function_name;
31
+ symbol_tablet *symbol_table;
32
+ goto_functionst *goto_functions;
33
+
34
+ // / \see goto_harness_generatort::generate
35
+ void generate (goto_modelt &goto_model, const irep_idt &harness_function_name);
36
+ // / Non-deterministically initialise the parameters of the entry function
37
+ // / and insert function call to the passed code block.
38
+ void setup_parameters_and_call_entry_function (code_blockt &function_body);
39
+ // / Return a reference to the entry function or throw if it doesn't exist.
40
+ const symbolt &lookup_function_to_call ();
41
+ // / Generate initialisation code for one lvalue inside block.
42
+ void generate_initialisation_code_for (code_blockt &block, const exprt &lhs);
43
+ // / Throw if the harness function already exists in the symbol table.
44
+ void ensure_harness_does_not_already_exist ();
45
+ // / Update the goto-model with the new harness function.
46
+ void add_harness_function_to_goto_model (code_blockt function_body);
26
47
};
27
48
28
49
function_call_harness_generatort::function_call_harness_generatort (
@@ -53,82 +74,124 @@ void function_call_harness_generatort::generate(
53
74
goto_modelt &goto_model,
54
75
const irep_idt &harness_function_name)
55
76
{
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);
77
+ p_impl->generate (goto_model, harness_function_name);
78
+ }
60
79
61
- if (function_found == nullptr )
80
+ void function_call_harness_generatort::implt::
81
+ setup_parameters_and_call_entry_function (code_blockt &function_body)
82
+ {
83
+ const auto &function_to_call = lookup_function_to_call ();
84
+ const auto &function_type = to_code_type (function_to_call.type );
85
+ const auto ¶meters = function_type.parameters ();
86
+
87
+ code_function_callt::operandst arguments{};
88
+
89
+ auto allocate_objects = allocate_objectst{function_to_call.mode ,
90
+ function_to_call.location ,
91
+ " __goto_harness" ,
92
+ *symbol_table};
93
+ for (const auto ¶meter : parameters)
62
94
{
63
- throw invalid_command_line_argument_exceptiont{
64
- " function that should be harnessed is not found " + id2string (function),
65
- " -- " FUNCTION_HARNESS_GENERATOR_FUNCTION_OPT} ;
95
+ auto argument = allocate_objects. allocate_automatic_local_object (
96
+ parameter. type (), parameter. get_base_name ());
97
+ arguments. push_back (argument) ;
66
98
}
67
-
68
- if (harness_function_found != nullptr )
99
+ allocate_objects. declare_created_symbols (function_body);
100
+ for ( auto const &argument : arguments )
69
101
{
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};
102
+ generate_initialisation_code_for (function_body, argument);
74
103
}
104
+ code_function_callt function_call{function_to_call.symbol_expr (),
105
+ std::move (arguments)};
106
+ function_call.add_source_location () = function_to_call.location ;
75
107
76
- auto allocate_objects = allocate_objectst{function_found->mode ,
77
- function_found->location ,
78
- " __goto_harness" ,
79
- symbol_table};
108
+ function_body.add (std::move (function_call));
109
+ }
110
+
111
+ void function_call_harness_generatort::implt::generate (
112
+ goto_modelt &goto_model,
113
+ const irep_idt &harness_function_name)
114
+ {
115
+ symbol_table = &goto_model.symbol_table ;
116
+ goto_functions = &goto_model.goto_functions ;
117
+ this ->harness_function_name = harness_function_name;
118
+ ensure_harness_does_not_already_exist ();
80
119
81
120
// create body for the function
82
121
code_blockt function_body{};
83
122
84
- const auto &function_type = to_code_type (function_found->type );
85
- const auto ¶meters = function_type.parameters ();
123
+ setup_parameters_and_call_entry_function (function_body);
124
+ add_harness_function_to_goto_model (std::move (function_body));
125
+ }
86
126
87
- code_function_callt::operandst arguments{};
88
- arguments.reserve (parameters.size ());
127
+ void function_call_harness_generatort::implt::generate_initialisation_code_for (
128
+ code_blockt &block,
129
+ const exprt &lhs)
130
+ {
131
+ block.add (code_assignt{lhs, side_effect_expr_nondett{lhs.type ()}});
132
+ }
89
133
90
- for (const auto ¶meter : parameters)
134
+ void function_call_harness_generatort::validate_options ()
135
+ {
136
+ if (p_impl->function == ID_empty)
137
+ throw invalid_command_line_argument_exceptiont{
138
+ " required parameter entry function not set" ,
139
+ " --" FUNCTION_HARNESS_GENERATOR_FUNCTION_OPT};
140
+ }
141
+
142
+ const symbolt &
143
+ function_call_harness_generatort::implt::lookup_function_to_call ()
144
+ {
145
+ auto function_found = symbol_table->lookup (function);
146
+
147
+ if (function_found == nullptr )
91
148
{
92
- auto argument = allocate_objects. allocate_automatic_local_object (
93
- parameter. type (), parameter. get_base_name ());
94
- arguments. push_back ( std::move (argument)) ;
149
+ throw invalid_command_line_argument_exceptiont{
150
+ " function that should be harnessed is not found " + id2string (function),
151
+ " -- " FUNCTION_HARNESS_GENERATOR_FUNCTION_OPT} ;
95
152
}
96
153
97
- code_function_callt function_call{function_found->symbol_expr (),
98
- std::move (arguments)};
99
- function_call.add_source_location () = function_found->location ;
154
+ return *function_found;
155
+ }
100
156
101
- function_body.add (std::move (function_call));
157
+ void function_call_harness_generatort::implt::
158
+ ensure_harness_does_not_already_exist ()
159
+ {
160
+ if (symbol_table->lookup (harness_function_name))
161
+ {
162
+ throw invalid_command_line_argument_exceptiont{
163
+ " harness function already exists in the symbol table" ,
164
+ " --" GOTO_HARNESS_GENERATOR_HARNESS_FUNCTION_NAME_OPT};
165
+ }
166
+ }
167
+
168
+ void function_call_harness_generatort::implt::
169
+ add_harness_function_to_goto_model (code_blockt function_body)
170
+ {
171
+ const auto &function_to_call = symbol_table->lookup_ref (function);
102
172
103
173
// create the function symbol
104
174
symbolt harness_function_symbol{};
105
175
harness_function_symbol.name = harness_function_symbol.base_name =
106
176
harness_function_symbol.pretty_name = harness_function_name;
107
177
108
178
harness_function_symbol.is_lvalue = true ;
109
- harness_function_symbol.mode = function_found-> mode ;
179
+ harness_function_symbol.mode = function_to_call. mode ;
110
180
harness_function_symbol.type = code_typet{{}, empty_typet{}};
111
- harness_function_symbol.value = function_body;
181
+ harness_function_symbol.value = std::move ( function_body) ;
112
182
113
- symbol_table. insert (harness_function_symbol);
183
+ symbol_table-> insert (harness_function_symbol);
114
184
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 ;
185
+ auto const &generated_harness =
186
+ symbol_table->lookup_ref (harness_function_name);
187
+ goto_functions->function_map [harness_function_name].type =
188
+ to_code_type (generated_harness.type );
189
+ auto &body = goto_functions->function_map [harness_function_name].body ;
119
190
goto_convert (
120
- static_cast <const codet &>(harness_function_symbol .value ),
121
- goto_model. symbol_table ,
191
+ static_cast <const codet &>(generated_harness .value ),
192
+ * symbol_table,
122
193
body,
123
- *p_impl-> message_handler ,
124
- function_found-> mode );
194
+ *message_handler,
195
+ function_to_call. mode );
125
196
body.add (goto_programt::make_end_function ());
126
197
}
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