@@ -43,46 +43,44 @@ static std::pair<goto_programt::targett, bool> insert_nondet_init_code(
43
43
const irep_idt &mode)
44
44
{
45
45
const auto next_instr = std::next (target);
46
- bool changed = false ;
47
46
48
47
// We only expect to find nondets in the rhs of an assignments or in return
49
48
// statements
50
49
for (exprt &op : target->code .operands ())
51
50
{
52
- if (op. id () != ID_side_effect )
51
+ if (!can_cast_expr<side_effect_expr_nondett>(op) )
53
52
{
54
53
continue ;
55
54
}
56
55
57
- const auto &side_effect = to_side_effect_expr (op);
58
- if (side_effect.get_statement () != ID_nondet)
59
- {
60
- continue ;
61
- }
56
+ const auto &nondet_expr = to_side_effect_expr_nondet (op);
62
57
63
- const typet &type = side_effect.type ();
64
58
// If the lhs type doesn't have a subtype then I guess it's primitive and
65
- // we want to bail out now
66
- if (type.id () != ID_pointer)
67
- {
68
- continue ;
69
- }
70
-
71
- // Although, if the type is a ptr-to-void or a function pointer then we also
72
- // want to bail
73
- if (type.subtype ().id () == ID_empty || type.subtype ().id () == ID_code)
59
+ // we want to bail out now. If the type is a ptr-to-void or a function
60
+ // pointer then we also want to bail.
61
+ const typet &type = nondet_expr.type ();
62
+ if (
63
+ type.id () != ID_pointer || type.subtype ().id () == ID_empty ||
64
+ type.subtype ().id () == ID_code)
74
65
{
75
66
continue ;
76
67
}
77
68
78
- if (!to_side_effect_expr_nondet (side_effect) .get_nullable ())
69
+ if (!nondet_expr .get_nullable ())
79
70
object_factory_parameters.max_nonnull_tree_depth = 1 ;
80
71
81
- // Get the symbol to nondet-init
82
72
const auto source_loc = target->source_location ;
83
73
84
- // Create symbol for storing nondet object. We will replace `op` with this
85
- // symbol.
74
+ // Currently the code looks like this
75
+ // target: original instruction
76
+ // When we are done it will look like this
77
+ // target : declare aux_symbol
78
+ // . <gen_nondet_init_instructions - many lines>
79
+ // . <gen_nondet_init_instructions - many lines>
80
+ // . <gen_nondet_init_instructions - many lines>
81
+ // target2: orig instruction with op replaced by aux_symbol
82
+ // dead aux_symbol
83
+
86
84
symbolt &aux_symbol = get_fresh_aux_symbol (
87
85
type,
88
86
id2string (goto_programt::get_function_id (goto_program)),
@@ -93,54 +91,54 @@ static std::pair<goto_programt::targett, bool> insert_nondet_init_code(
93
91
aux_symbol.is_static_lifetime = false ;
94
92
95
93
const symbol_exprt aux_symbol_expr = aux_symbol.symbol_expr ();
96
- code_declt decl (aux_symbol_expr);
97
- decl.add_source_location () = source_loc;
94
+ op = aux_symbol_expr;
98
95
99
- // Create goto instructions for declaring and deading aux_symbol
100
- goto_programt aux_instructions;
101
- code_blockt aux_block;
102
- aux_block.move (decl);
103
- goto_convert (
104
- aux_block, symbol_table, aux_instructions, message_handler, mode);
105
- CHECK_RETURN (aux_instructions.instructions .size () == 2 );
96
+ // It is simplest to insert the final instruction first, before everything
97
+ // gets moved around
98
+ goto_programt::targett dead_aux_symbol = goto_program.insert_after (target);
99
+ dead_aux_symbol->type = DEAD;
100
+ dead_aux_symbol->code = code_deadt (aux_symbol_expr);
101
+ dead_aux_symbol->source_location = source_loc;
102
+
103
+ // Insert an instruction declaring `aux_symbol` before `target`, being
104
+ // careful to preserve jumps to `target`
105
+ goto_programt::instructiont decl_aux_symbol (DECL);
106
+ decl_aux_symbol.code = code_declt (aux_symbol_expr);
107
+ decl_aux_symbol.source_location = source_loc;
108
+ goto_program.insert_before_swap (target, decl_aux_symbol);
106
109
107
- code_blockt init_code;
110
+ // Keep track of the new location of the original instruction.
111
+ const goto_programt::targett target2 = std::next (target);
108
112
113
+ code_blockt gen_nondet_init_code;
109
114
const bool skip_classid = true ;
110
115
gen_nondet_init (
111
116
aux_symbol_expr,
112
- init_code ,
117
+ gen_nondet_init_code ,
113
118
symbol_table,
114
119
source_loc,
115
120
skip_classid,
116
121
allocation_typet::DYNAMIC,
117
122
object_factory_parameters,
118
123
update_in_placet::NO_UPDATE_IN_PLACE);
119
124
120
- goto_programt nondet_init_instructions ;
125
+ goto_programt gen_nondet_init_instructions ;
121
126
goto_convert (
122
- init_code, symbol_table, nondet_init_instructions, message_handler, mode);
123
-
124
- // First insert the declaration of aux_symbol at the front of
125
- // nondet_init_instructions
126
- nondet_init_instructions.insert_before_swap (
127
- nondet_init_instructions.instructions .begin (),
128
- aux_instructions.instructions .front ());
129
-
130
- // Insert nondet_init_instructions into the instruction list before target
131
- goto_program.destructive_insert (target, nondet_init_instructions);
132
-
133
- // Replace op with aux symbol in target
134
- op = aux_symbol_expr;
127
+ gen_nondet_init_code,
128
+ symbol_table,
129
+ gen_nondet_init_instructions,
130
+ message_handler,
131
+ mode);
135
132
136
- // Finally insert the dead instruction for aux_symbol after target
137
- goto_program.insert_after (target)->swap (
138
- aux_instructions.instructions .back ());
133
+ goto_program.destructive_insert (target2, gen_nondet_init_instructions);
139
134
140
- changed = true ;
135
+ // In theory target could have more than one operand which should be
136
+ // replaced by convert_nondet, so we return target2 so that it
137
+ // will be checked again
138
+ return std::make_pair (target2, true );
141
139
}
142
140
143
- return std::make_pair (next_instr, changed );
141
+ return std::make_pair (next_instr, false );
144
142
}
145
143
146
144
// / For each instruction in the goto program, checks if it is an assignment from
0 commit comments