Skip to content

Commit 9d5231d

Browse files
committed
Add struct encoding class
1 parent 26b8027 commit 9d5231d

File tree

5 files changed

+156
-0
lines changed

5 files changed

+156
-0
lines changed

src/solvers/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ SRC = $(BOOLEFORCE_SRC) \
210210
smt2_incremental/smt_solver_process.cpp \
211211
smt2_incremental/smt_to_smt2_string.cpp \
212212
smt2_incremental/smt2_incremental_decision_procedure.cpp \
213+
smt2_incremental/struct_encoding.cpp \
213214
smt2_incremental/theories/smt_array_theory.cpp \
214215
smt2_incremental/theories/smt_bit_vector_theory.cpp \
215216
smt2_incremental/theories/smt_core_theory.cpp \
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Author: Diffblue Ltd.
2+
3+
#include "struct_encoding.h"
4+
5+
#include <util/bitvector_types.h>
6+
#include <util/make_unique.h>
7+
8+
#include <solvers/flattening/boolbv_width.h>
9+
10+
#include <queue>
11+
12+
struct_encodingt::struct_encodingt(const namespacet &ns)
13+
: boolbv_width{util_make_unique<boolbv_widtht>(ns)}
14+
{
15+
}
16+
17+
struct_encodingt::struct_encodingt(const struct_encodingt &other)
18+
: boolbv_width{util_make_unique<boolbv_widtht>(*other.boolbv_width)}
19+
{
20+
}
21+
22+
struct_encodingt::~struct_encodingt() = default;
23+
24+
typet struct_encodingt::encode(typet type) const
25+
{
26+
std::queue<typet *> work_queue;
27+
work_queue.push(&type);
28+
while(!work_queue.empty())
29+
{
30+
typet &current = *work_queue.front();
31+
work_queue.pop();
32+
if(const auto struct_tag = type_try_dynamic_cast<struct_tag_typet>(current))
33+
{
34+
current = bv_typet{(*boolbv_width)(*struct_tag)};
35+
}
36+
if(const auto array = type_try_dynamic_cast<array_typet>(current))
37+
{
38+
work_queue.push(&array->element_type());
39+
}
40+
}
41+
return type;
42+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Author: Diffblue Ltd.
2+
3+
#ifndef CPROVER_SOLVERS_SMT2_INCREMENTAL_STRUCT_ENCODING_H
4+
#define CPROVER_SOLVERS_SMT2_INCREMENTAL_STRUCT_ENCODING_H
5+
6+
#include <util/type.h> // For passing `typet` by value. // IWYU pragma: keep
7+
8+
#include <memory>
9+
10+
class namespacet;
11+
class boolbv_widtht;
12+
13+
/// Encodes struct types/values into non-struct expressions/types.
14+
class struct_encodingt final
15+
{
16+
public:
17+
explicit struct_encodingt(const namespacet &ns);
18+
struct_encodingt(const struct_encodingt &other);
19+
~struct_encodingt();
20+
21+
typet encode(typet type) const;
22+
23+
private:
24+
std::unique_ptr<boolbv_widtht> boolbv_width;
25+
};
26+
27+
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_STRUCT_ENCODING_H

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ SRC += analyses/ai/ai.cpp \
114114
solvers/smt2_incremental/smt_object_size.cpp \
115115
solvers/smt2_incremental/smt_response_validation.cpp \
116116
solvers/smt2_incremental/smt_to_smt2_string.cpp \
117+
solvers/smt2_incremental/struct_encoding.cpp \
117118
solvers/smt2_incremental/theories/smt_array_theory.cpp \
118119
solvers/smt2_incremental/theories/smt_bit_vector_theory.cpp \
119120
solvers/smt2_incremental/theories/smt_core_theory.cpp \
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Author: Diffblue Ltd.
2+
3+
#include <util/arith_tools.h>
4+
#include <util/bitvector_types.h>
5+
#include <util/namespace.h>
6+
#include <util/symbol_table.h>
7+
8+
#include <solvers/smt2_incremental/struct_encoding.h>
9+
#include <testing-utils/use_catch.h>
10+
11+
struct struct_encoding_test_environmentt
12+
{
13+
symbol_tablet symbol_table;
14+
namespacet ns{symbol_table};
15+
struct_encodingt struct_encoding{ns};
16+
17+
static struct_encoding_test_environmentt make()
18+
{
19+
return {};
20+
}
21+
22+
private:
23+
struct_encoding_test_environmentt() = default;
24+
};
25+
26+
TEST_CASE(
27+
"struct encoding of non-stuct type is a no-op",
28+
"[core][smt2_incremental]")
29+
{
30+
auto test = struct_encoding_test_environmentt::make();
31+
typet input = signedbv_typet{8};
32+
REQUIRE(test.struct_encoding.encode(input) == input);
33+
}
34+
35+
TEST_CASE("struct encoding of struct_tag_type", "[core][smt2_incremental]")
36+
{
37+
const struct_union_typet::componentst components{
38+
{"foo", unsignedbv_typet{8}}, {"bar", signedbv_typet{16}}};
39+
struct_typet struct_type{components};
40+
type_symbolt type_symbol{"my_structt", struct_type, ID_C};
41+
auto test = struct_encoding_test_environmentt::make();
42+
test.symbol_table.insert(type_symbol);
43+
struct_tag_typet struct_tag{type_symbol.name};
44+
REQUIRE(test.struct_encoding.encode(struct_tag) == bv_typet{24});
45+
}
46+
47+
TEST_CASE("struct encoding of array of structs", "[core][smt2_incremental]")
48+
{
49+
const struct_union_typet::componentst components{
50+
{"foo", unsignedbv_typet{8}}, {"bar", signedbv_typet{16}}};
51+
struct_typet struct_type{components};
52+
type_symbolt type_symbol{"my_structt", struct_type, ID_C};
53+
auto test = struct_encoding_test_environmentt::make();
54+
test.symbol_table.insert(type_symbol);
55+
struct_tag_typet struct_tag{type_symbol.name};
56+
const auto index_type = signedbv_typet{32};
57+
const auto array_size = from_integer(5, index_type);
58+
array_typet array_of_struct{struct_tag, array_size};
59+
array_typet expected_encoded_array{bv_typet{24}, array_size};
60+
REQUIRE(
61+
test.struct_encoding.encode(array_of_struct) == expected_encoded_array);
62+
}
63+
64+
TEST_CASE(
65+
"struct encoding of array of array of structs",
66+
"[core][smt2_incremental]")
67+
{
68+
const struct_union_typet::componentst components{
69+
{"foo", unsignedbv_typet{8}}, {"bar", signedbv_typet{16}}};
70+
struct_typet struct_type{components};
71+
type_symbolt type_symbol{"my_structt", struct_type, ID_C};
72+
auto test = struct_encoding_test_environmentt::make();
73+
test.symbol_table.insert(type_symbol);
74+
struct_tag_typet struct_tag{type_symbol.name};
75+
const auto index_type = signedbv_typet{32};
76+
const auto array_size_inner = from_integer(4, index_type);
77+
const auto array_size_outer = from_integer(2, index_type);
78+
array_typet array_of_struct{struct_tag, array_size_inner};
79+
array_typet array_of_array_of_struct{array_of_struct, array_size_outer};
80+
array_typet expected_encoded_array{
81+
array_typet{bv_typet{24}, array_size_inner}, array_size_outer};
82+
REQUIRE(
83+
test.struct_encoding.encode(array_of_array_of_struct) ==
84+
expected_encoded_array);
85+
}

0 commit comments

Comments
 (0)