Skip to content

Commit da48fba

Browse files
authored
Merge pull request #7782 from qinheping/migrate_synthesizer_utils
CONTRACTS: Move some functions from `synthesizer_utils` to `contracts/utils`
2 parents 14fce73 + 0351b58 commit da48fba

File tree

4 files changed

+175
-183
lines changed

4 files changed

+175
-183
lines changed

src/goto-instrument/contracts/utils.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Date: September 2021
2323

2424
#include <goto-programs/cfg.h>
2525

26+
#include <analyses/natural_loops.h>
2627
#include <ansi-c/c_expr.h>
2728
#include <langapi/language_util.h>
2829

@@ -610,3 +611,130 @@ unsigned get_suffix_unsigned(const std::string &str, const std::string &prefix)
610611
std::string result = str.substr(first_index, last_index - first_index);
611612
return std::stol(result);
612613
}
614+
615+
goto_programt::const_targett get_loop_end_from_loop_head_and_content(
616+
const goto_programt::const_targett &loop_head,
617+
const loop_templatet<
618+
goto_programt::const_targett,
619+
goto_programt::target_less_than> &loop)
620+
{
621+
goto_programt::const_targett loop_end = loop_head;
622+
for(const auto &t : loop)
623+
{
624+
// an instruction is the loop end if it is a goto instruction
625+
// and it jumps backward to the loop head
626+
if(
627+
t->is_goto() && t->get_target() == loop_head &&
628+
t->location_number > loop_end->location_number)
629+
loop_end = t;
630+
}
631+
INVARIANT(
632+
loop_head != loop_end,
633+
"Could not find end of the loop starting at: " +
634+
loop_head->source_location().as_string());
635+
636+
return loop_end;
637+
}
638+
639+
goto_programt::targett get_loop_end_from_loop_head_and_content_mutable(
640+
const goto_programt::targett &loop_head,
641+
const loop_templatet<goto_programt::targett, goto_programt::target_less_than>
642+
&loop)
643+
{
644+
goto_programt::targett loop_end = loop_head;
645+
for(const auto &t : loop)
646+
{
647+
// an instruction is the loop end if it is a goto instruction
648+
// and it jumps backward to the loop head
649+
if(
650+
t->is_goto() && t->get_target() == loop_head &&
651+
t->location_number > loop_end->location_number)
652+
loop_end = t;
653+
}
654+
INVARIANT(
655+
loop_head != loop_end,
656+
"Could not find end of the loop starting at: " +
657+
loop_head->source_location().as_string());
658+
659+
return loop_end;
660+
}
661+
662+
goto_programt::targett get_loop_head_or_end(
663+
const unsigned int target_loop_number,
664+
goto_functiont &function,
665+
bool finding_head)
666+
{
667+
natural_loops_mutablet natural_loops(function.body);
668+
669+
// iterate over all natural loops to find the loop with `target_loop_number`
670+
for(const auto &loop_p : natural_loops.loop_map)
671+
{
672+
const goto_programt::targett loop_head = loop_p.first;
673+
goto_programt::targett loop_end =
674+
get_loop_end_from_loop_head_and_content_mutable(loop_head, loop_p.second);
675+
// check if the current loop is the target loop by comparing loop number
676+
if(loop_end->loop_number == target_loop_number)
677+
{
678+
if(finding_head)
679+
return loop_head;
680+
else
681+
return loop_end;
682+
}
683+
}
684+
685+
UNREACHABLE;
686+
}
687+
688+
goto_programt::targett
689+
get_loop_end(const unsigned int target_loop_number, goto_functiont &function)
690+
{
691+
return get_loop_head_or_end(target_loop_number, function, false);
692+
}
693+
694+
goto_programt::targett
695+
get_loop_head(const unsigned int target_loop_number, goto_functiont &function)
696+
{
697+
return get_loop_head_or_end(target_loop_number, function, true);
698+
}
699+
700+
void annotate_invariants(
701+
const invariant_mapt &invariant_map,
702+
goto_modelt &goto_model)
703+
{
704+
for(const auto &invariant_map_entry : invariant_map)
705+
{
706+
loop_idt loop_id = invariant_map_entry.first;
707+
irep_idt function_id = loop_id.function_id;
708+
unsigned int loop_number = loop_id.loop_number;
709+
710+
// get the last instruction of the target loop
711+
auto &function = goto_model.goto_functions.function_map[function_id];
712+
goto_programt::targett loop_end = get_loop_end(loop_number, function);
713+
714+
// annotate the invariant to the condition of `loop_end`
715+
loop_end->condition_nonconst().add(ID_C_spec_loop_invariant) =
716+
invariant_map_entry.second;
717+
}
718+
}
719+
720+
void annotate_assigns(
721+
const std::map<loop_idt, std::set<exprt>> &assigns_map,
722+
goto_modelt &goto_model)
723+
{
724+
for(const auto &assigns_map_entry : assigns_map)
725+
{
726+
loop_idt loop_id = assigns_map_entry.first;
727+
irep_idt function_id = loop_id.function_id;
728+
unsigned int loop_number = loop_id.loop_number;
729+
730+
// get the last instruction of the target loop
731+
auto &function = goto_model.goto_functions.function_map[function_id];
732+
goto_programt::targett loop_end = get_loop_end(loop_number, function);
733+
734+
exprt &condition = loop_end->condition_nonconst();
735+
auto assigns = exprt(ID_target_list);
736+
for(const auto &e : assigns_map_entry.second)
737+
assigns.add_to_operands(e);
738+
condition.add(ID_C_spec_assigns) = assigns;
739+
}
740+
}

src/goto-instrument/contracts/utils.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Date: September 2021
1414
#include <goto-programs/goto_convert_class.h>
1515

1616
#include <goto-programs/goto_model.h>
17+
#include <goto-programs/loop_ids.h>
1718

1819
#include <goto-instrument/havoc_utils.h>
1920

@@ -24,6 +25,10 @@ Date: September 2021
2425
#define IN_LOOP_HAVOC_BLOCK "__in_loop_havoc_block"
2526
#define INIT_INVARIANT "__init_invariant"
2627

28+
template <class T, typename C>
29+
class loop_templatet;
30+
typedef std::map<loop_idt, exprt> invariant_mapt;
31+
2732
/// Class that allows to clean expressions of side effects and to generate
2833
/// havoc_slice expressions.
2934
class cleanert : public goto_convertt
@@ -271,4 +276,45 @@ bool is_assignment_to_instrumented_variable(
271276
/// Convert the suffix digits right after `prefix` of `str` into unsigned.
272277
unsigned get_suffix_unsigned(const std::string &str, const std::string &prefix);
273278

279+
/// Find the goto instruction of `loop` that jumps to `loop_head`
280+
goto_programt::targett get_loop_end_from_loop_head_and_content_mutable(
281+
const goto_programt::targett &loop_head,
282+
const loop_templatet<goto_programt::targett, goto_programt::target_less_than>
283+
&loop);
284+
285+
goto_programt::const_targett get_loop_end_from_loop_head_and_content(
286+
const goto_programt::const_targett &loop_head,
287+
const loop_templatet<
288+
goto_programt::const_targett,
289+
goto_programt::target_less_than> &loop);
290+
291+
/// Return loop head if `finding_head` is true,
292+
/// Otherwise return loop end.
293+
goto_programt::targett get_loop_head_or_end(
294+
const unsigned int loop_number,
295+
goto_functiont &function,
296+
bool finding_head);
297+
298+
/// Find and return the last instruction of the natural loop with
299+
/// `loop_number` in `function`. loop_end -> loop_head
300+
goto_programt::targett
301+
get_loop_end(const unsigned int loop_number, goto_functiont &function);
302+
303+
/// Find and return the first instruction of the natural loop with
304+
/// `loop_number` in `function`. loop_end -> loop_head
305+
goto_programt::targett
306+
get_loop_head(const unsigned int loop_number, goto_functiont &function);
307+
308+
/// Annotate the invariants in `invariant_map` to their corresponding
309+
/// loops. Corresponding loops are specified by keys of `invariant_map`
310+
void annotate_invariants(
311+
const invariant_mapt &invariant_map,
312+
goto_modelt &goto_model);
313+
314+
/// Annotate the assigns in `assigns_map` to their corresponding
315+
/// loops. Corresponding loops are specified by keys of `assigns_map`
316+
void annotate_assigns(
317+
const std::map<loop_idt, std::set<exprt>> &assigns_map,
318+
goto_modelt &goto_model);
319+
274320
#endif // CPROVER_GOTO_INSTRUMENT_CONTRACTS_UTILS_H

src/goto-synthesizer/synthesizer_utils.cpp

Lines changed: 0 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -8,139 +8,6 @@ Author: Qinheping Hu
88

99
#include "synthesizer_utils.h"
1010

11-
#include <util/optional.h>
12-
13-
#include <analyses/natural_loops.h>
14-
#include <goto-instrument/contracts/utils.h>
15-
#include <goto-instrument/havoc_utils.h>
16-
17-
goto_programt::const_targett get_loop_end_from_loop_head_and_content(
18-
const goto_programt::const_targett &loop_head,
19-
const loop_templatet<
20-
goto_programt::const_targett,
21-
goto_programt::target_less_than> &loop)
22-
{
23-
goto_programt::const_targett loop_end = loop_head;
24-
for(const auto &t : loop)
25-
{
26-
// an instruction is the loop end if it is a goto instruction
27-
// and it jumps backward to the loop head
28-
if(
29-
t->is_goto() && t->get_target() == loop_head &&
30-
t->location_number > loop_end->location_number)
31-
loop_end = t;
32-
}
33-
INVARIANT(
34-
loop_head != loop_end,
35-
"Could not find end of the loop starting at: " +
36-
loop_head->source_location().as_string());
37-
38-
return loop_end;
39-
}
40-
41-
goto_programt::targett get_loop_end_from_loop_head_and_content_mutable(
42-
const goto_programt::targett &loop_head,
43-
const loop_templatet<goto_programt::targett, goto_programt::target_less_than>
44-
&loop)
45-
{
46-
goto_programt::targett loop_end = loop_head;
47-
for(const auto &t : loop)
48-
{
49-
// an instruction is the loop end if it is a goto instruction
50-
// and it jumps backward to the loop head
51-
if(
52-
t->is_goto() && t->get_target() == loop_head &&
53-
t->location_number > loop_end->location_number)
54-
loop_end = t;
55-
}
56-
INVARIANT(
57-
loop_head != loop_end,
58-
"Could not find end of the loop starting at: " +
59-
loop_head->source_location().as_string());
60-
61-
return loop_end;
62-
}
63-
64-
goto_programt::targett get_loop_head_or_end(
65-
const unsigned int target_loop_number,
66-
goto_functiont &function,
67-
bool finding_head)
68-
{
69-
natural_loops_mutablet natural_loops(function.body);
70-
71-
// iterate over all natural loops to find the loop with `target_loop_number`
72-
for(const auto &loop_p : natural_loops.loop_map)
73-
{
74-
const goto_programt::targett loop_head = loop_p.first;
75-
goto_programt::targett loop_end =
76-
get_loop_end_from_loop_head_and_content_mutable(loop_head, loop_p.second);
77-
// check if the current loop is the target loop by comparing loop number
78-
if(loop_end->loop_number == target_loop_number)
79-
{
80-
if(finding_head)
81-
return loop_head;
82-
else
83-
return loop_end;
84-
}
85-
}
86-
87-
UNREACHABLE;
88-
}
89-
90-
goto_programt::targett
91-
get_loop_end(const unsigned int target_loop_number, goto_functiont &function)
92-
{
93-
return get_loop_head_or_end(target_loop_number, function, false);
94-
}
95-
96-
goto_programt::targett
97-
get_loop_head(const unsigned int target_loop_number, goto_functiont &function)
98-
{
99-
return get_loop_head_or_end(target_loop_number, function, true);
100-
}
101-
102-
void annotate_invariants(
103-
const invariant_mapt &invariant_map,
104-
goto_modelt &goto_model)
105-
{
106-
for(const auto &invariant_map_entry : invariant_map)
107-
{
108-
loop_idt loop_id = invariant_map_entry.first;
109-
irep_idt function_id = loop_id.function_id;
110-
unsigned int loop_number = loop_id.loop_number;
111-
112-
// get the last instruction of the target loop
113-
auto &function = goto_model.goto_functions.function_map[function_id];
114-
goto_programt::targett loop_end = get_loop_end(loop_number, function);
115-
116-
// annotate the invariant to the condition of `loop_end`
117-
loop_end->condition_nonconst().add(ID_C_spec_loop_invariant) =
118-
invariant_map_entry.second;
119-
}
120-
}
121-
122-
void annotate_assigns(
123-
const std::map<loop_idt, std::set<exprt>> &assigns_map,
124-
goto_modelt &goto_model)
125-
{
126-
for(const auto &assigns_map_entry : assigns_map)
127-
{
128-
loop_idt loop_id = assigns_map_entry.first;
129-
irep_idt function_id = loop_id.function_id;
130-
unsigned int loop_number = loop_id.loop_number;
131-
132-
// get the last instruction of the target loop
133-
auto &function = goto_model.goto_functions.function_map[function_id];
134-
goto_programt::targett loop_end = get_loop_end(loop_number, function);
135-
136-
exprt &condition = loop_end->condition_nonconst();
137-
auto assigns = exprt(ID_target_list);
138-
for(const auto &e : assigns_map_entry.second)
139-
assigns.add_to_operands(e);
140-
condition.add(ID_C_spec_assigns) = assigns;
141-
}
142-
}
143-
14411
invariant_mapt combine_in_and_post_invariant_clauses(
14512
const invariant_mapt &in_clauses,
14613
const invariant_mapt &post_clauses,

0 commit comments

Comments
 (0)