Skip to content

Commit 4985554

Browse files
committed
Symex: expose call stack to unwinding decision making
This enables unwind handlers to use the calling context to decide when to unwind a particular loop, the first use case being generic array clone methods called from enumeration type methods with known bounds.
1 parent 7c066f9 commit 4985554

File tree

5 files changed

+16
-11
lines changed

5 files changed

+16
-11
lines changed

jbmc/src/jbmc/jbmc_parse_options.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,12 +480,12 @@ int jbmc_parse_optionst::doit()
480480
configure_bmc = [](bmct &bmc, const symbol_tablet &symbol_table) {
481481
bmc.add_loop_unwind_handler(
482482
[&symbol_table](
483-
const irep_idt &function_id,
483+
const goto_symex_statet::call_stackt &context,
484484
unsigned loop_number,
485485
unsigned unwind,
486486
unsigned &max_unwind) {
487487
return java_enum_static_init_unwind_handler(
488-
function_id,
488+
context,
489489
loop_number,
490490
unwind,
491491
max_unwind,

src/cbmc/symex_bmc.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ void symex_bmct::merge_goto(
106106

107107
bool symex_bmct::get_unwind(
108108
const symex_targett::sourcet &source,
109+
const goto_symex_statet::call_stackt &context,
109110
unsigned unwind)
110111
{
111112
const irep_idt id=goto_programt::loop_id(*source.pc);
@@ -117,7 +118,7 @@ bool symex_bmct::get_unwind(
117118
{
118119
abort_unwind_decision =
119120
handler(
120-
source.pc->function,
121+
context,
121122
source.pc->loop_number,
122123
unwind,
123124
this_loop_limit);

src/cbmc/symex_bmc.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ class symex_bmct: public goto_symext
3535
// To show progress
3636
source_locationt last_source_location;
3737

38-
/// Loop unwind handlers take the function ID and loop number, the unwind
39-
/// count so far, and an out-parameter specifying an advisory maximum, which
40-
/// they may set. If set the advisory maximum is set it is *only* used to
41-
/// print useful information for the user (e.g. "unwinding iteration N, max
42-
/// M"), and is not enforced. They return true to halt unwinding, false to
43-
/// authorise unwinding, or Unknown to indicate they have no opinion.
38+
/// Loop unwind handlers take the call stack, loop number, the unwind count so
39+
/// far, and an out-parameter specifying an advisory maximum, which they may
40+
/// set. If set the advisory maximum is set it is *only* used to print useful
41+
/// information for the user (e.g. "unwinding iteration N, max M"), and is not
42+
/// enforced. They return true to halt unwinding, false to authorise
43+
/// unwinding, or Unknown to indicate they have no opinion.
4444
typedef
45-
std::function<tvt(const irep_idt &, unsigned, unsigned, unsigned &)>
45+
std::function<tvt(
46+
const goto_symex_statet::call_stackt &, unsigned, unsigned, unsigned &)>
4647
loop_unwind_handlert;
4748

4849
/// Recursion unwind handlers take the function ID, the unwind count so far,
@@ -105,6 +106,7 @@ class symex_bmct: public goto_symext
105106
// for loop unwinding
106107
virtual bool get_unwind(
107108
const symex_targett::sourcet &source,
109+
const goto_symex_statet::call_stackt &context,
108110
unsigned unwind);
109111

110112
virtual bool get_unwind_recursion(

src/goto-symex/goto_symex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ class goto_symext
328328
// with false we continue.
329329
virtual bool get_unwind(
330330
const symex_targett::sourcet &source,
331+
const goto_symex_statet::call_stackt &context,
331332
unsigned unwind);
332333

333334
virtual void loop_bound_exceeded(statet &, const exprt &guard);

src/goto-symex/symex_goto.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void goto_symext::symex_goto(statet &state)
8686
unwind++;
8787

8888
// continue unwinding?
89-
if(get_unwind(state.source, unwind))
89+
if(get_unwind(state.source, state.call_stack(), unwind))
9090
{
9191
// no!
9292
loop_bound_exceeded(state, new_guard);
@@ -540,6 +540,7 @@ void goto_symext::loop_bound_exceeded(
540540

541541
bool goto_symext::get_unwind(
542542
const symex_targett::sourcet &source,
543+
const goto_symex_statet::call_stackt &context,
543544
unsigned unwind)
544545
{
545546
// by default, we keep going

0 commit comments

Comments
 (0)