|
7 | 7 | #include <util/make_unique.h>
|
8 | 8 | #include <util/namespace.h>
|
9 | 9 | #include <util/range.h>
|
| 10 | +#include <util/simplify_expr.h> |
10 | 11 |
|
11 | 12 | #include <solvers/flattening/boolbv_width.h>
|
12 | 13 |
|
@@ -177,3 +178,31 @@ exprt struct_encodingt::encode(exprt expr) const
|
177 | 178 | }
|
178 | 179 | return expr;
|
179 | 180 | }
|
| 181 | + |
| 182 | +exprt struct_encodingt::decode( |
| 183 | + const exprt &encoded, |
| 184 | + const struct_tag_typet &original_type) const |
| 185 | +{ |
| 186 | + // The algorithm below works by extracting each of the separate fields from |
| 187 | + // the combined encoded value using a `member_exprt` which is itself encoded |
| 188 | + // into a `bit_extract_exprt`. These separated fields can then be combined |
| 189 | + // using a `struct_exprt`. This is expected to duplicate the input encoded |
| 190 | + // expression for each of the fields. However for the case where the input |
| 191 | + // encoded expression is a `constant_exprt`, expression simplification will be |
| 192 | + // able simplify away the duplicated portions of the constant and the bit |
| 193 | + // extraction expressions. This yields a clean struct expression where each |
| 194 | + // field is a separate constant containing the data solely relevant to that |
| 195 | + // field. |
| 196 | + INVARIANT( |
| 197 | + can_cast_type<bv_typet>(encoded.type()), |
| 198 | + "Structs are expected to be encoded into bit vectors."); |
| 199 | + const struct_typet definition = ns.get().follow_tag(original_type); |
| 200 | + exprt::operandst encoded_fields; |
| 201 | + for(const auto &component : definition.components()) |
| 202 | + { |
| 203 | + encoded_fields.push_back(typecast_exprt::conditional_cast( |
| 204 | + encode(member_exprt{typecast_exprt{encoded, original_type}, component}), |
| 205 | + component.type())); |
| 206 | + } |
| 207 | + return simplify_expr(struct_exprt{encoded_fields, original_type}, ns); |
| 208 | +} |
0 commit comments