Skip to content

Commit 3ebf8a4

Browse files
committed
Add build_declaration_hops
1 parent 53fe0e5 commit 3ebf8a4

File tree

2 files changed

+156
-7
lines changed

2 files changed

+156
-7
lines changed

src/goto-programs/goto_convert.cpp

Lines changed: 150 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Daniel Kroening, [email protected]
1010
/// Program Transformation
1111

1212
#include "goto_convert.h"
13+
#include "goto_convert_class.h"
1314

1415
#include <util/arith_tools.h>
1516
#include <util/c_types.h>
@@ -24,10 +25,14 @@ Author: Daniel Kroening, [email protected]
2425
#include <util/string_constant.h>
2526
#include <util/symbol_table_builder.h>
2627

27-
#include "goto_convert_class.h"
2828
#include "destructor.h"
2929
#include "remove_skip.h"
3030

31+
#include <iostream>
32+
#define WATCHVAR(var) \
33+
std::cerr << "DBG: " << __FILE__ << "(" << __LINE__ << ") " << #var \
34+
<< " = [" << (var) << "]" << std::endl
35+
3136
static bool is_empty(const goto_programt &goto_program)
3237
{
3338
forall_goto_program_instructions(it, goto_program)
@@ -134,6 +139,136 @@ goto_programt goto_convertt::build_declaration_stack(
134139
return declarations;
135140
}
136141

142+
struct build_declaration_hops_inputst
143+
{
144+
irep_idt mode;
145+
irep_idt label;
146+
goto_programt::targett goto_instruction;
147+
goto_programt::targett label_instruction;
148+
node_indext label_scope_index = 0;
149+
node_indext end_scope_index = 0;
150+
};
151+
152+
void goto_convertt::build_declaration_hops(
153+
goto_programt &program,
154+
std::unordered_map<irep_idt, symbolt, irep_id_hash> &label_flags,
155+
const build_declaration_hops_inputst &inputs)
156+
{
157+
// In the case of a goto jumping into a scope, the declarations (but not the
158+
// initialisations) need to be executed. This function performs a
159+
// transformation from code that looks like -
160+
// {
161+
// statement_block_a();
162+
// if(...)
163+
// goto label;
164+
// statement_block_b();
165+
// user_label:
166+
// x_label:
167+
// int x;
168+
// x = 0;
169+
// statement_block_c();
170+
// int y;
171+
// y = 0;
172+
// statement_block_d();
173+
// label:
174+
// statement_block_e();
175+
// }
176+
// to code which looks like -
177+
// {
178+
// __CPROVER_bool going_to_label;
179+
// going_to_label = false;
180+
// statement_block_a();
181+
// if(...)
182+
// going_to_label = true;
183+
// goto scope_x_label;
184+
// statement_block_b();
185+
// scope_x_label:
186+
// int x;
187+
// if going_to_label goto scope_y_label:
188+
// x = 0;
189+
// statement_block_c();
190+
// scope_y_label:
191+
// int y;
192+
// if going_to_label goto label:
193+
// y = 0;
194+
// statement_block_d();
195+
// label:
196+
// going_to_label = false;
197+
// statement_block_e();
198+
// }
199+
200+
PRECONDITION(inputs.label_scope_index != inputs.end_scope_index);
201+
202+
source_locationt hidden{};
203+
hidden.set_hide();
204+
const auto flag = [&]() -> symbolt {
205+
const auto existing_flag = label_flags.find(inputs.label);
206+
if(existing_flag != label_flags.end())
207+
return existing_flag->second;
208+
const symbolt &new_flag = get_fresh_aux_symbol(
209+
bool_typet{},
210+
id2string(inputs.label),
211+
"going_to",
212+
hidden,
213+
inputs.mode,
214+
symbol_table);
215+
label_flags.emplace(inputs.label, new_flag);
216+
217+
// Create and initialise flag.
218+
goto_programt flag_creation;
219+
flag_creation.instructions.push_back(
220+
goto_programt::make_decl(new_flag.symbol_expr(), hidden));
221+
const auto make_clear_flag = [&]() -> goto_programt::instructiont {
222+
return goto_programt::make_assignment(
223+
new_flag.symbol_expr(), false_exprt{}, hidden);
224+
};
225+
flag_creation.instructions.push_back(make_clear_flag());
226+
program.destructive_insert(program.instructions.begin(), flag_creation);
227+
228+
// Clear flag on arrival at label.
229+
auto clear_on_arrival = make_clear_flag();
230+
program.insert_before_swap(inputs.label_instruction, clear_on_arrival);
231+
return new_flag;
232+
}();
233+
234+
{
235+
// Set flag before the goto.
236+
auto set_flag =
237+
goto_programt::make_assignment(flag.symbol_expr(), true_exprt{}, hidden);
238+
program.insert_before_swap(inputs.goto_instruction, set_flag);
239+
}
240+
241+
auto target = inputs.label_instruction;
242+
targets.scope_stack.set_current_node(inputs.label_scope_index);
243+
while(targets.scope_stack.get_current_node() > inputs.end_scope_index)
244+
{
245+
node_indext current_node = targets.scope_stack.get_current_node();
246+
auto &declaration = targets.scope_stack.get_declaration(current_node);
247+
targets.scope_stack.descend_tree();
248+
if(!declaration)
249+
continue;
250+
251+
// TODO - TYPE CHECK FOR VAR ARRAYS!
252+
253+
WATCHVAR(declaration->instruction->to_string());
254+
bool add_if = declaration->if_conditions_added.find(flag.name) ==
255+
declaration->if_conditions_added.end();
256+
if(add_if)
257+
{
258+
auto if_goto =
259+
goto_programt::make_goto(target, flag.symbol_expr(), hidden);
260+
program.instructions.insert(
261+
std::next(declaration->instruction), std::move(if_goto));
262+
declaration->if_conditions_added.insert(flag.name);
263+
}
264+
target = declaration->instruction;
265+
}
266+
267+
// We need to look at the list node after goto_instruction because this
268+
// iterator now refers to the flag assignment.
269+
std::next(inputs.goto_instruction)->set_target(target);
270+
}
271+
137272
/******************************************************************* \
138273
139274
Function: goto_convertt::finish_gotos
@@ -148,6 +283,8 @@ Function: goto_convertt::finish_gotos
148283

149284
void goto_convertt::finish_gotos(goto_programt &dest, const irep_idt &mode)
150285
{
286+
std::unordered_map<irep_idt, symbolt, irep_id_hash> label_flags;
287+
151288
for(const auto &g_it : targets.gotos)
152289
{
153290
goto_programt::instructiont &i=*(g_it.first);
@@ -179,6 +316,7 @@ void goto_convertt::finish_gotos(goto_programt &dest, const irep_idt &mode)
179316
}
180317

181318
i.complete_goto(l_it->second.first);
319+
WATCHVAR(i.get_target()->to_string());
182320

183321
node_indext label_target = l_it->second.second;
184322
node_indext goto_target = g_it.second;
@@ -222,9 +360,15 @@ void goto_convertt::finish_gotos(goto_programt &dest, const irep_idt &mode)
222360
debug() << "adding declaration code on jump to '" << goto_label << "'"
223361
<< eom;
224362

225-
auto declaration_code = build_declaration_stack(
226-
mode, label_target, intersection_result.common_ancestor);
227-
dest.destructive_insert(g_it.first, declaration_code);
363+
build_declaration_hops_inputst inputs;
364+
inputs.mode = mode;
365+
inputs.label = l_it->first;
366+
inputs.goto_instruction = g_it.first;
367+
inputs.label_instruction = l_it->second.first;
368+
inputs.label_scope_index = label_target;
369+
inputs.end_scope_index = intersection_result.common_ancestor;
370+
build_declaration_hops(dest, label_flags, inputs);
371+
//WATCHVAR(i.get_target()->to_string());
228372
}
229373
}
230374
else
@@ -660,7 +804,7 @@ void goto_convertt::convert_frontend_decl(
660804
if(code.operands().size() == 1)
661805
{
662806
copy(code, DECL, dest);
663-
return dest.instructions.end()--;
807+
return std::prev(dest.instructions.end());
664808
}
665809

666810
exprt initializer = code.op1();
@@ -673,7 +817,7 @@ void goto_convertt::convert_frontend_decl(
673817
// Break up into decl and assignment.
674818
// Decl must be visible before initializer.
675819
copy(tmp, DECL, dest);
676-
const auto declaration_iterator = dest.instructions.end()--;
820+
const auto declaration_iterator = std::prev(dest.instructions.end());
677821

678822
auto initializer_location = initializer.find_source_location();
679823
clean_expr(initializer, dest, mode);
@@ -696,7 +840,6 @@ void goto_convertt::convert_frontend_decl(
696840

697841
{
698842
code_deadt code_dead(symbol_expr);
699-
700843
targets.scope_stack.add(code_dead, {declaration_iterator});
701844
}
702845

src/goto-programs/goto_convert_class.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Author: Daniel Kroening, [email protected]
2626
#include <vector>
2727

2828
class side_effect_expr_overflowt;
29+
struct build_declaration_hops_inputst;
2930

3031
class goto_convertt:public messaget
3132
{
@@ -367,6 +368,11 @@ class goto_convertt:public messaget
367368
node_indext declaration_start_point,
368369
node_indext declaration_end_point);
369370

371+
void build_declaration_hops(
372+
goto_programt &dest,
373+
std::unordered_map<irep_idt, symbolt, irep_id_hash> &label_flags,
374+
const build_declaration_hops_inputst &inputs);
375+
370376
//
371377
// gotos
372378
//

0 commit comments

Comments
 (0)