Skip to content

Commit 9288864

Browse files
authored
Merge pull request #5832 from tautschnig/bv_pointers-api
bv_pointerst: encapsulate offset/object bit layout
2 parents eeb48a2 + ad7584b commit 9288864

File tree

2 files changed

+104
-85
lines changed

2 files changed

+104
-85
lines changed

src/solvers/flattening/bv_pointers.cpp

Lines changed: 61 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -128,21 +128,20 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
128128
if(!bv.empty())
129129
{
130130
const pointer_typet &type = to_pointer_type(operands[0].type());
131+
bvt object_bv = object_literals(bv, type);
131132

132-
bvt invalid_bv = encode(pointer_logic.get_invalid_object(), type);
133+
bvt invalid_bv = object_literals(
134+
encode(pointer_logic.get_invalid_object(), type), type);
133135

134136
const std::size_t object_bits =
135137
bv_pointers_width.get_object_width(type);
136-
const std::size_t offset_bits =
137-
bv_pointers_width.get_offset_width(type);
138138

139139
bvt equal_invalid_bv;
140-
equal_invalid_bv.resize(object_bits);
140+
equal_invalid_bv.reserve(object_bits);
141141

142142
for(std::size_t i=0; i<object_bits; i++)
143143
{
144-
equal_invalid_bv[i]=prop.lequal(bv[offset_bits+i],
145-
invalid_bv[offset_bits+i]);
144+
equal_invalid_bv.push_back(prop.lequal(object_bv[i], invalid_bv[i]));
146145
}
147146

148147
return prop.land(equal_invalid_bv);
@@ -601,20 +600,18 @@ bvt bv_pointerst::convert_bitvector(const exprt &expr)
601600
expr.id() == ID_pointer_offset &&
602601
to_unary_expr(expr).op().type().id() == ID_pointer)
603602
{
604-
const exprt &op0 = to_unary_expr(expr).op();
605-
bvt op0_bv = convert_bv(op0);
606-
607603
std::size_t width=boolbv_width(expr.type());
608604

609605
if(width==0)
610606
return conversion_failed(expr);
611607

612-
// we need to strip off the object part
613-
op0_bv.resize(
614-
bv_pointers_width.get_offset_width(to_pointer_type(op0.type())));
608+
const exprt &op0 = to_unary_expr(expr).op();
609+
const bvt &op0_bv = convert_bv(op0);
610+
611+
bvt offset_bv = offset_literals(op0_bv, to_pointer_type(op0.type()));
615612

616613
// we do a sign extension to permit negative offsets
617-
return bv_utils.sign_extension(op0_bv, width);
614+
return bv_utils.sign_extension(offset_bv, width);
618615
}
619616
else if(
620617
expr.id() == ID_object_size &&
@@ -641,22 +638,17 @@ bvt bv_pointerst::convert_bitvector(const exprt &expr)
641638
expr.id() == ID_pointer_object &&
642639
to_unary_expr(expr).op().type().id() == ID_pointer)
643640
{
644-
const exprt &op0 = to_unary_expr(expr).op();
645-
bvt op0_bv = convert_bv(op0);
646-
647641
std::size_t width=boolbv_width(expr.type());
648642

649643
if(width==0)
650644
return conversion_failed(expr);
651645

652-
// erase offset bits
646+
const exprt &op0 = to_unary_expr(expr).op();
647+
const bvt &op0_bv = convert_bv(op0);
653648

654-
op0_bv.erase(
655-
op0_bv.begin() + 0,
656-
op0_bv.begin() +
657-
bv_pointers_width.get_offset_width(to_pointer_type(op0.type())));
649+
bvt object_bv = object_literals(op0_bv, to_pointer_type(op0.type()));
658650

659-
return bv_utils.zero_extension(op0_bv, width);
651+
return bv_utils.zero_extension(object_bv, width);
660652
}
661653
else if(
662654
expr.id() == ID_typecast &&
@@ -678,42 +670,47 @@ bvt bv_pointerst::convert_bitvector(const exprt &expr)
678670
return SUB::convert_bitvector(expr);
679671
}
680672

681-
exprt bv_pointerst::bv_get_rec(
682-
const exprt &expr,
683-
const bvt &bv,
684-
std::size_t offset,
685-
const typet &type) const
673+
static std::string bits_to_string(const propt &prop, const bvt &bv)
686674
{
687-
if(type.id()!=ID_pointer)
688-
return SUB::bv_get_rec(expr, bv, offset, type);
675+
std::string result;
689676

690-
std::string value_addr, value_offset, value;
691-
692-
const std::size_t bits = boolbv_width(to_pointer_type(type));
693-
const std::size_t offset_bits =
694-
bv_pointers_width.get_offset_width(to_pointer_type(type));
695-
for(std::size_t i=0; i<bits; i++)
677+
for(const auto &literal : bv)
696678
{
697679
char ch=0;
698-
std::size_t bit_nr=i+offset;
699680

700681
// clang-format off
701-
switch(prop.l_get(bv[bit_nr]).get_value())
682+
switch(prop.l_get(literal).get_value())
702683
{
703684
case tvt::tv_enumt::TV_FALSE: ch = '0'; break;
704685
case tvt::tv_enumt::TV_TRUE: ch = '1'; break;
705686
case tvt::tv_enumt::TV_UNKNOWN: ch = '0'; break;
706687
}
707688
// clang-format on
708689

709-
value=ch+value;
710-
711-
if(i<offset_bits)
712-
value_offset=ch+value_offset;
713-
else
714-
value_addr=ch+value_addr;
690+
result = ch + result;
715691
}
716692

693+
return result;
694+
}
695+
696+
exprt bv_pointerst::bv_get_rec(
697+
const exprt &expr,
698+
const bvt &bv,
699+
std::size_t offset,
700+
const typet &type) const
701+
{
702+
if(type.id() != ID_pointer)
703+
return SUB::bv_get_rec(expr, bv, offset, type);
704+
705+
const pointer_typet &pt = to_pointer_type(type);
706+
const std::size_t bits = boolbv_width(pt);
707+
bvt value_bv(bv.begin() + offset, bv.begin() + offset + bits);
708+
709+
std::string value = bits_to_string(prop, value_bv);
710+
std::string value_addr = bits_to_string(prop, object_literals(value_bv, pt));
711+
std::string value_offset =
712+
bits_to_string(prop, offset_literals(value_bv, pt));
713+
717714
// we treat these like bit-vector constants, but with
718715
// some additional annotation
719716

@@ -729,8 +726,7 @@ exprt bv_pointerst::bv_get_rec(
729726
pointer.offset=binary2integer(value_offset, true);
730727

731728
// we add the elaborated expression as operand
732-
result.copy_to_operands(
733-
pointer_logic.pointer_expr(pointer, to_pointer_type(type)));
729+
result.copy_to_operands(pointer_logic.pointer_expr(pointer, pt));
734730

735731
return std::move(result);
736732
}
@@ -740,18 +736,15 @@ bvt bv_pointerst::encode(std::size_t addr, const pointer_typet &type) const
740736
const std::size_t offset_bits = bv_pointers_width.get_offset_width(type);
741737
const std::size_t object_bits = bv_pointers_width.get_object_width(type);
742738

743-
bvt bv;
744-
bv.reserve(boolbv_width(type));
745-
746-
// set offset to zero
747-
for(std::size_t i=0; i<offset_bits; i++)
748-
bv.push_back(const_literal(false));
739+
bvt zero_offset(offset_bits, const_literal(false));
749740

750741
// set variable part
742+
bvt object;
743+
object.reserve(object_bits);
751744
for(std::size_t i=0; i<object_bits; i++)
752-
bv.push_back(const_literal((addr & (std::size_t(1) << i)) != 0));
745+
object.push_back(const_literal((addr & (std::size_t(1) << i)) != 0));
753746

754-
return bv;
747+
return object_offset_encoding(object, zero_offset);
755748
}
756749

757750
bvt bv_pointerst::offset_arithmetic(
@@ -761,19 +754,13 @@ bvt bv_pointerst::offset_arithmetic(
761754
{
762755
const std::size_t offset_bits = bv_pointers_width.get_offset_width(type);
763756

764-
bvt bv1=bv;
765-
bv1.resize(offset_bits); // strip down
757+
bvt bv1 = offset_literals(bv, type);
766758

767759
bvt bv2=bv_utils.build_constant(x, offset_bits);
768760

769761
bvt tmp=bv_utils.add(bv1, bv2);
770762

771-
// copy offset bits
772-
bvt result = bv;
773-
for(std::size_t i=0; i<offset_bits; i++)
774-
result[i] = tmp[i];
775-
776-
return result;
763+
return object_offset_encoding(object_literals(bv, type), tmp);
777764
}
778765

779766
bvt bv_pointerst::offset_arithmetic(
@@ -810,17 +797,14 @@ bvt bv_pointerst::offset_arithmetic(
810797
bv_index=bv_utils.unsigned_multiplier(index, bv_factor);
811798
}
812799

813-
bv_index=bv_utils.zero_extension(bv_index, bv.size());
800+
const std::size_t offset_bits = bv_pointers_width.get_offset_width(type);
801+
bv_index = bv_utils.zero_extension(bv_index, offset_bits);
814802

815-
bvt bv_tmp=bv_utils.add(bv, bv_index);
803+
bvt offset_bv = offset_literals(bv, type);
816804

817-
// copy lower parts of result
818-
bvt result = bv;
819-
const std::size_t offset_bits = bv_pointers_width.get_offset_width(type);
820-
for(std::size_t i=0; i<offset_bits; i++)
821-
result[i] = bv_tmp[i];
805+
bvt bv_tmp = bv_utils.add(offset_bv, bv_index);
822806

823-
return result;
807+
return object_offset_encoding(object_literals(bv, type), bv_tmp);
824808
}
825809

826810
bvt bv_pointerst::add_addr(const exprt &expr)
@@ -846,9 +830,8 @@ void bv_pointerst::do_postponed(
846830
{
847831
if(postponed.expr.id() == ID_is_dynamic_object)
848832
{
849-
const std::size_t offset_bits = bv_pointers_width.get_offset_width(
850-
to_pointer_type(to_unary_expr(postponed.expr).op().type()));
851-
833+
const auto &type =
834+
to_pointer_type(to_unary_expr(postponed.expr).op().type());
852835
const auto &objects = pointer_logic.objects;
853836
std::size_t number=0;
854837

@@ -860,12 +843,9 @@ void bv_pointerst::do_postponed(
860843

861844
// only compare object part
862845
pointer_typet pt = pointer_type(expr.type());
863-
bvt bv = encode(number, pt);
864-
865-
bv.erase(bv.begin(), bv.begin()+offset_bits);
846+
bvt bv = object_literals(encode(number, pt), type);
866847

867-
bvt saved_bv=postponed.op;
868-
saved_bv.erase(saved_bv.begin(), saved_bv.begin()+offset_bits);
848+
bvt saved_bv = object_literals(postponed.op, type);
869849

870850
POSTCONDITION(bv.size()==saved_bv.size());
871851
PRECONDITION(postponed.bv.size()==1);
@@ -881,9 +861,8 @@ void bv_pointerst::do_postponed(
881861
}
882862
else if(postponed.expr.id()==ID_object_size)
883863
{
884-
const std::size_t offset_bits = bv_pointers_width.get_offset_width(
885-
to_pointer_type(to_unary_expr(postponed.expr).op().type()));
886-
864+
const auto &type =
865+
to_pointer_type(to_unary_expr(postponed.expr).op().type());
887866
const auto &objects = pointer_logic.objects;
888867
std::size_t number=0;
889868

@@ -904,12 +883,9 @@ void bv_pointerst::do_postponed(
904883

905884
// only compare object part
906885
pointer_typet pt = pointer_type(expr.type());
907-
bvt bv = encode(number, pt);
908-
909-
bv.erase(bv.begin(), bv.begin()+offset_bits);
886+
bvt bv = object_literals(encode(number, pt), type);
910887

911-
bvt saved_bv=postponed.op;
912-
saved_bv.erase(saved_bv.begin(), saved_bv.begin()+offset_bits);
888+
bvt saved_bv = object_literals(postponed.op, type);
913889

914890
bvt size_bv = convert_bv(object_size);
915891

src/solvers/flattening/bv_pointers.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,49 @@ class bv_pointerst:public boolbvt
104104
postponed_listt postponed_list;
105105

106106
void do_postponed(const postponedt &postponed);
107+
108+
/// Given a pointer encoded in \p bv, extract the literals identifying the
109+
/// object that the pointer points to.
110+
/// \param bv: Encoded pointer
111+
/// \param type: Type of the encoded pointer
112+
/// \return Vector of literals identifying the object part of \p bv
113+
bvt object_literals(const bvt &bv, const pointer_typet &type) const
114+
{
115+
const std::size_t offset_width = bv_pointers_width.get_offset_width(type);
116+
const std::size_t object_width = bv_pointers_width.get_object_width(type);
117+
PRECONDITION(bv.size() >= offset_width + object_width);
118+
119+
return bvt(
120+
bv.begin() + offset_width, bv.begin() + offset_width + object_width);
121+
}
122+
123+
/// Given a pointer encoded in \p bv, extract the literals representing the
124+
/// offset into an object that the pointer points to.
125+
/// \param bv: Encoded pointer
126+
/// \param type: Type of the encoded pointer
127+
/// \return Vector of literals identifying the offset part of \p bv
128+
bvt offset_literals(const bvt &bv, const pointer_typet &type) const
129+
{
130+
const std::size_t offset_width = bv_pointers_width.get_offset_width(type);
131+
PRECONDITION(bv.size() >= offset_width);
132+
133+
return bvt(bv.begin(), bv.begin() + offset_width);
134+
}
135+
136+
/// Construct a pointer encoding from given encodings of \p object and \p
137+
/// offset.
138+
/// \param object: Encoded object
139+
/// \param offset: Encoded offset
140+
/// \return Pointer encoding
141+
static bvt object_offset_encoding(const bvt &object, const bvt &offset)
142+
{
143+
bvt result;
144+
result.reserve(offset.size() + object.size());
145+
result.insert(result.end(), offset.begin(), offset.end());
146+
result.insert(result.end(), object.begin(), object.end());
147+
148+
return result;
149+
}
107150
};
108151

109152
#endif // CPROVER_SOLVERS_FLATTENING_BV_POINTERS_H

0 commit comments

Comments
 (0)