diff --git a/src/goto-symex/goto_symex.h b/src/goto-symex/goto_symex.h
index 096c4766377..5535791e0aa 100644
--- a/src/goto-symex/goto_symex.h
+++ b/src/goto-symex/goto_symex.h
@@ -80,6 +80,40 @@ class goto_symext
const goto_functionst &goto_functions,
const goto_programt &goto_program);
+ /// Symexes from the first instruction and the given state, terminating as
+ /// soon as the last instruction is reached. This is useful to explicitly
+ /// symex certain ranges of a program, e.g. in an incremental decision
+ /// procedure.
+ /// \param state Symex state to start with.
+ /// \param goto_functions GOTO model to symex.
+ /// \param first Entry point in form of a first instruction.
+ /// \param limit Final instruction, which itself will not be symexed.
+ virtual void operator()(
+ statet &state,
+ const goto_functionst &goto_functions,
+ goto_programt::const_targett first,
+ goto_programt::const_targett limit);
+
+ /// Initialise the symbolic execution and the given state with pc
+ /// as entry point.
+ /// \param state Symex state to initialise.
+ /// \param goto_functions GOTO model to symex.
+ /// \param pc first instruction to symex
+ /// \param limit final instruction, which itself will not
+ /// be symexed.
+ void symex_entry_point(
+ statet &state,
+ const goto_functionst &goto_functions,
+ goto_programt::const_targett pc,
+ goto_programt::const_targett limit);
+
+ /// Invokes symex_step and verifies whether additional threads can be
+ /// executed.
+ /// \param state Current GOTO symex step.
+ /// \param goto_functions GOTO model to symex.
+ void symex_threaded_step(
+ statet &state, const goto_functionst &goto_functions);
+
/** execute just one step */
virtual void symex_step(
const goto_functionst &goto_functions,
diff --git a/src/goto-symex/symex_main.cpp b/src/goto-symex/symex_main.cpp
index 3deef4ae22c..787775c23a0 100644
--- a/src/goto-symex/symex_main.cpp
+++ b/src/goto-symex/symex_main.cpp
@@ -114,8 +114,8 @@ void goto_symext::rewrite_quantifiers(exprt &expr, statet &state)
{
// forall X. P -> P
// we keep the quantified variable unique by means of L2 renaming
- assert(expr.operands().size()==2);
- assert(expr.op0().id()==ID_symbol);
+ PRECONDITION(expr.operands().size()==2);
+ PRECONDITION(expr.op0().id()==ID_symbol);
symbol_exprt tmp0=
to_symbol_expr(to_ssa_expr(expr.op0()).get_original_expr());
symex_decl(state, tmp0);
@@ -124,44 +124,72 @@ void goto_symext::rewrite_quantifiers(exprt &expr, statet &state)
}
}
-/// symex from given state
-void goto_symext::operator()(
+void goto_symext::symex_entry_point(
statet &state,
const goto_functionst &goto_functions,
- const goto_programt &goto_program)
+ const goto_programt::const_targett pc,
+ const goto_programt::const_targett limit)
{
- assert(!goto_program.instructions.empty());
-
- state.source=symex_targett::sourcet(goto_program);
- assert(!state.threads.empty());
- assert(!state.call_stack().empty());
- state.top().end_of_function=--goto_program.instructions.end();
+ PRECONDITION(!state.threads.empty());
+ PRECONDITION(!state.call_stack().empty());
+ state.source=symex_targett::sourcet(pc);
+ state.top().end_of_function=limit;
state.top().calling_location.pc=state.top().end_of_function;
state.symex_target=⌖
state.dirty=util_make_unique(goto_functions);
symex_transition(state, state.source.pc);
+}
- assert(state.top().end_of_function->is_end_function());
+void goto_symext::symex_threaded_step(
+ statet &state, const goto_functionst &goto_functions)
+{
+ symex_step(goto_functions, state);
- while(!state.call_stack().empty())
+ // is there another thread to execute?
+ if(state.call_stack().empty() &&
+ state.source.thread_nr+1is_end_function());
+
+ while(!state.call_stack().empty())
+ symex_threaded_step(state, goto_functions);
state.dirty=nullptr;
}
+void goto_symext::operator()(
+ statet &state,
+ const goto_functionst &goto_functions,
+ const goto_programt::const_targett first,
+ const goto_programt::const_targett limit)
+{
+ symex_entry_point(state, goto_functions, first, limit);
+ while(state.source.pc->function!=limit->function || state.source.pc!=limit)
+ symex_threaded_step(state, goto_functions);
+}
+
/// symex starting from given program
void goto_symext::operator()(
const goto_functionst &goto_functions,
@@ -197,8 +225,8 @@ void goto_symext::symex_step(
std::cout << "Code: " << from_expr(ns, "", state.source.pc->code) << '\n';
#endif
- assert(!state.threads.empty());
- assert(!state.call_stack().empty());
+ PRECONDITION(!state.threads.empty());
+ PRECONDITION(!state.call_stack().empty());
const goto_programt::instructiont &instruction=*state.source.pc;