Skip to content

Commit 05ccb75

Browse files
Merge pull request #7961 from thomasspriggs/tas/smt_union_member
Add support for union member expressions in incremental smt2 decision procedure
2 parents a531056 + 5985e55 commit 05ccb75

File tree

21 files changed

+54
-25
lines changed

21 files changed

+54
-25
lines changed

regression/cbmc/Union_Initialization1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/Union_Initialization5/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union10/union_list2.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
union_list2.c
33

44
^EXIT=0$

regression/cbmc/union11/union_list.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
union_list.c
33

44
^EXIT=0$

regression/cbmc/union13/no-arch.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33
--arch none --little-endian
44
(Starting CEGAR Loop|^Generated 1 VCC\(s\), 1 remaining after simplification$)

regression/cbmc/union13/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union14/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union15/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union16/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union18/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^Generated 1 VCC\(s\), 0 remaining after simplification$

regression/cbmc/union2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union3/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union4/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union5/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=10$

regression/cbmc/union6/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33
--little-endian
44
^EXIT=0$

regression/cbmc/union7/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33
--big-endian
44
^EXIT=0$

regression/cbmc/union8/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

regression/cbmc/union9/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
CORE new-smt-backend
22
main.c
33

44
^EXIT=0$

src/solvers/smt2_incremental/encoding/struct_encoding.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,19 +176,26 @@ static std::size_t count_trailing_bit_width(
176176
trailing_widths.begin(), trailing_widths.end(), std::size_t{0});
177177
}
178178

179-
/// The member expression selects the value of a field from a struct. The
180-
/// struct is encoded as a single bitvector where the first field is stored
179+
/// The member expression selects the value of a field from a struct or union.
180+
/// Both structs and unions are encoded into a single large bit vector.
181+
/// The fields of a union are encoded into the lowest bits, with padding in the
182+
/// highest bits if needed.
183+
/// Structs are encoded as a single bitvector where the first field is stored
181184
/// in the highest bits. The second field is stored in the next highest set of
182185
/// bits and so on. As offsets are indexed from the lowest bit, any field can be
183186
/// selected by extracting the range of bits starting from an offset based on
184187
/// the combined width of the fields which follow the field being selected.
185188
exprt struct_encodingt::encode_member(const member_exprt &member_expr) const
186189
{
187-
const auto &struct_type = type_checked_cast<struct_typet>(
188-
ns.get().follow(member_expr.compound().type()));
189-
const std::size_t offset_bits = count_trailing_bit_width(
190-
struct_type, member_expr.get_component_name(), *boolbv_width);
190+
const auto &type = ns.get().follow(member_expr.compound().type());
191191
const auto member_bits_width = (*boolbv_width)(member_expr.type());
192+
const auto offset_bits = [&]() -> std::size_t {
193+
if(can_cast_type<union_typet>(type))
194+
return 0;
195+
const auto &struct_type = type_checked_cast<struct_typet>(type);
196+
return count_trailing_bit_width(
197+
struct_type, member_expr.get_component_name(), *boolbv_width);
198+
}();
192199
return extractbits_exprt{
193200
member_expr.compound(),
194201
offset_bits + member_bits_width - 1,

unit/solvers/smt2_incremental/encoding/struct_encoding.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,4 +501,26 @@ TEST_CASE("encoding of union expressions", "[core][smt2_incremental]")
501501
const auto bv_equal = equal_exprt{symbol_expr_as_bv, partial_union_as_bv};
502502
REQUIRE(test.struct_encoding.encode(union_equal) == bv_equal);
503503
}
504+
SECTION("member expression selecting a data member of a union")
505+
{
506+
SECTION("Member which fits the size of the whole union")
507+
{
508+
const typet field_type = signedbv_typet{32};
509+
const exprt zero = from_integer(0, field_type);
510+
const exprt input =
511+
equal_exprt{zero, member_exprt{symbol_expr, "ham", field_type}};
512+
const exprt expected = equal_exprt{
513+
zero, extractbits_exprt{symbol_expr_as_bv, 31, 0, field_type}};
514+
REQUIRE(test.struct_encoding.encode(input) == expected);
515+
}
516+
SECTION("Member which is smaller than the union as a whole")
517+
{
518+
const typet field_type = unsignedbv_typet{8};
519+
const exprt input =
520+
equal_exprt{dozen, member_exprt{symbol_expr, "eggs", field_type}};
521+
const exprt expected = equal_exprt{
522+
dozen, extractbits_exprt{symbol_expr_as_bv, 7, 0, field_type}};
523+
REQUIRE(test.struct_encoding.encode(input) == expected);
524+
}
525+
}
504526
}

0 commit comments

Comments
 (0)