Skip to content

Commit b8a80cb

Browse files
authored
Merge pull request #5746 from tautschnig/find_widest_union_component
Make computation of widest union member widely available
2 parents 9f164e4 + 4acaa86 commit b8a80cb

File tree

4 files changed

+50
-52
lines changed

4 files changed

+50
-52
lines changed

src/solvers/lowering/byte_operators.cpp

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,41 +21,6 @@ Author: Daniel Kroening, [email protected]
2121
#include <util/simplify_expr.h>
2222
#include <util/string_constant.h>
2323

24-
/// Determine the member of maximum fixed bit width in a union type. If no
25-
/// member, or no member of fixed and non-zero width can be found, return
26-
/// nullopt.
27-
/// \param union_type: Type to determine the member of.
28-
/// \param ns: Namespace to resolve tag types.
29-
/// \return Pair of a componentt pointing to the maximum fixed bit-width
30-
/// member of \p union_type and the bit width of that member.
31-
static optionalt<std::pair<struct_union_typet::componentt, mp_integer>>
32-
find_widest_union_component(const union_typet &union_type, const namespacet &ns)
33-
{
34-
const union_typet::componentst &components = union_type.components();
35-
36-
mp_integer max_width = 0;
37-
typet max_comp_type;
38-
irep_idt max_comp_name;
39-
40-
for(const auto &comp : components)
41-
{
42-
auto element_width = pointer_offset_bits(comp.type(), ns);
43-
44-
if(!element_width.has_value() || *element_width <= max_width)
45-
continue;
46-
47-
max_width = *element_width;
48-
max_comp_type = comp.type();
49-
max_comp_name = comp.get_name();
50-
}
51-
52-
if(max_width == 0)
53-
return {};
54-
else
55-
return std::make_pair(
56-
struct_union_typet::componentt{max_comp_name, max_comp_type}, max_width);
57-
}
58-
5924
static exprt bv_to_expr(
6025
const exprt &bitvector_expr,
6126
const typet &target_type,
@@ -155,7 +120,7 @@ static union_exprt bv_to_union_expr(
155120
if(components.empty())
156121
return union_exprt{irep_idt{}, nil_exprt{}, union_type};
157122

158-
const auto widest_member = find_widest_union_component(union_type, ns);
123+
const auto widest_member = union_type.find_widest_union_component(ns);
159124

160125
std::size_t component_bits;
161126
if(widest_member.has_value())
@@ -1222,7 +1187,7 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
12221187
{
12231188
const union_typet &union_type = to_union_type(ns.follow(src.type()));
12241189

1225-
const auto widest_member = find_widest_union_component(union_type, ns);
1190+
const auto widest_member = union_type.find_widest_union_component(ns);
12261191

12271192
if(widest_member.has_value())
12281193
{
@@ -2029,7 +1994,7 @@ static exprt lower_byte_update_union(
20291994
const optionalt<exprt> &non_const_update_bound,
20301995
const namespacet &ns)
20311996
{
2032-
const auto widest_member = find_widest_union_component(union_type, ns);
1997+
const auto widest_member = union_type.find_widest_union_component(ns);
20331998

20341999
PRECONDITION_WITH_DIAGNOSTICS(
20352000
widest_member.has_value(),

src/util/pointer_offset_size.cpp

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -154,23 +154,16 @@ pointer_offset_bits(const typet &type, const namespacet &ns)
154154
else if(type.id()==ID_union)
155155
{
156156
const union_typet &union_type=to_union_type(type);
157-
mp_integer result=0;
158-
159-
// compute max
160-
161-
for(const auto &c : union_type.components())
162-
{
163-
const typet &subtype = c.type();
164-
auto sub_size = pointer_offset_bits(subtype, ns);
165157

166-
if(!sub_size.has_value())
167-
return {};
158+
if(union_type.components().empty())
159+
return mp_integer{0};
168160

169-
if(*sub_size > result)
170-
result = *sub_size;
171-
}
161+
const auto widest_member = union_type.find_widest_union_component(ns);
172162

173-
return result;
163+
if(widest_member.has_value())
164+
return widest_member->second;
165+
else
166+
return {};
174167
}
175168
else if(type.id()==ID_signedbv ||
176169
type.id()==ID_unsignedbv ||

src/util/std_types.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Author: Daniel Kroening, [email protected]
1515
#include "arith_tools.h"
1616
#include "bv_arithmetic.h"
1717
#include "namespace.h"
18+
#include "pointer_offset_size.h"
1819
#include "std_expr.h"
1920
#include "string2int.h"
2021

@@ -287,3 +288,34 @@ constant_exprt &vector_typet::size()
287288
{
288289
return static_cast<constant_exprt &>(add(ID_size));
289290
}
291+
292+
optionalt<std::pair<struct_union_typet::componentt, mp_integer>>
293+
union_typet::find_widest_union_component(const namespacet &ns) const
294+
{
295+
const union_typet::componentst &comps = components();
296+
297+
optionalt<mp_integer> max_width;
298+
typet max_comp_type;
299+
irep_idt max_comp_name;
300+
301+
for(const auto &comp : comps)
302+
{
303+
auto element_width = pointer_offset_bits(comp.type(), ns);
304+
305+
if(!element_width.has_value())
306+
return {};
307+
308+
if(max_width.has_value() && *element_width <= *max_width)
309+
continue;
310+
311+
max_width = *element_width;
312+
max_comp_type = comp.type();
313+
max_comp_name = comp.get_name();
314+
}
315+
316+
if(!max_width.has_value())
317+
return {};
318+
else
319+
return std::make_pair(
320+
struct_union_typet::componentt{max_comp_name, max_comp_type}, *max_width);
321+
}

src/util/std_types.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,14 @@ class union_typet:public struct_union_typet
400400
: struct_union_typet(ID_union, std::move(_components))
401401
{
402402
}
403+
404+
/// Determine the member of maximum bit width in a union type. If no member,
405+
/// or a member of non-fixed width can be found, return nullopt.
406+
/// \param ns: Namespace to resolve tag types.
407+
/// \return Pair of a componentt pointing to the maximum fixed bit-width
408+
/// member of the union type and the bit width of that member.
409+
optionalt<std::pair<struct_union_typet::componentt, mp_integer>>
410+
find_widest_union_component(const namespacet &ns) const;
403411
};
404412

405413
/// Check whether a reference to a typet is a \ref union_typet.

0 commit comments

Comments
 (0)