Skip to content

Regularise the style and division of responsibilities in symex dispatch #4309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/goto-symex/goto_symex.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,14 @@ class goto_symext
virtual void symex_dead(statet &);
virtual void symex_other(statet &);

void symex_assert(const goto_programt::instructiont &, statet &);
virtual void vcc(
const exprt &,
const std::string &msg,
statet &);

virtual void symex_assume(statet &, const exprt &cond);
void symex_assume_l2(statet &, const exprt &cond);

// gotos
void merge_gotos(statet &);
Expand Down
13 changes: 11 additions & 2 deletions src/goto-symex/symex_function_call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,18 @@ void goto_symext::symex_function_call(
void goto_symext::symex_function_call_symbol(
const get_goto_functiont &get_goto_function,
statet &state,
const code_function_callt &code)
const code_function_callt &original_code)
{
code_function_callt code = original_code;

if(code.lhs().is_not_nil())
clean_expr(code.lhs(), state, true);

clean_expr(code.function(), state, false);

Forall_expr(it, code.arguments())
clean_expr(*it, state, false);

target.location(state.guard.as_expr(), state.source);

PRECONDITION(code.function().id() == ID_symbol);
Expand Down Expand Up @@ -437,4 +447,3 @@ static void locality(
state.l1_history.insert(l1_name);
}
}

20 changes: 7 additions & 13 deletions src/goto-symex/symex_goto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ void goto_symext::symex_goto(statet &state)
const goto_programt::instructiont &instruction=*state.source.pc;
framet &frame = state.top();

if(state.guard.is_false())
{
// next instruction
symex_transition(state);
return; // nothing to do
}

exprt new_guard = instruction.get_condition();
clean_expr(new_guard, state, false);

Expand Down Expand Up @@ -75,9 +68,9 @@ void goto_symext::symex_goto(statet &state)
// generate assume(false) or a suitable negation if this
// instruction is a conditional goto
if(new_guard.is_true())
symex_assume(state, false_exprt());
symex_assume_l2(state, false_exprt());
else
symex_assume(state, not_exprt(new_guard));
symex_assume_l2(state, not_exprt(new_guard));

// next instruction
symex_transition(state);
Expand Down Expand Up @@ -559,17 +552,18 @@ void goto_symext::loop_bound_exceeded(
if(symex_config.unwinding_assertions)
{
// Generate VCC for unwinding assertion.
vcc(negated_cond,
"unwinding assertion loop "+std::to_string(loop_number),
state);
vcc(
negated_cond,
"unwinding assertion loop " + std::to_string(loop_number),
state);

// add to state guard to prevent further assignments
state.guard.add(negated_cond);
}
else
{
// generate unwinding assumption, unless we permit partial loops
symex_assume(state, negated_cond);
symex_assume_l2(state, negated_cond);
}
}
}
Expand Down
93 changes: 46 additions & 47 deletions src/goto-symex/symex_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,51 +76,71 @@ void symex_transition(goto_symext::statet &state)
symex_transition(state, next, false);
}

void goto_symext::vcc(
const exprt &vcc_expr,
const std::string &msg,
void goto_symext::symex_assert(
const goto_programt::instructiont &instruction,
statet &state)
{
state.total_vccs++;
path_segment_vccs++;

exprt expr=vcc_expr;
exprt condition = instruction.get_condition();
clean_expr(condition, state, false);

// we are willing to re-write some quantified expressions
if(has_subexpr(expr, ID_exists) || has_subexpr(expr, ID_forall))
if(has_subexpr(condition, ID_exists) || has_subexpr(condition, ID_forall))
{
// have negation pushed inwards as far as possible
do_simplify(expr);
rewrite_quantifiers(expr, state);
do_simplify(condition);
rewrite_quantifiers(condition, state);
}

// now rename, enables propagation
exprt l2_expr = state.rename(std::move(expr), ns);
exprt l2_condition = state.rename(std::move(condition), ns);

// now try simplifier on it
do_simplify(l2_expr);
do_simplify(l2_condition);

if(l2_expr.is_true())
std::string msg = id2string(instruction.source_location.get_comment());
if(msg == "")
msg = "assertion";

vcc(l2_condition, msg, state);
}

void goto_symext::vcc(
const exprt &condition,
const std::string &msg,
statet &state)
{
state.total_vccs++;
path_segment_vccs++;

if(condition.is_true())
return;

state.guard.guard_expr(l2_expr);
exprt guarded_condition = condition;
state.guard.guard_expr(guarded_condition);

state.remaining_vccs++;
target.assertion(state.guard.as_expr(), l2_expr, msg, state.source);
target.assertion(state.guard.as_expr(), guarded_condition, msg, state.source);
}

void goto_symext::symex_assume(statet &state, const exprt &cond)
{
exprt simplified_cond=cond;

clean_expr(simplified_cond, state, false);
simplified_cond = state.rename(std::move(simplified_cond), ns);
do_simplify(simplified_cond);

if(simplified_cond.is_true())
symex_assume_l2(state, simplified_cond);
}

void goto_symext::symex_assume_l2(statet &state, const exprt &cond)
{
if(cond.is_true())
return;

if(state.threads.size()==1)
{
exprt tmp=simplified_cond;
exprt tmp = cond;
state.guard.guard_expr(tmp);
target.assumption(state.guard.as_expr(), tmp, state.source);
}
Expand All @@ -131,7 +151,7 @@ void goto_symext::symex_assume(statet &state, const exprt &cond)
// x=0; assume(x==1);
// assert(x!=42); x=42;
else
state.guard.add(simplified_cond);
state.guard.add(cond);

if(state.atomic_section_id!=0 &&
state.guard.is_false())
Expand Down Expand Up @@ -402,31 +422,21 @@ void goto_symext::symex_step(
break;

case GOTO:
symex_goto(state);
if(!state.guard.is_false())
symex_goto(state);
else
symex_transition(state);
break;

case ASSUME:
if(!state.guard.is_false())
{
exprt tmp = instruction.get_condition();
clean_expr(tmp, state, false);
symex_assume(state, state.rename(std::move(tmp), ns));
}

symex_assume(state, instruction.get_condition());
symex_transition(state);
break;

case ASSERT:
if(!state.guard.is_false())
{
std::string msg=id2string(state.source.pc->source_location.get_comment());
if(msg=="")
msg="assertion";
exprt tmp(instruction.get_condition());
clean_expr(tmp, state, false);
vcc(tmp, msg, state);
}

symex_assert(instruction, state);
symex_transition(state);
break;

Expand All @@ -445,17 +455,8 @@ void goto_symext::symex_step(
case FUNCTION_CALL:
if(!state.guard.is_false())
{
code_function_callt deref_code = instruction.get_function_call();

if(deref_code.lhs().is_not_nil())
clean_expr(deref_code.lhs(), state, true);

clean_expr(deref_code.function(), state, false);

Forall_expr(it, deref_code.arguments())
clean_expr(*it, state, false);

symex_function_call(get_goto_function, state, deref_code);
symex_function_call(
get_goto_function, state, instruction.get_function_call());
}
else
symex_transition(state);
Expand All @@ -464,14 +465,12 @@ void goto_symext::symex_step(
case OTHER:
if(!state.guard.is_false())
symex_other(state);

symex_transition(state);
break;

case DECL:
if(!state.guard.is_false())
symex_decl(state);

symex_transition(state);
break;

Expand Down
2 changes: 1 addition & 1 deletion src/goto-symex/symex_throw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ void goto_symext::symex_throw(statet &state)
#endif

// An un-caught exception. Behaves like assume(0);
symex_assume(state, false_exprt());
symex_assume_l2(state, false_exprt());
}