|
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_expr: Expression to use as compound operand in the resulting |
| 28 | +/// member_exprt. |
| 29 | +/// \param union_type: Type to determine the member of. |
| 30 | +/// \param ns: Namespace to resolve tag types. |
| 31 | +/// \return Pair of a member_exprt pointing to the maximum fixed bit-width |
| 32 | +/// member of \p union_type and the bit width of that member. |
| 33 | +static optionalt<std::pair<member_exprt, mp_integer>> |
| 34 | +find_maximum_union_component( |
| 35 | + const exprt &union_expr, |
| 36 | + const union_typet &union_type, |
| 37 | + const namespacet &ns) |
| 38 | +{ |
| 39 | + const union_typet::componentst &components = union_type.components(); |
| 40 | + |
| 41 | + mp_integer max_width = 0; |
| 42 | + typet max_comp_type; |
| 43 | + irep_idt max_comp_name; |
| 44 | + |
| 45 | + for(const auto &comp : components) |
| 46 | + { |
| 47 | + auto element_width = pointer_offset_bits(comp.type(), ns); |
| 48 | + |
| 49 | + if(!element_width.has_value() || *element_width <= max_width) |
| 50 | + continue; |
| 51 | + |
| 52 | + max_width = *element_width; |
| 53 | + max_comp_type = comp.type(); |
| 54 | + max_comp_name = comp.get_name(); |
| 55 | + } |
| 56 | + |
| 57 | + if(max_width == 0) |
| 58 | + return {}; |
| 59 | + else |
| 60 | + return std::make_pair( |
| 61 | + member_exprt{union_expr, max_comp_name, max_comp_type}, max_width); |
| 62 | +} |
| 63 | + |
24 | 64 | static exprt bv_to_expr(
|
25 | 65 | const exprt &bitvector_expr,
|
26 | 66 | const typet &target_type,
|
@@ -1124,31 +1164,19 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
|
1124 | 1164 | else if(src.type().id() == ID_union || src.type().id() == ID_union_tag)
|
1125 | 1165 | {
|
1126 | 1166 | 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 |
| - |
1133 |
| - for(const auto &comp : components) |
1134 |
| - { |
1135 |
| - auto element_width = pointer_offset_bits(comp.type(), ns); |
1136 | 1167 |
|
1137 |
| - if(!element_width.has_value() || *element_width <= max_width) |
1138 |
| - continue; |
| 1168 | + const auto max_member_expr = |
| 1169 | + find_maximum_union_component(src, union_type, ns); |
1139 | 1170 |
|
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) |
| 1171 | + if(max_member_expr.has_value()) |
1146 | 1172 | {
|
1147 | 1173 | byte_extract_exprt tmp(unpacked);
|
1148 |
| - tmp.type() = max_comp_type; |
| 1174 | + tmp.type() = max_member_expr->first.type(); |
1149 | 1175 |
|
1150 | 1176 | return union_exprt(
|
1151 |
| - max_comp_name, lower_byte_extract(tmp, ns), src.type()); |
| 1177 | + max_member_expr->first.get_component_name(), |
| 1178 | + lower_byte_extract(tmp, ns), |
| 1179 | + src.type()); |
1152 | 1180 | }
|
1153 | 1181 | }
|
1154 | 1182 |
|
@@ -1945,34 +1973,19 @@ static exprt lower_byte_update_union(
|
1945 | 1973 | const optionalt<exprt> &non_const_update_bound,
|
1946 | 1974 | const namespacet &ns)
|
1947 | 1975 | {
|
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 |
| - } |
| 1976 | + const auto max_member_expr = |
| 1977 | + find_maximum_union_component(src.op(), union_type, ns); |
1965 | 1978 |
|
1966 | 1979 | PRECONDITION_WITH_DIAGNOSTICS(
|
1967 |
| - max_width > 0, |
| 1980 | + max_member_expr.has_value(), |
1968 | 1981 | "lower_byte_update of union of unknown size is not supported");
|
1969 | 1982 |
|
1970 | 1983 | 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; |
| 1984 | + bu.set_op(max_member_expr->first); |
| 1985 | + bu.type() = max_member_expr->first.type(); |
1973 | 1986 |
|
1974 | 1987 | return union_exprt{
|
1975 |
| - max_comp_name, |
| 1988 | + max_member_expr->first.get_component_name(), |
1976 | 1989 | lower_byte_update(bu, value_as_byte_array, non_const_update_bound, ns),
|
1977 | 1990 | src.type()};
|
1978 | 1991 | }
|
|
0 commit comments