@@ -91,33 +91,79 @@ std::size_t bv_pointerst::get_address_width(const pointer_typet &type) const
91
91
}
92
92
93
93
bvt bv_pointerst::object_literals (const bvt &bv, const pointer_typet &type)
94
- const
95
94
{
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);
99
99
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);
102
114
}
103
115
104
116
bvt bv_pointerst::offset_literals (const bvt &bv, const pointer_typet &type)
105
- const
106
117
{
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);
109
122
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);
111
137
}
112
138
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)
114
143
{
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 ();
119
145
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
+ }
121
167
}
122
168
123
169
literalt bv_pointerst::convert_rest (const exprt &expr)
@@ -794,42 +840,49 @@ exprt bv_pointerst::bv_get_rec(
794
840
bvt value_bv (bv.begin () + offset, bv.begin () + offset + bits);
795
841
796
842
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
-
801
843
// we treat these like bit-vector constants, but with
802
844
// some additional annotation
803
-
804
845
const irep_idt bvrep = make_bvrep (bits, [&value](std::size_t i) {
805
846
return value[value.size () - 1 - i] == ' 1' ;
806
847
});
807
848
808
849
constant_exprt result (bvrep, type);
809
850
810
851
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
+ }
814
872
815
873
return annotated_pointer_constant_exprt{
816
874
bvrep, pointer_logic.pointer_expr (pointer, pt)};
817
875
}
818
876
819
877
bvt bv_pointerst::encode (std::size_t addr, const pointer_typet &type) const
820
878
{
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 ();
825
880
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 );
831
882
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 )});
833
886
}
834
887
835
888
bvt bv_pointerst::offset_arithmetic (
@@ -884,7 +937,7 @@ bvt bv_pointerst::offset_arithmetic(
884
937
885
938
bvt bv_tmp = bv_utils.add (offset_bv, bv_index);
886
939
887
- return object_offset_encoding (object_literals (bv, type), bv_tmp);
940
+ return object_offset_encoding (object_literals (bv, type), bv_tmp, type );
888
941
}
889
942
890
943
bvt bv_pointerst::add_addr (const exprt &expr)
0 commit comments