Skip to content

Commit ea476f7

Browse files
author
Daniel Kroening
authored
Merge pull request #151 from tautschnig/symex-improvements
Symex improvements
2 parents 0cad6f4 + 73adfb0 commit ea476f7

9 files changed

+184
-83
lines changed

src/path-symex/path_symex.cpp

+52-34
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,14 @@ void path_symext::assign_rec(
422422
var_state.value=propagate(ssa_rhs)?ssa_rhs:nil_exprt();
423423
}
424424
}
425+
else if(ssa_lhs.id()==ID_typecast)
426+
{
427+
// dereferencing might yield a typecast
428+
const exprt &new_lhs=to_typecast_expr(ssa_lhs).op();
429+
typecast_exprt new_rhs(ssa_rhs, new_lhs.type());
430+
431+
assign_rec(state, guard, new_lhs, new_rhs);
432+
}
425433
else if(ssa_lhs.id()==ID_member)
426434
{
427435
#ifdef DEBUG
@@ -541,14 +549,30 @@ void path_symext::assign_rec(
541549

542550
assert(operands.size()==components.size());
543551

544-
for(std::size_t i=0; i<components.size(); i++)
552+
if(ssa_rhs.id()==ID_struct &&
553+
ssa_rhs.operands().size()==components.size())
545554
{
546-
exprt new_rhs=
547-
ssa_rhs.is_nil()?ssa_rhs:
548-
simplify_expr(
549-
member_exprt(ssa_rhs, components[i].get_name(), components[i].type()),
550-
state.var_map.ns);
551-
assign_rec(state, guard, operands[i], new_rhs);
555+
exprt::operandst::const_iterator lhs_it=operands.begin();
556+
forall_operands(it, ssa_rhs)
557+
{
558+
assign_rec(state, guard, *lhs_it, *it);
559+
++lhs_it;
560+
}
561+
}
562+
else
563+
{
564+
for(std::size_t i=0; i<components.size(); i++)
565+
{
566+
exprt new_rhs=
567+
ssa_rhs.is_nil()?ssa_rhs:
568+
simplify_expr(
569+
member_exprt(
570+
ssa_rhs,
571+
components[i].get_name(),
572+
components[i].type()),
573+
state.var_map.ns);
574+
assign_rec(state, guard, operands[i], new_rhs);
575+
}
552576
}
553577
}
554578
else if(ssa_lhs.id()==ID_array)
@@ -564,36 +588,30 @@ void path_symext::assign_rec(
564588
const exprt::operandst &operands=ssa_lhs.operands();
565589

566590
// split up into elements
567-
for(std::size_t i=0; i<operands.size(); i++)
591+
if(ssa_rhs.id()==ID_array &&
592+
ssa_rhs.operands().size()==operands.size())
568593
{
569-
exprt new_rhs=
570-
ssa_rhs.is_nil()?ssa_rhs:
571-
simplify_expr(
572-
index_exprt(
573-
ssa_rhs,
574-
from_integer(i, index_type()), array_type.subtype()),
575-
state.var_map.ns);
576-
assign_rec(state, guard, operands[i], new_rhs);
594+
exprt::operandst::const_iterator lhs_it=operands.begin();
595+
forall_operands(it, ssa_rhs)
596+
{
597+
assign_rec(state, guard, *lhs_it, *it);
598+
++lhs_it;
599+
}
577600
}
578-
}
579-
else if(ssa_lhs.id()==ID_vector)
580-
{
581-
const vector_typet &vector_type=
582-
to_vector_type(state.var_map.ns.follow(ssa_lhs.type()));
583-
584-
const exprt::operandst &operands=ssa_lhs.operands();
585-
586-
// split up into elements
587-
for(std::size_t i=0; i<operands.size(); i++)
601+
else
588602
{
589-
exprt new_rhs=
590-
ssa_rhs.is_nil()?ssa_rhs:
591-
simplify_expr(
592-
index_exprt(
593-
ssa_rhs,
594-
from_integer(i, index_type()), vector_type.subtype()),
595-
state.var_map.ns);
596-
assign_rec(state, guard, operands[i], new_rhs);
603+
for(std::size_t i=0; i<operands.size(); i++)
604+
{
605+
exprt new_rhs=
606+
ssa_rhs.is_nil()?ssa_rhs:
607+
simplify_expr(
608+
index_exprt(
609+
ssa_rhs,
610+
from_integer(i, index_type()),
611+
array_type.subtype()),
612+
state.var_map.ns);
613+
assign_rec(state, guard, operands[i], new_rhs);
614+
}
597615
}
598616
}
599617
else if(ssa_lhs.id()==ID_string_constant ||

src/path-symex/path_symex_state.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,6 @@ path_symex_statet initial_state(
4141
return s;
4242
}
4343

44-
loc_reft path_symex_statet::get_pc() const
45-
{
46-
assert(current_thread<threads.size());
47-
return threads[current_thread].pc;
48-
}
49-
5044
void path_symex_statet::output(const threadt &thread, std::ostream &out) const
5145
{
5246
out << " PC: " << thread.pc << '\n';

src/path-symex/path_symex_state.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Author: Daniel Kroening, [email protected]
1212
#ifndef CPROVER_PATH_SYMEX_PATH_SYMEX_STATE_H
1313
#define CPROVER_PATH_SYMEX_PATH_SYMEX_STATE_H
1414

15+
#include <util/invariant.h>
16+
1517
#include "locs.h"
1618
#include "var_map.h"
1719
#include "path_symex_history.h"
@@ -111,11 +113,9 @@ struct path_symex_statet
111113
current_thread=_thread;
112114
}
113115

114-
loc_reft get_pc() const;
115-
116116
goto_programt::const_targett get_instruction() const
117117
{
118-
return locs[get_pc()].target;
118+
return locs[pc()].target;
119119
}
120120

121121
bool is_executable() const
@@ -145,6 +145,7 @@ struct path_symex_statet
145145

146146
loc_reft pc() const
147147
{
148+
PRECONDITION(current_thread<threads.size());
148149
return threads[current_thread].pc;
149150
}
150151

src/path-symex/path_symex_state_read.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,14 @@ exprt path_symex_statet::instantiate_rec(
247247
{
248248
irep_idt id="symex::nondet"+std::to_string(var_map.nondet_count);
249249
var_map.nondet_count++;
250-
return symbol_exprt(id, src.type());
250+
251+
auxiliary_symbolt nondet_symbol;
252+
nondet_symbol.name=id;
253+
nondet_symbol.base_name=id;
254+
nondet_symbol.type=src.type();
255+
var_map.new_symbols.add(nondet_symbol);
256+
257+
return nondet_symbol.symbol_expr();
251258
}
252259
else
253260
throw "instantiate_rec: unexpected side effect "+id2string(statement);

src/path-symex/var_map.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,17 @@ Author: Daniel Kroening, [email protected]
1818
#include <util/namespace.h>
1919
#include <util/type.h>
2020
#include <util/std_expr.h>
21+
#include <util/symbol_table.h>
2122

2223
class var_mapt
2324
{
2425
public:
2526
explicit var_mapt(const namespacet &_ns):
26-
ns(_ns), shared_count(0), local_count(0), nondet_count(0), dynamic_count(0)
27+
ns(_ns.get_symbol_table(), new_symbols),
28+
shared_count(0),
29+
local_count(0),
30+
nondet_count(0),
31+
dynamic_count(0)
2732
{
2833
}
2934

@@ -93,7 +98,8 @@ class var_mapt
9398

9499
void init(var_infot &var_info);
95100

96-
const namespacet &ns;
101+
const namespacet ns;
102+
symbol_tablet new_symbols;
97103

98104
void output(std::ostream &) const;
99105

src/symex/path_search.cpp

+70-11
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ path_searcht::resultt path_searcht::operator()(
6868
statet &state=tmp_queue.front();
6969

7070
// record we have seen it
71-
loc_data[state.get_pc().loc_number].visited=true;
71+
loc_data[state.pc().loc_number].visited=true;
7272

73-
debug() << "Loc: #" << state.get_pc().loc_number
73+
debug() << "Loc: #" << state.pc().loc_number
7474
<< ", queue: " << queue.size()
7575
<< ", depth: " << state.get_depth();
7676
for(const auto &s : queue)
@@ -102,10 +102,13 @@ path_searcht::resultt path_searcht::operator()(
102102

103103
if(number_of_steps%1000==0)
104104
{
105+
time_periodt running_time=current_time()-start_time;
105106
status() << "Queue " << queue.size()
106-
<< " thread " << state.get_current_thread()
107+
<< " thread " << state.get_current_thread()+1
107108
<< '/' << state.threads.size()
108-
<< " PC " << state.pc() << messaget::eom;
109+
<< " PC " << state.pc()
110+
<< " [" << number_of_steps << " steps, "
111+
<< running_time << "s]" << messaget::eom;
109112
}
110113

111114
// an error, possibly?
@@ -264,34 +267,90 @@ bool path_searcht::drop_state(const statet &state)
264267
{
265268
goto_programt::const_targett pc=state.get_instruction();
266269

270+
const source_locationt &source_location=pc->source_location;
271+
272+
if(!source_location.is_nil() &&
273+
last_source_location!=source_location)
274+
{
275+
debug() << "SYMEX at file " << source_location.get_file()
276+
<< " line " << source_location.get_line()
277+
<< " function " << source_location.get_function()
278+
<< eom;
279+
280+
last_source_location=source_location;
281+
}
282+
267283
// depth limit
268-
if(depth_limit_set && state.get_depth()>depth_limit)
284+
if(depth_limit>=0 && state.get_depth()>depth_limit)
269285
return true;
270286

271287
// context bound
272-
if(context_bound_set && state.get_no_thread_interleavings()>context_bound)
288+
if(context_bound>=0 && state.get_no_thread_interleavings()>context_bound)
273289
return true;
274290

275291
// branch bound
276-
if(branch_bound_set && state.get_no_branches()>branch_bound)
292+
if(branch_bound>=0 && state.get_no_branches()>branch_bound)
277293
return true;
278294

279295
// unwinding limit -- loops
280-
if(unwind_limit_set && state.get_instruction()->is_backwards_goto())
296+
if(unwind_limit>=0 && pc->is_backwards_goto())
281297
{
298+
bool stop=false;
299+
282300
for(const auto &loop_info : state.unwinding_map)
283301
if(loop_info.second>unwind_limit)
284-
return true;
302+
{
303+
stop=true;
304+
break;
305+
}
306+
307+
const irep_idt id=goto_programt::loop_id(pc);
308+
path_symex_statet::unwinding_mapt::const_iterator entry=
309+
state.unwinding_map.find(state.pc());
310+
debug() << (stop?"Not unwinding":"Unwinding")
311+
<< " loop " << id << " iteration "
312+
<< (entry==state.unwinding_map.end()?-1:entry->second)
313+
<< " (" << unwind_limit << " max)"
314+
<< " " << source_location
315+
<< " thread " << state.get_current_thread() << eom;
316+
317+
if(stop)
318+
return true;
285319
}
286320

287321
// unwinding limit -- recursion
288-
if(unwind_limit_set && state.get_instruction()->is_function_call())
322+
if(unwind_limit>=0 && pc->is_function_call())
289323
{
324+
bool stop=false;
325+
290326
for(const auto &rec_info : state.recursion_map)
291327
if(rec_info.second>unwind_limit)
292-
return true;
328+
{
329+
stop=true;
330+
break;
331+
}
332+
333+
exprt function=to_code_function_call(pc->code).function();
334+
const irep_idt id=function.get(ID_identifier); // could be nil
335+
path_symex_statet::recursion_mapt::const_iterator entry=
336+
state.recursion_map.find(id);
337+
if(entry!=state.recursion_map.end())
338+
debug() << (stop?"Not unwinding":"Unwinding")
339+
<< " recursion " << id << " iteration "
340+
<< entry->second
341+
<< " (" << unwind_limit << " max)"
342+
<< " " << source_location
343+
<< " thread " << state.get_current_thread() << eom;
344+
345+
if(stop)
346+
return true;
293347
}
294348

349+
// search time limit (--max-search-time)
350+
if(time_limit>=0 &&
351+
current_time().get_t()>start_time.get_t()+time_limit*1000)
352+
return true;
353+
295354
if(pc->is_assume() &&
296355
simplify_expr(pc->guard, ns).is_false())
297356
{

0 commit comments

Comments
 (0)