Skip to content

Commit 177173d

Browse files
committed
Symex: implement lift_lets
This executes let expressions like ordinary assignments, avoiding the need for all other components of cbmc to understand the little-used local definition expression. It also means that symex's usual constant propagator, value-set and other analyses are brought to bear on the definition just as if the front-end had used an instruction to make the definition.
1 parent fd5ef9c commit 177173d

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/goto-symex/goto_symex.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,12 @@ class goto_symext
492492

493493
typedef symex_targett::assignment_typet assignment_typet;
494494

495+
void lift_lets(statet &, exprt &, assignment_typet);
496+
void lift_let(
497+
statet &state,
498+
const let_exprt &let_expr,
499+
assignment_typet assignment_type);
500+
495501
void symex_assign_rec(
496502
statet &,
497503
const exprt &lhs,

src/goto-symex/symex_clean_expr.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414
#include <util/arith_tools.h>
1515
#include <util/byte_operators.h>
1616
#include <util/c_types.h>
17+
#include <util/expr_iterator.h>
1718
#include <util/pointer_offset_size.h>
1819
#include <util/simplify_expr.h>
1920

@@ -169,6 +170,51 @@ replace_nondet(exprt &expr, symex_nondet_generatort &build_symex_nondet)
169170
}
170171
}
171172

173+
void goto_symext::lift_let(
174+
statet &state,
175+
const let_exprt &let_expr,
176+
assignment_typet assignment_type)
177+
{
178+
exprt let_value = let_expr.value();
179+
clean_expr(let_value, state, false);
180+
let_value = state.rename(std::move(let_value), ns).get();
181+
do_simplify(let_value);
182+
183+
exprt::operandst value_assignment_guard;
184+
symex_assign_symbol(
185+
state,
186+
to_ssa_expr(state.rename<L1>(let_expr.symbol(), ns).get()),
187+
nil_exprt(),
188+
let_value,
189+
value_assignment_guard,
190+
assignment_type);
191+
}
192+
193+
void goto_symext::lift_lets(
194+
statet &state,
195+
exprt &rhs,
196+
assignment_typet assignment_type)
197+
{
198+
for(auto it = rhs.depth_begin(), itend = rhs.depth_end(); it != itend;)
199+
{
200+
if(it->id() == ID_let)
201+
{
202+
// Visit post-order, so more-local definitions are made before usage:
203+
exprt &replaced_expr = it.mutate();
204+
let_exprt &replaced_let = to_let_expr(replaced_expr);
205+
lift_lets(state, replaced_let.value(), assignment_type);
206+
lift_lets(state, replaced_let.where(), assignment_type);
207+
208+
lift_let(state, replaced_let, assignment_type);
209+
replaced_expr = replaced_let.where();
210+
211+
it.next_sibling_or_parent();
212+
}
213+
else
214+
++it;
215+
}
216+
}
217+
172218
void goto_symext::clean_expr(
173219
exprt &expr,
174220
statet &state,

0 commit comments

Comments
 (0)