Skip to content

Commit 103b87e

Browse files
Make field sensitivity max array size configurable
This will allow the user of symex to set this limit as needed instead of fixing it to an arbitrary value.
1 parent 3d681e9 commit 103b87e

14 files changed

+49
-20
lines changed

src/goto-instrument/accelerate/scratch_program.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ bool scratch_programt::check_sat(bool do_slice, guard_managert &guard_manager)
3838

3939
symex_state = util_make_unique<goto_symex_statet>(
4040
symex_targett::sourcet(goto_functionst::entry_point(), *this),
41+
symex.field_sensitivity,
4142
guard_manager,
4243
[this](const irep_idt &id) {
4344
return path_storage.get_unique_l2_index(id);

src/goto-symex/field_sensitivity.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ exprt field_sensitivityt::apply(
114114
if(
115115
l2_size.id() == ID_constant &&
116116
numeric_cast_v<mp_integer>(to_constant_expr(l2_size)) <=
117-
MAX_FIELD_SENSITIVITY_ARRAY_SIZE)
117+
max_field_sensitivity_array_size)
118118
{
119119
if(l2_index.get().id() == ID_constant)
120120
{
@@ -183,7 +183,7 @@ exprt field_sensitivityt::get_fields(
183183
to_array_type(ssa_expr.type()).size().id() == ID_constant &&
184184
numeric_cast_v<mp_integer>(
185185
to_constant_expr(to_array_type(ssa_expr.type()).size())) <=
186-
MAX_FIELD_SENSITIVITY_ARRAY_SIZE)
186+
max_field_sensitivity_array_size)
187187
{
188188
const array_typet &type = to_array_type(ssa_expr.type());
189189
const std::size_t array_size =
@@ -305,7 +305,7 @@ void field_sensitivityt::field_assignments_rec(
305305
numeric_cast_v<std::size_t>(to_constant_expr(type->size()));
306306
PRECONDITION(lhs_fs.operands().size() == array_size);
307307

308-
if(array_size > MAX_FIELD_SENSITIVITY_ARRAY_SIZE)
308+
if(array_size > max_field_sensitivity_array_size)
309309
return;
310310

311311
exprt::operandst::const_iterator fs_it = lhs_fs.operands().begin();
@@ -339,7 +339,7 @@ void field_sensitivityt::field_assignments_rec(
339339
}
340340
}
341341

342-
bool field_sensitivityt::is_divisible(const ssa_exprt &expr)
342+
bool field_sensitivityt::is_divisible(const ssa_exprt &expr) const
343343
{
344344
if(expr.type().id() == ID_struct || expr.type().id() == ID_struct_tag)
345345
return true;
@@ -349,7 +349,7 @@ bool field_sensitivityt::is_divisible(const ssa_exprt &expr)
349349
expr.type().id() == ID_array &&
350350
to_array_type(expr.type()).size().id() == ID_constant &&
351351
numeric_cast_v<mp_integer>(to_constant_expr(
352-
to_array_type(expr.type()).size())) <= MAX_FIELD_SENSITIVITY_ARRAY_SIZE)
352+
to_array_type(expr.type()).size())) <= max_field_sensitivity_array_size)
353353
{
354354
return true;
355355
}

src/goto-symex/field_sensitivity.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class symex_targett;
6262
/// When `index` is not a constant, `array[index]` is replaced by
6363
/// `{array[[0]]; array[[1]]; …index]`.
6464
/// Note that this process does not apply to arrays whose size is not constant,
65-
/// and arrays whose size exceed the bound \ref MAX_FIELD_SENSITIVITY_ARRAY_SIZE
65+
/// and arrays whose size exceed the bound \c max_field_sensitivity_array_size.
6666
/// See \ref field_sensitivityt::apply.
6767
///
6868
/// ### Symbols representing arrays
@@ -80,6 +80,13 @@ class symex_targett;
8080
class field_sensitivityt
8181
{
8282
public:
83+
/// \param max_array_size: maximum size for which field sensitivity will be
84+
/// applied to array cells
85+
field_sensitivityt(std::size_t max_array_size)
86+
: max_field_sensitivity_array_size(max_array_size)
87+
{
88+
}
89+
8390
/// Assign to the individual fields of a non-expanded symbol \p lhs. This is
8491
/// required whenever prior steps have updated the full object rather than
8592
/// individual fields, e.g., in case of assignments to an array at an unknown
@@ -133,12 +140,14 @@ class field_sensitivityt
133140
/// \param expr: the expression to evaluate
134141
/// \return False, if and only if, \p expr would be a single field-sensitive
135142
/// SSA expression.
136-
static bool is_divisible(const ssa_exprt &expr);
143+
bool is_divisible(const ssa_exprt &expr) const;
137144

138145
private:
139146
/// whether or not to invoke \ref field_sensitivityt::apply
140147
bool run_apply = true;
141148

149+
const std::size_t max_field_sensitivity_array_size;
150+
142151
void field_assignments_rec(
143152
const namespacet &ns,
144153
goto_symex_statet &state,

src/goto-symex/goto_symex.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ struct symex_configt final
7070
/// includes diagnostic information about call stack and guard size.
7171
bool show_symex_steps;
7272

73+
/// Maximum sizes for which field sensitivity will be applied to array cells
74+
std::size_t max_field_sensitivity_array_size;
75+
7376
/// \brief Construct a symex_configt using options specified in an
7477
/// \ref optionst
7578
explicit symex_configt(const optionst &options);
@@ -104,6 +107,7 @@ class goto_symext
104107
guard_managert &guard_manager)
105108
: should_pause_symex(false),
106109
symex_config(options),
110+
field_sensitivity(symex_config.max_field_sensitivity_array_size),
107111
outer_symbol_table(outer_symbol_table),
108112
ns(outer_symbol_table),
109113
guard_manager(guard_manager),
@@ -259,6 +263,9 @@ class goto_symext
259263
/// if we know the source language in use, irep_idt() otherwise.
260264
irep_idt language_mode;
261265

266+
/// Functor controling granularity of object accesses
267+
field_sensitivityt field_sensitivity;
268+
262269
protected:
263270
/// The symbol table associated with the goto-program being executed.
264271
/// This symbol table will not have objects that are dynamically created as

src/goto-symex/goto_symex_state.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ static void get_l1_name(exprt &expr);
3434

3535
goto_symex_statet::goto_symex_statet(
3636
const symex_targett::sourcet &_source,
37+
field_sensitivityt &field_sensitivity,
3738
guard_managert &manager,
3839
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider)
3940
: goto_statet(manager),
4041
source(_source),
42+
field_sensitivity(field_sensitivity),
4143
guard_manager(manager),
4244
symex_target(nullptr),
4345
record_events({true}),
@@ -370,7 +372,7 @@ bool goto_symex_statet::l2_thread_read_encoding(
370372
}
371373

372374
// only continue if an indivisible object is being accessed
373-
if(field_sensitivityt::is_divisible(expr))
375+
if(field_sensitivity.is_divisible(expr))
374376
return false;
375377

376378
const ssa_exprt ssa_l1 = remove_level_2(expr);
@@ -498,7 +500,7 @@ goto_symex_statet::write_is_shared_resultt goto_symex_statet::write_is_shared(
498500
}
499501

500502
// only continue if an indivisible object is being accessed
501-
if(field_sensitivityt::is_divisible(expr))
503+
if(field_sensitivity.is_divisible(expr))
502504
return write_is_shared_resultt::NOT_SHARED;
503505

504506
if(atomic_section_id != 0)

src/goto-symex/goto_symex_state.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class goto_symex_statet final : public goto_statet
4747
public:
4848
goto_symex_statet(
4949
const symex_targett::sourcet &,
50+
field_sensitivityt &field_sensitivity,
5051
guard_managert &manager,
5152
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider);
5253
~goto_symex_statet();
@@ -67,6 +68,9 @@ class goto_symex_statet final : public goto_statet
6768
/// for error traces even after symbolic execution has finished.
6869
symbol_tablet symbol_table;
6970

71+
/// Reference to the functor, owned by goto_symext, used for renaming.
72+
field_sensitivityt &field_sensitivity;
73+
7074
// Manager is required to be able to resize the thread vector
7175
guard_managert &guard_manager;
7276
symex_target_equationt *symex_target;
@@ -120,8 +124,6 @@ class goto_symex_statet final : public goto_statet
120124
bool record_value,
121125
bool allow_pointer_unsoundness = false);
122126

123-
field_sensitivityt field_sensitivity;
124-
125127
protected:
126128
template <levelt>
127129
void rename_address(exprt &expr, const namespacet &ns);

src/goto-symex/symex_assign.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ void symex_assignt::assign_non_struct_symbol(
204204
current_assignment_type);
205205

206206
const ssa_exprt &l1_lhs = assignment.lhs;
207-
if(field_sensitivityt::is_divisible(l1_lhs))
207+
if(state.field_sensitivity.is_divisible(l1_lhs))
208208
{
209209
// Split composite symbol lhs into its components
210210
state.field_sensitivity.field_assignments(

src/goto-symex/symex_builtin_functions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ void goto_symext::symex_printf(
394394
else
395395
{
396396
clean_expr(*va_args, state, false);
397-
*va_args = field_sensitivityt{}.apply(ns, state, *va_args, false);
397+
*va_args = field_sensitivity.apply(ns, state, *va_args, false);
398398
*va_args = state.rename(*va_args, ns).get();
399399
if(va_args->id() != ID_array)
400400
{

src/goto-symex/symex_goto.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ static void merge_names(
618618
}
619619

620620
// field sensitivity: only merge on individual fields
621-
if(field_sensitivityt::is_divisible(ssa))
621+
if(dest_state.field_sensitivity.is_divisible(ssa))
622622
return;
623623

624624
// shared variables are renamed on every access anyway, we don't need to

src/goto-symex/symex_main.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ symex_configt::symex_configt(const optionst &options)
4444
partial_loops(options.get_bool_option("partial-loops")),
4545
debug_level(unsafe_string2int(options.get_option("debug-level"))),
4646
run_validation_checks(options.get_bool_option("validate-ssa-equation")),
47-
show_symex_steps(options.get_bool_option("show-goto-symex-steps"))
47+
show_symex_steps(options.get_bool_option("show-goto-symex-steps")),
48+
max_field_sensitivity_array_size(
49+
options.get_unsigned_int_option("max-field-sensitivity-array-size"))
4850
{
4951
}
5052

@@ -347,6 +349,7 @@ std::unique_ptr<goto_symext::statet> goto_symext::initialize_entry_point_state(
347349
// create and prepare the state
348350
auto state = util_make_unique<statet>(
349351
symex_targett::sourcet(entry_point_id, start_function->body),
352+
field_sensitivity,
350353
guard_manager,
351354
[storage](const irep_idt &id) { return storage->get_unique_l2_index(id); });
352355

src/util/magic.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ constexpr std::size_t DSTRING_NUMBERS_MAX = 64;
1818

1919
/// Limit the size of arrays for which field_sensitivity gets applied.
2020
/// Necessary because large constant arrays slow-down the process.
21-
constexpr std::size_t MAX_FIELD_SENSITIVITY_ARRAY_SIZE = 64;
21+
constexpr std::size_t DEFAULT_MAX_FIELD_SENSITIVITY_ARRAY_SIZE = 64;
2222

2323
#endif

unit/goto-symex/goto_symex_state.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ SCENARIO(
3535
// Initialize goto state
3636
std::list<goto_programt::instructiont> target;
3737
symex_targett::sourcet source{"fun", target.begin()};
38+
field_sensitivityt field_sensitivity{
39+
DEFAULT_MAX_FIELD_SENSITIVITY_ARRAY_SIZE};
3840
guard_managert manager;
3941
std::size_t fresh_name_count = 1;
4042
auto fresh_name = [&fresh_name_count](const irep_idt &) {
4143
return fresh_name_count++;
4244
};
43-
goto_symex_statet state{source, manager, fresh_name};
45+
goto_symex_statet state{source, field_sensitivity, manager, fresh_name};
4446

4547
// Initialize dirty field of state
4648
incremental_dirtyt dirty;

unit/goto-symex/symex_assign.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,14 @@ SCENARIO(
4343
// Initialize goto state
4444
std::list<goto_programt::instructiont> target;
4545
symex_targett::sourcet source{"fun", target.begin()};
46+
field_sensitivityt field_sensitivity{
47+
DEFAULT_MAX_FIELD_SENSITIVITY_ARRAY_SIZE};
4648
guard_managert manager;
4749
std::size_t fresh_name_count = 1;
4850
auto fresh_name = [&fresh_name_count](const irep_idt &) {
4951
return fresh_name_count++;
5052
};
51-
goto_symex_statet state{source, manager, fresh_name};
53+
goto_symex_statet state{source, field_sensitivity, manager, fresh_name};
5254

5355
// Initialize dirty field of state
5456
incremental_dirtyt dirty;

unit/goto-symex/try_evaluate_pointer_comparisons.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@ SCENARIO(
5252
// Initialize goto state
5353
std::list<goto_programt::instructiont> target;
5454
symex_targett::sourcet source{"fun", target.begin()};
55+
field_sensitivityt field_sensitivity{
56+
DEFAULT_MAX_FIELD_SENSITIVITY_ARRAY_SIZE};
5557
guard_managert guard_manager;
5658
std::size_t count = 0;
5759
auto fresh_name = [&count](const irep_idt &) { return count++; };
58-
goto_symex_statet state{source, guard_manager, fresh_name};
60+
goto_symex_statet state{source, field_sensitivity, guard_manager, fresh_name};
5961

6062
GIVEN("A value set in which pointer symbol `ptr1` only points to `&value1`")
6163
{
@@ -246,7 +248,6 @@ SCENARIO(
246248

247249
// struct_symbol..pointer_field <- &value1
248250
{
249-
field_sensitivityt field_sensitivity;
250251
const exprt index_fs =
251252
field_sensitivity.apply(ns, state, member_l1.get(), true);
252253
value_set.assign(index_fs, address1_l1.get(), ns, false, false);

0 commit comments

Comments
 (0)