@@ -71,25 +71,6 @@ bv_pointerst::endianness_map(const typet &type, bool little_endian) const
71
71
return bv_endianness_mapt{type, little_endian, ns, bv_width};
72
72
}
73
73
74
- std::size_t bv_pointerst::get_object_width (const pointer_typet &) const
75
- {
76
- // not actually type-dependent for now
77
- return config.bv_encoding .object_bits ;
78
- }
79
-
80
- std::size_t bv_pointerst::get_offset_width (const pointer_typet &type) const
81
- {
82
- const std::size_t pointer_width = type.get_width ();
83
- const std::size_t object_width = get_object_width (type);
84
- PRECONDITION (pointer_width >= object_width);
85
- return pointer_width - object_width;
86
- }
87
-
88
- std::size_t bv_pointerst::get_address_width (const pointer_typet &type) const
89
- {
90
- return type.get_width ();
91
- }
92
-
93
74
bvt bv_pointerst::object_literals (const bvt &bv, const pointer_typet &type)
94
75
{
95
76
const auto width = type.get_width ();
@@ -110,7 +91,7 @@ bvt bv_pointerst::object_literals(const bvt &bv, const pointer_typet &type)
110
91
}
111
92
112
93
// the top bit distinguishes 'object only' vs. 'table encoded'
113
- return bv_utils.select (bv.back (), bv_utils. zeros (width), result );
94
+ return bv_utils.select (bv.back (), result, bv );
114
95
}
115
96
116
97
bvt bv_pointerst::offset_literals (const bvt &bv, const pointer_typet &type)
@@ -133,24 +114,26 @@ bvt bv_pointerst::offset_literals(const bvt &bv, const pointer_typet &type)
133
114
}
134
115
135
116
// the top bit distinguishes 'object only' vs. 'table encoded'
136
- return bv_utils.select (bv.back (), bv_utils.zeros (width), result );
117
+ return bv_utils.select (bv.back (), result, bv_utils.zeros (width));
137
118
}
138
119
139
120
bvt bv_pointerst::object_offset_encoding (
140
- const bvt &object ,
141
- const bvt &offset ,
121
+ const bvt &object_bv ,
122
+ const bvt &offset_bv ,
142
123
const pointer_typet &type)
143
124
{
144
125
const auto width = type.get_width ();
126
+ PRECONDITION (object_bv.size () == width);
127
+ PRECONDITION (offset_bv.size () == width);
145
128
146
129
// is the offset zero?
147
- if (std::find_if_not (offset .begin (), offset .end (), [](literalt l) {
130
+ if (std::find_if_not (offset_bv .begin (), offset_bv .end (), [](literalt l) {
148
131
return l == const_literal (false );
149
- }) != offset .end ())
132
+ }) != offset_bv .end ())
150
133
{
151
134
// offset is not zero, add to the pointer table
152
135
auto number = numbered_pointers.size ();
153
- numbered_pointers.emplace_back (object, offset );
136
+ numbered_pointers.emplace_back (object_bv, offset_bv );
154
137
155
138
// Encode the table index.
156
139
// Also set top bit to distinguish from object-only pointers.
@@ -162,7 +145,7 @@ bvt bv_pointerst::object_offset_encoding(
162
145
// Offset is zero, just zero-extend object number.
163
146
// Top bit is zero to indicate object-only pointer.
164
147
return bv_utilst::concatenate (
165
- bv_utilst::zero_extension (object , width - 1 ), {const_literal (false )});
148
+ bv_utilst::zero_extension (object_bv , width - 1 ), {const_literal (false )});
166
149
}
167
150
}
168
151
@@ -187,17 +170,7 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
187
170
bvt invalid_bv = object_literals (
188
171
encode (pointer_logic.get_invalid_object (), type), type);
189
172
190
- const std::size_t object_bits = get_object_width (type);
191
-
192
- bvt equal_invalid_bv;
193
- equal_invalid_bv.reserve (object_bits);
194
-
195
- for (std::size_t i=0 ; i<object_bits; i++)
196
- {
197
- equal_invalid_bv.push_back (prop.lequal (object_bv[i], invalid_bv[i]));
198
- }
199
-
200
- return prop.land (equal_invalid_bv);
173
+ return bv_utils.equal (object_bv, invalid_bv);
201
174
}
202
175
}
203
176
}
@@ -214,6 +187,32 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
214
187
return l;
215
188
}
216
189
}
190
+ else if (expr.id () == ID_equal || expr.id () == ID_notequal)
191
+ {
192
+ if (
193
+ operands.size () == 2 && operands[0 ].type ().id () == ID_pointer &&
194
+ operands[1 ].type ().id () == ID_pointer)
195
+ {
196
+ // bit-wise comparison doesn't work because of numbered pointers
197
+ const bvt &bv0 = convert_bv (operands[0 ]);
198
+ const bvt &bv1 = convert_bv (operands[1 ]);
199
+
200
+ const pointer_typet &type0 = to_pointer_type (operands[0 ].type ());
201
+ bvt object_bv0 = object_literals (bv0, type0);
202
+ bvt offset_bv0 = offset_literals (bv0, type0);
203
+
204
+ const pointer_typet &type1 = to_pointer_type (operands[1 ].type ());
205
+ bvt object_bv1 = object_literals (bv1, type1);
206
+ bvt offset_bv1 = offset_literals (bv1, type1);
207
+
208
+ // object and offset need to match
209
+ auto equal = prop.land (
210
+ bv_utils.equal (object_bv0, object_bv1),
211
+ bv_utils.equal (offset_bv0, offset_bv1));
212
+
213
+ return expr.id () == ID_equal ? equal : !equal;
214
+ }
215
+ }
217
216
else if (expr.id ()==ID_lt || expr.id ()==ID_le ||
218
217
expr.id ()==ID_gt || expr.id ()==ID_ge)
219
218
{
@@ -509,8 +508,7 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr)
509
508
count == 1 ,
510
509
" there should be exactly one pointer-type operand in a pointer-type sum" );
511
510
512
- const std::size_t offset_bits = get_offset_width (type);
513
- bvt sum = bv_utils.build_constant (0 , offset_bits);
511
+ bvt sum = bv_utils.build_constant (0 , bits);
514
512
515
513
forall_operands (it, plus_expr)
516
514
{
@@ -530,7 +528,8 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr)
530
528
bvt op=convert_bv (*it);
531
529
CHECK_RETURN (!op.empty ());
532
530
533
- op = bv_utils.extension (op, offset_bits, rep);
531
+ op = bv_utils.extension (op, bits, rep);
532
+ CHECK_RETURN (op.size () == sum.size ());
534
533
535
534
sum=bv_utils.add (sum, op);
536
535
}
@@ -853,15 +852,24 @@ exprt bv_pointerst::bv_get_rec(
853
852
// Top bit set?
854
853
if (value.front () == ' 1' )
855
854
{
856
- // It's a pointer into the table.
857
- std::string value_addr =
858
- bits_to_string (prop, object_literals (value_bv, pt));
859
- std::string value_offset =
860
- bits_to_string (prop, offset_literals (value_bv, pt));
861
-
862
- pointer.object =
863
- numeric_cast_v<std::size_t >(binary2integer (value_addr, false ));
864
- pointer.offset = binary2integer (value_offset, true );
855
+ // It's a pointer into the table. Turn bits into number, but
856
+ // first strip top bit.
857
+ auto index = binary2integer (value.substr (1 , std::string::npos), false );
858
+
859
+ if (index >= 0 && index < numbered_pointers.size ())
860
+ {
861
+ // copy from table
862
+ const auto &entry = numbered_pointers[numeric_cast_v<std::size_t >(index )];
863
+ pointer.object = numeric_cast_v<std::size_t >(
864
+ binary2integer (bits_to_string (prop, entry.first ), false ));
865
+ pointer.offset = binary2integer (bits_to_string (prop, entry.second ), true );
866
+ }
867
+ else
868
+ {
869
+ // out of bounds, we'll make it an 'invalid pointer'
870
+ pointer.object = pointer_logic.get_invalid_object ();
871
+ pointer.offset = 0 ;
872
+ }
865
873
}
866
874
else
867
875
{
@@ -890,7 +898,7 @@ bvt bv_pointerst::offset_arithmetic(
890
898
const bvt &bv,
891
899
const mp_integer &x)
892
900
{
893
- const std::size_t offset_bits = get_offset_width ( type);
901
+ const std::size_t offset_bits = type. get_width ( );
894
902
895
903
return offset_arithmetic (
896
904
type, bv, 1 , bv_utils.build_constant (x, offset_bits));
@@ -908,44 +916,53 @@ bvt bv_pointerst::offset_arithmetic(
908
916
index .type ().id ()==ID_signedbv?bv_utilst::representationt::SIGNED:
909
917
bv_utilst::representationt::UNSIGNED;
910
918
911
- const std::size_t offset_bits = get_offset_width (type);
912
- bv_index=bv_utils.extension (bv_index, offset_bits, rep);
919
+ PRECONDITION (bv.size () == type.get_width ());
920
+
921
+ bv_index = bv_utils.extension (bv_index, bv.size (), rep);
913
922
914
923
return offset_arithmetic (type, bv, factor, bv_index);
915
924
}
916
925
917
926
bvt bv_pointerst::offset_arithmetic (
918
927
const pointer_typet &type,
919
- const bvt &bv ,
928
+ const bvt &pointer_bv ,
920
929
const mp_integer &factor,
921
- const bvt &index )
930
+ const bvt &index_bv )
922
931
{
923
- bvt bv_index;
932
+ PRECONDITION (pointer_bv.size () == type.get_width ());
933
+ PRECONDITION (index_bv.size () == type.get_width ());
934
+
935
+ bvt index_scaled_bv;
924
936
925
937
if (factor==1 )
926
- bv_index=index ;
938
+ {
939
+ index_scaled_bv = index_bv;
940
+ }
927
941
else
928
942
{
929
- bvt bv_factor=bv_utils.build_constant (factor, index .size ());
930
- bv_index = bv_utils.signed_multiplier (index , bv_factor);
943
+ bvt factor_bv = bv_utils.build_constant (factor, pointer_bv.size ());
944
+ index_scaled_bv = bv_utils.signed_multiplier (
945
+ bv_utils.sign_extension (index_bv, pointer_bv.size ()), factor_bv);
931
946
}
932
947
933
- const std:: size_t offset_bits = get_offset_width ( type);
934
- bv_index = bv_utils. sign_extension (bv_index, offset_bits );
948
+ bvt offset_bv = offset_literals (pointer_bv, type);
949
+ CHECK_RETURN (offset_bv. size () == pointer_bv. size () );
935
950
936
- bvt offset_bv = offset_literals (bv, type);
951
+ DATA_INVARIANT (
952
+ offset_bv.size () == index_scaled_bv.size (),
953
+ " pointer offset bitvector width" );
937
954
938
- bvt bv_tmp = bv_utils.add (offset_bv, bv_index );
955
+ bvt sum = bv_utils.add (offset_bv, index_scaled_bv );
939
956
940
- return object_offset_encoding (object_literals (bv , type), bv_tmp , type);
957
+ return object_offset_encoding (object_literals (pointer_bv , type), sum , type);
941
958
}
942
959
943
960
bvt bv_pointerst::add_addr (const exprt &expr)
944
961
{
945
962
std::size_t a=pointer_logic.add_object (expr);
946
963
947
964
const pointer_typet type = pointer_type (expr.type ());
948
- const std::size_t object_bits = get_object_width ( type);
965
+ const std::size_t object_bits = type. get_width ( );
949
966
const std::size_t max_objects=std::size_t (1 )<<object_bits;
950
967
951
968
if (a==max_objects)
0 commit comments