Skip to content

double-width pointer encoding #6836

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-library/memcpy-01/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--bounds-check --pointer-check
^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc/Pointer28/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--pointer-check --little-endian
^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc/Pointer29/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc/Pointer_array4/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.i
--32
^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc/Pointer_byte_extract8/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--64 --unwind 4 --unwinding-assertions
^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc/address_space_size_limit1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE thorough-paths broken-smt-backend
KNOWNBUG thorough-paths broken-smt-backend
test.c
--no-simplify --unwind 300 --object-bits 8
too many addressed objects
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc/pointer-primitive-check-03/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--pointer-primitive-check
^EXIT=10$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc/union10/union_list2.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE broken-z3-smt-backend
KNOWNBUG broken-z3-smt-backend
union_list2.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc/union11/union_list.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE broken-z3-smt-backend
KNOWNBUG broken-z3-smt-backend
union_list.c

^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--harness-type call-function --max-nondet-tree-depth 4 --min-null-tree-depth 1 --function test_function
\[test_function.assertion.\d+\] line \d+ assertion list_walker->datum == \+\+i: SUCCESS
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--harness-type call-function --max-nondet-tree-depth 4 --min-null-tree-depth 1 --function test_function --nondet-globals
\[test_function.assertion.\d+\] line \d+ assertion list_walker->datum == \+\+i: SUCCESS
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 4 --harness-type call-function
^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 3 --harness-type call-function --treat-pointers-equal 'p,q;r,s,t'
^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 3 --harness-type call-function
^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 2 --harness-type call-function
^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--function func --min-null-tree-depth 10 --max-nondet-tree-depth 3 --harness-type call-function
^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE
KNOWNBUG
main.c
--harness-type call-function --function test_ptr_array --treat-pointer-as-array input_array
\[test_ptr_array\.assertion\.1\] line \d+ assertion input_array\[0\] == 0: SUCCESS
Expand Down
3 changes: 2 additions & 1 deletion src/goto-programs/goto_trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ std::string trace_numeric_value(
{
const auto &annotated_pointer_constant =
to_annotated_pointer_constant_expr(expr);
auto width = to_pointer_type(expr.type()).get_width();
// pointers use double-width
auto width = 2 * to_pointer_type(expr.type()).get_width();
auto &value = annotated_pointer_constant.get_value();
auto c = constant_exprt(value, unsignedbv_typet(width));
return numeric_representation(c, ns, options);
Expand Down
5 changes: 4 additions & 1 deletion src/solvers/flattening/boolbv_width.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,10 @@ const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const
CHECK_RETURN(entry.total_width > 0);
}
else if(type_id==ID_pointer)
entry.total_width = type_checked_cast<pointer_typet>(type).get_width();
{
// encode pointers using twice the number of bits
entry.total_width = 2 * type_checked_cast<pointer_typet>(type).get_width();
}
else if(type_id==ID_struct_tag)
entry.total_width = operator()(ns.follow_tag(to_struct_tag_type(type)));
else if(type_id==ID_union_tag)
Expand Down
71 changes: 50 additions & 21 deletions src/solvers/flattening/bv_pointers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ Author: Daniel Kroening, [email protected]
#include <util/arith_tools.h>
#include <util/byte_operators.h>
#include <util/c_types.h>
#include <util/config.h>
#include <util/exception_utils.h>
#include <util/expr_util.h>
#include <util/namespace.h>
Expand Down Expand Up @@ -71,25 +70,19 @@ bv_pointerst::endianness_map(const typet &type, bool little_endian) const
return bv_endianness_mapt{type, little_endian, ns, bv_width};
}

std::size_t bv_pointerst::get_object_width(const pointer_typet &) const
std::size_t bv_pointerst::get_object_width(const pointer_typet &type) const
{
// not actually type-dependent for now
return config.bv_encoding.object_bits;
return type.get_width();
}

std::size_t bv_pointerst::get_offset_width(const pointer_typet &type) const
{
const std::size_t pointer_width = type.get_width();
const std::size_t pointer_width = 2 * type.get_width();
const std::size_t object_width = get_object_width(type);
PRECONDITION(pointer_width >= object_width);
return pointer_width - object_width;
}

std::size_t bv_pointerst::get_address_width(const pointer_typet &type) const
{
return type.get_width();
}

bvt bv_pointerst::object_literals(const bvt &bv, const pointer_typet &type)
const
{
Expand Down Expand Up @@ -380,12 +373,34 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr)
can_cast_type<bitvector_typet>(op_type) || op_type.id() == ID_bool ||
op_type.id() == ID_c_enum || op_type.id() == ID_c_enum_tag)
{
// Cast from a bitvector type to pointer.
// We just do a zero extension.

// Cast from a bitvector type 'i' to pointer.
// 1) top bit not set: NULL + i, zero extended
// 2) top bit set: numbered pointer
const bvt &op_bv=convert_bv(op);
auto top_bit = op_bv.back();
const auto numbered_pointer_bv = prop.new_variables(bits);

for(std::size_t i = 1; i < numbered_pointers.size(); i++)
{
auto cond = bv_utils.equal(
op_bv,
bv_utilst::concatenate(
bv_utilst::build_constant(i, op_bv.size() - 1),
{const_literal(true)}));
bv_utils.cond_implies_equal(
cond,
bv_utilst::zero_extension(numbered_pointers[i], bits),
numbered_pointer_bv);
}

return bv_utils.zero_extension(op_bv, bits);
auto null_object_bv = object_offset_encoding(
bv_utilst::build_constant(
pointer_logic.get_null_object(), get_object_width(type)),
bv_utilst::concatenate(
bv_utilst::zero_extension(op_bv, get_offset_width(type) - 1),
{const_literal(false)}));

return bv_utils.select(top_bit, numbered_pointer_bv, null_object_bv);
}
}
else if(expr.id()==ID_if)
Expand Down Expand Up @@ -736,17 +751,31 @@ bvt bv_pointerst::convert_bitvector(const exprt &expr)
expr.id() == ID_typecast &&
to_typecast_expr(expr).op().type().id() == ID_pointer)
{
// pointer to int
bvt op0 = convert_pointer_type(to_typecast_expr(expr).op());
// Pointer to int.
// We special-case NULL, which should always yield 0.
// Otherwise, we 'number' these, which are indicated by setting
// the top bit.
const auto &pointer_expr = to_typecast_expr(expr).op();
const bvt pointer_bv = convert_pointer_type(pointer_expr);
const auto is_null = bv_utils.is_zero(pointer_bv);
const auto target_width = boolbv_width(expr.type());

if(target_width == 0)
return conversion_failed(expr);

// squeeze it in!
if(numbered_pointers.empty())
numbered_pointers.emplace_back(bvt{});

std::size_t width=boolbv_width(expr.type());
const auto number = numbered_pointers.size();

if(width==0)
return conversion_failed(expr);
numbered_pointers.push_back(pointer_bv);

return bv_utils.zero_extension(op0, width);
return bv_utils.select(
is_null,
bv_utils.zeros(target_width),
bv_utilst::concatenate(
bv_utils.build_constant(number, target_width - 1),
{const_literal(true)}));
}
else if(expr.id() == ID_object_address)
{
Expand Down
5 changes: 4 additions & 1 deletion src/solvers/flattening/bv_pointers.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class bv_pointerst:public boolbvt

std::size_t get_object_width(const pointer_typet &) const;
std::size_t get_offset_width(const pointer_typet &) const;
std::size_t get_address_width(const pointer_typet &) const;

// NOLINTNEXTLINE(readability/identifiers)
typedef boolbvt SUB;
Expand Down Expand Up @@ -109,6 +108,10 @@ class bv_pointerst:public boolbvt
/// \param offset: Encoded offset
/// \return Pointer encoding
static bvt object_offset_encoding(const bvt &object, const bvt &offset);

/// Table that maps a 'pointer number' to its full-width bit-vector.
/// Used for conversion of pointers to integers.
std::vector<bvt> numbered_pointers;
};

#endif // CPROVER_SOLVERS_FLATTENING_BV_POINTERS_H
6 changes: 3 additions & 3 deletions src/solvers/flattening/bv_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,17 +179,17 @@ class bv_utilst
static bvt
extension(const bvt &bv, std::size_t new_size, representationt rep);

bvt sign_extension(const bvt &bv, std::size_t new_size)
static bvt sign_extension(const bvt &bv, std::size_t new_size)
{
return extension(bv, new_size, representationt::SIGNED);
}

bvt zero_extension(const bvt &bv, std::size_t new_size)
static bvt zero_extension(const bvt &bv, std::size_t new_size)
{
return extension(bv, new_size, representationt::UNSIGNED);
}

bvt zeros(std::size_t new_size) const
static bvt zeros(std::size_t new_size)
{
bvt result;
result.resize(new_size, const_literal(false));
Expand Down