Skip to content

Commit 19b8b80

Browse files
committed
byte_extract lowering of unions
We previously handled unions like PODs.
1 parent ebd69f5 commit 19b8b80

File tree

8 files changed

+68
-7
lines changed

8 files changed

+68
-7
lines changed

regression/cbmc/equality_through_union1/test.desc

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

44
^EXIT=0$

regression/cbmc/equality_through_union2/test.desc

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

44
^EXIT=0$

regression/cbmc/equality_through_union3/test.desc

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

44
^EXIT=0$

regression/cbmc/trace_address_arithmetic1/test.desc

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

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 broken-smt-backend
1+
CORE
22
union_list.c
33

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 broken-smt-backend
1+
CORE
22
main.c
33

44
^EXIT=0$

src/solvers/lowering/byte_operators.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,37 @@ static exprt unpack_rec(
237237
member_offset_bits += *element_width;
238238
}
239239
}
240+
else if(src.type().id() == ID_union || src.type().id() == ID_union_tag)
241+
{
242+
const union_typet &union_type = to_union_type(ns.follow(src.type()));
243+
const union_typet::componentst &components = union_type.components();
244+
245+
mp_integer max_width = 0;
246+
typet max_comp_type;
247+
irep_idt max_comp_name;
248+
249+
for(const auto &comp : components)
250+
{
251+
auto element_width = pointer_offset_bits(comp.type(), ns);
252+
253+
if(!element_width.has_value() || *element_width <= max_width)
254+
continue;
255+
256+
max_width = *element_width;
257+
max_comp_type = comp.type();
258+
max_comp_name = comp.get_name();
259+
}
260+
261+
if(max_width > 0)
262+
{
263+
member_exprt member(src, max_comp_name, max_comp_type);
264+
exprt sub =
265+
unpack_rec(member, little_endian, offset, max_bytes, ns, true);
266+
267+
for(const auto &op : sub.operands())
268+
array.copy_to_operands(op);
269+
}
270+
}
240271
else if(src.type().id()!=ID_empty)
241272
{
242273
// a basic type; we turn that into extractbits while considering
@@ -456,6 +487,36 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
456487
if(!failed)
457488
return simplify_expr(s, ns);
458489
}
490+
else if(src.type().id() == ID_union || src.type().id() == ID_union_tag)
491+
{
492+
const union_typet &union_type = to_union_type(ns.follow(src.type()));
493+
const union_typet::componentst &components = union_type.components();
494+
495+
mp_integer max_width = 0;
496+
typet max_comp_type;
497+
irep_idt max_comp_name;
498+
499+
for(const auto &comp : components)
500+
{
501+
auto element_width = pointer_offset_bits(comp.type(), ns);
502+
503+
if(!element_width.has_value() || *element_width <= max_width)
504+
continue;
505+
506+
max_width = *element_width;
507+
max_comp_type = comp.type();
508+
max_comp_name = comp.get_name();
509+
}
510+
511+
if(max_width > 0)
512+
{
513+
byte_extract_exprt tmp(unpacked);
514+
tmp.type() = max_comp_type;
515+
516+
return union_exprt(
517+
max_comp_name, lower_byte_extract(tmp, ns), union_type);
518+
}
519+
}
459520

460521
const exprt &root=unpacked.op();
461522
const exprt &offset=unpacked.offset();

unit/solvers/lowering/byte_operators.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ SCENARIO("byte_extract_lowering", "[core][solvers][lowering][byte_extract]")
113113
{"pad", c_bit_field_typet(u8, 4)},
114114
{"comp2", u8}}),
115115
#endif
116-
// union_typet({{"compA", u32}, {"compB", u64}}),
116+
union_typet({{"compA", u32}, {"compB", u64}}),
117117
c_enum_typet(u16),
118118
c_enum_typet(unsignedbv_typet(128)),
119119
array_typet(u8, size),

0 commit comments

Comments
 (0)