|
2 | 2 |
|
3 | 3 | #include "struct_encoding.h" |
4 | 4 |
|
| 5 | +#include <util/arith_tools.h> |
5 | 6 | #include <util/bitvector_expr.h> |
6 | 7 | #include <util/bitvector_types.h> |
7 | 8 | #include <util/make_unique.h> |
@@ -38,9 +39,14 @@ typet struct_encodingt::encode(typet type) const |
38 | 39 | work_queue.pop(); |
39 | 40 | if(const auto struct_tag = type_try_dynamic_cast<struct_tag_typet>(current)) |
40 | 41 | { |
41 | | - const auto width = (*boolbv_width)(*struct_tag); |
| 42 | + auto width = (*boolbv_width)(*struct_tag); |
| 43 | + // The bit vector theory of SMT disallows zero bit length length bit |
| 44 | + // vectors. C++ gives a minimum size for a struct (even an empty struct) |
| 45 | + // as being one byte; in order to ensure that structs have unique memory |
| 46 | + // locations. Therefore encoding empty structs as having 8 bits / 1 byte |
| 47 | + // is a reasonable solution in this case. |
42 | 48 | if(width == 0) |
43 | | - UNIMPLEMENTED_FEATURE("support for zero bit width structs."); |
| 49 | + width = 8; |
44 | 50 | current = bv_typet{width}; |
45 | 51 | } |
46 | 52 | if(const auto array = type_try_dynamic_cast<array_typet>(current)) |
@@ -102,11 +108,16 @@ static exprt encode(const with_exprt &with, const namespacet &ns) |
102 | 108 | return struct_exprt{components, tag_type}; |
103 | 109 | } |
104 | 110 |
|
| 111 | +/// Non-empty structs are flattened into a large bit vector using concatenation |
| 112 | +/// to express all the member operands of \p struct_expr. Empty structs are |
| 113 | +/// encoded as a zero byte. This has useful properties such as - |
| 114 | +/// * A zero byte is valid SMT, unlike zero length bit vectors. |
| 115 | +/// * Any two zero byte instances are always equal. This property would not |
| 116 | +/// be true of two instances of a non-det byte for instance. |
105 | 117 | static exprt encode(const struct_exprt &struct_expr) |
106 | 118 | { |
107 | | - INVARIANT( |
108 | | - !struct_expr.operands().empty(), |
109 | | - "empty structs may not be encoded into SMT terms."); |
| 119 | + if(struct_expr.operands().empty()) |
| 120 | + return from_integer(0, bv_typet{8}); |
110 | 121 | if(struct_expr.operands().size() == 1) |
111 | 122 | return struct_expr.operands().front(); |
112 | 123 | return concatenation_exprt{struct_expr.operands(), struct_expr.type()}; |
|
0 commit comments