-
Notifications
You must be signed in to change notification settings - Fork 273
Field sensitive goto-symex #2574
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
Conversation
+1 #doeswant |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some initial comments
src/goto-symex/field_sensitivity.cpp
Outdated
Forall_operands(it, expr) | ||
operator()(ns, *it, write); | ||
|
||
if(expr.id()==ID_symbol && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_ssa_expr
src/goto-symex/field_sensitivity.cpp
Outdated
bool write) const | ||
{ | ||
#if 1 | ||
if(expr.id()!=ID_address_of) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment here why address-of is special?
src/goto-symex/field_sensitivity.cpp
Outdated
{ | ||
member_exprt &member=to_member_expr(expr); | ||
|
||
if(member.struct_op().id()==ID_symbol && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_ssa_expr
src/goto-symex/field_sensitivity.cpp
Outdated
|
||
member.struct_op()=tmp.get_original_expr(); | ||
|
||
tmp.type()=member.type(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does tmp
retain any aspect of the original struct-op here?
src/goto-symex/field_sensitivity.cpp
Outdated
++it, ++number) | ||
{ | ||
member_exprt member_rhs(lhs, it->get_name(), it->type()); | ||
exprt member_lhs=lhs_fs.operands()[number]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const ref
src/goto-symex/field_sensitivity.cpp
Outdated
for(unsigned i=0; i<array_size_u; ++i) | ||
{ | ||
index_rhs.index()=from_integer(i, index_type()); | ||
exprt index_lhs=lhs_fs.operands()[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const ref
src/goto-symex/field_sensitivity.cpp
Outdated
field_assignments_rec(ns, state, target, member_lhs, member_rhs); | ||
} | ||
} | ||
else if(followed_type.id()==ID_array) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth retaining the ability to represent a whole-array assignment compactly? String constants are the main thing that springs to mind -- then break it down into smaller pieces once the program starts making individual array cell assignments?
src/goto-symex/symex_assign.cpp
Outdated
@@ -227,11 +227,117 @@ void goto_symext::symex_assign_symbol( | |||
tmp_ssa_rhs.swap(ssa_rhs); | |||
} | |||
|
|||
state.field_sensitivity(ns, ssa_rhs, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unclear whether this does anything or just accrues state -- give the function name a verb
src/goto-symex/field_sensitivity.cpp
Outdated
|
||
Purpose: | ||
|
||
\*******************************************************************/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doxygen (entire PR)
src/goto-symex/field_sensitivity.cpp
Outdated
dest=struct_exprt(ssa_expr.type()); | ||
dest.reserve_operands(components.size()); | ||
|
||
for(struct_union_typet::componentst::const_iterator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ranged for (entire PR)
src/goto-symex/field_sensitivity.cpp
Outdated
const struct_union_typet::componentst &components= | ||
type.components(); | ||
|
||
assert(components.empty() || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
INVARIANT (entire PR)
src/goto-symex/field_sensitivity.cpp
Outdated
(lhs_fs.has_operands() && | ||
lhs_fs.operands().size()==components.size())); | ||
|
||
unsigned number=0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
size_t
src/goto-symex/field_sensitivity.cpp
Outdated
for(exprt::operandst::const_iterator it=lhs.operands().begin(); | ||
it!=lhs.operands().end(); | ||
++it, ++fs_it) | ||
field_assignments_rec(ns, state, target, *fs_it, *it); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
braces
src/goto-symex/field_sensitivity.cpp
Outdated
mp_integer array_size; | ||
if(to_integer(type.size(), array_size)) | ||
assert(false); | ||
unsigned array_size_u=integer2unsigned(array_size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
size_t?
src/goto-symex/field_sensitivity.cpp
Outdated
exprt &expr, | ||
bool write) const | ||
{ | ||
#if 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we have command line options to turn on/off field-sensitivity for structs/arrays to make it easier to perform experiments with it?
src/goto-symex/symex_assign.cpp
Outdated
} | ||
#endif | ||
|
||
std::cerr << from_expr(ns, "", ssa_rhs) << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deactivate debug output
^EXIT=0$ | ||
^SIGNAL=0$ | ||
^VERIFICATION SUCCESSFUL$ | ||
\(Starting CEGAR Loop\|VCC(s), 0 remaining after simplification$\) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the CEGAR Loop
here? ^^
src/goto-symex/symex_assign.cpp
Outdated
@@ -234,6 +234,50 @@ void goto_symext::symex_assign_symbol( | |||
|
|||
ssa_exprt lhs_mod=lhs; | |||
|
|||
if(ssa_rhs.id()==ID_byte_update_little_endian || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a test that triggers this case?
ad814f9
to
d5b7a9b
Compare
src/goto-symex/symex_assign.cpp
Outdated
lhs_mod = to_ssa_expr(fs_lhs); | ||
} | ||
#endif | ||
|
||
do_simplify(ssa_rhs); | ||
|
||
ssa_exprt ssa_lhs=lhs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ssa_exprt ssa_lhs=lhs; | |
ssa_exprt ssa_lhs = lhs_mod; |
This makes regression/cbmc/Anonymous_Struct2 pass, and a few others.
src/goto-symex/field_sensitivity.h
Outdated
/// \param ns: a namespace to resolve type symbols/tag types | ||
/// \param state: symbolic execution state | ||
/// \param target: symbolic execution equation store | ||
/// \param lhs_f: expanded symbol |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lhs_fs
src/goto-symex/goto_symex_state.cpp
Outdated
@@ -453,6 +458,10 @@ bool goto_symex_statet::l2_thread_read_encoding( | |||
(!ns.lookup(obj_identifier).is_shared() && !(dirty)(obj_identifier))) | |||
return false; | |||
|
|||
// is it an indivisible object being accessed? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment here on why in that case the rest of this function is inapplicable
d5b7a9b
to
0bfb212
Compare
0bfb212
to
705eaeb
Compare
2b6ea5c
to
04ad940
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've only partially reviewed the first commit and I think it should be split into several commits.
Ensure ssa_expr's l1-identifier is consistent with its identifier [blocks: #2574]
7f16d25
to
4c23625
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR failed Diffblue compatibility checks (cbmc commit: 7f16d25).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/107604152
Status will be re-evaluated on next push.
Common spurious failures include: the cbmc commit has disappeared in the mean time (e.g. in a force-push); the author is not in the list of contributors (e.g. first-time contributors); compatibility was already broken by an earlier merge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR failed Diffblue compatibility checks (cbmc commit: 4c23625).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/107608202
Status will be re-evaluated on next push.
Common spurious failures include: the cbmc commit has disappeared in the mean time (e.g. in a force-push); the author is not in the list of contributors (e.g. first-time contributors); compatibility was already broken by an earlier merge.
4c23625
to
092d8fb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: 092d8fb).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/107795688
092d8fb
to
63936ad
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: 5b86aba).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/108113827
5b86aba
to
098c0cb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: 098c0cb).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/108161278
098c0cb
to
9329cc2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: 9329cc2).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/108198940
9329cc2
to
5dd0b3a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: 5dd0b3a).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/108226499
field_sensitivity::apply needs to avoid expanding struct-typed symbols into fields when they're being used as lvalues.
Struct member and array index expressions are replaced by new SSA symbols such that updates to individual fields of structs or arrays do not affect the SSA index of the remaining object. This enables more fine-grained constant propagation, which should be particularly beneficial to Java (where structs/classes prevail).
The Array_Propagation1 test is no longer solved during symex in this case.
This makes it easier to read the difference between an atomic symbol and a field of a composite.
Previously this could turn e.g. struct@x#y into struct.field@x#y, regardless of whether the L2 generation #y for that field existed or not. This meant that when an L2 name was passed through field-sensitivity expansion it could end up referring to an unbound symbol, whereas an L1 name would remain coherent (e.g. struct@x -> struct.field@x), later being renamed using the ordinary level2_names map. That means the generation numbers for structs and their fields may get out of sync, but that should be harmless so long as "latest generation" is used consistently. We can now also remove constant propagator lookup after applying field sensitivity, because field_sensitivity::apply uses state.rename to apply L2 renaming, which itself consults the constant propagator. Also make is_divisible test cheaper, at the expense that synchronisation with get_fields needs to be maintained manually.
This is because a pointer into the middle of a struct can resolve into something like &struct.field, in which case we need to rewrite that as the field-sensitive SSA symbol before any further dereferencing.
…updated Otherwise e.g. in "memset2" we had the whole object being initialised with "{0, 0}" (which is stored in const prop and then expanded to individual fields), then later any operation that needed the whole-struct representation (such as the memset-of-one-field in that test, which expanded to "whole_struct = byte_update(whole_struct, offset, int, 0)") would get the whole-struct definition stored in const-prop, disregarding any intermediate updates that were able to directly reference a single field. This avoids having two different versions of a symbol (the field-of-composite and the indivisible field versions) in the most direct way possible.
…mations The function name was previously incorrect (it did more than it said), so now I just call both transformations from symex_assign.
Otherwise while everything works correctly for the state, the target sees the field expansions before the composite definition, which is a problem if the values are non-constant and so the expansion RHSes refer to the composite!
…s already L2 For an L1 or lower expression, get_fields already recursed, e.g. to turn `x` -> `{ { x..a..g, x..a..h }, x..b }` rather than `{ x..a, a..b }` when its `a` member is itself struct-typed. However this recursion was omitted in the case where the input expression is already L2 renamed.
5dd0b3a
to
8cd443c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: 8cd443c).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/108538361
This is the rebased version of an old patch collection. It's likely broken at present, but should be a starting point for discussing and evaluating this.@smowton Has put a lot of work into this, and this PR now reflects our combined effort. It is now ready for review.