Skip to content

Commit 848e633

Browse files
committed
Use bv_typet to fix type consistency in byte-operator lowering
Previously we fixed the extracted bytes to be unsigned bitvectors, but we should not actually impose (un)signedness as we do not actually interpret the bytes as numeric values. This fixes byte operators over floating-point values, and makes various SMT-solver tests pass as the SMT back-end is more strict about typing and therefore was more frequently affected by this bug. To make all this work it was also necessary to extend and fix the simplifier's handling of bv_typet expressions, and also cover one more case of type casts in the bitvector back-end. The tests Array_operations1/test.desc Float-equality1/test_no_equality.desc memory_allocation1/test.desc union12/test.desc union6/test.desc union7/test.desc continue to fail on Windows and thus cannot yet be enabled.
1 parent eed359b commit 848e633

File tree

16 files changed

+143
-91
lines changed

16 files changed

+143
-91
lines changed

regression/cbmc/Bitfields3/paths.desc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ main.c
66
^VERIFICATION SUCCESSFUL$
77
--
88
^warning: ignoring
9+
--
10+
This test is marked broken-smt-backend for performance reasons only: it passes,
11+
but takes 5 seconds to do so.

regression/cbmc/Bitfields3/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--pointer-check --bounds-check
44
^EXIT=0$

regression/cbmc/Malloc23/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--pointer-check
44
^EXIT=10$

regression/cbmc/Pointer_Arithmetic11/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--pointer-check --little-endian
44
^EXIT=0$

regression/cbmc/Pointer_byte_extract2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--little-endian
44
^EXIT=10$

regression/cbmc/Pointer_byte_extract9/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33

44
^EXIT=10$

regression/cbmc/Quantifiers-assignment/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33

44
^\*\* Results:$

regression/cbmc/byte_update3/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--little-endian
44
^EXIT=0$

regression/cbmc/byte_update5/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--little-endian
44
^EXIT=0$

regression/cbmc/memory_allocation2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33
--bounds-check
44
^EXIT=10$

src/solvers/flattening/boolbv_typecast.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,13 @@ bool boolbvt::type_conversion(
415415
}
416416
break;
417417

418+
case bvtypet::IS_BV:
419+
INVARIANT(
420+
src_width == dest_width,
421+
"source bitvector with shall equal the destination bitvector width");
422+
dest=src;
423+
return false;
424+
418425
default:
419426
if(src_type.id()==ID_bool)
420427
{

src/solvers/lowering/byte_operators.cpp

Lines changed: 61 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,11 @@ static exprt bv_to_expr(
274274
target_type.id() == ID_c_enum || target_type.id() == ID_c_enum_tag ||
275275
target_type.id() == ID_string)
276276
{
277+
std::size_t width = to_bitvector_type(bitvector_expr.type()).get_width();
278+
exprt bv_expr =
279+
typecast_exprt::conditional_cast(bitvector_expr, bv_typet{width});
277280
return simplify_expr(
278-
typecast_exprt::conditional_cast(bitvector_expr, target_type), ns);
281+
typecast_exprt::conditional_cast(bv_expr, target_type), ns);
279282
}
280283

281284
if(target_type.id() == ID_struct)
@@ -371,7 +374,7 @@ static array_exprt unpack_array_vector(
371374
// insert offset_bytes-many nil bytes into the output array
372375
byte_operands.resize(
373376
numeric_cast_v<std::size_t>(*offset_bytes - (*offset_bytes % el_bytes)),
374-
from_integer(0, unsignedbv_typet(8)));
377+
from_integer(0, bv_typet{8}));
375378
}
376379
}
377380

@@ -409,7 +412,7 @@ static array_exprt unpack_array_vector(
409412
const std::size_t size = byte_operands.size();
410413
return array_exprt(
411414
std::move(byte_operands),
412-
array_typet(unsignedbv_typet(8), from_integer(size, size_type())));
415+
array_typet{bv_typet{8}, from_integer(size, size_type())});
413416
}
414417

415418
/// Extract bytes from a sequence of bitvector-typed elements.
@@ -432,7 +435,7 @@ static void process_bit_fields(
432435
const namespacet &ns)
433436
{
434437
const concatenation_exprt concatenation{std::move(bit_fields),
435-
unsignedbv_typet{total_bits}};
438+
bv_typet{total_bits}};
436439

437440
exprt sub =
438441
unpack_rec(concatenation, little_endian, offset_bytes, max_bytes, ns, true);
@@ -530,7 +533,7 @@ static array_exprt unpack_struct(
530533
const std::size_t bits_int = numeric_cast_v<std::size_t>(*component_bits);
531534
bit_fields->first.insert(
532535
little_endian ? bit_fields->first.begin() : bit_fields->first.end(),
533-
typecast_exprt::conditional_cast(member, unsignedbv_typet{bits_int}));
536+
typecast_exprt::conditional_cast(member, bv_typet{bits_int}));
534537
bit_fields->second += bits_int;
535538

536539
member_offset_bits += *component_bits;
@@ -565,9 +568,8 @@ static array_exprt unpack_struct(
565568
ns);
566569

567570
const std::size_t size = byte_operands.size();
568-
return array_exprt{
569-
std::move(byte_operands),
570-
array_typet{unsignedbv_typet{8}, from_integer(size, size_type())}};
571+
return array_exprt{std::move(byte_operands),
572+
array_typet{bv_typet{8}, from_integer(size, size_type())}};
571573
}
572574

573575
/// Rewrite a complex_exprt into its individual bytes.
@@ -607,9 +609,8 @@ unpack_complex(const exprt &src, bool little_endian, const namespacet &ns)
607609
std::make_move_iterator(sub_imag.operands().end()));
608610

609611
const std::size_t size = byte_operands.size();
610-
return array_exprt{
611-
std::move(byte_operands),
612-
array_typet{unsignedbv_typet(8), from_integer(size, size_type())}};
612+
return array_exprt{std::move(byte_operands),
613+
array_typet{bv_typet{8}, from_integer(size, size_type())}};
613614
}
614615

615616
/// Rewrite an object into its individual bytes.
@@ -713,8 +714,7 @@ static exprt unpack_rec(
713714
else if(src.type().id() == ID_pointer)
714715
{
715716
return unpack_rec(
716-
typecast_exprt(
717-
src, unsignedbv_typet(to_pointer_type(src.type()).get_width())),
717+
typecast_exprt{src, bv_typet{to_pointer_type(src.type()).get_width()}},
718718
little_endian,
719719
offset_bytes,
720720
max_bytes,
@@ -759,10 +759,11 @@ static exprt unpack_rec(
759759
for(mp_integer i=0; i<bits; i+=8)
760760
{
761761
extractbits_exprt extractbits(
762-
src,
763-
from_integer(i+7, index_type()),
762+
typecast_exprt::conditional_cast(
763+
src, bv_typet{numeric_cast_v<std::size_t>(bits)}),
764+
from_integer(i + 7, index_type()),
764765
from_integer(i, index_type()),
765-
unsignedbv_typet(8));
766+
bv_typet{8});
766767

767768
// endianness_mapt should be the point of reference for mapping out
768769
// endianness, but we need to work on elements here instead of
@@ -776,11 +777,11 @@ static exprt unpack_rec(
776777
const std::size_t size = byte_operands.size();
777778
return array_exprt(
778779
std::move(byte_operands),
779-
array_typet(unsignedbv_typet(8), from_integer(size, size_type())));
780+
array_typet{bv_typet{8}, from_integer(size, size_type())});
780781
}
781782

782783
return array_exprt(
783-
{}, array_typet(unsignedbv_typet(8), from_integer(0, size_type())));
784+
{}, array_typet{bv_typet{8}, from_integer(0, size_type())});
784785
}
785786

786787
/// Rewrite a byte extraction of a complex-typed result to byte extraction of
@@ -1258,7 +1259,7 @@ static exprt lower_byte_update_array_vector_non_const(
12581259
byte_extract_exprt{extract_opcode,
12591260
value_as_byte_array,
12601261
from_integer(0, src.offset().type()),
1261-
array_typet{unsignedbv_typet{8}, initial_bytes}}},
1262+
array_typet{bv_typet{8}, initial_bytes}}},
12621263
ns)};
12631264

12641265
// We will update one array/vector element at a time - compute the number of
@@ -1298,7 +1299,7 @@ static exprt lower_byte_update_array_vector_non_const(
12981299
byte_extract_exprt{extract_opcode,
12991300
value_as_byte_array,
13001301
std::move(offset_expr),
1301-
array_typet{unsignedbv_typet{8}, subtype_size}}},
1302+
array_typet{bv_typet{8}, subtype_size}}},
13021303
ns);
13031304

13041305
result.add_to_operands(std::move(where), std::move(element));
@@ -1318,11 +1319,11 @@ static exprt lower_byte_update_array_vector_non_const(
13181319
src.id(),
13191320
index_exprt{src.op(), where},
13201321
from_integer(0, src.offset().type()),
1321-
byte_extract_exprt{extract_opcode,
1322-
value_as_byte_array,
1323-
from_integer(offset, src.offset().type()),
1324-
array_typet{unsignedbv_typet{8},
1325-
from_integer(tail_size, size_type())}}},
1322+
byte_extract_exprt{
1323+
extract_opcode,
1324+
value_as_byte_array,
1325+
from_integer(offset, src.offset().type()),
1326+
array_typet{bv_typet{8}, from_integer(tail_size, size_type())}}},
13261327
ns);
13271328

13281329
result.add_to_operands(std::move(where), std::move(element));
@@ -1414,9 +1415,9 @@ static exprt lower_byte_update_array_vector(
14141415
src.id(),
14151416
index_exprt{src.op(), from_integer(i, index_type())},
14161417
from_integer(update_offset < 0 ? 0 : update_offset, src.offset().type()),
1417-
array_exprt{std::move(update_values),
1418-
array_typet{unsignedbv_typet{8},
1419-
from_integer(update_size, size_type())}}};
1418+
array_exprt{
1419+
std::move(update_values),
1420+
array_typet{bv_typet{8}, from_integer(update_size, size_type())}}};
14201421
elements.push_back(lower_byte_operators(bu, ns));
14211422
}
14221423

@@ -1493,21 +1494,18 @@ static exprt lower_byte_update_struct(
14931494
extract_opcode,
14941495
src.op(),
14951496
from_integer(0, src.offset().type()),
1496-
array_typet{unsignedbv_typet{8}, src_size_opt.value()}};
1497+
array_typet{bv_typet{8}, src_size_opt.value()}};
14971498

14981499
byte_update_exprt bu = src;
14991500
bu.op() = lower_byte_extract(byte_extract_expr, ns);
15001501

15011502
return lower_byte_extract(
1502-
byte_extract_exprt{extract_opcode,
1503-
lower_byte_update_byte_array_vector(
1504-
bu,
1505-
unsignedbv_typet{8},
1506-
value_as_byte_array,
1507-
non_const_update_bound,
1508-
ns),
1509-
from_integer(0, src.offset().type()),
1510-
src.type()},
1503+
byte_extract_exprt{
1504+
extract_opcode,
1505+
lower_byte_update_byte_array_vector(
1506+
bu, bv_typet{8}, value_as_byte_array, non_const_update_bound, ns),
1507+
from_integer(0, src.offset().type()),
1508+
src.type()},
15111509
ns);
15121510
}
15131511

@@ -1544,11 +1542,10 @@ static exprt lower_byte_update_struct(
15441542
const bool little_endian = src.id() == ID_byte_update_little_endian;
15451543
if(shift != 0)
15461544
{
1547-
member =
1548-
concatenation_exprt{typecast_exprt::conditional_cast(
1549-
member, unsignedbv_typet{element_bits_int}),
1550-
from_integer(0, unsignedbv_typet{shift}),
1551-
unsignedbv_typet{shift + element_bits_int}};
1545+
member = concatenation_exprt{
1546+
typecast_exprt::conditional_cast(member, bv_typet{element_bits_int}),
1547+
from_integer(0, bv_typet{shift}),
1548+
bv_typet{shift + element_bits_int}};
15521549
if(!little_endian)
15531550
member.op0().swap(member.op1());
15541551
}
@@ -1557,9 +1554,9 @@ static exprt lower_byte_update_struct(
15571554
src.id(),
15581555
std::move(member),
15591556
offset,
1560-
array_exprt{std::move(update_values),
1561-
array_typet{unsignedbv_typet{8},
1562-
from_integer(update_size, size_type())}}};
1557+
array_exprt{
1558+
std::move(update_values),
1559+
array_typet{bv_typet{8}, from_integer(update_size, size_type())}}};
15631560

15641561
if(shift == 0)
15651562
elements.push_back(lower_byte_operators(bu, ns));
@@ -1569,7 +1566,7 @@ static exprt lower_byte_update_struct(
15691566
extractbits_exprt{lower_byte_operators(bu, ns),
15701567
element_bits_int - 1 + (little_endian ? shift : 0),
15711568
(little_endian ? shift : 0),
1572-
unsignedbv_typet{element_bits_int}},
1569+
bv_typet{element_bits_int}},
15731570
comp.type()));
15741571
}
15751572

@@ -1701,12 +1698,12 @@ static exprt lower_byte_update(
17011698
// build mask
17021699
exprt mask;
17031700
if(is_little_endian)
1704-
mask =
1705-
from_integer(power(2, update_size * 8) - 1, unsignedbv_typet{width});
1701+
mask = from_integer(power(2, update_size * 8) - 1, bv_typet{width});
17061702
else
1703+
{
17071704
mask = from_integer(
1708-
power(2, width) - power(2, width - update_size * 8),
1709-
unsignedbv_typet{width});
1705+
power(2, width) - power(2, width - update_size * 8), bv_typet{width});
1706+
}
17101707

17111708
const typet &offset_type = src.offset().type();
17121709
mult_exprt offset_times_eight{src.offset(), from_integer(8, offset_type)};
@@ -1722,13 +1719,13 @@ static exprt lower_byte_update(
17221719

17231720
// original_bits &= ~mask
17241721
exprt val_before =
1725-
typecast_exprt::conditional_cast(src.op(), unsignedbv_typet{type_bits});
1722+
typecast_exprt::conditional_cast(src.op(), bv_typet{type_bits});
17261723
if(width > type_bits)
17271724
{
1728-
val_before = concatenation_exprt{
1729-
from_integer(0, unsignedbv_typet{width - type_bits}),
1730-
val_before,
1731-
unsignedbv_typet{width}};
1725+
val_before =
1726+
concatenation_exprt{from_integer(0, bv_typet{width - type_bits}),
1727+
val_before,
1728+
bv_typet{width}};
17321729

17331730
if(!is_little_endian)
17341731
val_before.op0().swap(val_before.op1());
@@ -1737,17 +1734,17 @@ static exprt lower_byte_update(
17371734

17381735
// concatenate and zero-extend the value
17391736
concatenation_exprt value{exprt::operandst{value_as_byte_array.operands()},
1740-
unsignedbv_typet{update_size * 8}};
1737+
bv_typet{update_size * 8}};
17411738
if(is_little_endian)
17421739
std::reverse(value.operands().begin(), value.operands().end());
17431740

17441741
exprt zero_extended;
17451742
if(width > update_size * 8)
17461743
{
1747-
zero_extended = concatenation_exprt{
1748-
from_integer(0, unsignedbv_typet{width - update_size * 8}),
1749-
value,
1750-
unsignedbv_typet{width}};
1744+
zero_extended =
1745+
concatenation_exprt{from_integer(0, bv_typet{width - update_size * 8}),
1746+
value,
1747+
bv_typet{width}};
17511748

17521749
if(!is_little_endian)
17531750
zero_extended.op0().swap(zero_extended.op1());
@@ -1769,10 +1766,8 @@ static exprt lower_byte_update(
17691766
{
17701767
return simplify_expr(
17711768
typecast_exprt::conditional_cast(
1772-
extractbits_exprt{bitor_expr,
1773-
width - 1,
1774-
width - type_bits,
1775-
unsignedbv_typet{type_bits}},
1769+
extractbits_exprt{
1770+
bitor_expr, width - 1, width - type_bits, bv_typet{type_bits}},
17761771
src.type()),
17771772
ns);
17781773
}
@@ -1840,8 +1835,7 @@ exprt lower_byte_update(const byte_update_exprt &src, const namespacet &ns)
18401835
extract_opcode,
18411836
src.value(),
18421837
from_integer(0, src.offset().type()),
1843-
array_typet{unsignedbv_typet{8},
1844-
from_integer(max_update_bytes, size_type())}};
1838+
array_typet{bv_typet{8}, from_integer(max_update_bytes, size_type())}};
18451839

18461840
const array_exprt value_as_byte_array =
18471841
to_array_expr(lower_byte_extract(byte_extract_expr, ns));

src/solvers/smt2/smt2_conv.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2243,8 +2243,9 @@ void smt2_convt::convert_typecast(const typecast_exprt &expr)
22432243
// this just passes through
22442244
convert_expr(src);
22452245
}
2246-
else if(src_type.id()==ID_unsignedbv ||
2247-
src_type.id()==ID_signedbv)
2246+
else if(
2247+
src_type.id() == ID_unsignedbv || src_type.id() == ID_signedbv ||
2248+
src_type.id() == ID_bv)
22482249
{
22492250
// integer to pointer
22502251

0 commit comments

Comments
 (0)