Skip to content

SMT2 back-end: flatten with_exprt operands #8670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions .github/workflows/pull-request-checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ jobs:
make TAGS="[!shouldfail]" -C jbmc/unit test IPASIR=$PWD/riss.git/riss
- name: Run regression tests
run: |
export PATH=$PATH:`pwd`/src/solvers
make -C regression test-parallel JOBS=${{env.linux-vcpus}} LIBS="$PWD/riss.git/release/lib/libriss-coprocessor.a -lpthread" IPASIR=$PWD/riss.git/riss
make -C regression/cbmc test-paths-lifo
env PATH=$PATH:`pwd`/src/solvers make -C regression/cbmc test-cprover-smt2
make -C regression/cbmc test-cprover-smt2
make -C jbmc/regression test-parallel JOBS=${{env.linux-vcpus}}
- name: Check cleanup
run: |
Expand Down Expand Up @@ -153,9 +154,10 @@ jobs:
make TAGS="[!shouldfail]" -C jbmc/unit test
- name: Run regression tests
run: |
export PATH=$PATH:`pwd`/src/solvers
make -C regression test-parallel JOBS=${{env.linux-vcpus}}
make -C regression/cbmc test-paths-lifo
env PATH=$PATH:`pwd`/src/solvers make -C regression/cbmc test-cprover-smt2
make -C regression/cbmc test-cprover-smt2
make -C jbmc/regression test-parallel JOBS=${{env.linux-vcpus}}

# This job has been copied from the one above it, and modified to only build CBMC
Expand Down Expand Up @@ -339,9 +341,10 @@ jobs:
make TAGS="[!shouldfail]" -C jbmc/unit test
- name: Run regression tests
run: |
export PATH=$PATH:`pwd`/src/solvers
make -C regression test-parallel JOBS=${{env.linux-vcpus}}
make -C regression/cbmc test-paths-lifo
env PATH=$PATH:`pwd`/src/solvers make -C regression/cbmc test-cprover-smt2
make -C regression/cbmc test-cprover-smt2
make -C jbmc/regression test-parallel JOBS=${{env.linux-vcpus}}

# This job takes approximately 17 to 41 minutes
Expand Down Expand Up @@ -689,7 +692,9 @@ jobs:
- name: Run JBMC unit tests
run: cd jbmc/unit; ./unit_tests
- name: Run regression tests
run: make -C regression test-parallel JOBS=4
run: |
export PATH=$PATH:`pwd`/src/solvers
make -C regression test-parallel JOBS=4
- name: Run JBMC regression tests
run: make -C jbmc/regression test-parallel JOBS=4

Expand Down Expand Up @@ -855,7 +860,9 @@ jobs:
- name: Download minisat with make
run: make -C src minisat2-download
- name: Build CBMC with make
run: make CXX=clcache BUILD_ENV=MSVC -j${{env.windows-vcpus}} -C src
run: |
make CXX=clcache BUILD_ENV=MSVC -j${{env.windows-vcpus}} -C src
echo "$pwd\src\solvers;" >> $env:GITHUB_PATH
- name: Build unit tests with make
run: make CXX=clcache BUILD_ENV=MSVC -j${{env.windows-vcpus}} -C unit all
- name: Build jbmc with make
Expand Down
19 changes: 12 additions & 7 deletions regression/contracts-dfcc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,15 @@ add_test_pl_profile(
#)

# solver appears on the PATH in Windows already
#if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
# set_property(
# TEST "cbmc-cprover-smt2-CORE"
# PROPERTY ENVIRONMENT
# "PATH=$ENV{PATH}:$<TARGET_FILE_DIR:smt2_solver>"
# )
#endif()
if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
set_property(
TEST "contracts-dfcc-CORE"
PROPERTY ENVIRONMENT
"PATH=$ENV{PATH}:$<TARGET_FILE_DIR:smt2_solver>"
)
set_property(
TEST "contracts-non-dfcc-CORE"
PROPERTY ENVIRONMENT
"PATH=$ENV{PATH}:$<TARGET_FILE_DIR:smt2_solver>"
)
endif()
17 changes: 17 additions & 0 deletions regression/contracts-dfcc/array_struct_smt/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
typedef struct
{
int coeffs[2];
} mlk_poly;

// clang-format off
void mlk_poly_add(mlk_poly *r, const mlk_poly *b)
__CPROVER_ensures(r->coeffs[0] == __CPROVER_old(*r).coeffs[0] + b->coeffs[0])
__CPROVER_assigns(__CPROVER_object_upto(r, sizeof(mlk_poly)));
// clang-format on

int main()
{
mlk_poly r[1];
mlk_poly b[1];
mlk_poly_add(&r[0], &b[0]);
}
12 changes: 12 additions & 0 deletions regression/contracts-dfcc/array_struct_smt/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CORE
main.c
--dfcc main --replace-call-with-contract mlk_poly_add _ --no-array-field-sensitivity --cprover-smt2
^\[mlk_poly_add.overflow.1\] line 8 arithmetic overflow on signed \+
^\*\* 1 of \d+ failed
^VERIFICATION FAILED$
^EXIT=10$
^SIGNAL=0$
--
--
Make sure the SMT back-end produces valid SMT2 when structs and arrays are
nested in each other.
77 changes: 45 additions & 32 deletions src/solvers/smt2/smt2_conv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4400,50 +4400,63 @@ void smt2_convt::convert_with(const with_exprt &expr)
}
else
{
auto convert_operand = [this](const exprt &op)
{
// may need to flatten array-theory arrays in there
if(op.type().id() == ID_array && use_array_theory(op))
flatten_array(op);
else if(op.type().id() == ID_bool)
flatten2bv(op);
else
convert_expr(op);
};

std::size_t struct_width=boolbv_width(struct_type);

// figure out the offset and width of the member
const boolbv_widtht::membert &m =
boolbv_width.get_member(struct_type, component_name);

out << "(let ((?withop ";
convert_expr(expr.old());
out << ")) ";

if(m.width==struct_width)
{
// the struct is the same as the member, no concat needed,
// ?withop won't be used
convert_expr(value);
}
else if(m.offset==0)
{
// the member is at the beginning
out << "(concat "
<< "((_ extract " << (struct_width-1) << " "
<< m.width << ") ?withop) ";
convert_expr(value);
out << ")"; // concat
}
else if(m.offset+m.width==struct_width)
{
// the member is at the end
out << "(concat ";
convert_expr(value);
out << " ((_ extract " << (m.offset - 1) << " 0) ?withop))";
// the struct is the same as the member, no concat needed
convert_operand(value);
}
else
{
// most general case, need two concat-s
out << "(concat (concat "
<< "((_ extract " << (struct_width-1) << " "
<< (m.offset+m.width) << ") ?withop) ";
convert_expr(value);
out << ") ((_ extract " << (m.offset-1) << " 0) ?withop)";
out << ")"; // concat
}
out << "(let ((?withop ";
convert_operand(expr.old());
out << ")) ";

if(m.offset == 0)
{
// the member is at the beginning
out << "(concat "
<< "((_ extract " << (struct_width - 1) << " " << m.width
<< ") ?withop) ";
convert_operand(value);
out << ")"; // concat
}
else if(m.offset + m.width == struct_width)
{
// the member is at the end
out << "(concat ";
convert_operand(value);
out << " ((_ extract " << (m.offset - 1) << " 0) ?withop))";
}
else
{
// most general case, need two concat-s
out << "(concat (concat "
<< "((_ extract " << (struct_width - 1) << " "
<< (m.offset + m.width) << ") ?withop) ";
convert_operand(value);
out << ") ((_ extract " << (m.offset - 1) << " 0) ?withop)";
out << ")"; // concat
}

out << ")"; // let ?withop
out << ")"; // let ?withop
}
}
}
else if(expr_type.id() == ID_union || expr_type.id() == ID_union_tag)
Expand Down
Loading