Skip to content

Commit 8b1f65e

Browse files
pkesselipolgreen
authored andcommitted
Added range-based symex operations
Extended goto_symext with range-based instructions which allow terminating the symex process not at an empty call stack, but instead once a given instruction is reached.
1 parent 1a33c87 commit 8b1f65e

File tree

2 files changed

+88
-26
lines changed

2 files changed

+88
-26
lines changed

src/goto-symex/goto_symex.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,40 @@ class goto_symext
8080
const goto_functionst &goto_functions,
8181
const goto_programt &goto_program);
8282

83+
/// Symexes from the first instruction and the given state, terminating as
84+
/// soon as the last instruction is reached. This is useful to explicitly
85+
/// symex certain ranges of a program, e.g. in an incremental decision
86+
/// procedure.
87+
/// \param state Symex state to start with.
88+
/// \param goto_functions GOTO model to symex.
89+
/// \param first Entry point in form of a first instruction.
90+
/// \param limit Final instruction, which itself will not be symexed.
91+
virtual void operator()(
92+
statet &state,
93+
const goto_functionst &goto_functions,
94+
goto_programt::const_targett first,
95+
goto_programt::const_targett limit);
96+
97+
/// Initialise the symbolic execution and the given state with <code>pc</code>
98+
/// as entry point.
99+
/// \param state Symex state to initialise.
100+
/// \param goto_functions GOTO model to symex.
101+
/// \param pc first instruction to symex
102+
/// \param limit final instruction, which itself will not
103+
/// be symexed.
104+
void symex_entry_point(
105+
statet &state,
106+
const goto_functionst &goto_functions,
107+
goto_programt::const_targett pc,
108+
goto_programt::const_targett limit);
109+
110+
/// Invokes symex_step and verifies whether additional threads can be
111+
/// executed.
112+
/// \param state Current GOTO symex step.
113+
/// \param goto_functions GOTO model to symex.
114+
void symex_threaded_step(
115+
statet &state, const goto_functionst &goto_functions);
116+
83117
/** execute just one step */
84118
virtual void symex_step(
85119
const goto_functionst &goto_functions,

src/goto-symex/symex_main.cpp

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ void goto_symext::rewrite_quantifiers(exprt &expr, statet &state)
114114
{
115115
// forall X. P -> P
116116
// we keep the quantified variable unique by means of L2 renaming
117-
assert(expr.operands().size()==2);
118-
assert(expr.op0().id()==ID_symbol);
117+
PRECONDITION(expr.operands().size()==2);
118+
PRECONDITION(expr.op0().id()==ID_symbol);
119119
symbol_exprt tmp0=
120120
to_symbol_expr(to_ssa_expr(expr.op0()).get_original_expr());
121121
symex_decl(state, tmp0);
@@ -124,44 +124,72 @@ void goto_symext::rewrite_quantifiers(exprt &expr, statet &state)
124124
}
125125
}
126126

127-
/// symex from given state
128-
void goto_symext::operator()(
127+
void goto_symext::symex_entry_point(
129128
statet &state,
130129
const goto_functionst &goto_functions,
131-
const goto_programt &goto_program)
130+
const goto_programt::const_targett pc,
131+
const goto_programt::const_targett limit)
132132
{
133-
assert(!goto_program.instructions.empty());
134-
135-
state.source=symex_targett::sourcet(goto_program);
136-
assert(!state.threads.empty());
137-
assert(!state.call_stack().empty());
138-
state.top().end_of_function=--goto_program.instructions.end();
133+
PRECONDITION(!state.threads.empty());
134+
PRECONDITION(!state.call_stack().empty());
135+
state.source=symex_targett::sourcet(pc);
136+
state.top().end_of_function=limit;
139137
state.top().calling_location.pc=state.top().end_of_function;
140138
state.symex_target=&target;
141139
state.dirty=util_make_unique<dirtyt>(goto_functions);
142140

143141
symex_transition(state, state.source.pc);
142+
}
144143

145-
assert(state.top().end_of_function->is_end_function());
144+
void goto_symext::symex_threaded_step(
145+
statet &state, const goto_functionst &goto_functions)
146+
{
147+
symex_step(goto_functions, state);
146148

147-
while(!state.call_stack().empty())
149+
// is there another thread to execute?
150+
if(state.call_stack().empty() &&
151+
state.source.thread_nr+1<state.threads.size())
148152
{
149-
symex_step(goto_functions, state);
150-
151-
// is there another thread to execute?
152-
if(state.call_stack().empty() &&
153-
state.source.thread_nr+1<state.threads.size())
154-
{
155-
unsigned t=state.source.thread_nr+1;
156-
// std::cout << "********* Now executing thread " << t << '\n';
157-
state.switch_to_thread(t);
158-
symex_transition(state, state.source.pc);
159-
}
153+
unsigned t=state.source.thread_nr+1;
154+
#if 0
155+
std::cout << "********* Now executing thread " << t << '\n';
156+
#endif
157+
state.switch_to_thread(t);
158+
symex_transition(state, state.source.pc);
160159
}
160+
}
161+
162+
/// symex from given state
163+
void goto_symext::operator()(
164+
statet &state,
165+
const goto_functionst &goto_functions,
166+
const goto_programt &goto_program)
167+
{
168+
PRECONDITION(!goto_program.instructions.empty());
169+
symex_entry_point(
170+
state,
171+
goto_functions,
172+
goto_program.instructions.begin(),
173+
prev(goto_program.instructions.end()));
174+
PRECONDITION(state.top().end_of_function->is_end_function());
175+
176+
while(!state.call_stack().empty())
177+
symex_threaded_step(state, goto_functions);
161178

162179
state.dirty=nullptr;
163180
}
164181

182+
void goto_symext::operator()(
183+
statet &state,
184+
const goto_functionst &goto_functions,
185+
const goto_programt::const_targett first,
186+
const goto_programt::const_targett limit)
187+
{
188+
symex_entry_point(state, goto_functions, first, limit);
189+
while(state.source.pc->function!=limit->function || state.source.pc!=limit)
190+
symex_threaded_step(state, goto_functions);
191+
}
192+
165193
/// symex starting from given program
166194
void goto_symext::operator()(
167195
const goto_functionst &goto_functions,
@@ -197,8 +225,8 @@ void goto_symext::symex_step(
197225
std::cout << "Code: " << from_expr(ns, "", state.source.pc->code) << '\n';
198226
#endif
199227

200-
assert(!state.threads.empty());
201-
assert(!state.call_stack().empty());
228+
PRECONDITION(!state.threads.empty());
229+
PRECONDITION(!state.call_stack().empty());
202230

203231
const goto_programt::instructiont &instruction=*state.source.pc;
204232

0 commit comments

Comments
 (0)