Skip to content

Commit 2de1a3e

Browse files
committed
pointer encoding
1 parent 971b8ba commit 2de1a3e

File tree

2 files changed

+98
-38
lines changed

2 files changed

+98
-38
lines changed

src/solvers/flattening/bv_pointers.cpp

Lines changed: 88 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -91,33 +91,79 @@ std::size_t bv_pointerst::get_address_width(const pointer_typet &type) const
9191
}
9292

9393
bvt bv_pointerst::object_literals(const bvt &bv, const pointer_typet &type)
94-
const
9594
{
96-
const std::size_t offset_width = get_offset_width(type);
97-
const std::size_t object_width = get_object_width(type);
98-
PRECONDITION(bv.size() >= offset_width + object_width);
95+
const auto width = type.get_width();
96+
PRECONDITION(width == bv.size());
97+
98+
const auto result = prop.new_variables(width);
9999

100-
return bvt(
101-
bv.begin() + offset_width, bv.begin() + offset_width + object_width);
100+
for(std::size_t i = 0; i < numbered_pointers.size(); i++)
101+
{
102+
auto cond = bv_utils.equal(
103+
bv,
104+
bv_utilst::concatenate(
105+
bv_utilst::build_constant(i, width - 1), {const_literal(true)}));
106+
bv_utils.cond_implies_equal(
107+
cond,
108+
bv_utilst::zero_extension(numbered_pointers[i].first, width),
109+
result);
110+
}
111+
112+
// the top bit distinguishes 'object only' vs. 'table encoded'
113+
return bv_utils.select(bv.back(), bv_utils.zeros(width), result);
102114
}
103115

104116
bvt bv_pointerst::offset_literals(const bvt &bv, const pointer_typet &type)
105-
const
106117
{
107-
const std::size_t offset_width = get_offset_width(type);
108-
PRECONDITION(bv.size() >= offset_width);
118+
const auto width = type.get_width();
119+
PRECONDITION(width == bv.size());
120+
121+
const auto result = prop.new_variables(width);
109122

110-
return bvt(bv.begin(), bv.begin() + offset_width);
123+
for(std::size_t i = 0; i < numbered_pointers.size(); i++)
124+
{
125+
auto cond = bv_utils.equal(
126+
bv,
127+
bv_utilst::concatenate(
128+
bv_utilst::build_constant(i, width - 1), {const_literal(true)}));
129+
bv_utils.cond_implies_equal(
130+
cond,
131+
bv_utilst::sign_extension(numbered_pointers[i].second, width),
132+
result);
133+
}
134+
135+
// the top bit distinguishes 'object only' vs. 'table encoded'
136+
return bv_utils.select(bv.back(), bv_utils.zeros(width), result);
111137
}
112138

113-
bvt bv_pointerst::object_offset_encoding(const bvt &object, const bvt &offset)
139+
bvt bv_pointerst::object_offset_encoding(
140+
const bvt &object,
141+
const bvt &offset,
142+
const pointer_typet &type)
114143
{
115-
bvt result;
116-
result.reserve(offset.size() + object.size());
117-
result.insert(result.end(), offset.begin(), offset.end());
118-
result.insert(result.end(), object.begin(), object.end());
144+
const auto width = type.get_width();
119145

120-
return result;
146+
// is the offset zero?
147+
if(std::find_if_not(offset.begin(), offset.end(), [](literalt l) {
148+
return l == const_literal(false);
149+
}) != offset.end())
150+
{
151+
// offset is not zero, add to the pointer table
152+
auto number = numbered_pointers.size();
153+
numbered_pointers.emplace_back(object, offset);
154+
155+
// Encode the table index.
156+
// Also set top bit to distinguish from object-only pointers.
157+
return bv_utilst::concatenate(
158+
bv_utilst::build_constant(number, width - 1), {const_literal(true)});
159+
}
160+
else
161+
{
162+
// Offset is zero, just zero-extend object number.
163+
// Top bit is zero to indicate object-only pointer.
164+
return bv_utilst::concatenate(
165+
bv_utilst::zero_extension(object, width - 1), {const_literal(false)});
166+
}
121167
}
122168

123169
literalt bv_pointerst::convert_rest(const exprt &expr)
@@ -794,42 +840,49 @@ exprt bv_pointerst::bv_get_rec(
794840
bvt value_bv(bv.begin() + offset, bv.begin() + offset + bits);
795841

796842
std::string value = bits_to_string(prop, value_bv);
797-
std::string value_addr = bits_to_string(prop, object_literals(value_bv, pt));
798-
std::string value_offset =
799-
bits_to_string(prop, offset_literals(value_bv, pt));
800-
801843
// we treat these like bit-vector constants, but with
802844
// some additional annotation
803-
804845
const irep_idt bvrep = make_bvrep(bits, [&value](std::size_t i) {
805846
return value[value.size() - 1 - i] == '1';
806847
});
807848

808849
constant_exprt result(bvrep, type);
809850

810851
pointer_logict::pointert pointer;
811-
pointer.object =
812-
numeric_cast_v<std::size_t>(binary2integer(value_addr, false));
813-
pointer.offset=binary2integer(value_offset, true);
852+
853+
// Top bit set?
854+
if(value.front() == '1')
855+
{
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);
865+
}
866+
else
867+
{
868+
// It's an object only, offset is zero.
869+
pointer.object = numeric_cast_v<std::size_t>(binary2integer(value, false));
870+
pointer.offset = 0;
871+
}
814872

815873
return annotated_pointer_constant_exprt{
816874
bvrep, pointer_logic.pointer_expr(pointer, pt)};
817875
}
818876

819877
bvt bv_pointerst::encode(std::size_t addr, const pointer_typet &type) const
820878
{
821-
const std::size_t offset_bits = get_offset_width(type);
822-
const std::size_t object_bits = get_object_width(type);
823-
824-
bvt zero_offset(offset_bits, const_literal(false));
879+
const auto width = type.get_width();
825880

826-
// set variable part
827-
bvt object;
828-
object.reserve(object_bits);
829-
for(std::size_t i=0; i<object_bits; i++)
830-
object.push_back(const_literal((addr & (std::size_t(1) << i)) != 0));
881+
auto object = bv_utilst::build_constant(addr, width - 1);
831882

832-
return object_offset_encoding(object, zero_offset);
883+
// Offset is zero, just zero-extend object number.
884+
// Top bit is zero to indicate object-only pointer.
885+
return bv_utilst::concatenate(object, {const_literal(false)});
833886
}
834887

835888
bvt bv_pointerst::offset_arithmetic(
@@ -884,7 +937,7 @@ bvt bv_pointerst::offset_arithmetic(
884937

885938
bvt bv_tmp = bv_utils.add(offset_bv, bv_index);
886939

887-
return object_offset_encoding(object_literals(bv, type), bv_tmp);
940+
return object_offset_encoding(object_literals(bv, type), bv_tmp, type);
888941
}
889942

890943
bvt bv_pointerst::add_addr(const exprt &expr)

src/solvers/flattening/bv_pointers.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,21 +94,28 @@ class bv_pointerst:public boolbvt
9494
/// \param bv: Encoded pointer
9595
/// \param type: Type of the encoded pointer
9696
/// \return Vector of literals identifying the object part of \p bv
97-
bvt object_literals(const bvt &bv, const pointer_typet &type) const;
97+
bvt object_literals(const bvt &bv, const pointer_typet &type);
9898

9999
/// Given a pointer encoded in \p bv, extract the literals representing the
100100
/// offset into an object that the pointer points to.
101101
/// \param bv: Encoded pointer
102102
/// \param type: Type of the encoded pointer
103103
/// \return Vector of literals identifying the offset part of \p bv
104-
bvt offset_literals(const bvt &bv, const pointer_typet &type) const;
104+
bvt offset_literals(const bvt &bv, const pointer_typet &type);
105105

106106
/// Construct a pointer encoding from given encodings of \p object and \p
107107
/// offset.
108108
/// \param object: Encoded object
109109
/// \param offset: Encoded offset
110+
/// \param type: Type of the encoded pointer
110111
/// \return Pointer encoding
111-
static bvt object_offset_encoding(const bvt &object, const bvt &offset);
112+
bvt object_offset_encoding(
113+
const bvt &object,
114+
const bvt &offset,
115+
const pointer_typet &type);
116+
117+
/// Table that maps a 'pointer number' to its object/offset pair
118+
std::vector<std::pair<bvt, bvt>> numbered_pointers;
112119
};
113120

114121
#endif // CPROVER_SOLVERS_FLATTENING_BV_POINTERS_H

0 commit comments

Comments
 (0)