diff --git a/regression/goto-instrument-unwind/Makefile b/regression/goto-instrument-unwind/Makefile new file mode 100644 index 00000000000..45c2db4d8c2 --- /dev/null +++ b/regression/goto-instrument-unwind/Makefile @@ -0,0 +1,33 @@ +default: tests.log + +testalpha: + @../test.pl -c ../unwind-chain.sh -C + +testbeta: + @../test.pl -c ../unwind-chain.sh -T + +testimpr: + @../test.pl -c ../unwind-chain.sh -K + +testnew: + @../test.pl -c ../unwind-chain.sh -F + +test: + @../test.pl -c ../unwind-chain.sh + +tests.log: ../test.pl + @../test.pl -c ../unwind-chain.sh + +clean: + @for dir in *; do \ + if [ -d "$$dir" ]; then \ + rm $$dir/*.txt $$dir/*.dot $$dir/*.gb $$dir/*.out; \ + fi; \ + done; + +show: + @for dir in *; do \ + if [ -d "$$dir" ]; then \ + vim -o "$$dir/*.c" "$$dir/*.out"; \ + fi; \ + done; diff --git a/regression/goto-instrument-unwind/break-loop1/main.c b/regression/goto-instrument-unwind/break-loop1/main.c new file mode 100644 index 00000000000..b5323c4ff5d --- /dev/null +++ b/regression/goto-instrument-unwind/break-loop1/main.c @@ -0,0 +1,30 @@ + +void f() {} + +int main() +{ + /** + * This is a test case for the unwind operation of goto-instrument; + * every loop will be unwound K times + **/ + const unsigned K=10; + + const unsigned n=100; + unsigned c=0, i; + unsigned tres=K/2;; + + for(i=1; i<=n; i++) + { + f(); + c++; + if(i==tres) + break; + } + + unsigned eva=n; + if(Ktres) + continue; + c++; + } + + unsigned eva=n; + if(Ktres) + continue; + c++; + } + + unsigned eva=n; + if(K - +#include #include "unwind.h" +#include "loop_utils.h" /*******************************************************************\ @@ -170,3 +171,61 @@ void unwind( // update it all goto_program.update(); } + +/*******************************************************************\ + +Function: goto_unwind + + Inputs: + + Outputs: + + Purpose: + +\*******************************************************************/ + +void goto_unwind( + goto_functionst &goto_functions, + const unsigned k) +{ + // Here we unwind all loops in the program. + // Each loop body is simply repeated k times (if condition holds) + Forall_goto_functions(it, goto_functions) + { + goto_functionst::goto_functiont &goto_function=it->second; + if(!goto_function.body_available()) + { + continue; + } + goto_programt &goto_program=goto_function.body; + + // the unwinding continues until there is no loop in the function + while(true) + { + natural_loops_mutablet natural_loops(goto_program); + // if there is no loop anymore in the current function, + // then go to the next function for unwinding + if(natural_loops.loop_map.size()==0) + { + break; + } + typedef const natural_loops_mutablet::natural_loopt loopt; + for(natural_loops_mutablet::loop_mapt::const_iterator + l_it=natural_loops.loop_map.begin(); + l_it!=natural_loops.loop_map.end(); + l_it++) + { + // save a copy of the loop guard + const exprt loop_guard=l_it->first->guard; + + const loopt &loop=l_it->second; + assert(!loop.empty()); + goto_programt::targett loop_exit=get_loop_exit(loop); + + unwind(goto_program, l_it->first, loop_exit, k); + + } + } + } +} + diff --git a/src/goto-instrument/unwind.h b/src/goto-instrument/unwind.h index ae7fb8798f7..ac93496a842 100644 --- a/src/goto-instrument/unwind.h +++ b/src/goto-instrument/unwind.h @@ -24,4 +24,8 @@ void unwind( const unsigned k, std::vector &iteration_points); +void goto_unwind( + goto_functionst &goto_functions, + const unsigned k); + #endif