Skip to content

Commit 712af97

Browse files
committed
Add union_exprt encoding
1 parent 30364f5 commit 712af97

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
util
1+
solvers/smt2_incremental/encoding
2+
util

src/solvers/smt2_incremental/encoding/struct_encoding.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <util/simplify_expr.h>
1313

1414
#include <solvers/flattening/boolbv_width.h>
15+
#include <solvers/smt2_incremental/encoding/nondet_padding.h>
1516

1617
#include <algorithm>
1718
#include <numeric>
@@ -136,6 +137,22 @@ static exprt encode(const struct_exprt &struct_expr)
136137
return concatenation_exprt{struct_expr.operands(), struct_expr.type()};
137138
}
138139

140+
static exprt
141+
encode(const union_exprt &union_expr, const boolbv_widtht &bit_width)
142+
{
143+
const std::size_t union_width = bit_width(union_expr.type());
144+
const exprt &component = union_expr.op();
145+
const std::size_t component_width = bit_width(union_expr.op().type());
146+
if(union_width == component_width)
147+
return typecast_exprt(component, bv_typet{union_width});
148+
INVARIANT(
149+
union_width >= component_width,
150+
"Union must be at least as wide as its component.");
151+
return concatenation_exprt{
152+
{nondet_padding_exprt{bv_typet{union_width - component_width}}, component},
153+
bv_typet{union_width}};
154+
}
155+
139156
static std::size_t count_trailing_bit_width(
140157
const struct_typet &type,
141158
const irep_idt name,
@@ -195,6 +212,8 @@ exprt struct_encodingt::encode(exprt expr) const
195212
current.type() = encode(current.type());
196213
if(const auto struct_expr = expr_try_dynamic_cast<struct_exprt>(current))
197214
current = ::encode(*struct_expr);
215+
if(const auto union_expr = expr_try_dynamic_cast<union_exprt>(current))
216+
current = ::encode(*union_expr, *boolbv_width);
198217
if(const auto member_expr = expr_try_dynamic_cast<member_exprt>(current))
199218
current = encode_member(*member_expr);
200219
for(auto &operand : current.operands())

unit/solvers/smt2_incremental/encoding/struct_encoding.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <util/namespace.h>
99
#include <util/symbol_table.h>
1010

11+
#include <solvers/smt2_incremental/encoding/nondet_padding.h>
1112
#include <solvers/smt2_incremental/encoding/struct_encoding.h>
1213
#include <testing-utils/use_catch.h>
1314

@@ -453,3 +454,39 @@ TEST_CASE(
453454
REQUIRE(test.struct_encoding.encode(struct_expr) == dozen);
454455
}
455456
}
457+
458+
TEST_CASE("encoding of union expressions", "[core][smt2_incremental]")
459+
{
460+
const struct_union_typet::componentst components{
461+
{"eggs", unsignedbv_typet{8}}, {"ham", signedbv_typet{32}}};
462+
const type_symbolt type_symbol{"foot", union_typet{components}, ID_C};
463+
auto test = struct_encoding_test_environmentt::make();
464+
test.symbol_table.insert(type_symbol);
465+
const union_tag_typet union_tag{type_symbol.name};
466+
const symbolt union_value_symbol{"foo", union_tag, ID_C};
467+
test.symbol_table.insert(union_value_symbol);
468+
const auto symbol_expr = union_value_symbol.symbol_expr();
469+
const auto symbol_expr_as_bv = symbol_exprt{"foo", bv_typet{32}};
470+
const auto dozen = from_integer(12, unsignedbv_typet{8});
471+
const auto partial_union = union_exprt{"eggs", dozen, union_tag};
472+
const auto partial_union_as_bv = concatenation_exprt{
473+
{nondet_padding_exprt{bv_typet{24}}, dozen}, bv_typet{32}};
474+
SECTION("Union typed symbol expression")
475+
{
476+
REQUIRE(test.struct_encoding.encode(symbol_expr) == symbol_expr_as_bv);
477+
}
478+
SECTION("Expression for a union from a component")
479+
{
480+
REQUIRE(test.struct_encoding.encode(partial_union) == partial_union_as_bv);
481+
const auto one = from_integer(1, unsignedbv_typet{32});
482+
const auto full_union = union_exprt{"ham", one, union_tag};
483+
const auto full_union_as_bv = typecast_exprt{one, bv_typet{32}};
484+
REQUIRE(test.struct_encoding.encode(full_union) == full_union_as_bv);
485+
}
486+
SECTION("Union equality expression")
487+
{
488+
const auto union_equal = equal_exprt{symbol_expr, partial_union};
489+
const auto bv_equal = equal_exprt{symbol_expr_as_bv, partial_union_as_bv};
490+
REQUIRE(test.struct_encoding.encode(union_equal) == bv_equal);
491+
}
492+
}

0 commit comments

Comments
 (0)