Skip to content

Commit 15d8038

Browse files
author
Daniel Kroening
committed
support for base 256 bitvector representation
1 parent 0a6bdd1 commit 15d8038

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed

src/util/arith_tools.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,11 +278,23 @@ void mp_max(mp_integer &a, const mp_integer &b)
278278
a=b;
279279
}
280280

281+
#define B256
282+
281283
/// Get a bit with given index from bit-vector representation.
282284
/// \param src: the bitvector representation
283285
/// \param bit_index: index (0 is the least significant)
284286
bool get_bitvector_bit(const irep_idt &src, std::size_t bit_index)
285287
{
288+
#ifdef B256
289+
const auto byte_index = bit_index >> 3;
290+
291+
if(byte_index >= src.size())
292+
return false;
293+
294+
unsigned char byte = src[src.size() - 1 - byte_index];
295+
296+
return ((byte >> (bit_index & 7)) & 1) != 0;
297+
#else
286298
// The representation is hex, most significant nibble first.
287299
const auto nibble_index = bit_index >> 2;
288300

@@ -298,8 +310,10 @@ bool get_bitvector_bit(const irep_idt &src, std::size_t bit_index)
298310
: islower(nibble) ? nibble - 'a' + 10 : nibble - 'A' + 10;
299311

300312
return ((nibble_value >> (bit_index & 3)) & 1) != 0;
313+
#endif
301314
}
302315

316+
#ifndef B256
303317
static char nibble2hex(unsigned nibble)
304318
{
305319
PRECONDITION(nibble <= 0xf);
@@ -309,6 +323,7 @@ static char nibble2hex(unsigned nibble)
309323
else
310324
return '0' + nibble;
311325
}
326+
#endif
312327

313328
/// construct a bit-vector representation from a functor
314329
/// \param width: the width of the bit-vector
@@ -317,6 +332,35 @@ static char nibble2hex(unsigned nibble)
317332
irep_idt
318333
make_bvrep(const std::size_t width, const std::function<bool(std::size_t)> f)
319334
{
335+
#ifdef B256
336+
std::string result;
337+
result.reserve(width / 8 + 1);
338+
unsigned byte = 0;
339+
340+
for(std::size_t i = 0; i < width; i++)
341+
{
342+
const auto bit_in_byte = i % 8;
343+
344+
byte |= ((unsigned)f(i)) << bit_in_byte;
345+
346+
if(bit_in_byte == 7)
347+
{
348+
result += (char)byte;
349+
byte = 0;
350+
}
351+
}
352+
353+
if(byte != 0)
354+
result += (char)byte;
355+
356+
// drop leading zeros
357+
while(!result.empty() && result.back() == 0)
358+
result.resize(result.size() - 1);
359+
360+
std::reverse(result.begin(), result.end());
361+
362+
return result;
363+
#else
320364
std::string result;
321365
result.reserve(width / 4 + 1);
322366
unsigned nibble = 0;
@@ -347,6 +391,7 @@ make_bvrep(const std::size_t width, const std::function<bool(std::size_t)> f)
347391
return ID_0;
348392
else
349393
return result;
394+
#endif
350395
}
351396

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

src/util/expr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ bool exprt::is_boolean() const
165165
return type().id()==ID_bool;
166166
}
167167

168+
#define B256
169+
168170
/// Return whether the expression is a constant representing 0.
169171
/// Will consider the following types: ID_integer, ID_natural, ID_rational,
170172
/// ID_unsignedbv, ID_signedbv, ID_c_bool, ID_c_bit_field, ID_fixedbv,
@@ -195,7 +197,11 @@ bool exprt::is_zero() const
195197
type_id == ID_unsignedbv || type_id == ID_signedbv ||
196198
type_id == ID_c_bool || type_id == ID_c_bit_field)
197199
{
200+
#ifdef B256
201+
return constant.get_value().empty();
202+
#else
198203
return constant.value_is_zero_string();
204+
#endif
199205
}
200206
else if(type_id==ID_fixedbv)
201207
{

src/util/mp_arith.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,47 @@ const mp_integer binary2integer(const std::string &n, bool is_signed)
185185
#endif
186186
}
187187

188+
#define B256
189+
190+
#ifdef B256
191+
std::string dump_integer(mp_integer src)
192+
{
193+
std::size_t d = src.digits(256) + 1;
194+
unsigned char *buf = new unsigned char[d], *p = buf;
195+
src.dump(buf, d);
196+
while(d > 0 && *p == 0)
197+
{
198+
d--;
199+
p++;
200+
}
201+
return std::string((char *)p, d);
202+
}
203+
#endif
204+
188205
/// convert an integer to bit-vector representation with given width
189206
/// This uses two's complement for negative numbers.
190207
/// If the value is out of range, it is 'wrapped around'.
191208
const std::string integer2bv(const mp_integer &src, std::size_t width)
192209
{
210+
#ifdef B256
211+
const mp_integer p = power(2, width);
212+
213+
if(src.is_negative())
214+
{
215+
// do two's complement encoding of negative numbers
216+
mp_integer tmp = src;
217+
tmp.negate();
218+
tmp %= p;
219+
if(tmp != 0)
220+
tmp = p - tmp;
221+
return dump_integer(tmp);
222+
}
223+
else
224+
{
225+
// we 'wrap around' if 'src' is too large
226+
return dump_integer(src % p);
227+
}
228+
#else
193229
const mp_integer p = power(2, width);
194230

195231
if(src.is_negative())
@@ -207,12 +243,37 @@ const std::string integer2bv(const mp_integer &src, std::size_t width)
207243
// we 'wrap around' if 'src' is too large
208244
return integer2string(src % p, 16);
209245
}
246+
#endif
210247
}
211248

212249
/// convert a bit-vector representation (possibly signed) to integer
213250
const mp_integer
214251
bv2integer(const std::string &src, std::size_t width, bool is_signed)
215252
{
253+
#ifdef B256
254+
if(is_signed)
255+
{
256+
PRECONDITION(width >= 1);
257+
mp_integer tmp;
258+
tmp.load((const unsigned char *)src.data(), src.size());
259+
const auto p = power(2, width - 1);
260+
if(tmp >= p)
261+
{
262+
const auto result = tmp - 2 * p;
263+
PRECONDITION(result >= -p);
264+
return result;
265+
}
266+
else
267+
return tmp;
268+
}
269+
else
270+
{
271+
mp_integer result;
272+
result.load((const unsigned char *)src.data(), src.size());
273+
PRECONDITION(result < power(2, width));
274+
return result;
275+
}
276+
#else
216277
if(is_signed)
217278
{
218279
PRECONDITION(width >= 1);
@@ -233,6 +294,7 @@ bv2integer(const std::string &src, std::size_t width, bool is_signed)
233294
PRECONDITION(result < power(2, width));
234295
return result;
235296
}
297+
#endif
236298
}
237299

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

0 commit comments

Comments
 (0)