Skip to content

Commit 5c2fa72

Browse files
committed
Add support for mapping the sizes of expression subtypes in the new SMT backend.
This will be needed later to support pointer arithmetic.
1 parent 679ab3f commit 5c2fa72

File tree

8 files changed

+127
-14
lines changed

8 files changed

+127
-14
lines changed

src/solvers/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ SRC = $(BOOLEFORCE_SRC) \
196196
smt2_incremental/construct_value_expr_from_smt.cpp \
197197
smt2_incremental/convert_expr_to_smt.cpp \
198198
smt2_incremental/object_tracking.cpp \
199+
smt2_incremental/type_size_mapping.cpp \
199200
smt2_incremental/smt_bit_vector_theory.cpp \
200201
smt2_incremental/smt_commands.cpp \
201202
smt2_incremental/smt_core_theory.cpp \

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,8 @@ static optionalt<smt_termt> try_relational_conversion(
587587

588588
static smt_termt convert_expr_to_smt(
589589
const plus_exprt &plus,
590-
const sub_expression_mapt &converted)
590+
const sub_expression_mapt &converted,
591+
const type_size_mapt &pointer_sizes)
591592
{
592593
if(std::all_of(
593594
plus.operands().cbegin(), plus.operands().cend(), [](exprt operand) {
@@ -606,7 +607,8 @@ static smt_termt convert_expr_to_smt(
606607

607608
static smt_termt convert_expr_to_smt(
608609
const minus_exprt &minus,
609-
const sub_expression_mapt &converted)
610+
const sub_expression_mapt &converted,
611+
const type_size_mapt &pointer_sizes)
610612
{
611613
const bool both_operands_bitvector =
612614
can_cast_type<integer_bitvector_typet>(minus.lhs().type()) &&
@@ -1299,6 +1301,7 @@ static smt_termt dispatch_expr_to_smt_conversion(
12991301
const exprt &expr,
13001302
const sub_expression_mapt &converted,
13011303
const smt_object_mapt &object_map,
1304+
const type_size_mapt &pointer_sizes,
13021305
const smt_object_sizet::make_applicationt &call_object_size)
13031306
{
13041307
if(const auto symbol = expr_try_dynamic_cast<symbol_exprt>(expr))
@@ -1415,7 +1418,7 @@ static smt_termt dispatch_expr_to_smt_conversion(
14151418
}
14161419
if(const auto plus = expr_try_dynamic_cast<plus_exprt>(expr))
14171420
{
1418-
return convert_expr_to_smt(*plus, converted);
1421+
return convert_expr_to_smt(*plus, converted, pointer_sizes);
14191422
}
14201423
if(const auto minus = expr_try_dynamic_cast<minus_exprt>(expr))
14211424
{
@@ -1658,6 +1661,7 @@ at_scope_exitt<functiont> at_scope_exit(functiont exit_function)
16581661
smt_termt convert_expr_to_smt(
16591662
const exprt &expr,
16601663
const smt_object_mapt &object_map,
1664+
const type_size_mapt &pointer_sizes,
16611665
const smt_object_sizet::make_applicationt &object_size)
16621666
{
16631667
#ifndef CPROVER_INVARIANT_DO_NOT_CHECK
@@ -1676,7 +1680,7 @@ smt_termt convert_expr_to_smt(
16761680
if(find_result != sub_expression_map.cend())
16771681
return;
16781682
smt_termt term = dispatch_expr_to_smt_conversion(
1679-
expr, sub_expression_map, object_map, object_size);
1683+
expr, sub_expression_map, object_map, pointer_sizes, object_size);
16801684
sub_expression_map.emplace_hint(find_result, expr, std::move(term));
16811685
});
16821686
return std::move(sub_expression_map.at(expr));

src/solvers/smt2_incremental/convert_expr_to_smt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <solvers/smt2_incremental/smt_object_size.h>
88
#include <solvers/smt2_incremental/smt_sorts.h>
99
#include <solvers/smt2_incremental/smt_terms.h>
10+
#include <solvers/smt2_incremental/type_size_mapping.h>
1011

1112
class exprt;
1213
class typet;
@@ -20,6 +21,7 @@ smt_sortt convert_type_to_smt_sort(const typet &type);
2021
smt_termt convert_expr_to_smt(
2122
const exprt &expression,
2223
const smt_object_mapt &object_map,
24+
const type_size_mapt &pointer_sizes,
2325
const smt_object_sizet::make_applicationt &object_size);
2426

2527
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_CONVERT_EXPR_TO_SMT_H

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,6 @@
22

33
#include "smt2_incremental_decision_procedure.h"
44

5-
#include <solvers/smt2_incremental/construct_value_expr_from_smt.h>
6-
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
7-
#include <solvers/smt2_incremental/smt_commands.h>
8-
#include <solvers/smt2_incremental/smt_core_theory.h>
9-
#include <solvers/smt2_incremental/smt_responses.h>
10-
#include <solvers/smt2_incremental/smt_solver_process.h>
11-
#include <solvers/smt2_incremental/smt_terms.h>
125
#include <util/expr.h>
136
#include <util/namespace.h>
147
#include <util/nodiscard.h>
@@ -17,6 +10,15 @@
1710
#include <util/string_utils.h>
1811
#include <util/symbol.h>
1912

13+
#include <solvers/smt2_incremental/construct_value_expr_from_smt.h>
14+
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
15+
#include <solvers/smt2_incremental/smt_commands.h>
16+
#include <solvers/smt2_incremental/smt_core_theory.h>
17+
#include <solvers/smt2_incremental/smt_responses.h>
18+
#include <solvers/smt2_incremental/smt_solver_process.h>
19+
#include <solvers/smt2_incremental/smt_terms.h>
20+
#include <solvers/smt2_incremental/type_size_mapping.h>
21+
2022
#include <stack>
2123

2224
/// Issues a command to the solving process which is expected to optionally
@@ -163,8 +165,14 @@ smt_termt
163165
smt2_incremental_decision_proceduret::convert_expr_to_smt(const exprt &expr)
164166
{
165167
track_expression_objects(expr, ns, object_map);
168+
associate_pointer_sizes(
169+
expr,
170+
ns,
171+
pointer_sizes_map,
172+
object_map,
173+
object_size_function.make_application);
166174
return ::convert_expr_to_smt(
167-
expr, object_map, object_size_function.make_application);
175+
expr, object_map, pointer_sizes_map, object_size_function.make_application);
168176
}
169177

170178
exprt smt2_incremental_decision_proceduret::handle(const exprt &expr)
@@ -208,7 +216,10 @@ exprt smt2_incremental_decision_proceduret::get(const exprt &expr) const
208216
"Objects in expressions being read should already be tracked from "
209217
"point of being set/handled.");
210218
descriptor = ::convert_expr_to_smt(
211-
expr, object_map, object_size_function.make_application);
219+
expr,
220+
object_map,
221+
pointer_sizes_map,
222+
object_size_function.make_application);
212223
}
213224
else
214225
{

src/solvers/smt2_incremental/smt2_incremental_decision_procedure.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <solvers/smt2_incremental/object_tracking.h>
1313
#include <solvers/smt2_incremental/smt_object_size.h>
1414
#include <solvers/smt2_incremental/smt_terms.h>
15+
#include <solvers/smt2_incremental/type_size_mapping.h>
1516
#include <solvers/stack_decision_procedure.h>
1617

1718
#include <memory>
@@ -89,6 +90,7 @@ class smt2_incremental_decision_proceduret final
8990
smt_object_mapt object_map;
9091
std::vector<bool> object_size_defined;
9192
smt_object_sizet object_size_function;
93+
type_size_mapt pointer_sizes_map;
9294
};
9395

9496
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_SMT2_INCREMENTAL_DECISION_PROCEDURE_H
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Author: Diffblue Ltd.
2+
3+
#include "type_size_mapping.h"
4+
5+
#include <util/arith_tools.h>
6+
#include <util/c_types.h>
7+
#include <util/invariant.h>
8+
#include <util/pointer_expr.h>
9+
#include <util/pointer_offset_size.h>
10+
11+
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
12+
13+
void associate_pointer_sizes(
14+
const exprt &expression,
15+
const namespacet &ns,
16+
type_size_mapt &type_size_map,
17+
const smt_object_mapt &object_map,
18+
const smt_object_sizet::make_applicationt &object_size)
19+
{
20+
expression.visit_pre(
21+
[&](const exprt &sub_expression)
22+
{
23+
if(
24+
const auto &pointer_type =
25+
type_try_dynamic_cast<pointer_typet>(sub_expression.type()))
26+
{
27+
const auto find_result = type_size_map.find(pointer_type->base_type());
28+
if(find_result != type_size_map.cend())
29+
return;
30+
exprt pointer_size_expr;
31+
// There's a special case for a pointer subtype here: the case where the pointer is
32+
// `void *`. This means that we don't know the underlying base type, so we're just
33+
// assigning a size expression value of 1 (given that this is going to be used in a
34+
// multiplication and 1 is the identity value for multiplcation)
35+
if(is_void_pointer(*pointer_type))
36+
{
37+
pointer_size_expr = from_integer(1, size_type());
38+
}
39+
else
40+
{
41+
auto pointer_size_opt = size_of_expr(pointer_type->base_type(), ns);
42+
PRECONDITION(pointer_size_opt.has_value());
43+
pointer_size_expr = pointer_size_opt.value();
44+
}
45+
auto pointer_size_term = convert_expr_to_smt(
46+
pointer_size_expr, object_map, type_size_map, object_size);
47+
type_size_map.emplace_hint(
48+
find_result, pointer_type->base_type(), pointer_size_term);
49+
}
50+
});
51+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Author: Diffblue Ltd.
2+
3+
/// \file
4+
/// Utilities for making a map of types to associated sizes.
5+
6+
#ifndef CPROVER_SOLVERS_SMT2_INCREMENTAL_TYPE_SIZE_MAPPING_H
7+
#define CPROVER_SOLVERS_SMT2_INCREMENTAL_TYPE_SIZE_MAPPING_H
8+
9+
#include <util/expr.h>
10+
11+
#include <solvers/smt2_incremental/object_tracking.h>
12+
#include <solvers/smt2_incremental/smt_object_size.h>
13+
#include <solvers/smt2_incremental/smt_terms.h>
14+
15+
#include <unordered_map>
16+
17+
using type_size_mapt = std::unordered_map<typet, smt_termt, irep_full_hash>;
18+
19+
/// This function populates the (pointer) type -> size map.
20+
/// \param expression: the expression we're building the map for.
21+
/// \param ns:
22+
/// A namespace - passed to size_of_expr to lookup type symbols in case the
23+
/// pointers have type `tag_typet`, rather than a more completely defined type.
24+
/// \param type_size_map:
25+
/// A map of types to terms expressing the size of the type (in bytes). This
26+
/// function adds new entries to the map for instances of pointer.base_type()
27+
/// from \p expression which are not already keys in the map.
28+
/// \param object_map: passed through to convert_expr_to_smt
29+
/// \param object_size: passed through to convert_expr_to_smt
30+
void associate_pointer_sizes(
31+
const exprt &expression,
32+
const namespacet &ns,
33+
type_size_mapt &type_size_map,
34+
const smt_object_mapt &object_map,
35+
const smt_object_sizet::make_applicationt &object_size);
36+
37+
#endif

unit/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <solvers/smt2_incremental/convert_expr_to_smt.h>
1616
#include <solvers/smt2_incremental/object_tracking.h>
17+
#include <solvers/smt2_incremental/pointer_size_mapping.h>
1718
#include <solvers/smt2_incremental/smt_bit_vector_theory.h>
1819
#include <solvers/smt2_incremental/smt_core_theory.h>
1920
#include <solvers/smt2_incremental/smt_terms.h>
@@ -57,6 +58,7 @@ struct expr_to_smt_conversion_test_environmentt
5758

5859
smt_object_mapt object_map;
5960
smt_object_sizet object_size_function;
61+
pointer_size_mapt pointer_sizes;
6062

6163
private:
6264
// This is private to ensure the above make() function is used to make
@@ -88,7 +90,10 @@ smt_termt
8890
expr_to_smt_conversion_test_environmentt::convert(const exprt &expression) const
8991
{
9092
return convert_expr_to_smt(
91-
expression, object_map, object_size_function.make_application);
93+
expression,
94+
object_map,
95+
pointer_sizes,
96+
object_size_function.make_application);
9297
}
9398

9499
TEST_CASE("\"symbol_exprt\" to smt term conversion", "[core][smt2_incremental]")

0 commit comments

Comments
 (0)