@@ -34,8 +34,7 @@ class code_contractst
34
34
goto_functionst &_goto_functions):
35
35
ns (_symbol_table),
36
36
symbol_table (_symbol_table),
37
- goto_functions (_goto_functions),
38
- temporary_counter (0 )
37
+ goto_functions (_goto_functions)
39
38
{
40
39
}
41
40
@@ -46,10 +45,6 @@ class code_contractst
46
45
symbol_tablet &symbol_table;
47
46
goto_functionst &goto_functions;
48
47
49
- unsigned temporary_counter;
50
-
51
- std::unordered_set<irep_idt> summarized;
52
-
53
48
void apply_code_contracts ();
54
49
void check_code_contracts ();
55
50
@@ -76,160 +71,11 @@ class code_contractst
76
71
const goto_programt::targett loop_head,
77
72
const loopt &loop);
78
73
79
- void add_contract_check (
80
- const irep_idt &function,
81
- goto_programt &dest);
82
-
83
74
const symbolt &new_tmp_symbol (
84
75
const typet &type,
85
76
const source_locationt &source_location);
86
77
};
87
78
88
- static void check_apply_invariants (
89
- goto_functionst::goto_functiont &goto_function,
90
- const local_may_aliast &local_may_alias,
91
- const goto_programt::targett loop_head,
92
- const loopt &loop)
93
- {
94
- PRECONDITION (!loop.empty ());
95
-
96
- // find the last back edge
97
- goto_programt::targett loop_end=loop_head;
98
- for (const goto_programt::targett &inst : loop)
99
- {
100
- if (inst->is_goto () &&
101
- inst->get_target () == loop_head &&
102
- inst->location_number >loop_end->location_number )
103
- {
104
- loop_end = inst;
105
- }
106
- }
107
-
108
- // see whether we have an invariant
109
- exprt invariant=
110
- static_cast <const exprt&>(
111
- loop_end->guard .find (ID_C_spec_loop_invariant));
112
- if (invariant.is_nil ())
113
- {
114
- return ;
115
- }
116
-
117
- // change H: loop; E: ...
118
- // to
119
- // H: assert(invariant);
120
- // if(nondet) goto E:
121
- // havoc reads and writes of loop;
122
- // assume(invariant);
123
- // assume(guard) [only for for/while loops]
124
- // loop;
125
- // assert(invariant);
126
- // assume(false);
127
- // E: havoc writes of loop;
128
- // assume(invariant)
129
- // assume(!guard)
130
- // ...
131
-
132
- // find out what can get changed in the loop
133
- modifiest modifies;
134
- get_modifies (local_may_alias, loop, modifies);
135
-
136
- // find out what is used by the loop
137
- usest uses;
138
- get_uses (local_may_alias, loop, uses);
139
-
140
- // build the havocking code
141
- goto_programt havoc_all_code;
142
- goto_programt havoc_writes_code;
143
-
144
- // assert the invariant
145
- {
146
- goto_programt::targett a=havoc_all_code.add_instruction (ASSERT);
147
- a->guard =invariant;
148
- a->function =loop_head->function ;
149
- a->source_location =loop_head->source_location ;
150
- a->source_location .set_comment (" Loop invariant violated before entry" );
151
- }
152
-
153
- // nondeterministically skip the loop
154
- {
155
- goto_programt::targett jump=havoc_all_code.add_instruction (GOTO);
156
- jump->guard =side_effect_expr_nondett (bool_typet ());
157
- jump->targets .push_back (loop_end);
158
- jump->function =loop_head->function ;
159
- jump->source_location =loop_head->source_location ;
160
- }
161
-
162
- // havoc variables being written to
163
- build_havoc_code (loop_head, uses, havoc_all_code);
164
-
165
- // assume the invariant
166
- {
167
- goto_programt::targett assume=havoc_all_code.add_instruction (ASSUME);
168
- assume->guard =invariant;
169
- assume->function =loop_head->function ;
170
- assume->source_location =loop_head->source_location ;
171
- }
172
-
173
- // assert the invariant at the end of the loop body
174
- {
175
- goto_programt::targett a = goto_function.body .insert_before (loop_end);
176
- a->type =ASSERT;
177
- a->guard =invariant;
178
- a->function =loop_end->function ;
179
- a->source_location =loop_end->source_location ;
180
- a->source_location .set_comment (" Loop invariant not preserved" );
181
- }
182
-
183
- // assume false at the end of the loop to discharge the havocking
184
- {
185
- goto_programt::targett assume = goto_function.body .insert_before (loop_end);
186
- assume->type =ASSUME;
187
- assume->guard .make_false ();
188
- assume->function =loop_end->function ;
189
- assume->source_location =loop_end->source_location ;
190
- }
191
-
192
- build_havoc_code (loop_end, modifies, havoc_writes_code);
193
-
194
- // Assume the invariant (now after the loop)
195
- {
196
- goto_programt::targett assume=havoc_writes_code.add_instruction (ASSUME);
197
- assume->guard =invariant;
198
- assume->function =loop_head->function ;
199
- assume->source_location =loop_head->source_location ;
200
- }
201
-
202
- // change the back edge into assume(!guard)
203
- loop_end->targets .clear ();
204
- loop_end->type =ASSUME;
205
- if (loop_head->is_goto ())
206
- {
207
- loop_end->guard = loop_head->guard ;
208
- }
209
- else
210
- {
211
- loop_end->guard .make_not ();
212
- }
213
-
214
- // Change the loop head to assume the guard if a for/while loop.
215
- // This needs to be done after we case on what loop_head is in the previous
216
- // section of setup.
217
- if (loop_head->is_goto ())
218
- {
219
- exprt guard = loop_head->guard ;
220
- guard.make_not ();
221
- loop_head->make_assumption (guard);
222
- }
223
-
224
- // Now havoc at the loop head. Use insert_swap to
225
- // preserve jumps to loop head.
226
- goto_function.body .insert_before_swap (loop_head, havoc_all_code);
227
-
228
- // Now havoc at the loop end. Use insert_swap to
229
- // preserve jumps to loop end.
230
- goto_function.body .insert_before_swap (loop_end, havoc_writes_code);
231
- }
232
-
233
79
void code_contractst::apply_contract (
234
80
goto_programt &goto_program,
235
81
goto_programt::targett target)
@@ -297,8 +143,6 @@ void code_contractst::apply_contract(
297
143
// TODO: Havoc write set of the function between assert and ensure.
298
144
299
145
target->make_assumption (ensures);
300
-
301
- summarized.insert (function);
302
146
}
303
147
304
148
void code_contractst::apply_invariant (
@@ -599,28 +443,6 @@ void code_contractst::check_apply_invariant(
599
443
goto_function.body .insert_before_swap (loop_head, havoc_code);
600
444
}
601
445
602
- void code_contractst::code_contracts (
603
- goto_functionst::goto_functiont &goto_function)
604
- {
605
- local_may_aliast local_may_alias (goto_function);
606
- natural_loops_mutablet natural_loops (goto_function.body );
607
-
608
- // iterate over the (natural) loops in the function
609
- for (const auto &l_it : natural_loops.loop_map )
610
- {
611
- check_apply_invariants (
612
- goto_function,
613
- local_may_alias,
614
- l_it.first ,
615
- l_it.second );
616
- }
617
-
618
- // look at all function calls
619
- Forall_goto_program_instructions (it, goto_function.body )
620
- if (it->is_function_call ())
621
- apply_contract (goto_function.body , it);
622
- }
623
-
624
446
const symbolt &code_contractst::new_tmp_symbol (
625
447
const typet &type,
626
448
const source_locationt &source_location)
@@ -634,122 +456,6 @@ const symbolt &code_contractst::new_tmp_symbol(
634
456
symbol_table);
635
457
}
636
458
637
- void code_contractst::add_contract_check (
638
- const irep_idt &function,
639
- goto_programt &dest)
640
- {
641
- PRECONDITION (!dest.instructions .empty ());
642
-
643
- goto_functionst::function_mapt::iterator f_it=
644
- goto_functions.function_map .find (function);
645
- assert (f_it!=goto_functions.function_map .end ());
646
-
647
- const goto_functionst::goto_functiont &gf=f_it->second ;
648
-
649
- exprt requires = static_cast <const exprt&>(gf.type .find (ID_C_spec_requires));
650
- exprt ensures = static_cast <const exprt&>(gf.type .find (ID_C_spec_ensures));
651
- assert (ensures.is_not_nil ());
652
-
653
- // build:
654
- // if(nondet)
655
- // decl ret
656
- // decl parameter1 ...
657
- // assume(requires) [optional]
658
- // ret=function(parameter1, ...)
659
- // assert(ensures)
660
- // assume(false)
661
- // skip: ...
662
-
663
- // build skip so that if(nondet) can refer to it
664
- goto_programt tmp_skip;
665
- goto_programt::targett skip=tmp_skip.add_instruction (SKIP);
666
- skip->function =dest.instructions .front ().function ;
667
- skip->source_location =ensures.source_location ();
668
-
669
- goto_programt check;
670
-
671
- // if(nondet)
672
- goto_programt::targett g=check.add_instruction ();
673
- g->make_goto (skip, side_effect_expr_nondett (bool_typet ()));
674
- g->function =skip->function ;
675
- g->source_location =skip->source_location ;
676
-
677
- // prepare function call including all declarations
678
- code_function_callt call;
679
- call.function ()=ns.lookup (function).symbol_expr ();
680
- replace_symbolt replace;
681
-
682
- // decl ret
683
- if (gf.type .return_type ()!=empty_typet ())
684
- {
685
- goto_programt::targett d=check.add_instruction (DECL);
686
- d->function =skip->function ;
687
- d->source_location =skip->source_location ;
688
-
689
- symbol_exprt r=
690
- new_tmp_symbol (gf.type .return_type (),
691
- d->source_location ).symbol_expr ();
692
- d->code =code_declt (r);
693
-
694
- call.lhs ()=r;
695
-
696
- replace.insert (" __CPROVER_return_value" , r);
697
- }
698
-
699
- // decl parameter1 ...
700
- for (const auto &p_it : gf.type .parameters ())
701
- {
702
- goto_programt::targett d=check.add_instruction (DECL);
703
- d->function =skip->function ;
704
- d->source_location =skip->source_location ;
705
-
706
- symbol_exprt p=
707
- new_tmp_symbol (p_it.type (),
708
- d->source_location ).symbol_expr ();
709
- d->code =code_declt (p);
710
-
711
- call.arguments ().push_back (p);
712
-
713
- if (!p_it.get_identifier ().empty ())
714
- replace.insert (p_it.get_identifier (), p);
715
- }
716
-
717
- // rewrite any use of parameters
718
- replace (requires);
719
- replace (ensures);
720
-
721
- // assume(requires)
722
- if (requires.is_not_nil ())
723
- {
724
- goto_programt::targett a=check.add_instruction ();
725
- a->make_assumption (requires);
726
- a->function =skip->function ;
727
- a->source_location =requires.source_location ();
728
- }
729
-
730
- // ret=function(parameter1, ...)
731
- goto_programt::targett f=check.add_instruction ();
732
- f->make_function_call (call);
733
- f->function =skip->function ;
734
- f->source_location =skip->source_location ;
735
-
736
- // assert(ensures)
737
- goto_programt::targett a=check.add_instruction ();
738
- a->make_assertion (ensures);
739
- a->function =skip->function ;
740
- a->source_location =ensures.source_location ();
741
-
742
- // assume(false)
743
- goto_programt::targett af=check.add_instruction ();
744
- af->make_assumption (false_exprt ());
745
- af->function =skip->function ;
746
- af->source_location =ensures.source_location ();
747
-
748
- // prepend the new code to dest
749
- check.destructive_append (tmp_skip);
750
- dest.destructive_insert (dest.instructions .begin (), check);
751
- }
752
-
753
459
void code_contractst::apply_code_contracts ()
754
460
{
755
461
Forall_goto_functions (it, goto_functions)
0 commit comments