Skip to content

Commit d3dff22

Browse files
zhixing-xutautschnig
authored andcommitted
Fix the update happening in function call problem
1 parent 92e9472 commit d3dff22

File tree

5 files changed

+126
-48
lines changed

5 files changed

+126
-48
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <stdlib.h>
2+
#define ROW 10
3+
4+
void boo(int* x)
5+
{
6+
*x = *x + 1;
7+
}
8+
9+
10+
void main()
11+
{
12+
int *x = (int*)malloc(sizeof(int));
13+
int buffer[ROW];
14+
*x = 2;
15+
// not shrinkable since x has a self-update in boo()
16+
for(int i = 0; i < ROW; i++)
17+
{
18+
boo(x);
19+
buffer[*x] = 1;
20+
}
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
main.c
3+
--bounds-check --pointer-check --abstract-loops --abstractset main.0
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
main\.0
8+
--
9+
ASSUME i < 10
10+
ASSUME i >= 0
11+
^warning: ignoring
12+
--
13+
This test ensures that the loops with loop variable i are not shrinked (so
14+
they appears in unwinding). Even when the instruction that makes the loop
15+
unshrinkable is in another function
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include <stdlib.h>
2-
#define ROW 3
3-
#define COL 10
2+
#define ROW 10
43

54
void boo(int* x)
65
{
@@ -12,11 +11,11 @@ void main()
1211
{
1312
int *x = (int*)malloc(sizeof(int));
1413
int buffer[ROW];
15-
// not shrinkable since x is used in mem-safe assertion in boo()
16-
// and r update itself in loop
14+
*x = 2;
15+
// not shrinkable since x has a self-update in boo()
1716
for(int i = 0; i < ROW; i++)
1817
{
1918
boo(x);
20-
buffer[*x];
19+
buffer[*x] = 1;
2120
}
2221
}
Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
1-
KNOWNBUG
1+
CORE
22
main.c
3-
--bounds-check --pointer-check --abstract-loops --abstractset boo.0,main.0
3+
--bounds-check --pointer-check --add-library --abstract-loops --abstractset main.0
44
^EXIT=10$
55
^SIGNAL=0$
66
^VERIFICATION FAILED$
77
main\.0
8-
main\.1
9-
ASSUME j < 10
10-
ASSUME j >= 0
118
--
12-
boo\.0
139
ASSUME i < 10
1410
ASSUME i >= 0
1511
^warning: ignoring
1612
--
1713
This test ensures that the loops with loop variable i are not shrinked (so
18-
they appears in unwinding). Although the second loop in main is shrinkable, but
19-
it's not in the target loop set provided by --abstractset, so it shouldn't be
20-
shrinked.
21-
It also ensures the loop in boo() with loop variable j is shrinked and the
22-
constraints are correctly applied.
14+
they appears in unwinding). Even when the instruction that makes the loop
15+
unshrinkable is in another function

src/goto-instrument/abstract_loops.cpp

Lines changed: 82 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ Author: Zhixing Xu, [email protected]
2020
#include <analyses/goto_rw.h>
2121

2222
#include <goto-programs/remove_skip.h>
23+
#include <goto-programs/cfg.h>
2324

2425
// debug
2526
#ifdef DEBUG_ABSTRACT_LOOPS
2627
#include "iostream"
27-
#include <util/expr_iterator.h>
2828
#endif
2929

3030
class abstract_loopst
@@ -43,6 +43,8 @@ class abstract_loopst
4343
dependence_grapht dep_graph(_ns);
4444
// data structures initialization
4545
dep_graph(goto_model.goto_functions, _ns);
46+
// build the CFG data structure
47+
cfg(goto_model.goto_functions);
4648
// call main function
4749
abstract_loops(goto_model, dep_graph, target_loop_map);
4850
}
@@ -53,8 +55,8 @@ class abstract_loopst
5355
// target abstract loop number for each function
5456
loop_mapt target_loop_map;
5557
// set of all leaf dependency nodes for loop variables
56-
nodeset leaf_nodes;
57-
nodeset update_nodes;
58+
//nodeset leaf_nodes;
59+
//nodeset update_nodes;
5860
// current function
5961
irep_idt fn;
6062
// map from instruction line # to the set of loops it belongs to
@@ -65,6 +67,18 @@ class abstract_loopst
6567
typedef dep_graph_domaint::depst depst;
6668
// name space for program
6769
const namespacet ns;
70+
// cfg
71+
struct cfg_nodet
72+
{
73+
cfg_nodet():node_required(false)
74+
{
75+
}
76+
77+
bool node_required;
78+
};
79+
80+
typedef cfg_baset<cfg_nodet> cfgt;
81+
cfgt cfg;
6882

6983
// functions in this class
7084
void abstract_loops(goto_modelt &goto_model,
@@ -75,7 +89,8 @@ class abstract_loopst
7589

7690
void update_shrinkability(unsigned loc, irep_idt func);
7791

78-
void check_assertion(unsigned location, const dependence_grapht &dep_graph);
92+
void check_assertion(unsigned location, const dependence_grapht &dep_graph,
93+
const goto_functionst &goto_functions);
7994

8095
void abstract_goto_program(unsigned loop_num,
8196
const dependence_grapht &dep_graph,
@@ -185,6 +200,7 @@ class abstract_loopst
185200
}; // end of class abstract_loopst
186201

187202

203+
#ifdef DEBUG_ABSTRACT_LOOPS
188204
/// print out nodes in set
189205
void print_nodes(abstract_loopst::nodeset &node_set)
190206
{
@@ -198,6 +214,7 @@ void print_nodes(abstract_loopst::nodeset &node_set)
198214
}
199215
std::cout << '\n';
200216
}
217+
#endif
201218

202219
/// Do the abstraction on goto program (modify goto program)
203220
/// \param loop_num: target loop number
@@ -241,16 +258,10 @@ void abstract_loopst::abstract_goto_program(unsigned loop_num,
241258
f_it = goto_functions.function_map.find(fn);
242259
i_it = f_it->second.body.instructions.begin();
243260
std::advance(i_it, loop_info->init_loc - i_it->location_number);
244-
245-
//init values can be nondet
246-
const code_assignt &code_assign = to_code_assign(i_it->code);
247-
if(!(code_assign.rhs().id() == ID_side_effect))
248-
{
249-
expr = i_it->code;
250-
expr.id(is_inc ? ID_ge : ID_le);
251-
expr.type().id(ID_bool);
252-
i_it->make_assumption(expr);
253-
}
261+
expr = i_it->code;
262+
expr.id(is_inc ? ID_ge : ID_le);
263+
expr.type().id(ID_bool);
264+
i_it->make_assumption(expr);
254265

255266
// change loop head into assumption, skip goto at loop end
256267
loop_info->build_assumption();
@@ -276,7 +287,7 @@ void abstract_loopst::update_shrinkability(unsigned loc, irep_idt func)
276287
/// \param location: line number for assertion
277288
/// \param dep_graph: dependency graph for the program
278289
void abstract_loopst::check_assertion(unsigned location,
279-
const dependence_grapht &dep_graph)
290+
const dependence_grapht &dep_graph, const goto_functionst &goto_functions)
280291
{
281292
#ifdef DEBUG_ABSTRACT_LOOPS
282293
std::cout << "Check assertion at: " << location << "\n";
@@ -339,6 +350,18 @@ void abstract_loopst::check_assertion(unsigned location,
339350
print_nodes(update_set);
340351
#endif
341352

353+
// node set
354+
nodeset leaf_nodes;
355+
nodeset update_nodes;
356+
for(auto loop_n: insloop_map[location])
357+
{
358+
irep_idt func = dep_graph[location].PC->function;
359+
abstract_loopt *loop_info = &(absloop_map[func].find(loop_n)->second);
360+
leaf_nodes.insert(loop_info->var_leaves.begin(),
361+
loop_info->var_leaves.end());
362+
update_nodes.insert(loop_info->var_updates.begin(),
363+
loop_info->var_updates.end());
364+
}
342365
// check dependence of leaf set
343366
nodeset diff;
344367
std::set_difference(leaf_set.begin(), leaf_set.end(),
@@ -358,13 +381,39 @@ void abstract_loopst::check_assertion(unsigned location,
358381
{
359382
if(is_in_cycle(loc, dep_graph))
360383
{
361-
update_shrinkability(loc, dep_graph[loc].PC->function);
384+
nodeset entry_set;
385+
std::queue<unsigned> entry_queue;
386+
add_to_queue(entry_set, entry_queue, loc);
387+
while(!entry_queue.empty())
388+
{
389+
unsigned node = entry_queue.front();
390+
entry_queue.pop();
391+
update_shrinkability(node, dep_graph[node].PC->function);
392+
// check loops calling this function call
393+
goto_functionst::function_mapt::const_iterator f_it=
394+
goto_functions.function_map.find(dep_graph[node].PC->function);
395+
396+
goto_programt::const_targett begin_function=
397+
f_it->second.body.instructions.begin();
398+
399+
cfgt::entry_mapt::const_iterator entry=
400+
cfg.entry_map.find(begin_function);
401+
if(entry!=cfg.entry_map.end())
402+
{
403+
for(cfgt::edgest::const_iterator
404+
it=cfg[entry->second].in.begin();
405+
it!=cfg[entry->second].in.end();
406+
++it)
407+
{
408+
add_to_queue(entry_set, entry_queue, it->first);
409+
}
410+
}
411+
}
362412
}
363413
else
364414
{
365415
// check if the update depends on loop variable
366416
const goto_programt::instructiont &inst = *(dep_graph[loc].PC);
367-
std::cout << "check location " << loc << " type " << inst.type << "\n";
368417
if(!inst.is_assign())
369418
continue;
370419
value_setst &value_sets=
@@ -496,34 +545,34 @@ void abstract_loopst::get_loop_info(
496545
return;
497546
}
498547

548+
// This is for SVcomp cases where values can be nondet
549+
const code_assignt &code_assign =
550+
to_code_assign(dep_graph[loop_info.init_loc].PC->code);
551+
if(code_assign.rhs().id() == ID_side_effect)
552+
{
553+
#ifdef DEBUG_ABSTRACT_LOOPS
554+
std::cout << "Unshrinkable: Loop variable init to nondet\n";
555+
#endif
556+
return;
557+
}
558+
499559
#ifdef DEBUG_ABSTRACT_LOOPS
500560
std::cout << " Leaf dependency nodes for loop variable: ";
501561
print_nodes(loop_info.var_leaves);
502562
std::cout << " Update node for loop variable: ";
503563
print_nodes(loop_info.var_updates);
504564
#endif
505565

506-
//// This is for SVcomp cases where values can be nondet
507-
//const code_assignt &code_assign =
508-
//to_code_assign(dep_graph[loop_info.init_loc].PC->code);
509-
//if(code_assign.rhs().id() == ID_side_effect)
510-
//{
511-
//#ifdef DEBUG_ABSTRACT_LOOPS
512-
//std::cout << "Unshrinkable: Loop variable init to nondet\n";
513-
//#endif
514-
//return;
515-
//}
516-
517566
// add to the instruction # -> loop # map
518567
// unsafe with function call, further check when doing abstraction
519568
for(unsigned n = head->location_number;
520569
n <= last->location_number; n++)
521570
insloop_map[n].insert(last->loop_number);
522571

523572
absloop_map[fn].insert(loopnum_pair(last->loop_number, loop_info));
524-
leaf_nodes.insert(loop_info.var_leaves.begin(), loop_info.var_leaves.end());
525-
update_nodes.insert(loop_info.var_updates.begin(),
526-
loop_info.var_updates.end());
573+
//leaf_nodes.insert(loop_info.var_leaves.begin(), loop_info.var_leaves.end());
574+
//update_nodes.insert(loop_info.var_updates.begin(),
575+
//loop_info.var_updates.end());
527576
}
528577

529578
/// Main function for abstraction, has 3 iterations to
@@ -557,7 +606,8 @@ void abstract_loopst::abstract_loops(goto_modelt &goto_model,
557606
Forall_goto_program_instructions(i_it, it->second.body)
558607
{
559608
if(i_it->is_assert())
560-
check_assertion(i_it->location_number, dep_graph);
609+
check_assertion(i_it->location_number, dep_graph,
610+
goto_model.goto_functions);
561611
}
562612
}
563613
}

0 commit comments

Comments
 (0)