@@ -14,6 +14,7 @@ Date: September 2011
14
14
#include " nondet_volatile.h"
15
15
16
16
#include < util/cmdline.h>
17
+ #include < util/fresh_symbol.h>
17
18
#include < util/options.h>
18
19
#include < util/std_expr.h>
19
20
#include < util/string_utils.h>
@@ -46,11 +47,23 @@ class nondet_volatilet
46
47
private:
47
48
static bool is_volatile (const namespacet &ns, const typet &src);
48
49
49
- void handle_volatile_expression (exprt &expr, const namespacet &ns);
50
+ void handle_volatile_expression (
51
+ exprt &expr,
52
+ const namespacet &ns,
53
+ goto_programt &pre,
54
+ goto_programt &post);
50
55
51
- void nondet_volatile_rhs (const symbol_tablet &symbol_table, exprt &expr);
56
+ void nondet_volatile_rhs (
57
+ const symbol_tablet &symbol_table,
58
+ exprt &expr,
59
+ goto_programt &pre,
60
+ goto_programt &post);
52
61
53
- void nondet_volatile_lhs (const symbol_tablet &symbol_table, exprt &expr);
62
+ void nondet_volatile_lhs (
63
+ const symbol_tablet &symbol_table,
64
+ exprt &expr,
65
+ goto_programt &pre,
66
+ goto_programt &post);
54
67
55
68
void
56
69
nondet_volatile (symbol_tablet &symbol_table, goto_programt &goto_program);
@@ -89,8 +102,11 @@ bool nondet_volatilet::is_volatile(const namespacet &ns, const typet &src)
89
102
90
103
void nondet_volatilet::handle_volatile_expression (
91
104
exprt &expr,
92
- const namespacet &ns)
105
+ const namespacet &ns,
106
+ goto_programt &pre,
107
+ goto_programt &post)
93
108
{
109
+ // Check if we should replace the variable by a nondet expression
94
110
if (
95
111
all_nondet ||
96
112
(expr.id () == ID_symbol &&
@@ -99,18 +115,56 @@ void nondet_volatilet::handle_volatile_expression(
99
115
typet t = expr.type ();
100
116
t.remove (ID_C_volatile);
101
117
102
- // replace by nondet
103
118
side_effect_expr_nondett nondet_expr (t, expr.source_location ());
104
119
expr.swap (nondet_expr);
120
+
121
+ return ;
122
+ }
123
+
124
+ // Now check if we should replace the variable by a model
125
+
126
+ if (expr.id () != ID_symbol)
127
+ {
128
+ return ;
129
+ }
130
+
131
+ const irep_idt &id = to_symbol_expr (expr).get_identifier ();
132
+ const auto &it = variable_models.find (id);
133
+
134
+ if (it == variable_models.end ())
135
+ {
136
+ return ;
105
137
}
138
+
139
+ const auto &model_symbol = ns.lookup (it->second );
140
+
141
+ const auto &new_variable = get_fresh_aux_symbol (
142
+ to_code_type (model_symbol.type ).return_type (),
143
+ " " ,
144
+ " modelled_volatile" ,
145
+ source_locationt (),
146
+ ID_C,
147
+ goto_model.symbol_table )
148
+ .symbol_expr ();
149
+
150
+ pre.instructions .push_back (goto_programt::make_decl (new_variable));
151
+
152
+ code_function_callt call (new_variable, model_symbol.symbol_expr (), {});
153
+ pre.instructions .push_back (goto_programt::make_function_call (call));
154
+
155
+ post.instructions .push_back (goto_programt::make_dead (new_variable));
156
+
157
+ expr = new_variable;
106
158
}
107
159
108
160
void nondet_volatilet::nondet_volatile_rhs (
109
161
const symbol_tablet &symbol_table,
110
- exprt &expr)
162
+ exprt &expr,
163
+ goto_programt &pre,
164
+ goto_programt &post)
111
165
{
112
166
Forall_operands (it, expr)
113
- nondet_volatile_rhs (symbol_table, *it);
167
+ nondet_volatile_rhs (symbol_table, *it, pre, post );
114
168
115
169
if (expr.id ()==ID_symbol ||
116
170
expr.id ()==ID_dereference)
@@ -119,33 +173,37 @@ void nondet_volatilet::nondet_volatile_rhs(
119
173
120
174
if (is_volatile (ns, expr.type ()))
121
175
{
122
- handle_volatile_expression (expr, ns);
176
+ handle_volatile_expression (expr, ns, pre, post );
123
177
}
124
178
}
125
179
}
126
180
127
181
void nondet_volatilet::nondet_volatile_lhs (
128
182
const symbol_tablet &symbol_table,
129
- exprt &expr)
183
+ exprt &expr,
184
+ goto_programt &pre,
185
+ goto_programt &post)
130
186
{
131
187
if (expr.id ()==ID_if)
132
188
{
133
- nondet_volatile_rhs (symbol_table, to_if_expr (expr).cond ());
134
- nondet_volatile_lhs (symbol_table, to_if_expr (expr).true_case ());
135
- nondet_volatile_lhs (symbol_table, to_if_expr (expr).false_case ());
189
+ nondet_volatile_rhs (symbol_table, to_if_expr (expr).cond (), pre, post );
190
+ nondet_volatile_lhs (symbol_table, to_if_expr (expr).true_case (), pre, post );
191
+ nondet_volatile_lhs (symbol_table, to_if_expr (expr).false_case (), pre, post );
136
192
}
137
193
else if (expr.id ()==ID_index)
138
194
{
139
- nondet_volatile_lhs (symbol_table, to_index_expr (expr).array ());
140
- nondet_volatile_rhs (symbol_table, to_index_expr (expr).index ());
195
+ nondet_volatile_lhs (symbol_table, to_index_expr (expr).array (), pre, post );
196
+ nondet_volatile_rhs (symbol_table, to_index_expr (expr).index (), pre, post );
141
197
}
142
198
else if (expr.id ()==ID_member)
143
199
{
144
- nondet_volatile_lhs (symbol_table, to_member_expr (expr).struct_op ());
200
+ nondet_volatile_lhs (
201
+ symbol_table, to_member_expr (expr).struct_op (), pre, post);
145
202
}
146
203
else if (expr.id ()==ID_dereference)
147
204
{
148
- nondet_volatile_rhs (symbol_table, to_dereference_expr (expr).pointer ());
205
+ nondet_volatile_rhs (
206
+ symbol_table, to_dereference_expr (expr).pointer (), pre, post);
149
207
}
150
208
}
151
209
@@ -155,14 +213,21 @@ void nondet_volatilet::nondet_volatile(
155
213
{
156
214
namespacet ns (symbol_table);
157
215
158
- Forall_goto_program_instructions (i_it, goto_program)
216
+ for (auto i_it = goto_program.instructions .begin ();
217
+ i_it != goto_program.instructions .end ();
218
+ i_it++)
159
219
{
160
- goto_programt::instructiont &instruction=*i_it;
220
+ goto_programt pre;
221
+ goto_programt post;
222
+
223
+ goto_programt::instructiont &instruction = *i_it;
161
224
162
225
if (instruction.is_assign ())
163
226
{
164
- nondet_volatile_rhs (symbol_table, to_code_assign (instruction.code ).rhs ());
165
- nondet_volatile_lhs (symbol_table, to_code_assign (instruction.code ).lhs ());
227
+ nondet_volatile_rhs (
228
+ symbol_table, to_code_assign (instruction.code ).rhs (), pre, post);
229
+ nondet_volatile_lhs (
230
+ symbol_table, to_code_assign (instruction.code ).lhs (), pre, post);
166
231
}
167
232
else if (instruction.is_function_call ())
168
233
{
@@ -176,18 +241,26 @@ void nondet_volatilet::nondet_volatile(
176
241
it=code_function_call.arguments ().begin ();
177
242
it!=code_function_call.arguments ().end ();
178
243
it++)
179
- nondet_volatile_rhs (symbol_table, *it);
244
+ nondet_volatile_rhs (symbol_table, *it, pre, post );
180
245
181
246
// do return value
182
- nondet_volatile_lhs (symbol_table, code_function_call.lhs ());
247
+ nondet_volatile_lhs (symbol_table, code_function_call.lhs (), pre, post );
183
248
}
184
249
else if (instruction.has_condition ())
185
250
{
186
251
// do condition
187
252
exprt cond = instruction.get_condition ();
188
- nondet_volatile_rhs (symbol_table, cond);
253
+ nondet_volatile_rhs (symbol_table, cond, pre, post );
189
254
instruction.set_condition (cond);
190
255
}
256
+
257
+ const auto pre_size = pre.instructions .size ();
258
+ goto_program.insert_before_swap (i_it, pre);
259
+ std::advance (i_it, pre_size);
260
+
261
+ const auto post_size = post.instructions .size ();
262
+ goto_program.destructive_insert (std::next (i_it), post);
263
+ std::advance (i_it, post_size);
191
264
}
192
265
}
193
266
0 commit comments