Skip to content

Commit 9384d50

Browse files
committed
Byte-operator lowering: Add support for byte-extracting unions
We already had support for structs, arrays, vectors in place; add unions following the same approach. This is required for some SV-COMP device driver benchmarks, including ldv-linux-3.16-rc1/43_2a_consumption_linux-3.16-rc1.tar.xz-43_2a-drivers--scsi--qla2xxx--tcm_qla2xxx.ko-entry_point.cil.out.i
1 parent f250e8b commit 9384d50

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/solvers/lowering/byte_operators.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,40 @@ static struct_exprt bv_to_struct_expr(
108108
return struct_exprt{std::move(operands), struct_type};
109109
}
110110

111+
/// Convert a bitvector-typed expression \p bitvector_expr to a union-typed
112+
/// expression. See \ref bv_to_expr for an overview.
113+
static union_exprt bv_to_union_expr(
114+
const exprt &bitvector_expr,
115+
const union_typet &union_type,
116+
const endianness_mapt &endianness_map,
117+
const namespacet &ns)
118+
{
119+
const union_typet::componentst &components = union_type.components();
120+
121+
mp_integer max_width = 0;
122+
typet max_comp_type;
123+
irep_idt max_comp_name;
124+
125+
for(const auto &comp : components)
126+
{
127+
auto element_width = pointer_offset_bits(comp.type(), ns);
128+
129+
if(!element_width.has_value() || *element_width <= max_width)
130+
continue;
131+
132+
max_width = *element_width;
133+
max_comp_type = comp.type();
134+
max_comp_name = comp.get_name();
135+
}
136+
137+
exprt operand = nil_exprt{};
138+
139+
if(max_width > 0)
140+
operand = bv_to_expr(bitvector_expr, max_comp_type, endianness_map, ns);
141+
142+
return union_exprt{std::move(max_comp_name), std::move(operand), union_type};
143+
}
144+
111145
/// Convert a bitvector-typed expression \p bitvector_expr to an array-typed
112146
/// expression. See \ref bv_to_expr for an overview.
113147
static array_exprt bv_to_array_expr(
@@ -296,6 +330,21 @@ static exprt bv_to_expr(
296330
result.type() = target_type;
297331
return std::move(result);
298332
}
333+
else if(target_type.id() == ID_union)
334+
{
335+
return bv_to_union_expr(
336+
bitvector_expr, to_union_type(target_type), endianness_map, ns);
337+
}
338+
else if(target_type.id() == ID_union_tag)
339+
{
340+
union_exprt result = bv_to_union_expr(
341+
bitvector_expr,
342+
ns.follow_tag(to_union_tag_type(target_type)),
343+
endianness_map,
344+
ns);
345+
result.type() = target_type;
346+
return std::move(result);
347+
}
299348
else if(target_type.id() == ID_array)
300349
{
301350
return bv_to_array_expr(

0 commit comments

Comments
 (0)