Skip to content

Commit 9b9f1e2

Browse files
committed
Value-set supported simplifier: add object_size, is_invalid_pointer
We can also use the value set to simplify `object_size` and `is_invalid_pointer` expressions.
1 parent 6b6c8d3 commit 9b9f1e2

File tree

3 files changed

+111
-2
lines changed

3 files changed

+111
-2
lines changed

src/goto-symex/simplify_expr_with_value_set.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Michael Tautschnig
1010

1111
#include <util/expr_util.h>
1212
#include <util/pointer_expr.h>
13+
#include <util/pointer_offset_size.h>
1314
#include <util/simplify_expr.h>
1415
#include <util/ssa_expr.h>
1516

@@ -193,6 +194,12 @@ simplify_expr_with_value_sett::simplify_inequality_pointer_object(
193194
to_object_descriptor_expr(value_set_element).root_object());
194195
}
195196
}
197+
else if(
198+
pointer.is_constant() && to_constant_expr(pointer).is_null_pointer())
199+
{
200+
objects.insert(
201+
exprt{ID_null_object, to_pointer_type(pointer.type()).base_type()});
202+
}
196203
return objects;
197204
};
198205

@@ -281,3 +288,99 @@ simplify_expr_with_value_sett::simplify_pointer_offset(
281288
return changed(
282289
simplify_rec(typecast_exprt::conditional_cast(*offset, expr.type())));
283290
}
291+
292+
simplify_exprt::resultt<> simplify_expr_with_value_sett::simplify_object_size(
293+
const object_size_exprt &expr)
294+
{
295+
const exprt &ptr = expr.pointer();
296+
297+
if(ptr.type().id() != ID_pointer)
298+
return unchanged(expr);
299+
300+
const ssa_exprt *ssa_symbol_expr = expr_try_dynamic_cast<ssa_exprt>(ptr);
301+
302+
if(!ssa_symbol_expr)
303+
return simplify_exprt::simplify_object_size(expr);
304+
305+
ssa_exprt l1_expr{*ssa_symbol_expr};
306+
l1_expr.remove_level_2();
307+
const std::vector<exprt> value_set_elements =
308+
value_set.get_value_set(l1_expr, ns);
309+
310+
std::optional<exprt> object_size;
311+
312+
for(const auto &value_set_element : value_set_elements)
313+
{
314+
if(
315+
value_set_element.id() == ID_unknown ||
316+
value_set_element.id() == ID_invalid ||
317+
is_failed_symbol(
318+
to_object_descriptor_expr(value_set_element).root_object()) ||
319+
to_object_descriptor_expr(value_set_element).offset().id() == ID_unknown)
320+
{
321+
object_size.reset();
322+
break;
323+
}
324+
325+
auto this_object_size_opt = size_of_expr(
326+
to_object_descriptor_expr(value_set_element).root_object().type(), ns);
327+
if(
328+
!this_object_size_opt.has_value() ||
329+
(object_size.has_value() && *this_object_size_opt != *object_size))
330+
{
331+
object_size.reset();
332+
break;
333+
}
334+
else if(!object_size.has_value())
335+
{
336+
object_size = this_object_size_opt;
337+
}
338+
}
339+
340+
if(!object_size.has_value())
341+
return simplify_exprt::simplify_object_size(expr);
342+
343+
return changed(
344+
simplify_rec(typecast_exprt::conditional_cast(*object_size, expr.type())));
345+
}
346+
347+
simplify_exprt::resultt<>
348+
simplify_expr_with_value_sett::simplify_is_invalid_pointer(
349+
const unary_exprt &expr)
350+
{
351+
const exprt &ptr = expr.op();
352+
353+
if(ptr.type().id() != ID_pointer)
354+
return unchanged(expr);
355+
356+
const ssa_exprt *ssa_symbol_expr = expr_try_dynamic_cast<ssa_exprt>(ptr);
357+
358+
if(!ssa_symbol_expr)
359+
return simplify_exprt::simplify_is_invalid_pointer(expr);
360+
361+
ssa_exprt l1_expr{*ssa_symbol_expr};
362+
l1_expr.remove_level_2();
363+
const std::vector<exprt> value_set_elements =
364+
value_set.get_value_set(l1_expr, ns);
365+
366+
bool all_valid = !value_set_elements.empty();
367+
368+
for(const auto &value_set_element : value_set_elements)
369+
{
370+
if(
371+
value_set_element.id() == ID_unknown ||
372+
value_set_element.id() == ID_invalid ||
373+
is_failed_symbol(
374+
to_object_descriptor_expr(value_set_element).root_object()) ||
375+
to_object_descriptor_expr(value_set_element).offset().id() == ID_unknown)
376+
{
377+
all_valid = false;
378+
break;
379+
}
380+
}
381+
382+
if(all_valid)
383+
return changed(static_cast<exprt>(false_exprt{}));
384+
else
385+
return simplify_exprt::simplify_is_invalid_pointer(expr);
386+
}

src/goto-symex/simplify_expr_with_value_set.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ class simplify_expr_with_value_sett : public simplify_exprt
3131
[[nodiscard]] resultt<>
3232
simplify_inequality_pointer_object(const binary_relation_exprt &) override;
3333
[[nodiscard]] resultt<>
34+
simplify_is_invalid_pointer(const unary_exprt &) override;
35+
[[nodiscard]] resultt<>
36+
simplify_object_size(const object_size_exprt &) override;
37+
[[nodiscard]] resultt<>
3438
simplify_pointer_offset(const pointer_offset_exprt &) override;
3539

3640
protected:

src/util/simplify_expr_class.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,11 @@ class simplify_exprt
193193
[[nodiscard]] resultt<> simplify_pointer_object(const pointer_object_exprt &);
194194
[[nodiscard]] resultt<>
195195
simplify_unary_pointer_predicate_preorder(const unary_exprt &);
196-
[[nodiscard]] resultt<> simplify_object_size(const object_size_exprt &);
196+
[[nodiscard]] virtual resultt<>
197+
simplify_object_size(const object_size_exprt &);
197198
[[nodiscard]] resultt<> simplify_is_dynamic_object(const unary_exprt &);
198-
[[nodiscard]] resultt<> simplify_is_invalid_pointer(const unary_exprt &);
199+
[[nodiscard]] virtual resultt<>
200+
simplify_is_invalid_pointer(const unary_exprt &);
199201
[[nodiscard]] resultt<> simplify_object(const exprt &);
200202
[[nodiscard]] resultt<> simplify_unary_minus(const unary_minus_exprt &);
201203
[[nodiscard]] resultt<> simplify_unary_plus(const unary_plus_exprt &);

0 commit comments

Comments
 (0)