Skip to content

Commit a536e77

Browse files
committed
Remove original_loop_number from instructiont
In this commit, we remove original_loop_number from instructiont. Instead, we use a map in code_contracts to store the original loop numbers for some instrumented instructions.
1 parent 17579cc commit a536e77

File tree

7 files changed

+94
-58
lines changed

7 files changed

+94
-58
lines changed

src/goto-instrument/contracts/contracts.cpp

+23-6
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ void code_contractst::check_apply_loop_contracts(
5959
const irep_idt &mode)
6060
{
6161
const auto loop_head_location = loop_head->source_location();
62+
const unsigned loop_number = loop_end->loop_number;
6263

6364
// Vector representing a (possibly multidimensional) decreases clause
6465
const auto &decreases_clause_exprs = decreases_clause.operands();
@@ -294,12 +295,6 @@ void code_contractst::check_apply_loop_contracts(
294295
// Generate havocing code for assignment targets.
295296
havoc_assigns_targetst havoc_gen(to_havoc, ns);
296297
havoc_gen.append_full_havoc_code(loop_head_location, pre_loop_head_instrs);
297-
// Add loop number to the havoc_code
298-
for(auto &havoc_instr : pre_loop_head_instrs.instructions)
299-
{
300-
if(is_loop_havoc(havoc_instr))
301-
havoc_instr.original_loop_number = loop_end->loop_number;
302-
}
303298

304299
// Insert the second block of pre_loop_head_instrs: the havocing code.
305300
// We do not `add_pragma_disable_assigns_check`,
@@ -446,6 +441,28 @@ void code_contractst::check_apply_loop_contracts(
446441
loop_end,
447442
add_pragma_disable_assigns_check(pre_loop_end_instrs));
448443

444+
// Record original loop number for some instrumented instructions.
445+
for(goto_programt::const_targett it_instr =
446+
goto_function.body.instructions.begin();
447+
it_instr != goto_function.body.instructions.end();
448+
it_instr++)
449+
{
450+
// Don't override original loop numbers.
451+
if(original_loop_number_map.count(it_instr) != 0)
452+
continue;
453+
454+
// Store loop number for
455+
// ASSIGN ENTERED_LOOP = TRUE
456+
if(
457+
is_assignment_to_instrumented_variable(it_instr, ENTERED_LOOP) &&
458+
it_instr->assign_rhs() == true_exprt())
459+
original_loop_number_map[it_instr] = loop_number;
460+
461+
// Store loop number for loop havoc.
462+
if(is_loop_havoc(*it_instr))
463+
original_loop_number_map[it_instr] = loop_number;
464+
}
465+
449466
// change the back edge into assume(false) or assume(guard)
450467
loop_end->turn_into_assume();
451468
loop_end->condition_nonconst() = boolean_negate(loop_end->condition());

src/goto-instrument/contracts/contracts.h

+13
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ class code_contractst
122122
symbol_tablet &get_symbol_table();
123123
goto_functionst &get_goto_functions();
124124

125+
std::unordered_map<goto_programt::const_targett, unsigned, const_target_hash>
126+
get_original_loop_number_map() const
127+
{
128+
return original_loop_number_map;
129+
}
130+
125131
namespacet ns;
126132

127133
protected:
@@ -137,6 +143,13 @@ class code_contractst
137143
/// Name of loops we are going to unwind.
138144
std::list<std::string> loop_names;
139145

146+
/// Store the map from instrumented instructions for loop contracts to their
147+
/// original loop numbers. Following instrumented instructions are stored.
148+
/// 1. loop-havoc --- begin of transformed loops
149+
/// 2. ASSIGN ENTERED_LOOP = TRUE --- end of transformed loops
150+
std::unordered_map<goto_programt::const_targett, unsigned, const_target_hash>
151+
original_loop_number_map;
152+
140153
public:
141154
/// \brief Enforce contract of a single function
142155
void enforce_contract(const irep_idt &function);

src/goto-programs/goto_program.h

-4
Original file line numberDiff line numberDiff line change
@@ -541,10 +541,6 @@ class goto_programt
541541
/// Number unique per function to identify loops
542542
unsigned loop_number = 0;
543543

544-
/// We record the original loop number for some instrumended instructions
545-
/// so that we know which loop they are transformed from.
546-
optionalt<unsigned> original_loop_number;
547-
548544
/// A number to identify branch targets.
549545
/// This is \ref nil_target if it's not a target.
550546
unsigned target_number = nil_target;

src/goto-synthesizer/cegis_verifier.cpp

+46-2
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,58 @@ optionalt<loop_idt> cegis_verifiert::get_cause_loop_id(
154154
from.has_value() && to.has_value() &&
155155
dependence_graph.is_flow_dependent(from.value(), to.value()))
156156
{
157-
result =
158-
loop_idt(step.function_id, step.pc->original_loop_number.value());
157+
result = loop_idt(step.function_id, original_loop_number_map[step.pc]);
159158
return result;
160159
}
161160
}
162161
}
163162
return result;
164163
}
165164

165+
bool cegis_verifiert::is_instruction_in_transfomed_loop(
166+
const loop_idt &loop_id,
167+
const goto_functiont &function,
168+
unsigned location_number_of_target)
169+
{
170+
// The loop body after transformation are instructions from
171+
// loop havocing instructions
172+
// to
173+
// loop end of transformed code.
174+
unsigned location_number_of_havocing = 0;
175+
176+
for(goto_programt::const_targett it = function.body.instructions.begin();
177+
it != function.body.instructions.end();
178+
++it)
179+
{
180+
// Record the location number of the begin of a transformed loop.
181+
if(
182+
is_loop_havoc(*it) && original_loop_number_map[it] == loop_id.loop_number)
183+
{
184+
location_number_of_havocing = it->location_number;
185+
}
186+
187+
// Reach the end of a transformed loop.
188+
if(
189+
is_transformed_loop_end(it) &&
190+
original_loop_number_map[it] == loop_id.loop_number)
191+
{
192+
INVARIANT(
193+
location_number_of_havocing != 0,
194+
"We must have entered the transformed loop before reaching the end");
195+
196+
// Check if `location_number_of_target` is between the begin and the end
197+
// of the transformed loop.
198+
if((location_number_of_havocing < location_number_of_target &&
199+
location_number_of_target < it->location_number))
200+
{
201+
return true;
202+
}
203+
}
204+
}
205+
206+
return false;
207+
}
208+
166209
cext cegis_verifiert::build_cex(
167210
const goto_tracet &goto_trace,
168211
const source_locationt &loop_entry_loc)
@@ -391,6 +434,7 @@ optionalt<cext> cegis_verifiert::verify()
391434
// Apply loop contracts we annotated.
392435
code_contractst cont(goto_model, log);
393436
cont.apply_loop_contracts();
437+
original_loop_number_map = cont.get_original_loop_number_map();
394438

395439
// Get the checker same as CBMC api without any flag.
396440
// TODO: replace the checker with CBMC api once it is implemented.

src/goto-synthesizer/cegis_verifier.h

+12
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,25 @@ class cegis_verifiert
131131
const goto_tracet &goto_trace,
132132
const source_locationt &loop_entry_loc);
133133

134+
/// Decide whether the target instruction is in the body of the transformed
135+
/// loop specified by `loop_id`.
136+
bool is_instruction_in_transfomed_loop(
137+
const loop_idt &loop_id,
138+
const goto_functiont &function,
139+
unsigned location_number_of_target);
140+
134141
const invariant_mapt &invariant_candidates;
135142
goto_modelt &goto_model;
136143
messaget log;
137144

138145
/// Map from function names to original functions. It is used to
139146
/// restore functions with annotated loops to original functions.
140147
std::unordered_map<irep_idt, goto_programt> original_functions;
148+
149+
/// Map from instrumented instructions for loop contracts to their
150+
/// original loop numbers. Returned by `code_contractst`
151+
std::unordered_map<goto_programt::const_targett, unsigned, const_target_hash>
152+
original_loop_number_map;
141153
};
142154

143155
#endif // CPROVER_GOTO_SYNTHESIZER_CEGIS_VERIFIER_H

src/goto-synthesizer/synthesizer_utils.cpp

-39
Original file line numberDiff line numberDiff line change
@@ -116,45 +116,6 @@ void annotate_invariants(
116116
}
117117
}
118118

119-
bool is_instruction_in_transfomed_loop(
120-
const loop_idt &loop_id,
121-
const goto_functiont &function,
122-
unsigned location_number_of_target)
123-
{
124-
// The loop body after transformation are instructions from
125-
// loop havocing instructions
126-
// to
127-
// loop end of transformed code.
128-
129-
unsigned location_number_of_havocing = 0;
130-
131-
for(goto_programt::const_targett it = function.body.instructions.begin();
132-
it != function.body.instructions.end();
133-
++it)
134-
{
135-
// Record the location number of the begin of a transformed loop.
136-
if(is_loop_havoc(*it) && it->loop_number == loop_id.loop_number)
137-
{
138-
location_number_of_havocing = it->location_number;
139-
}
140-
141-
// Reach the end of a transformed loop.
142-
if(is_transformed_loop_end(it) && it->loop_number == loop_id.loop_number)
143-
{
144-
// Check if `location_number_of_target` is between the begin and the end
145-
// of the transformed loop.
146-
147-
if((location_number_of_havocing < location_number_of_target &&
148-
location_number_of_target < it->location_number))
149-
{
150-
return true;
151-
}
152-
}
153-
}
154-
155-
return false;
156-
}
157-
158119
invariant_mapt combine_in_and_post_invariant_clauses(
159120
const invariant_mapt &in_clauses,
160121
const invariant_mapt &post_clauses,

src/goto-synthesizer/synthesizer_utils.h

-7
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,6 @@ void annotate_invariants(
5151
const invariant_mapt &invariant_map,
5252
goto_modelt &goto_model);
5353

54-
/// Decide whether the target instruction is in the body of the transformed loop
55-
/// specified by `loop_id`.
56-
bool is_instruction_in_transfomed_loop(
57-
const loop_idt &loop_id,
58-
const goto_functiont &function,
59-
unsigned location_number_of_target);
60-
6154
/// Combine invariant of form
6255
/// (in_inv || !guard) && (!guard -> pos_inv)
6356
invariant_mapt combine_in_and_post_invariant_clauses(

0 commit comments

Comments
 (0)