Skip to content

Commit 3be994d

Browse files
committed
Add struct decoding to encoding class
1 parent 384772f commit 3be994d

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

src/solvers/smt2_incremental/encoding/struct_encoding.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <util/make_unique.h>
88
#include <util/namespace.h>
99
#include <util/range.h>
10+
#include <util/simplify_expr.h>
1011

1112
#include <solvers/flattening/boolbv_width.h>
1213

@@ -177,3 +178,31 @@ exprt struct_encodingt::encode(exprt expr) const
177178
}
178179
return expr;
179180
}
181+
182+
exprt struct_encodingt::decode(
183+
const exprt &encoded,
184+
const struct_tag_typet &original_type) const
185+
{
186+
// The algorithm below works by extracting each of the separate fields from
187+
// the combined encoded value using a `member_exprt` which is itself encoded
188+
// into a `bit_extract_exprt`. These separated fields can then be combined
189+
// using a `struct_exprt`. This is expected to duplicate the input encoded
190+
// expression for each of the fields. However for the case where the input
191+
// encoded expression is a `constant_exprt`, expression simplification will be
192+
// able simplify away the duplicated portions of the constant and the bit
193+
// extraction expressions. This yields a clean struct expression where each
194+
// field is a separate constant containing the data solely relevant to that
195+
// field.
196+
INVARIANT(
197+
can_cast_type<bv_typet>(encoded.type()),
198+
"Structs are expected to be encoded into bit vectors.");
199+
const struct_typet definition = ns.get().follow_tag(original_type);
200+
exprt::operandst encoded_fields;
201+
for(const auto &component : definition.components())
202+
{
203+
encoded_fields.push_back(typecast_exprt::conditional_cast(
204+
encode(member_exprt{typecast_exprt{encoded, original_type}, component}),
205+
component.type()));
206+
}
207+
return simplify_expr(struct_exprt{encoded_fields, original_type}, ns);
208+
}

src/solvers/smt2_incremental/encoding/struct_encoding.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
class namespacet;
1212
class boolbv_widtht;
1313
class member_exprt;
14+
class struct_tag_typet;
1415

1516
/// Encodes struct types/values into non-struct expressions/types.
1617
class struct_encodingt final
@@ -22,6 +23,10 @@ class struct_encodingt final
2223

2324
typet encode(typet type) const;
2425
exprt encode(exprt expr) const;
26+
/// Reconstructs a struct expression of the \p original_type using the data
27+
/// from the bit vector \p encoded expression.
28+
exprt
29+
decode(const exprt &encoded, const struct_tag_typet &original_type) const;
2530

2631
private:
2732
std::unique_ptr<boolbv_widtht> boolbv_width;

unit/solvers/smt2_incremental/encoding/struct_encoding.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,26 @@ TEST_CASE("struct encoding of expressions", "[core][smt2_incremental]")
321321
}
322322
}
323323

324+
TEST_CASE("decoding into struct expressions.", "[core][smt2_incremental]")
325+
{
326+
const struct_union_typet::componentst component_types{
327+
{"green", signedbv_typet{32}},
328+
{"eggs", unsignedbv_typet{16}},
329+
{"ham", signedbv_typet{24}}};
330+
const struct_typet struct_type{component_types};
331+
const type_symbolt type_symbol{"my_structt", struct_type, ID_C};
332+
auto test = struct_encoding_test_environmentt::make();
333+
test.symbol_table.insert(type_symbol);
334+
const struct_tag_typet struct_tag{type_symbol.name};
335+
const struct_exprt expected{
336+
{from_integer(3, signedbv_typet{32}),
337+
from_integer(2, unsignedbv_typet{16}),
338+
from_integer(1, signedbv_typet{24})},
339+
struct_tag};
340+
const exprt encoded = constant_exprt{"000000030002000001", bv_typet{72}};
341+
REQUIRE(test.struct_encoding.decode(encoded, struct_tag) == expected);
342+
}
343+
324344
TEST_CASE(
325345
"encoding of single member struct expressions",
326346
"[core][smt2_incremental]")

0 commit comments

Comments
 (0)