Skip to content

Commit 0a09814

Browse files
authored
Merge pull request #7144 from tautschnig/bugfixes/smt-array-flatten
SMT2 back-end: do not flatten flattened arrays
2 parents 8bd2617 + e5d94c8 commit 0a09814

File tree

4 files changed

+60
-71
lines changed

4 files changed

+60
-71
lines changed

regression/cbmc/Array_operations2/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 broken-cprover-smt-backend
22
main.c
33

44
^\[main.assertion.12\] line 34 assertion arr\[1\].c\[2\] == 0: FAILURE$

regression/cbmc/array-function-parameters/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
test.c
33
--function test --min-null-tree-depth 2 --max-nondet-tree-depth 2 --bounds-check
44
^EXIT=10$

src/solvers/lowering/byte_operators.cpp

Lines changed: 47 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,19 +1621,14 @@ static exprt lower_byte_update_array_vector_unbounded(
16211621
plus_exprt{last_index, from_integer(1, last_index.type())}}};
16221622

16231623
// The actual value of a partial update at the end.
1624-
exprt last_update_value = lower_byte_operators(
1624+
exprt last_update_value = lower_byte_update(
16251625
byte_update_exprt{
16261626
src.id(),
16271627
index_exprt{src.op(), last_index},
1628-
from_integer(0, src.offset().type()),
1629-
byte_extract_exprt{
1630-
extract_opcode,
1631-
value_as_byte_array,
1632-
mult_exprt{
1633-
typecast_exprt::conditional_cast(last_index, subtype_size.type()),
1634-
subtype_size},
1635-
src.get_bits_per_byte(),
1636-
array_typet{bv_typet{src.get_bits_per_byte()}, tail_size}},
1628+
unary_minus_exprt{mult_exprt{
1629+
typecast_exprt::conditional_cast(last_index, subtype_size.type()),
1630+
subtype_size}},
1631+
value_as_byte_array,
16371632
src.get_bits_per_byte()},
16381633
ns);
16391634

@@ -1675,10 +1670,6 @@ static exprt lower_byte_update_array_vector_non_const(
16751670
const optionalt<exprt> &non_const_update_bound,
16761671
const namespacet &ns)
16771672
{
1678-
const irep_idt extract_opcode = src.id() == ID_byte_update_little_endian
1679-
? ID_byte_extract_little_endian
1680-
: ID_byte_extract_big_endian;
1681-
16821673
// do all arithmetic below using index/offset types - the array theory
16831674
// back-end is really picky about indices having the same type
16841675
auto subtype_size_opt = size_of_expr(subtype, ns);
@@ -1699,6 +1690,8 @@ static exprt lower_byte_update_array_vector_non_const(
16991690

17001691
// compute the number of bytes (from the update value) that are going to be
17011692
// consumed for updating the first element
1693+
const exprt update_size =
1694+
from_integer(value_as_byte_array.operands().size(), subtype_size.type());
17021695
exprt initial_bytes = minus_exprt{subtype_size, update_offset};
17031696
exprt update_bound;
17041697
if(non_const_update_bound.has_value())
@@ -1711,28 +1704,23 @@ static exprt lower_byte_update_array_vector_non_const(
17111704
DATA_INVARIANT(
17121705
value_as_byte_array.id() == ID_array,
17131706
"value should be an array expression if the update bound is constant");
1714-
update_bound =
1715-
from_integer(value_as_byte_array.operands().size(), initial_bytes.type());
1707+
update_bound = update_size;
17161708
}
17171709
initial_bytes =
17181710
if_exprt{binary_predicate_exprt{initial_bytes, ID_lt, update_bound},
17191711
initial_bytes,
17201712
update_bound};
17211713
simplify(initial_bytes, ns);
17221714

1723-
// encode the first update: update the original element at first_index with
1724-
// initial_bytes-many bytes extracted from value_as_byte_array
1725-
exprt first_update_value = lower_byte_operators(
1715+
// encode the first update: update the original element at first_index (the
1716+
// actual update will only be initial_bytes-many bytes from
1717+
// value_as_byte_array)
1718+
exprt first_update_value = lower_byte_update(
17261719
byte_update_exprt{
17271720
src.id(),
17281721
index_exprt{src.op(), first_index},
17291722
update_offset,
1730-
byte_extract_exprt{
1731-
extract_opcode,
1732-
value_as_byte_array,
1733-
from_integer(0, src.offset().type()),
1734-
src.get_bits_per_byte(),
1735-
array_typet{bv_typet{src.get_bits_per_byte()}, initial_bytes}},
1723+
value_as_byte_array,
17361724
src.get_bits_per_byte()},
17371725
ns);
17381726

@@ -1768,63 +1756,45 @@ static exprt lower_byte_update_array_vector_non_const(
17681756

17691757
with_exprt result{src.op(), first_index, first_update_value};
17701758

1771-
std::size_t i = 1;
1772-
for(; offset + step_size <= value_as_byte_array.operands().size();
1773-
offset += step_size, ++i)
1774-
{
1759+
auto lower_byte_update_array_vector_non_const_one_element =
1760+
[&src,
1761+
&first_index,
1762+
&initial_bytes,
1763+
&subtype_size,
1764+
&value_as_byte_array,
1765+
&ns,
1766+
&result](std::size_t i) -> void {
17751767
exprt where = simplify_expr(
17761768
plus_exprt{first_index, from_integer(i, first_index.type())}, ns);
17771769

1778-
exprt offset_expr = simplify_expr(
1779-
plus_exprt{
1770+
exprt neg_offset_expr = simplify_expr(
1771+
unary_minus_exprt{plus_exprt{
17801772
initial_bytes,
1781-
mult_exprt{subtype_size, from_integer(i - 1, subtype_size.type())}},
1773+
mult_exprt{subtype_size, from_integer(i - 1, subtype_size.type())}}},
17821774
ns);
17831775

1784-
exprt element = lower_byte_operators(
1776+
exprt element = lower_byte_update(
17851777
byte_update_exprt{
17861778
src.id(),
17871779
index_exprt{src.op(), where},
1788-
from_integer(0, src.offset().type()),
1789-
byte_extract_exprt{
1790-
extract_opcode,
1791-
value_as_byte_array,
1792-
std::move(offset_expr),
1793-
src.get_bits_per_byte(),
1794-
array_typet{bv_typet{src.get_bits_per_byte()}, subtype_size}},
1780+
neg_offset_expr,
1781+
value_as_byte_array,
17951782
src.get_bits_per_byte()},
17961783
ns);
17971784

17981785
result.add_to_operands(std::move(where), std::move(element));
1786+
};
1787+
1788+
std::size_t i = 1;
1789+
for(; offset + step_size <= value_as_byte_array.operands().size();
1790+
offset += step_size, ++i)
1791+
{
1792+
lower_byte_update_array_vector_non_const_one_element(i);
17991793
}
18001794

18011795
// do the tail
18021796
if(offset < value_as_byte_array.operands().size())
1803-
{
1804-
const std::size_t tail_size =
1805-
value_as_byte_array.operands().size() - offset;
1806-
1807-
exprt where = simplify_expr(
1808-
plus_exprt{first_index, from_integer(i, first_index.type())}, ns);
1809-
1810-
exprt element = lower_byte_operators(
1811-
byte_update_exprt{
1812-
src.id(),
1813-
index_exprt{src.op(), where},
1814-
from_integer(0, src.offset().type()),
1815-
byte_extract_exprt{
1816-
extract_opcode,
1817-
value_as_byte_array,
1818-
from_integer(offset, src.offset().type()),
1819-
src.get_bits_per_byte(),
1820-
array_typet{
1821-
bv_typet{src.get_bits_per_byte()},
1822-
from_integer(tail_size, size_type())}},
1823-
src.get_bits_per_byte()},
1824-
ns);
1825-
1826-
result.add_to_operands(std::move(where), std::move(element));
1827-
}
1797+
lower_byte_update_array_vector_non_const_one_element(i);
18281798

18291799
return simplify_expr(std::move(result), ns);
18301800
}
@@ -2333,9 +2303,14 @@ static exprt lower_byte_update(
23332303
if_exprt mask_shifted{
23342304
offset_ge_zero,
23352305
shl_exprt{mask, offset_in_bits},
2336-
lshr_exprt{mask, offset_in_bits}};
2306+
lshr_exprt{mask, unary_minus_exprt{offset_in_bits}}};
23372307
if(!is_little_endian)
2308+
{
23382309
mask_shifted.true_case().swap(mask_shifted.false_case());
2310+
to_shift_expr(mask_shifted.true_case())
2311+
.distance()
2312+
.swap(to_shift_expr(mask_shifted.false_case()).distance());
2313+
}
23392314

23402315
// original_bits &= ~mask
23412316
bitand_exprt bitand_expr{val_before, bitnot_exprt{mask_shifted}};
@@ -2365,9 +2340,14 @@ static exprt lower_byte_update(
23652340
if_exprt value_shifted{
23662341
offset_ge_zero,
23672342
shl_exprt{zero_extended, offset_in_bits},
2368-
lshr_exprt{zero_extended, offset_in_bits}};
2343+
lshr_exprt{zero_extended, unary_minus_exprt{offset_in_bits}}};
23692344
if(!is_little_endian)
2345+
{
23702346
value_shifted.true_case().swap(value_shifted.false_case());
2347+
to_shift_expr(value_shifted.true_case())
2348+
.distance()
2349+
.swap(to_shift_expr(value_shifted.false_case()).distance());
2350+
}
23712351

23722352
// original_bits |= newvalue
23732353
bitor_exprt bitor_expr{bitand_expr, value_shifted};

src/solvers/smt2/smt2_conv.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3142,7 +3142,16 @@ void smt2_convt::convert_struct(const struct_exprt &expr)
31423142
else
31433143
{
31443144
if(components.size()==1)
3145-
convert_expr(expr.op0());
3145+
{
3146+
const exprt &op = expr.op0();
3147+
// may need to flatten array-theory arrays in there
3148+
if(op.type().id() == ID_array && use_array_theory(op))
3149+
flatten_array(op);
3150+
else if(op.type().id() == ID_bool)
3151+
flatten2bv(op);
3152+
else
3153+
convert_expr(op);
3154+
}
31463155
else
31473156
{
31483157
// SMT-LIB 2 concat is binary only
@@ -3153,7 +3162,7 @@ void smt2_convt::convert_struct(const struct_exprt &expr)
31533162
exprt op=expr.operands()[i-1];
31543163

31553164
// may need to flatten array-theory arrays in there
3156-
if(op.type().id() == ID_array)
3165+
if(op.type().id() == ID_array && use_array_theory(op))
31573166
flatten_array(op);
31583167
else if(op.type().id() == ID_bool)
31593168
flatten2bv(op);

0 commit comments

Comments
 (0)