@@ -14,6 +14,7 @@ Date: September 2011
1414#include " nondet_volatile.h"
1515
1616#include < util/cmdline.h>
17+ #include < util/fresh_symbol.h>
1718#include < util/options.h>
1819#include < util/std_expr.h>
1920#include < util/string_utils.h>
@@ -46,11 +47,23 @@ class nondet_volatilet
4647private:
4748 static bool is_volatile (const namespacet &ns, const typet &src);
4849
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 );
5055
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 );
5261
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 );
5467
5568 void
5669 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)
89102
90103void nondet_volatilet::handle_volatile_expression (
91104 exprt &expr,
92- const namespacet &ns)
105+ const namespacet &ns,
106+ goto_programt &pre ,
107+ goto_programt &post )
93108{
109+ // Check if we should replace the variable by a nondet expression
94110 if (
95111 all_nondet ||
96112 (expr.id () == ID_symbol &&
@@ -99,18 +115,56 @@ void nondet_volatilet::handle_volatile_expression(
99115 typet t = expr.type ();
100116 t.remove (ID_C_volatile);
101117
102- // replace by nondet
103118 side_effect_expr_nondett nondet_expr (t, expr.source_location ());
104119 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 ;
105137 }
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;
106158}
107159
108160void nondet_volatilet::nondet_volatile_rhs (
109161 const symbol_tablet &symbol_table,
110- exprt &expr)
162+ exprt &expr,
163+ goto_programt &pre ,
164+ goto_programt &post )
111165{
112166 Forall_operands (it, expr)
113- nondet_volatile_rhs (symbol_table, *it);
167+ nondet_volatile_rhs (symbol_table, *it, pre , post );
114168
115169 if (expr.id ()==ID_symbol ||
116170 expr.id ()==ID_dereference)
@@ -119,33 +173,37 @@ void nondet_volatilet::nondet_volatile_rhs(
119173
120174 if (is_volatile (ns, expr.type ()))
121175 {
122- handle_volatile_expression (expr, ns);
176+ handle_volatile_expression (expr, ns, pre , post );
123177 }
124178 }
125179}
126180
127181void nondet_volatilet::nondet_volatile_lhs (
128182 const symbol_tablet &symbol_table,
129- exprt &expr)
183+ exprt &expr,
184+ goto_programt &pre ,
185+ goto_programt &post )
130186{
131187 if (expr.id ()==ID_if)
132188 {
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 );
136192 }
137193 else if (expr.id ()==ID_index)
138194 {
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 );
141197 }
142198 else if (expr.id ()==ID_member)
143199 {
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 );
145202 }
146203 else if (expr.id ()==ID_dereference)
147204 {
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 );
149207 }
150208}
151209
@@ -155,14 +213,21 @@ void nondet_volatilet::nondet_volatile(
155213{
156214 namespacet ns (symbol_table);
157215
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++)
159219 {
160- goto_programt::instructiont &instruction=*i_it;
220+ goto_programt pre ;
221+ goto_programt post ;
222+
223+ goto_programt::instructiont &instruction = *i_it;
161224
162225 if (instruction.is_assign ())
163226 {
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 );
166231 }
167232 else if (instruction.is_function_call ())
168233 {
@@ -176,18 +241,26 @@ void nondet_volatilet::nondet_volatile(
176241 it=code_function_call.arguments ().begin ();
177242 it!=code_function_call.arguments ().end ();
178243 it++)
179- nondet_volatile_rhs (symbol_table, *it);
244+ nondet_volatile_rhs (symbol_table, *it, pre , post );
180245
181246 // 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 );
183248 }
184249 else if (instruction.has_condition ())
185250 {
186251 // do condition
187252 exprt cond = instruction.get_condition ();
188- nondet_volatile_rhs (symbol_table, cond);
253+ nondet_volatile_rhs (symbol_table, cond, pre , post );
189254 instruction.set_condition (cond);
190255 }
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);
191264 }
192265}
193266
0 commit comments