Skip to content

Commit e0a5ddf

Browse files
committed
fx
1 parent 2de1a3e commit e0a5ddf

File tree

2 files changed

+82
-69
lines changed

2 files changed

+82
-69
lines changed

src/solvers/flattening/bv_pointers.cpp

+82-65
Original file line numberDiff line numberDiff line change
@@ -71,25 +71,6 @@ bv_pointerst::endianness_map(const typet &type, bool little_endian) const
7171
return bv_endianness_mapt{type, little_endian, ns, bv_width};
7272
}
7373

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-
9374
bvt bv_pointerst::object_literals(const bvt &bv, const pointer_typet &type)
9475
{
9576
const auto width = type.get_width();
@@ -110,7 +91,7 @@ bvt bv_pointerst::object_literals(const bvt &bv, const pointer_typet &type)
11091
}
11192

11293
// 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);
11495
}
11596

11697
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)
133114
}
134115

135116
// 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));
137118
}
138119

139120
bvt bv_pointerst::object_offset_encoding(
140-
const bvt &object,
141-
const bvt &offset,
121+
const bvt &object_bv,
122+
const bvt &offset_bv,
142123
const pointer_typet &type)
143124
{
144125
const auto width = type.get_width();
126+
PRECONDITION(object_bv.size() == width);
127+
PRECONDITION(offset_bv.size() == width);
145128

146129
// 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) {
148131
return l == const_literal(false);
149-
}) != offset.end())
132+
}) != offset_bv.end())
150133
{
151134
// offset is not zero, add to the pointer table
152135
auto number = numbered_pointers.size();
153-
numbered_pointers.emplace_back(object, offset);
136+
numbered_pointers.emplace_back(object_bv, offset_bv);
154137

155138
// Encode the table index.
156139
// Also set top bit to distinguish from object-only pointers.
@@ -162,7 +145,7 @@ bvt bv_pointerst::object_offset_encoding(
162145
// Offset is zero, just zero-extend object number.
163146
// Top bit is zero to indicate object-only pointer.
164147
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)});
166149
}
167150
}
168151

@@ -187,17 +170,7 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
187170
bvt invalid_bv = object_literals(
188171
encode(pointer_logic.get_invalid_object(), type), type);
189172

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);
201174
}
202175
}
203176
}
@@ -214,6 +187,32 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
214187
return l;
215188
}
216189
}
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+
}
217216
else if(expr.id()==ID_lt || expr.id()==ID_le ||
218217
expr.id()==ID_gt || expr.id()==ID_ge)
219218
{
@@ -509,8 +508,7 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr)
509508
count == 1,
510509
"there should be exactly one pointer-type operand in a pointer-type sum");
511510

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);
514512

515513
forall_operands(it, plus_expr)
516514
{
@@ -530,7 +528,8 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr)
530528
bvt op=convert_bv(*it);
531529
CHECK_RETURN(!op.empty());
532530

533-
op = bv_utils.extension(op, offset_bits, rep);
531+
op = bv_utils.extension(op, bits, rep);
532+
CHECK_RETURN(op.size() == sum.size());
534533

535534
sum=bv_utils.add(sum, op);
536535
}
@@ -853,15 +852,24 @@ exprt bv_pointerst::bv_get_rec(
853852
// Top bit set?
854853
if(value.front() == '1')
855854
{
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+
}
865873
}
866874
else
867875
{
@@ -890,7 +898,7 @@ bvt bv_pointerst::offset_arithmetic(
890898
const bvt &bv,
891899
const mp_integer &x)
892900
{
893-
const std::size_t offset_bits = get_offset_width(type);
901+
const std::size_t offset_bits = type.get_width();
894902

895903
return offset_arithmetic(
896904
type, bv, 1, bv_utils.build_constant(x, offset_bits));
@@ -908,44 +916,53 @@ bvt bv_pointerst::offset_arithmetic(
908916
index.type().id()==ID_signedbv?bv_utilst::representationt::SIGNED:
909917
bv_utilst::representationt::UNSIGNED;
910918

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);
913922

914923
return offset_arithmetic(type, bv, factor, bv_index);
915924
}
916925

917926
bvt bv_pointerst::offset_arithmetic(
918927
const pointer_typet &type,
919-
const bvt &bv,
928+
const bvt &pointer_bv,
920929
const mp_integer &factor,
921-
const bvt &index)
930+
const bvt &index_bv)
922931
{
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;
924936

925937
if(factor==1)
926-
bv_index=index;
938+
{
939+
index_scaled_bv = index_bv;
940+
}
927941
else
928942
{
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);
931946
}
932947

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());
935950

936-
bvt offset_bv = offset_literals(bv, type);
951+
DATA_INVARIANT(
952+
offset_bv.size() == index_scaled_bv.size(),
953+
"pointer offset bitvector width");
937954

938-
bvt bv_tmp = bv_utils.add(offset_bv, bv_index);
955+
bvt sum = bv_utils.add(offset_bv, index_scaled_bv);
939956

940-
return object_offset_encoding(object_literals(bv, type), bv_tmp, type);
957+
return object_offset_encoding(object_literals(pointer_bv, type), sum, type);
941958
}
942959

943960
bvt bv_pointerst::add_addr(const exprt &expr)
944961
{
945962
std::size_t a=pointer_logic.add_object(expr);
946963

947964
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();
949966
const std::size_t max_objects=std::size_t(1)<<object_bits;
950967

951968
if(a==max_objects)

src/solvers/flattening/bv_pointers.h

-4
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ class bv_pointerst:public boolbvt
3232
protected:
3333
pointer_logict pointer_logic;
3434

35-
std::size_t get_object_width(const pointer_typet &) const;
36-
std::size_t get_offset_width(const pointer_typet &) const;
37-
std::size_t get_address_width(const pointer_typet &) const;
38-
3935
// NOLINTNEXTLINE(readability/identifiers)
4036
typedef boolbvt SUB;
4137

0 commit comments

Comments
 (0)