Skip to content

Commit 0a6bdd1

Browse files
author
Daniel Kroening
committed
switch representation of bit-vectors to hex
Simultaneously leading zeros are dropped. This reduces the memory consumption of bit-vectors by 4x or more.
1 parent 6c2ce78 commit 0a6bdd1

File tree

4 files changed

+107
-23
lines changed

4 files changed

+107
-23
lines changed

src/goto-programs/goto_trace.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,23 +131,34 @@ void goto_trace_stept::output(
131131
/// \return a string with the numeric representation
132132
static std::string numeric_representation(
133133
const constant_exprt &expr,
134+
const namespacet &ns,
134135
const trace_optionst &options)
135136
{
136137
std::string result;
137138
std::string prefix;
138139

140+
const typet &expr_type = expr.type();
141+
142+
const typet &underlying_type =
143+
expr_type.id() == ID_c_enum_tag
144+
? ns.follow_tag(to_c_enum_tag_type(expr_type)).subtype()
145+
: expr_type;
146+
139147
const irep_idt &value = expr.get_value();
140148

149+
const auto width = to_bitvector_type(underlying_type).get_width();
150+
151+
const mp_integer value_int = bv2integer(id2string(value), width, false);
152+
141153
if(options.hex_representation)
142154
{
143-
mp_integer value_int = bv2integer(id2string(value), value.size(), false);
144155
result = integer2string(value_int, 16);
145156
prefix = "0x";
146157
}
147158
else
148159
{
160+
result = integer2binary(value_int, width);
149161
prefix = "0b";
150-
result = id2string(value);
151162
}
152163

153164
std::ostringstream oss;
@@ -184,9 +195,7 @@ std::string trace_numeric_value(
184195
type.id()==ID_c_enum ||
185196
type.id()==ID_c_enum_tag)
186197
{
187-
const std::string &str =
188-
numeric_representation(to_constant_expr(expr), options);
189-
return str;
198+
return numeric_representation(to_constant_expr(expr), ns, options);
190199
}
191200
else if(type.id()==ID_bool)
192201
{

src/solvers/flattening/boolbv_constant.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,6 @@ bvt boolbvt::convert_constant(const constant_exprt &expr)
8181
{
8282
const auto &value = expr.get_value();
8383

84-
if(value.size() != width)
85-
{
86-
error().source_location=expr.find_source_location();
87-
error() << "wrong value length in constant: "
88-
<< expr.pretty() << eom;
89-
throw 0;
90-
}
91-
9284
for(std::size_t i=0; i<width; i++)
9385
{
9486
const bool bit = get_bitvector_bit(value, i);

src/util/arith_tools.cpp

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Author: Daniel Kroening, [email protected]
1414
#include "std_types.h"
1515
#include "std_expr.h"
1616

17+
#include <algorithm>
18+
1719
bool to_integer(const exprt &expr, mp_integer &int_value)
1820
{
1921
if(!expr.is_constant())
@@ -281,10 +283,31 @@ void mp_max(mp_integer &a, const mp_integer &b)
281283
/// \param bit_index: index (0 is the least significant)
282284
bool get_bitvector_bit(const irep_idt &src, std::size_t bit_index)
283285
{
284-
// The representation is binary, using '0'/'1',
285-
// most significant bit first.
286-
PRECONDITION(bit_index < src.size());
287-
return src[src.size() - 1 - bit_index] == '1';
286+
// The representation is hex, most significant nibble first.
287+
const auto nibble_index = bit_index >> 2;
288+
289+
if(nibble_index >= src.size())
290+
return false;
291+
292+
char nibble = src[src.size() - 1 - nibble_index];
293+
294+
DATA_INVARIANT(isxdigit(nibble), "");
295+
296+
unsigned nibble_value =
297+
isdigit(nibble) ? nibble - '0'
298+
: islower(nibble) ? nibble - 'a' + 10 : nibble - 'A' + 10;
299+
300+
return ((nibble_value >> (bit_index & 3)) & 1) != 0;
301+
}
302+
303+
static char nibble2hex(unsigned nibble)
304+
{
305+
PRECONDITION(nibble <= 0xf);
306+
307+
if(nibble >= 10)
308+
return 'A' + nibble - 10;
309+
else
310+
return '0' + nibble;
288311
}
289312

290313
/// construct a bit-vector representation from a functor
@@ -294,12 +317,36 @@ bool get_bitvector_bit(const irep_idt &src, std::size_t bit_index)
294317
irep_idt
295318
make_bvrep(const std::size_t width, const std::function<bool(std::size_t)> f)
296319
{
297-
std::string result(width, ' ');
320+
std::string result;
321+
result.reserve(width / 4 + 1);
322+
unsigned nibble = 0;
298323

299324
for(std::size_t i = 0; i < width; i++)
300-
result[width - 1 - i] = f(i) ? '1' : '0';
325+
{
326+
const auto bit_in_nibble = i % 4;
301327

302-
return result;
328+
nibble |= ((unsigned)f(i)) << bit_in_nibble;
329+
330+
if(bit_in_nibble == 3)
331+
{
332+
result += nibble2hex(nibble);
333+
nibble = 0;
334+
}
335+
}
336+
337+
if(nibble != 0)
338+
result += nibble2hex(nibble);
339+
340+
// drop leading zeros
341+
while(!result.empty() && result.back() == '0')
342+
result.resize(result.size() - 1);
343+
344+
std::reverse(result.begin(), result.end());
345+
346+
if(result.empty())
347+
return ID_0;
348+
else
349+
return result;
303350
}
304351

305352
/// perform a binary bit-wise operation, given as a functor,

src/util/mp_arith.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,17 +186,53 @@ const mp_integer binary2integer(const std::string &n, bool is_signed)
186186
}
187187

188188
/// convert an integer to bit-vector representation with given width
189+
/// This uses two's complement for negative numbers.
190+
/// If the value is out of range, it is 'wrapped around'.
189191
const std::string integer2bv(const mp_integer &src, std::size_t width)
190192
{
191-
return integer2binary(src, width);
193+
const mp_integer p = power(2, width);
194+
195+
if(src.is_negative())
196+
{
197+
// do two's complement encoding of negative numbers
198+
mp_integer tmp = src;
199+
tmp.negate();
200+
tmp %= p;
201+
if(tmp != 0)
202+
tmp = p - tmp;
203+
return integer2string(tmp, 16);
204+
}
205+
else
206+
{
207+
// we 'wrap around' if 'src' is too large
208+
return integer2string(src % p, 16);
209+
}
192210
}
193211

194212
/// convert a bit-vector representation (possibly signed) to integer
195213
const mp_integer
196214
bv2integer(const std::string &src, std::size_t width, bool is_signed)
197215
{
198-
PRECONDITION(src.size() == width);
199-
return binary2integer(src, is_signed);
216+
if(is_signed)
217+
{
218+
PRECONDITION(width >= 1);
219+
const auto tmp = string2integer(src, 16);
220+
const auto p = power(2, width - 1);
221+
if(tmp >= p)
222+
{
223+
const auto result = tmp - 2 * p;
224+
PRECONDITION(result >= -p);
225+
return result;
226+
}
227+
else
228+
return tmp;
229+
}
230+
else
231+
{
232+
const auto result = string2integer(src, 16);
233+
PRECONDITION(result < power(2, width));
234+
return result;
235+
}
200236
}
201237

202238
mp_integer::ullong_t integer2ulong(const mp_integer &n)

0 commit comments

Comments
 (0)