|
21 | 21 | #include <util/simplify_expr.h>
|
22 | 22 | #include <util/string_constant.h>
|
23 | 23 |
|
| 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 | + |
24 | 59 | static exprt bv_to_expr(
|
25 | 60 | const exprt &bitvector_expr,
|
26 | 61 | const typet &target_type,
|
@@ -1124,31 +1159,18 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
|
1124 | 1159 | else if(src.type().id() == ID_union || src.type().id() == ID_union_tag)
|
1125 | 1160 | {
|
1126 | 1161 | const union_typet &union_type = to_union_type(ns.follow(src.type()));
|
1127 |
| - const union_typet::componentst &components = union_type.components(); |
1128 |
| - |
1129 |
| - mp_integer max_width = 0; |
1130 |
| - typet max_comp_type; |
1131 |
| - irep_idt max_comp_name; |
1132 | 1162 |
|
1133 |
| - for(const auto &comp : components) |
1134 |
| - { |
1135 |
| - auto element_width = pointer_offset_bits(comp.type(), ns); |
1136 |
| - |
1137 |
| - if(!element_width.has_value() || *element_width <= max_width) |
1138 |
| - continue; |
| 1163 | + const auto widest_member = find_widest_union_component(union_type, ns); |
1139 | 1164 |
|
1140 |
| - max_width = *element_width; |
1141 |
| - max_comp_type = comp.type(); |
1142 |
| - max_comp_name = comp.get_name(); |
1143 |
| - } |
1144 |
| - |
1145 |
| - if(max_width > 0) |
| 1165 | + if(widest_member.has_value()) |
1146 | 1166 | {
|
1147 | 1167 | byte_extract_exprt tmp(unpacked);
|
1148 |
| - tmp.type() = max_comp_type; |
| 1168 | + tmp.type() = widest_member->first.type(); |
1149 | 1169 |
|
1150 | 1170 | return union_exprt(
|
1151 |
| - max_comp_name, lower_byte_extract(tmp, ns), src.type()); |
| 1171 | + widest_member->first.get_name(), |
| 1172 | + lower_byte_extract(tmp, ns), |
| 1173 | + src.type()); |
1152 | 1174 | }
|
1153 | 1175 | }
|
1154 | 1176 |
|
@@ -1945,34 +1967,19 @@ static exprt lower_byte_update_union(
|
1945 | 1967 | const optionalt<exprt> &non_const_update_bound,
|
1946 | 1968 | const namespacet &ns)
|
1947 | 1969 | {
|
1948 |
| - const union_typet::componentst &components = union_type.components(); |
1949 |
| - |
1950 |
| - mp_integer max_width = 0; |
1951 |
| - typet max_comp_type; |
1952 |
| - irep_idt max_comp_name; |
1953 |
| - |
1954 |
| - for(const auto &comp : components) |
1955 |
| - { |
1956 |
| - auto element_width = pointer_offset_bits(comp.type(), ns); |
1957 |
| - |
1958 |
| - if(!element_width.has_value() || *element_width <= max_width) |
1959 |
| - continue; |
1960 |
| - |
1961 |
| - max_width = *element_width; |
1962 |
| - max_comp_type = comp.type(); |
1963 |
| - max_comp_name = comp.get_name(); |
1964 |
| - } |
| 1970 | + const auto widest_member = find_widest_union_component(union_type, ns); |
1965 | 1971 |
|
1966 | 1972 | PRECONDITION_WITH_DIAGNOSTICS(
|
1967 |
| - max_width > 0, |
| 1973 | + widest_member.has_value(), |
1968 | 1974 | "lower_byte_update of union of unknown size is not supported");
|
1969 | 1975 |
|
1970 | 1976 | byte_update_exprt bu = src;
|
1971 |
| - bu.set_op(member_exprt{src.op(), max_comp_name, max_comp_type}); |
1972 |
| - bu.type() = max_comp_type; |
| 1977 | + bu.set_op(member_exprt{ |
| 1978 | + src.op(), widest_member->first.get_name(), widest_member->first.type()}); |
| 1979 | + bu.type() = widest_member->first.type(); |
1973 | 1980 |
|
1974 | 1981 | return union_exprt{
|
1975 |
| - max_comp_name, |
| 1982 | + widest_member->first.get_name(), |
1976 | 1983 | lower_byte_update(bu, value_as_byte_array, non_const_update_bound, ns),
|
1977 | 1984 | src.type()};
|
1978 | 1985 | }
|
|
0 commit comments