diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index dc2c95350c..1813a8ef4a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -21,7 +21,7 @@ env: LLVM_VERSION: 11 MINISAT_VERSION: "master" REQUIRES_RTTI: 0 - SOLVERS: Z3:STP + SOLVERS: BITWUZLA:Z3:STP STP_VERSION: 2.3.3 TCMALLOC_VERSION: 2.9.1 UCLIBC_VERSION: klee_uclibc_v1.3 @@ -29,6 +29,8 @@ env: USE_LIBCXX: 1 Z3_VERSION: 4.8.15 SQLITE_VERSION: 3400100 + BITWUZLA_VERSION: main + BITWUZLA_COMMIT: 80ef7cd803e1c71b5939c3eb951f1736388f7090 jobs: Linux: @@ -48,6 +50,7 @@ jobs: "Z3 only", "metaSMT", "STP master", + "Bitwuzla only", "Latest klee-uclibc", "Asserts disabled", "No TCMalloc, optimised runtime", @@ -109,6 +112,10 @@ jobs: env: SOLVERS: STP STP_VERSION: master + # Test just using Bitwuzla only + - name: "Bitwuzla only" + env: + SOLVERS: BITWUZLA # Check we can build latest klee-uclibc branch - name: "Latest klee-uclibc" env: @@ -172,6 +179,7 @@ jobs: name: [ "STP", "Z3", + "Bitwuzla", ] include: - name: "STP" @@ -180,6 +188,9 @@ jobs: - name: "Z3" env: SOLVERS: Z3:STP + - name: "Bitwuzla" + env: + SOLVERS: BITWUZLA:Z3 env: ENABLE_OPTIMIZED: 0 COVERAGE: 1 diff --git a/CMakeLists.txt b/CMakeLists.txt index e8317d04c0..5ce961bad5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,16 +17,16 @@ project(KLEE CXX C) # Project version ############################################################################### set(KLEE_VERSION_MAJOR 3) -set(KLEE_VERSION_MINOR 0-utbot) +set(KLEE_VERSION_MINOR 0) set(KLEE_VERSION "${KLEE_VERSION_MAJOR}.${KLEE_VERSION_MINOR}") # If a patch is needed, we can add KLEE_VERSION_PATCH # set(KLEE_VERSION_PATCH 0) # set(KLEE_VERSION "${KLEE_VERSION_MAJOR}.${KLEE_VERSION_MINOR}.${KLEE_VERSION_PATCH}") -message(STATUS "KLEE version ${KLEE_VERSION}") -set(PACKAGE_STRING "\"KLEE ${KLEE_VERSION}\"") -set(PACKAGE_URL "\"https://klee.github.io\"") +message(STATUS "KLEEF version ${KLEE_VERSION}") +set(PACKAGE_STRING "\"KLEEF ${KLEE_VERSION}\"") +set(PACKAGE_URL "\"https://toolchain-labs.com/projects/kleef.html\"") ################################################################################ # Sanity check - Disallow building in source. @@ -204,14 +204,19 @@ include(${CMAKE_SOURCE_DIR}/cmake/find_stp.cmake) include(${CMAKE_SOURCE_DIR}/cmake/find_z3.cmake) # metaSMT include(${CMAKE_SOURCE_DIR}/cmake/find_metasmt.cmake) +# bitwuzla +include(${CMAKE_SOURCE_DIR}/cmake/find_bitwuzla.cmake) -if ((NOT ${ENABLE_Z3}) AND (NOT ${ENABLE_STP}) AND (NOT ${ENABLE_METASMT})) + +if ((NOT ${ENABLE_Z3}) AND (NOT ${ENABLE_STP}) AND (NOT ${ENABLE_METASMT}) AND (NOT ${ENABLE_BITWUZLA})) message(FATAL_ERROR "No solver was specified. At least one solver is required." "You should enable a solver by passing one of more the following options" " to cmake:\n" "\"-DENABLE_SOLVER_STP=ON\"\n" "\"-DENABLE_SOLVER_Z3=ON\"\n" - "\"-DENABLE_SOLVER_METASMT=ON\"") + "\"-DENABLE_SOLVER_BITWUZLA=ON\"\n" + "\"-DENABLE_SOLVER_METASMT=ON\" + ") endif() ############################################################################### @@ -473,10 +478,10 @@ endif() ################################################################################ option(ENABLE_FLOATING_POINT "Enable KLEE's floating point extension" OFF) if (ENABLE_FLOATING_POINT) - if (NOT ${ENABLE_Z3}) + if ((NOT ${ENABLE_Z3}) AND (NOT ${ENABLE_BITWUZLA})) message (FATAL_ERROR "Floating point extension is availible only when using Z3 backend." - "You should enable Z3 by passing the following option to cmake:\n" - "\"-DENABLE_SOLVER_Z3=ON\"\n") + "You should enable either Z3 or Bitwuzla by passing the following options to cmake, respectively:\n" + "\"-DENABLE_SOLVER_Z3=ON\" or \"-DENABLE_SOLVER_BITWUZLA=ON\"\n") else() set(ENABLE_FP 1) # For config.h message(STATUS "Floating point extension enabled") @@ -506,19 +511,29 @@ endif() # KLEE uclibc support ################################################################################ set(KLEE_UCLIBC_PATH "" CACHE PATH "Path to klee-uclibc root directory") -set(KLEE_UCLIBC_BCA_NAME "klee-uclibc.bca") + +set(KLEE_UCLIBC_BCA_32_NAME "klee-uclibc-32.bca") +set(KLEE_UCLIBC_BCA_64_NAME "klee-uclibc-64.bca") + if (NOT KLEE_UCLIBC_PATH STREQUAL "") # Find the C library bitcode archive - set(KLEE_UCLIBC_C_BCA "${KLEE_UCLIBC_PATH}/lib/libc.a") - if (NOT EXISTS "${KLEE_UCLIBC_C_BCA}") + set(KLEE_UCLIBC_C_32_BCA "${KLEE_UCLIBC_PATH}-32/lib/libc.a") + set(KLEE_UCLIBC_C_64_BCA "${KLEE_UCLIBC_PATH}-64/lib/libc.a") + + if (NOT EXISTS "${KLEE_UCLIBC_C_32_BCA}" OR NOT EXISTS "${KLEE_UCLIBC_C_64_BCA}") message(FATAL_ERROR - "klee-uclibc library not found at \"${KLEE_UCLIBC_C_BCA}\". Set KLEE_UCLIBC_PATH to klee-uclibc root directory or empty string.") + "klee-uclibc library not found at \"${KLEE_UCLIBC_C_32_BCA}\" or \"${KLEE_UCLIBC_C_64_BCA}\". Set KLEE_UCLIBC_PATH to klee-uclibc root directory or empty string.") endif() - message(STATUS "Found klee-uclibc library: \"${KLEE_UCLIBC_C_BCA}\"") + message(STATUS "Found klee-uclibc library: \"${KLEE_UCLIBC_C_32_BCA}\" and \"${KLEE_UCLIBC_C_64_BCA}\"") # Copy KLEE_UCLIBC_C_BCA so KLEE can find it where it is expected. + # Create 32 and 64 bit versions execute_process(COMMAND ${CMAKE_COMMAND} -E copy - "${KLEE_UCLIBC_C_BCA}" - "${KLEE_RUNTIME_DIRECTORY}/${KLEE_UCLIBC_BCA_NAME}" + "${KLEE_UCLIBC_C_32_BCA}" + "${KLEE_RUNTIME_DIRECTORY}/${KLEE_UCLIBC_BCA_32_NAME}" + ) + execute_process(COMMAND ${CMAKE_COMMAND} -E copy + "${KLEE_UCLIBC_C_64_BCA}" + "${KLEE_RUNTIME_DIRECTORY}/${KLEE_UCLIBC_BCA_64_NAME}" ) else() message(STATUS "Skipping copying of klee-uclibc runtime") @@ -633,6 +648,12 @@ unset(_flags) configure_file(${CMAKE_SOURCE_DIR}/include/klee/Config/config.h.cmin ${CMAKE_BINARY_DIR}/include/klee/Config/config.h) +################################################################################ +# Generate `klee/klee.h` and `klee-test-comp.c` +################################################################################ +configure_file(${CMAKE_SOURCE_DIR}/include/klee/klee.h ${CMAKE_BINARY_DIR}/include/klee/klee.h COPYONLY) +configure_file(${CMAKE_SOURCE_DIR}/include/klee-test-comp.c ${CMAKE_BINARY_DIR}/include/klee-test-comp.c COPYONLY) + ################################################################################ # Generate `CompileTimeInfo.h` ################################################################################ diff --git a/README.md b/README.md index 9aefd2c9bf..b1577b18b3 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,9 @@ -KLEE Symbolic Virtual Machine +KLEEF Symbolic Virtual Machine ============================= -[![Build Status](https://github.com/klee/klee/workflows/CI/badge.svg)](https://github.com/klee/klee/actions?query=workflow%3ACI) -[![Build Status](https://api.cirrus-ci.com/github/klee/klee.svg)](https://cirrus-ci.com/github/klee/klee) -[![Coverage](https://codecov.io/gh/klee/klee/branch/master/graph/badge.svg)](https://codecov.io/gh/klee/klee) +[![Build Status](https://github.com/UnitTestBot/klee/workflows/CI/badge.svg)](https://github.com/UnitTestBot/klee/actions?query=workflow%3ACI) +[![Coverage](https://codecov.io/gh/UnitTestBot/klee/branch/main/graph/badge.svg)](https://codecov.io/gh/UnitTestBot/klee) -`KLEE` is a symbolic virtual machine built on top of the LLVM compiler -infrastructure. Currently, there are two primary components: +`KLEEF` is a complete overhaul of the KLEE symbolic execution engine for LLVM, fine-tuned for a robust analysis of industrial C/C++ code. - 1. The core symbolic virtual machine engine; this is responsible for - executing LLVM bitcode modules with support for symbolic - values. This is comprised of the code in lib/. - - 2. A POSIX/Linux emulation layer oriented towards supporting uClibc, - with additional support for making parts of the operating system - environment symbolic. - -Additionally, there is a simple library for replaying computed inputs -on native code (for closed programs). There is also a more complicated -infrastructure for replaying the inputs generated for the POSIX/Linux -emulation layer, which handles running native programs in an -environment that matches a computed test input, including setting up -files, pipes, environment variables, and passing command line -arguments. - -For further information, see the [webpage](http://klee.github.io/). +For further information, see the [webpage](https://toolchain-labs.com/projects/kleef.html). diff --git a/build.sh b/build.sh index 7d575dad08..24f537596b 100755 --- a/build.sh +++ b/build.sh @@ -29,13 +29,13 @@ SQLITE_VERSION="3400100" ## LLVM Required options LLVM_VERSION=14 ENABLE_OPTIMIZED=1 -ENABLE_DEBUG=1 +ENABLE_DEBUG=0 DISABLE_ASSERTIONS=1 REQUIRES_RTTI=1 ## Solvers Required options # SOLVERS=STP -SOLVERS=STP:Z3 +SOLVERS=BITWUZLA:Z3:STP ## Google Test Required options GTEST_VERSION=1.11.0 @@ -46,7 +46,11 @@ UCLIBC_VERSION=klee_uclibc_v1.3 ## Z3 Required options Z3_VERSION=4.8.15 + STP_VERSION=2.3.3 MINISAT_VERSION=master -BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION SQLITE_VERSION=$SQLITE_VERSION ./scripts/build/build.sh klee --install-system-deps +BITWUZLA_VERSION=main +BITWUZLA_COMMIT=80ef7cd803e1c71b5939c3eb951f1736388f7090 + +BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION BITWUZLA_VERSION=$BITWUZLA_VERSION BITWUZLA_COMMIT=$BITWUZLA_COMMIT SQLITE_VERSION=$SQLITE_VERSION ./scripts/build/build.sh klee --install-system-deps diff --git a/cmake/find_bitwuzla.cmake b/cmake/find_bitwuzla.cmake new file mode 100644 index 0000000000..82e9866dcc --- /dev/null +++ b/cmake/find_bitwuzla.cmake @@ -0,0 +1,46 @@ +#===------------------------------------------------------------------------===# +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +find_package (PkgConfig REQUIRED) +pkg_check_modules(BITWUZLA IMPORTED_TARGET bitwuzla) + +# Set the default so that if the following is true: +# * Bitwuzla was found +# * ENABLE_SOLVER_BITWUZLA is not already set as a cache variable +# +# then the default is set to `ON`. Otherwise set the default to `OFF`. +# A consequence of this is if we fail to detect Bitwuzla the first time +# subsequent calls to CMake will not change the default. + +if(BITWUZLA_FOUND) + set(ENABLE_SOLVER_BITWUZLA_DEFAULT ON) +else() + set(ENABLE_SOLVER_BITWUZLA_DEFAULT OFF) +endif() + +option(ENABLE_SOLVER_BITWUZLA "Enable Bitwuzla solver support" ${ENABLE_SOLVER_BITWUZLA_DEFAULT}) + +if (ENABLE_SOLVER_BITWUZLA) + message(STATUS "Bitwuzla solver support enabled") + if (BITWUZLA_FOUND) + message(STATUS "Found Bitwuzla") + set(ENABLE_BITWUZLA 1) # For config.h + + list(APPEND KLEE_COMPONENT_EXTRA_INCLUDE_DIRS ${BITWUZLA_INCLUDE_DIRS}) + list(APPEND KLEE_SOLVER_LIBRARIES ${BITWUZLA_LINK_LIBRARIES}) + list(APPEND KLEE_SOLVER_INCLUDE_DIRS ${BITWUZLA_INCLUDE_DIRS}) + list(APPEND KLEE_SOLVER_LIBRARY_DIRS ${BITWUZLA_LINK_LIBRARIES}) + + else() + message(FATAL_ERROR "Bitwuzla not found.") + endif() +else() + message(STATUS "Bitwuzla solver support disabled") + set(ENABLE_BITWUZLA 0) # For config.h +endif() diff --git a/include/klee-test-comp.c b/include/klee-test-comp.c index 3abfe2df5d..413011abea 100644 --- a/include/klee-test-comp.c +++ b/include/klee-test-comp.c @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// +#include #ifdef EXTERNAL #include "klee.h" #include #include -#include #include #else void klee_make_symbolic(void *addr, unsigned int nbytes, const char *name); @@ -19,19 +19,30 @@ void klee_assume(_Bool condition); __attribute__((noreturn)) void klee_silent_exit(int status); void __assert_fail(const char *assertion, const char *file, unsigned int line, const char *function); +void klee_prefer_cex(void *, uintptr_t); #endif int __VERIFIER_nondet_int(void) { int x; klee_make_symbolic(&x, sizeof(x), "int"); + klee_prefer_cex(&x, x < 1024); return x; } unsigned int __VERIFIER_nondet_uint(void) { unsigned int x; klee_make_symbolic(&x, sizeof(x), "unsigned int"); + klee_prefer_cex(&x, x < 1024); + return x; +} + +#ifdef __x86_64__ +unsigned __int128 __VERIFIER_nondet_uint128(void) { + unsigned __int128 x; + klee_make_symbolic(&x, sizeof(x), "unsigned __int128"); return x; } +#endif unsigned __VERIFIER_nondet_unsigned(void) { unsigned x; @@ -82,7 +93,7 @@ unsigned long __VERIFIER_nondet_ulong(void) { } double __VERIFIER_nondet_double(void) { - long x; + double x; klee_make_symbolic(&x, sizeof(x), "double"); return x; } @@ -96,7 +107,7 @@ void *__VERIFIER_nondet_pointer(void) { } float __VERIFIER_nondet_float(void) { - int x; + float x; klee_make_symbolic(&x, sizeof(x), "float"); return x; } diff --git a/include/klee/ADT/DisjointSetUnion.h b/include/klee/ADT/DisjointSetUnion.h new file mode 100644 index 0000000000..9a3673af64 --- /dev/null +++ b/include/klee/ADT/DisjointSetUnion.h @@ -0,0 +1,172 @@ +#ifndef KLEE_DISJOINEDSETUNION_H +#define KLEE_DISJOINEDSETUNION_H + +#include "klee/ADT/Either.h" +#include "klee/ADT/PersistentMap.h" +#include "klee/ADT/PersistentSet.h" +#include "klee/ADT/Ref.h" +#include "klee/Expr/Expr.h" +#include "klee/Expr/Symcrete.h" + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/raw_ostream.h" +DISABLE_WARNING_POP + +#include +#include +#include +#include +#include + +namespace klee { +using ExprOrSymcrete = either; + +template , + typename PRED = std::equal_to, + typename CMP = std::less> +class DisjointSetUnion { +public: + using internal_storage_ty = std::unordered_set; + using disjoint_sets_ty = + std::unordered_map, HASH, PRED>; + using iterator = typename internal_storage_ty::iterator; + +protected: + std::unordered_map parent; + std::set roots; + std::unordered_map rank; + + std::unordered_set internalStorage; + std::unordered_map, HASH, PRED> disjointSets; + + ValueType find(const ValueType &v) { // findparent + assert(parent.find(v) != parent.end()); + if (v == parent.at(v)) + return v; + parent.insert_or_assign(v, find(parent.at(v))); + return parent.at(v); + } + + ValueType constFind(const ValueType &v) const { + assert(parent.find(v) != parent.end()); + ValueType v1 = parent.at(v); + if (v == v1) + return v; + return constFind(v1); + } + + void merge(ValueType a, ValueType b) { + a = find(a); + b = find(b); + if (a == b) { + return; + } + + if (rank.at(a) < rank.at(b)) { + std::swap(a, b); + } + parent.insert_or_assign(b, a); + if (rank.at(a) == rank.at(b)) { + rank.insert_or_assign(a, rank.at(a) + 1); + } + + roots.erase(b); + disjointSets.insert_or_assign( + a, SetType::merge(disjointSets.at(a), disjointSets.at(b))); + disjointSets.erase(b); + } + + bool areJoined(const ValueType &i, const ValueType &j) const { + return constFind(i) == constFind(j); + } + +public: + iterator begin() const { return internalStorage.begin(); } + iterator end() const { return internalStorage.end(); } + + size_t numberOfValues() const noexcept { return internalStorage.size(); } + + size_t numberOfGroups() const noexcept { return disjointSets.size(); } + + bool empty() const noexcept { return numberOfValues() == 0; } + + ref findGroup(const ValueType &i) const { + return disjointSets.find(constFind(i))->second; + } + + ref findGroup(iterator it) const { + return disjointSets.find(constFind(*it))->second; + } + + void addValue(const ValueType value) { + if (internalStorage.find(value) != internalStorage.end()) { + return; + } + parent.insert({value, value}); + roots.insert(value); + rank.insert({value, 0}); + disjointSets.insert({value, new SetType(value)}); + + internalStorage.insert(value); + std::set oldRoots = roots; + for (ValueType v : oldRoots) { + if (!areJoined(v, value) && + SetType::intersects(disjointSets.at(find(v)), + disjointSets.at(find(value)))) { + merge(v, value); + } + } + } + void getAllIndependentSets(std::vector> &result) const { + for (ValueType v : roots) + result.push_back(findGroup(v)); + } + + void add(const DisjointSetUnion &b) { + std::set oldRoots = roots; + std::set newRoots = b.roots; + for (auto it : b.parent) { + parent.insert(it); + } + for (auto it : b.roots) { + roots.insert(it); + } + for (auto it : b.rank) { + rank.insert(it); + } + for (auto it : b.internalStorage) { + internalStorage.insert(it); + } + for (auto it : b.disjointSets) { + disjointSets.insert(it); + } + for (ValueType nv : newRoots) { + for (ValueType ov : oldRoots) { + if (!areJoined(ov, nv) && + SetType::intersects(disjointSets.at(find(ov)), + disjointSets.at(find(nv)))) { + merge(ov, nv); + } + } + } + } + + DisjointSetUnion() {} + + DisjointSetUnion(const internal_storage_ty &is) { + for (ValueType v : is) { + addValue(v); + } + } + +public: + internal_storage_ty is() const { return internalStorage; } + + disjoint_sets_ty ds() const { return disjointSets; } +}; +} // namespace klee + +#endif /* KLEE_DISJOINEDSETUNION_H */ diff --git a/include/klee/ADT/Either.h b/include/klee/ADT/Either.h new file mode 100644 index 0000000000..c941d33103 --- /dev/null +++ b/include/klee/ADT/Either.h @@ -0,0 +1,158 @@ +//===-- Either.h ------------------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_EITHER_H +#define KLEE_EITHER_H + +#include "klee/ADT/Ref.h" + +#include "klee/Support/Casting.h" + +#include + +namespace llvm { +class raw_ostream; +} // namespace llvm + +namespace klee { + +template class either_left; +template class either_right; + +template class either { +protected: + friend class ref>; + friend class ref>; + + /// @brief Required by klee::ref-managed objects + class ReferenceCounter _refCount; + unsigned hashValue; + + static const unsigned MAGIC_HASH_CONSTANT = 39; + +public: + using left = either_left; + using right = either_right; + + enum class EitherKind { Left, Right }; + + virtual ~either() {} + virtual EitherKind getKind() const = 0; + + static bool classof(const either *) { return true; } + virtual int compare(const either &b) = 0; + virtual bool equals(const either &b) = 0; + + unsigned hash() const { return hashValue; } +}; + +template class either_left : public either { +protected: + friend class ref>; + friend class ref>; + +private: + ref value_; + + unsigned computeHash() { + unsigned res = (unsigned)getKind(); + res = (res * either::MAGIC_HASH_CONSTANT) + value_->hash(); + either::hashValue = res; + return either::hashValue; + } + +public: + either_left(ref leftValue) : value_(leftValue) { computeHash(); }; + + ref value() const { return value_; } + operator ref const() { return value_; } + + virtual typename either::EitherKind getKind() const override { + return either::EitherKind::Left; + } + + static bool classof(const either *S) { + return S->getKind() == either::EitherKind::Left; + } + static bool classof(const either_left *) { return true; } + + virtual int compare(const either &b) override { + if (b.getKind() != getKind()) { + return b.getKind() < getKind() ? -1 : 1; + } + const either_left &el = static_cast &>(b); + if (el.value() != value()) { + return el.value() < value() ? -1 : 1; + } + return 0; + } + + virtual bool equals(const either &b) override { + if (b.getKind() != getKind()) { + return false; + } + const either_left &el = static_cast &>(b); + return el.value() == value(); + } +}; + +template class either_right : public either { +protected: + friend class ref>; + friend class ref>; + +private: + ref value_; + + unsigned computeHash() { + unsigned res = (unsigned)getKind(); + res = (res * either::MAGIC_HASH_CONSTANT) + value_->hash(); + either::hashValue = res; + return either::hashValue; + } + +public: + either_right(ref rightValue) : value_(rightValue) { computeHash(); }; + + ref value() const { return value_; } + operator ref const() { return value_; } + + virtual typename either::EitherKind getKind() const override { + return either::EitherKind::Right; + } + + static bool classof(const either *S) { + return S->getKind() == either::EitherKind::Right; + } + static bool classof(const either_right *) { return true; } + + virtual int compare(const either &b) override { + if (b.getKind() != getKind()) { + return b.getKind() < getKind() ? -1 : 1; + } + const either_right &el = + static_cast &>(b); + if (el.value() != value()) { + return el.value() < value() ? -1 : 1; + } + return 0; + } + + virtual bool equals(const either &b) override { + if (b.getKind() != getKind()) { + return false; + } + const either_right &el = + static_cast &>(b); + return el.value() == value(); + } +}; +} // end namespace klee + +#endif /* KLEE_EITHER_H */ diff --git a/include/klee/ADT/ImmutableList.h b/include/klee/ADT/ImmutableList.h new file mode 100644 index 0000000000..425036979e --- /dev/null +++ b/include/klee/ADT/ImmutableList.h @@ -0,0 +1,123 @@ +//===---- ImmutableList.h ---------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_IMMUTABLELIST_H +#define KLEE_IMMUTABLELIST_H + +#include +#include +#include + +namespace klee { + +template class ImmutableList { + struct ImmutableListNode { + std::shared_ptr prev; + const size_t prev_len; + std::vector values; + + [[nodiscard]] size_t size() const { return prev_len + values.size(); } + + ImmutableListNode() : prev(nullptr), prev_len(0), values() {} + + explicit ImmutableListNode(const ImmutableList &il) + : prev_len(il.size()), values() { + std::shared_ptr pr = il.node; + while (pr && pr->values.empty()) { + pr = pr->prev; + } + if (pr && pr->size()) { + prev = pr; + } else { + prev = nullptr; + } + } + }; + + std::shared_ptr node; + +public: + [[nodiscard]] size_t size() const { return node ? node->size() : 0; } + + struct iterator { + const ImmutableListNode *rootNode; + std::unique_ptr it; + size_t get; + + public: + explicit iterator(const ImmutableListNode *p) + : rootNode(p), it(nullptr), get(0) { + if (rootNode && rootNode->prev.get()) { + it = std::make_unique(rootNode->prev.get()); + } + } + + bool operator==(const iterator &b) const { + return rootNode == b.rootNode && get == b.get; + } + + bool operator!=(const iterator &b) const { return !(*this == b); } + + iterator &operator++() { + ++get; + if (get < rootNode->prev_len) { + it->operator++(); + } + return *this; + } + + const T &operator*() const { + if (get < rootNode->prev_len) { + return **it; + } + return rootNode->values[get - rootNode->prev_len]; + } + + const T &operator->() const { return **this; } + }; + + [[nodiscard]] iterator begin() const { return iterator(node.get()); } + + [[nodiscard]] iterator end() const { + auto it = iterator(node.get()); + it.get = size(); + return it; + } + + void push_back(T &&value) { + if (!node) { + node = std::make_shared(); + } + node->values.push_back(std::move(value)); + } + + void push_back(const T &value) { + if (!node) { + node = std::make_shared(); + } + node->values.push_back(value); + } + + bool empty() { return size() == 0; } + + const T &back() { + assert(node && "requiers not empty list"); + auto it = iterator(node.get()); + it.get = size() - 1; + return *it; + } + + ImmutableList() : node(){}; + ImmutableList(const ImmutableList &il) + : node(std::make_shared(il)) {} +}; + +} // namespace klee + +#endif /* KLEE_IMMUTABLELIST_H */ diff --git a/include/klee/ADT/ImmutableMap.h b/include/klee/ADT/ImmutableMap.h index d79a4d5790..44cacedc33 100644 --- a/include/klee/ADT/ImmutableMap.h +++ b/include/klee/ADT/ImmutableMap.h @@ -44,6 +44,32 @@ template > class ImmutableMap { return *this; } + bool operator==(const ImmutableMap &b) const { + if (size() != b.size()) { + return false; + } + for (iterator it1 = begin(), it2 = b.begin(); + it1 != end() && it2 != b.end(); ++it1, ++it2) { + if (*it1 != *it2) + return false; + } + return true; + } + + bool operator<(const ImmutableMap &b) const { + if (size() != b.size()) { + return size() < b.size(); + } + for (iterator it1 = begin(), it2 = b.begin(); + it1 != end() && it2 != b.end(); ++it1, ++it2) { + if (*it1 < *it2) + return true; + if (*it1 > *it2) + return false; + } + return false; + } + bool empty() const { return elts.empty(); } size_t count(const key_type &key) const { return elts.count(key); } const value_type *lookup(const key_type &key) const { @@ -80,6 +106,7 @@ template > class ImmutableMap { return elts.upper_bound(key); } + const D &at(const key_type &key) const { return find(key)->second; } static size_t getAllocated() { return Tree::allocated; } }; diff --git a/include/klee/ADT/Incremental.h b/include/klee/ADT/Incremental.h new file mode 100644 index 0000000000..6f16fd0867 --- /dev/null +++ b/include/klee/ADT/Incremental.h @@ -0,0 +1,360 @@ +//===---- Incremental.h -----------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_INCREMENTAL_H +#define KLEE_INCREMENTAL_H + +#include +#include +#include +#include +#include +#include + +#include "klee/Expr/ExprUtil.h" + +namespace klee { + +template +void extend(std::vector<_Tp, _Alloc> &ths, + const std::vector<_Tp, _Alloc> &other) { + ths.reserve(ths.size() + other.size()); + ths.insert(ths.end(), other.begin(), other.end()); +} + +template +void takeAfterv(std::vector<_Tp, _Alloc> &ths, size_t n) { + std::vector<_Tp, _Alloc>(ths.begin() + n, ths.end()).swap(ths); +} + +template > +class inc_vector { +public: + using vec = std::vector<_Tp, _Alloc>; + using frame_size_it = std::vector::const_iterator; + using frame_it = typename vec::const_iterator; + + /// It is public, so that all vector operations are supported + /// Everything pushed to v is pushed to the last frame + vec v; + + std::vector frame_sizes; + +private: + // v.size() == sum(frame_sizes) + size of the fresh frame + + size_t freshFrameSize() const { + return v.size() - + std::accumulate(frame_sizes.begin(), frame_sizes.end(), 0); + } + + void take(size_t n, size_t &frames_count, size_t &frame_index) const { + size_t i = 0; + size_t c = n; + for (; i < frame_sizes.size(); i++) { + if (frame_sizes[i] > c) + break; + c -= frame_sizes[i]; + } + frames_count = c; + frame_index = i; + } + +public: + inc_vector() {} + inc_vector(const std::vector<_Tp> &constraints) : v(constraints) {} + + void clear() { + v.clear(); + frame_sizes.clear(); + } + + frame_size_it begin() const { return frame_sizes.cbegin(); } + frame_size_it end() const { return frame_sizes.cend(); } + size_t framesSize() const { return frame_sizes.size() + 1; } + + frame_it begin(int frame_index) const { + assert(-(long long)framesSize() <= (long long)frame_index && + (long long)frame_index <= (long long)framesSize()); + if (frame_index < 0) + frame_index += framesSize(); + if ((long long)frame_index == (long long)framesSize()) + return v.end(); + auto fend = frame_sizes.begin() + frame_index; + auto shift = std::accumulate(frame_sizes.begin(), fend, 0); + return v.begin() + shift; + } + frame_it end(int frame_index) const { return begin(frame_index + 1); } + size_t size(size_t frame_index) const { + assert(frame_index < framesSize()); + if (frame_index == framesSize() - 1) // last frame + return freshFrameSize(); + return frame_sizes[frame_index]; + } + + void pop(size_t popFrames) { + assert(freshFrameSize() == 0); + if (popFrames == 0) + return; + size_t toPop = + std::accumulate(frame_sizes.end() - popFrames, frame_sizes.end(), 0); + v.resize(v.size() - toPop); + frame_sizes.resize(frame_sizes.size() - popFrames); + } + + void push() { + auto freshSize = freshFrameSize(); + frame_sizes.push_back(freshSize); + assert(freshFrameSize() == 0); + } + + /// ensures that last frame is empty + void extend(const std::vector<_Tp, _Alloc> &other) { + assert(freshFrameSize() == 0); + // push(); + klee::extend(v, other); + push(); + } + + /// ensures that last frame is empty + void extend(const inc_vector<_Tp, _Alloc> &other) { + assert(freshFrameSize() == 0); + for (size_t i = 0, e = other.framesSize(); i < e; i++) { + v.reserve(v.size() + other.size(i)); + v.insert(v.end(), other.begin(i), other.end(i)); + push(); + } + } + + void takeAfter(size_t n, inc_vector<_Tp, _Alloc> &result) const { + size_t frames_count, frame_index; + take(n, frames_count, frame_index); + result = *this; + takeAfterv(result.v, n); + takeAfterv(result.frame_sizes, frame_index); + if (frames_count && !result.frame_sizes.empty()) + result.frame_sizes[0] -= frames_count; + } + + void butLast(inc_vector<_Tp, _Alloc> &result) const { + assert(!v.empty() && "butLast of empty vector"); + assert(freshFrameSize() && "butLast of empty fresh frame"); + result = *this; + result.v.pop_back(); + } + + void takeBefore(size_t n, size_t &toPop, size_t &takeFromOther) const { + take(n, takeFromOther, toPop); + toPop = frame_sizes.size() - toPop; + } +}; + +using FrameId = size_t; +using FrameIds = std::unordered_set; + +template , + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value>> +class inc_uset { +private: + class MinFrameIds { + FrameIds ids; + FrameId min = std::numeric_limits::max(); + + public: + bool empty() const { return ids.empty(); } + + bool hasMin(FrameId other) const { return min == other && !ids.empty(); } + + void insert(FrameId i) { + ids.insert(i); + if (i < min) + min = i; + } + + MinFrameIds bound(FrameId upperBound) { + MinFrameIds result; + std::copy_if(ids.begin(), ids.end(), + std::inserter(result.ids, result.ids.begin()), + [upperBound](FrameId i) { return i <= upperBound; }); + auto min_it = std::min_element(result.ids.begin(), result.ids.end()); + if (min_it == result.ids.end()) + result.min = std::numeric_limits::max(); + else + result.min = *min_it; + return result; + } + }; + + using idMap = std::unordered_map<_Value, MinFrameIds, _Hash, _Pred, _Alloc>; + using citerator = typename idMap::const_iterator; + idMap ids; + FrameId current_frame = 0; + +public: + size_t framesSize() const { return current_frame + 1; } + + void clear() { + ids.clear(); + current_frame = 0; + } + + class frame_it + : public std::iterator, int> { + citerator set_it; + const citerator set_ite; + const FrameId frame_index = 0; + + void gotoNext() { + while (set_it != set_ite && !set_it->second.hasMin(frame_index)) + set_it++; + } + + public: + using value_type = _Value; + + explicit frame_it(const idMap &ids) + : set_it(ids.end()), set_ite(ids.end()) {} + explicit frame_it(const idMap &ids, FrameId frame_index) + : set_it(ids.begin()), set_ite(ids.end()), frame_index(frame_index) { + gotoNext(); + } + + bool operator!=(const frame_it &other) const { + return set_it != other.set_it; + } + + const _Value &operator*() const { return set_it->first; } + + frame_it &operator++() { + if (set_it != set_ite) { + set_it++; + gotoNext(); + } + return *this; + } + }; + + class all_it + : public std::iterator, int> { + citerator set_it; + + public: + using value_type = _Value; + + explicit all_it(citerator set_it) : set_it(set_it) {} + + bool operator!=(const all_it &other) const { + return set_it != other.set_it; + } + + const _Value &operator*() const { return set_it->first; } + + all_it &operator++() { + set_it++; + return *this; + } + }; + + all_it begin() const { return all_it(ids.begin()); } + all_it end() const { return all_it(ids.end()); } + + frame_it begin(int frame_index) const { + assert(-(long long)framesSize() <= (long long)frame_index && + (long long)frame_index <= (long long)framesSize()); + if (frame_index < 0) + frame_index += framesSize(); + return frame_it(ids, frame_index); + } + frame_it end(int frame_index) const { return frame_it(ids); } + + void insert(const _Value &v) { ids[v].insert(current_frame); } + + template + void insert(_InputIterator __first, _InputIterator __last) { + for (; __first != __last; __first++) + ids[*__first].insert(current_frame); + } + + void pop(size_t popFrames) { + current_frame -= popFrames; + idMap newIdMap; + for (auto &keyAndIds : ids) { + MinFrameIds newIds = keyAndIds.second.bound(current_frame); + if (!newIds.empty()) + newIdMap.insert(std::make_pair(keyAndIds.first, newIds)); + } + ids = newIdMap; + } + + void push() { current_frame++; } +}; + +template , + typename _Pred = std::equal_to<_Key>, + typename _Alloc = std::allocator>> +class inc_umap { +private: + std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> map; + using idMap = std::unordered_map<_Key, FrameIds, _Hash, _Pred, _Alloc>; + idMap ids; + FrameId current_frame = 0; + +public: + void clear() { + map.clear(); + ids.clear(); + current_frame = 0; + } + + void insert(const std::pair<_Key, _Tp> &pair) { + map.insert(pair); + ids[pair.first].insert(current_frame); + } + + _Tp &operator[](const _Key &key) { + ids[key].insert(current_frame); + return map[key]; + } + + size_t count(const _Key &key) const { return map.count(key); } + + const _Tp &at(_Key &key) const { return map.at(key); } + + void pop(size_t popFrames) { + current_frame -= popFrames; + idMap newIdMap; + for (auto &keyAndIds : ids) { + FrameIds newIds; + for (auto id : keyAndIds.second) + if (id <= current_frame) + newIds.insert(id); + if (newIds.empty()) + map.erase(keyAndIds.first); + else + newIdMap.insert(std::make_pair(keyAndIds.first, newIds)); + } + ids = newIdMap; + } + + void push() { current_frame++; } + + void dump() const { + for (auto kv : map) { + kv.first.dump(); + llvm::errs() << "----->\n"; + kv.second.dump(); + llvm::errs() << "\n;;;;;;;;;\n"; + } + } +}; + +} // namespace klee + +#endif /* KLEE_INCREMENTAL_H */ diff --git a/include/klee/ADT/KTest.h b/include/klee/ADT/KTest.h index 66c68c3417..d4c08d640d 100644 --- a/include/klee/ADT/KTest.h +++ b/include/klee/ADT/KTest.h @@ -46,6 +46,7 @@ struct KTest { unsigned numObjects; KTestObject *objects; + unsigned uninitCoeff; }; /* returns the current .ktest file format version */ diff --git a/include/klee/ADT/PersistentMap.h b/include/klee/ADT/PersistentMap.h index bfec1824a0..dabc5495db 100644 --- a/include/klee/ADT/PersistentMap.h +++ b/include/klee/ADT/PersistentMap.h @@ -37,6 +37,8 @@ template > class PersistentMap { elts = b.elts; return *this; } + bool operator==(const PersistentMap &b) const { return elts == b.elts; } + bool operator<(const PersistentMap &b) const { return elts < b.elts; } bool empty() const { return elts.empty(); } size_t count(const key_type &key) const { return elts.count(key); } @@ -77,6 +79,8 @@ template > class PersistentMap { return *lookup(key); } } + + const D &at(const key_type &key) const { return elts.at(key); } }; } // namespace klee diff --git a/include/klee/ADT/Ref.h b/include/klee/ADT/Ref.h index 45e9632ca2..eb082c2065 100644 --- a/include/klee/ADT/Ref.h +++ b/include/klee/ADT/Ref.h @@ -215,6 +215,19 @@ template class ref { bool operator!=(const ref &rhs) const { return !equals(rhs); } }; +template class OptionalRefEq { +public: + bool operator()(const ref &lhs, const ref &rhs) { + if (lhs.isNull() && rhs.isNull()) { + return true; + } + if (lhs.isNull() || rhs.isNull()) { + return false; + } + return lhs.get()->equals(*rhs.get()); + } +}; + template inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const ref &e) { os << *e; @@ -227,6 +240,18 @@ inline std::stringstream &operator<<(std::stringstream &os, const ref &e) { return os; } +template class box { + friend class ref>; + +private: + /// @brief Required by klee::ref-managed objects + class ReferenceCounter _refCount; + +public: + box(T value_) : value(value_) {} + ReferenceCounter count() { return _refCount; } + T value; +}; } // end namespace klee namespace llvm { diff --git a/include/klee/ADT/SparseStorage.h b/include/klee/ADT/SparseStorage.h index 84170600da..a78df85770 100644 --- a/include/klee/ADT/SparseStorage.h +++ b/include/klee/ADT/SparseStorage.h @@ -3,67 +3,56 @@ #include #include +#include #include #include +#include #include +namespace llvm { +class raw_ostream; +}; + namespace klee { -template class SparseStorage { +enum class Density { + Sparse, + Dense, +}; + +template > +class SparseStorage { private: - size_t capacity; - std::map internalStorage; + std::unordered_map internalStorage; ValueType defaultValue; + Eq eq; bool contains(size_t key) const { return internalStorage.count(key) != 0; } public: - struct Iterator { - using iterator_category = std::input_iterator_tag; - using difference_type = std::ptrdiff_t; - using value_type = ValueType; - using pointer = ValueType *; - using reference = ValueType &; - - private: - size_t idx; - const SparseStorage *owner; - - public: - Iterator(size_t idx, const SparseStorage *owner) : idx(idx), owner(owner) {} - - value_type operator*() const { return owner->load(idx); } - - Iterator &operator++() { - ++idx; - return *this; - } - - Iterator operator++(int) { - Iterator snap = *this; - ++(*this); - return snap; + SparseStorage(const ValueType &defaultValue = ValueType()) + : defaultValue(defaultValue) {} + + SparseStorage(const std::unordered_map &internalStorage, + const ValueType &defaultValue) + : defaultValue(defaultValue) { + for (auto &[index, value] : internalStorage) { + store(index, value); } - - bool operator==(const Iterator &other) const { return idx == other.idx; } - - bool operator!=(const Iterator &other) const { return !(*this == other); } - }; - - SparseStorage(size_t capacity = 0, - const ValueType &defaultValue = ValueType()) - : capacity(capacity), defaultValue(defaultValue) {} + } SparseStorage(const std::vector &values, const ValueType &defaultValue = ValueType()) - : capacity(values.capacity()), defaultValue(defaultValue) { - for (size_t idx = 0; idx < values.capacity(); ++idx) { - internalStorage[idx] = values[idx]; + : defaultValue(defaultValue) { + for (size_t idx = 0; idx < values.size(); ++idx) { + store(idx, values[idx]); } } void store(size_t idx, const ValueType &value) { - if (idx < capacity) { + if (eq(value, defaultValue)) { + internalStorage.erase(idx); + } else { internalStorage[idx] = value; } } @@ -77,32 +66,20 @@ template class SparseStorage { } ValueType load(size_t idx) const { - assert(idx < capacity && idx >= 0); - return contains(idx) ? internalStorage.at(idx) : defaultValue; + auto it = internalStorage.find(idx); + return it != internalStorage.end() ? it->second : defaultValue; } - size_t size() const { return capacity; } - - void resize(size_t newCapacity) { - assert(newCapacity >= 0); - // Free to extend - if (newCapacity >= capacity) { - capacity = newCapacity; - return; - } - - // Truncate unnessecary elements - auto iterOnNewSize = internalStorage.lower_bound(newCapacity); - while (iterOnNewSize != internalStorage.end()) { - iterOnNewSize = internalStorage.erase(iterOnNewSize); + size_t sizeOfSetRange() const { + size_t sizeOfRange = 0; + for (auto i : internalStorage) { + sizeOfRange = std::max(i.first, sizeOfRange); } - - capacity = newCapacity; + return internalStorage.empty() ? 0 : sizeOfRange + 1; } bool operator==(const SparseStorage &another) const { - return size() == another.size() && defaultValue == another.defaultValue && - internalStorage == another.internalStorage; + return eq(defaultValue, another.defaultValue) && compare(another) == 0; } bool operator!=(const SparseStorage &another) const { @@ -110,22 +87,61 @@ template class SparseStorage { } bool operator<(const SparseStorage &another) const { - return internalStorage < another.internalStorage; + return compare(another) == -1; } bool operator>(const SparseStorage &another) const { - return internalStorage > another.internalStorage; + return compare(another) == 1; + } + + int compare(const SparseStorage &other) const { + auto ordered = calculateOrderedStorage(); + auto otherOrdered = other.calculateOrderedStorage(); + + if (ordered == otherOrdered) { + return 0; + } else { + return ordered < otherOrdered ? -1 : 1; + } + } + + std::map calculateOrderedStorage() const { + std::map ordered; + for (const auto &i : internalStorage) { + ordered.insert(i); + } + return ordered; + } + + std::vector getFirstNIndexes(size_t n) const { + std::vector vectorized(n); + for (size_t i = 0; i < n; i++) { + vectorized[i] = load(i); + } + return vectorized; + } + + const std::unordered_map &storage() const { + return internalStorage; + }; + + const ValueType &defaultV() const { return defaultValue; }; + + void reset() { internalStorage.clear(); } + + void reset(ValueType newDefault) { + defaultValue = newDefault; + reset(); } - Iterator begin() const { return Iterator(0, this); } - Iterator end() const { return Iterator(size(), this); } + void print(llvm::raw_ostream &os, Density) const; }; template SparseStorage sparseBytesFromValue(const U &value) { const unsigned char *valueUnsignedCharIterator = reinterpret_cast(&value); - SparseStorage result(sizeof(value)); + SparseStorage result; result.store(0, valueUnsignedCharIterator, valueUnsignedCharIterator + sizeof(value)); return result; diff --git a/include/klee/Config/config.h.cmin b/include/klee/Config/config.h.cmin index 29a48405b7..1d3f1ac6dd 100644 --- a/include/klee/Config/config.h.cmin +++ b/include/klee/Config/config.h.cmin @@ -13,6 +13,9 @@ /* Using Z3 Solver backend */ #cmakedefine ENABLE_Z3 @ENABLE_Z3@ +/* Using Bitwuzla Solver backend */ +#cmakedefine ENABLE_BITWUZLA @ENABLE_BITWUZLA@ + /* Enable KLEE floating point extension */ #cmakedefine ENABLE_FP @ENABLE_FP@ @@ -102,7 +105,10 @@ #define RUNTIME_CONFIGURATION "@KLEE_RUNTIME_BUILD_TYPE@" /* Configure name of KLEE's uClibc library */ -#cmakedefine KLEE_UCLIBC_BCA_NAME "@KLEE_UCLIBC_BCA_NAME@" +#cmakedefine KLEE_UCLIBC_BCA_32_NAME "@KLEE_UCLIBC_BCA_32_NAME@" + +/* Configure name of KLEE's uClibc library */ +#cmakedefine KLEE_UCLIBC_BCA_64_NAME "@KLEE_UCLIBC_BCA_64_NAME@" /* Configure name of the libCXX bitcode library */ #cmakedefine KLEE_LIBCXX_BC_NAME "@KLEE_LIBCXX_BC_NAME@" diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 6c7ff2f878..43280ff28f 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -41,7 +41,6 @@ class ExecutionState; struct SarifReport; class Interpreter; class TreeStreamWriter; -class InstructionInfoTable; class InterpreterHandler { public: @@ -61,6 +60,12 @@ class InterpreterHandler { const char *suffix, bool isError = false) = 0; }; +/// [File][Line][Column] -> Opcode +using FLCtoOpcode = std::unordered_map< + std::string, + std::unordered_map< + unsigned, std::unordered_map>>>; + class Interpreter { public: enum class GuidanceKind { @@ -140,9 +145,9 @@ class Interpreter { setModule(std::vector> &userModules, std::vector> &libsModules, const ModuleOptions &opts, - const std::unordered_set &mainModuleFunctions, - const std::unordered_set &mainModuleGlobals, - std::unique_ptr origInfos) = 0; + std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, + FLCtoOpcode &&origInstructions) = 0; // supply a tree stream writer which the interpreter will use // to record the concrete path (as a stream of '0' and '1' bytes). @@ -172,6 +177,8 @@ class Interpreter { virtual void setHaltExecution(HaltExecution::Reason value) = 0; + virtual HaltExecution::Reason getHaltExecution() = 0; + virtual void setInhibitForking(bool value) = 0; virtual void prepareForEarlyExit() = 0; @@ -194,7 +201,7 @@ class Interpreter { virtual void getCoveredLines(const ExecutionState &state, - std::map> &res) = 0; + std::map> &res) = 0; virtual void getBlockPath(const ExecutionState &state, std::string &blockPath) = 0; diff --git a/include/klee/Core/TerminationTypes.h b/include/klee/Core/TerminationTypes.h index 06d1522923..a08b3585e7 100644 --- a/include/klee/Core/TerminationTypes.h +++ b/include/klee/Core/TerminationTypes.h @@ -40,7 +40,8 @@ enum class StateTerminationClass : std::uint8_t { TTYPE(OutOfMemory, 12U, "early") \ TTYPE(OutOfStackMemory, 13U, "early") \ TTYPE(MaxCycles, 14U, "early") \ - TTMARK(EARLY, 14U) \ + TTYPE(CoverOnTheFly, 15U, "early") \ + TTMARK(EARLY, 15U) \ TTYPE(Solver, 20U, "solver.err") \ TTMARK(SOLVERERR, 20U) \ TTYPE(Abort, 30U, "abort.err") \ @@ -96,6 +97,7 @@ enum Reason { CovCheck, NoMoreStates, ReachedTarget, + UnreachedTarget, ErrorOnWhichShouldExit, Interrupt, MaxDepth, diff --git a/include/klee/Expr/AlphaBuilder.h b/include/klee/Expr/AlphaBuilder.h new file mode 100644 index 0000000000..6a965c3962 --- /dev/null +++ b/include/klee/Expr/AlphaBuilder.h @@ -0,0 +1,45 @@ +//===-- AlphaBuilder.h -----------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_ALPHA_BUILDER_H +#define KLEE_ALPHA_BUILDER_H + +#include "klee/Expr/ArrayCache.h" +#include "klee/Expr/ExprHashMap.h" +#include "klee/Expr/ExprVisitor.h" + +namespace klee { + +class AlphaBuilder final : public ExprVisitor { +public: + ExprHashMap> reverseExprMap; + ArrayCache::ArrayHashMap reverseAlphaArrayMap; + ArrayCache::ArrayHashMap alphaArrayMap; + +private: + ArrayCache &arrayCache; + unsigned index = 0; + bool reverse = false; + + const Array *visitArray(const Array *arr); + UpdateList visitUpdateList(UpdateList u); + Action visitRead(const ReadExpr &re) override; + using ExprVisitor::visitExpr; + +public: + AlphaBuilder(ArrayCache &_arrayCache); + constraints_ty visitConstraints(constraints_ty cs); + ref build(ref v); + const Array *buildArray(const Array *arr) { return visitArray(arr); } + ref reverseBuild(ref v); +}; + +} // namespace klee + +#endif /*KLEE_ALPHA_BUILDER_H*/ diff --git a/include/klee/Expr/ArrayCache.h b/include/klee/Expr/ArrayCache.h index b46a1caab1..735b3d257b 100644 --- a/include/klee/Expr/ArrayCache.h +++ b/include/klee/Expr/ArrayCache.h @@ -61,10 +61,9 @@ class ArrayCache { klee::EquivArrayCmpFn> ArrayHashSet; ArrayHashSet cachedSymbolicArrays; - typedef std::vector ArrayPtrVec; - ArrayPtrVec concreteArrays; - unsigned getNextID() const; + // Number of arrays of each source allocated + std::unordered_map allocatedCount; }; } // namespace klee diff --git a/include/klee/Expr/Assignment.h b/include/klee/Expr/Assignment.h index ad48af0baa..bb86172a60 100644 --- a/include/klee/Expr/Assignment.h +++ b/include/klee/Expr/Assignment.h @@ -10,6 +10,7 @@ #ifndef KLEE_ASSIGNMENT_H #define KLEE_ASSIGNMENT_H +#include "klee/ADT/PersistentMap.h" #include "klee/ADT/SparseStorage.h" #include "klee/Expr/ExprEvaluator.h" @@ -24,12 +25,13 @@ class ConstraintSet; typedef std::set, SymcreteLess> SymcreteOrderedSet; using symcretes_ty = SymcreteOrderedSet; +typedef std::function)> ExprPredicate; class Assignment { public: - typedef std::map> bindings_ty; + using bindings_ty = + PersistentMap>; - bool allowFreeValues; bindings_ty bindings; friend bool operator==(const Assignment &lhs, const Assignment &rhs) { @@ -37,14 +39,10 @@ class Assignment { } public: - Assignment(bool _allowFreeValues = false) - : allowFreeValues(_allowFreeValues) {} - Assignment(const bindings_ty &_bindings, bool _allowFreeValues = false) - : allowFreeValues(_allowFreeValues), bindings(_bindings) {} + Assignment() {} + Assignment(const bindings_ty &_bindings) : bindings(_bindings) {} Assignment(const std::vector &objects, - const std::vector> &values, - bool _allowFreeValues = false) - : allowFreeValues(_allowFreeValues) { + const std::vector> &values) { assert(objects.size() == values.size()); for (unsigned i = 0; i < values.size(); ++i) { const Array *os = objects.at(i); @@ -53,19 +51,29 @@ class Assignment { } } - ref evaluate(const Array *mo, unsigned index) const; - ref evaluate(ref e) const; - ConstraintSet createConstraintsFromAssignment() const; + void addIndependentAssignment(const Assignment &b); + + ref evaluate(const Array *mo, unsigned index, + bool allowFreeValues = true) const; + ref evaluate(ref e, bool allowFreeValues = true) const; + constraints_ty createConstraintsFromAssignment() const; template - bool satisfies(InputIterator begin, InputIterator end); + bool satisfies(InputIterator begin, InputIterator end, + ExprPredicate predicate, bool allowFreeValues = true); + template + bool satisfies(InputIterator begin, InputIterator end, + bool allowFreeValues = true); + template + bool satisfiesOrConstant(InputIterator begin, InputIterator end, + bool allowFreeValues = true); void dump() const; Assignment diffWith(const Assignment &other) const; Assignment part(const SymcreteOrderedSet &symcretes) const; - bindings_ty::const_iterator begin() const { return bindings.begin(); } - bindings_ty::const_iterator end() const { return bindings.end(); } + bindings_ty::iterator begin() const { return bindings.begin(); } + bindings_ty::iterator end() const { return bindings.end(); } bool isEmpty() { return begin() == end(); } std::vector keys() const; @@ -74,23 +82,27 @@ class Assignment { class AssignmentEvaluator : public ExprEvaluator { const Assignment &a; + bool allowFreeValues; protected: ref getInitialValue(const Array &mo, unsigned index) { - return a.evaluate(&mo, index); + return a.evaluate(&mo, index, allowFreeValues); } public: - AssignmentEvaluator(const Assignment &_a) : a(_a) {} + AssignmentEvaluator(const Assignment &_a, bool _allowFreeValues) + : a(_a), allowFreeValues(_allowFreeValues) {} }; /***/ -inline ref Assignment::evaluate(const Array *array, - unsigned index) const { +inline ref Assignment::evaluate(const Array *array, unsigned index, + bool allowFreeValues) const { assert(array); - bindings_ty::const_iterator it = bindings.find(array); - if (it != bindings.end() && index < it->second.size()) { + auto sizeExpr = evaluate(array->size); + bindings_ty::iterator it = bindings.find(array); + if (it != bindings.end() && isa(sizeExpr) && + index < cast(sizeExpr)->getZExtValue()) { return ConstantExpr::alloc(it->second.load(index), array->getRange()); } else { if (allowFreeValues) { @@ -102,19 +114,49 @@ inline ref Assignment::evaluate(const Array *array, } } -inline ref Assignment::evaluate(ref e) const { - AssignmentEvaluator v(*this); +inline ref Assignment::evaluate(ref e, bool allowFreeValues) const { + AssignmentEvaluator v(*this, allowFreeValues); return v.visit(e); } +struct isTrueBoolean { + bool operator()(ref e) const { + return e->getWidth() == Expr::Bool && e->isTrue(); + } +}; + +struct isTrueBooleanOrConstantNotBoolean { + bool operator()(ref e) const { + return (e->getWidth() == Expr::Bool && e->isTrue()) || + ((isa(e) && e->getWidth() != Expr::Bool)); + } +}; + template -inline bool Assignment::satisfies(InputIterator begin, InputIterator end) { - AssignmentEvaluator v(*this); - for (; begin != end; ++begin) - if (!v.visit(*begin)->isTrue()) +inline bool Assignment::satisfies(InputIterator begin, InputIterator end, + ExprPredicate predicate, + bool allowFreeValues) { + AssignmentEvaluator v(*this, allowFreeValues); + for (; begin != end; ++begin) { + if (!predicate(v.visit(*begin))) return false; + } return true; } + +template +inline bool Assignment::satisfies(InputIterator begin, InputIterator end, + bool allowFreeValues) { + return satisfies(begin, end, isTrueBoolean(), allowFreeValues); +} + +template +inline bool Assignment::satisfiesOrConstant(InputIterator begin, + InputIterator end, + bool allowFreeValues) { + return satisfies(begin, end, isTrueBooleanOrConstantNotBoolean(), + allowFreeValues); +} } // namespace klee #endif /* KLEE_ASSIGNMENT_H */ diff --git a/include/klee/Expr/Constraints.h b/include/klee/Expr/Constraints.h index a14b9e191e..f4c0e22db8 100644 --- a/include/klee/Expr/Constraints.h +++ b/include/klee/Expr/Constraints.h @@ -12,10 +12,13 @@ #include "klee/ADT/Ref.h" +#include "klee/ADT/PersistentMap.h" #include "klee/Expr/Assignment.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" +#include "klee/Expr/IndependentConstraintSetUnion.h" +#include "klee/Expr/IndependentSet.h" #include "klee/Expr/Path.h" #include "klee/Expr/Symcrete.h" @@ -35,14 +38,23 @@ class ConstraintSet { public: ConstraintSet(constraints_ty cs, symcretes_ty symcretes, Assignment concretization); - ConstraintSet(); + explicit ConstraintSet(ref ics); + explicit ConstraintSet( + const std::vector> &ics); + explicit ConstraintSet(constraints_ty cs); + explicit ConstraintSet(); + void fork(); void addConstraint(ref e, const Assignment &delta); void addSymcrete(ref s, const Assignment &concretization); bool isSymcretized(ref expr) const; void rewriteConcretization(const Assignment &a); - ConstraintSet withExpr(ref e) const; + ConstraintSet withExpr(ref e) const { + ConstraintSet copy = ConstraintSet(*this); + copy.addConstraint(e, Assignment()); + return copy; + } std::vector gatherArrays() const; std::vector gatherSymcretizedArrays() const; @@ -55,7 +67,8 @@ class ConstraintSet { return _constraints < b._constraints || (_constraints == b._constraints && _symcretes < b._symcretes); } - + ConstraintSet getConcretizedVersion() const; + ConstraintSet getConcretizedVersion(const Assignment &c) const; void dump() const; void print(llvm::raw_ostream &os) const; @@ -64,20 +77,32 @@ class ConstraintSet { const constraints_ty &cs() const; const symcretes_ty &symcretes() const; const Assignment &concretization() const; + const IndependentConstraintSetUnion &independentElements() const; + + void getAllIndependentConstraintsSets( + ref queryExpr, + std::vector> &result) const; + + void getAllDependentConstraintsSets( + ref queryExpr, + std::vector> &result) const; private: constraints_ty _constraints; symcretes_ty _symcretes; Assignment _concretization; + std::shared_ptr _independentElements; }; class PathConstraints { public: using ordered_constraints_ty = - std::map; + PersistentMap; void advancePath(KInstruction *ki); void advancePath(const Path &path); + void fork(); + ExprHashSet addConstraint(ref e, const Assignment &delta, Path::PathIndex currIndex); ExprHashSet addConstraint(ref e, const Assignment &delta); @@ -135,6 +160,7 @@ class Simplificator { struct SetResult { constraints_ty simplified; ExprHashMap dependency; + bool wasSimplified; }; public: diff --git a/include/klee/Expr/Expr.h b/include/klee/Expr/Expr.h index 8e258b8f56..9937999e2e 100644 --- a/include/klee/Expr/Expr.h +++ b/include/klee/Expr/Expr.h @@ -260,6 +260,7 @@ class Expr { protected: unsigned hashValue; + unsigned heightValue; /// Compares `b` to `this` Expr and determines how they are ordered /// (ignoring their kid expressions - i.e. those returned by `getKid()`). @@ -303,11 +304,13 @@ class Expr { std::string toString() const; /// Returns the pre-computed hash of the current expression - virtual unsigned hash() const { return hashValue; } + unsigned hash() const { return hashValue; } + unsigned height() const { return heightValue; } /// (Re)computes the hash of the current expression. /// Returns the hash value. virtual unsigned computeHash(); + virtual unsigned computeHeight(); /// Compares `b` to `this` Expr for structural equivalence. /// @@ -328,6 +331,13 @@ class Expr { // Given an array of new kids return a copy of the expression // but using those children. virtual ref rebuild(ref kids[/* getNumKids() */]) const = 0; + virtual ref rebuild() const { + ref kids[getNumKids()]; + for (unsigned i = 0; i < getNumKids(); ++i) { + kids[i] = getKid(i); + } + return rebuild(kids); + } /// isZero - Is this a constant zero. bool isZero() const; @@ -405,7 +415,7 @@ struct Expr::CreateArg { // Comparison operators inline bool operator==(const Expr &lhs, const Expr &rhs) { - return lhs.compare(rhs) == 0; + return lhs.equals(rhs); } inline bool operator<(const Expr &lhs, const Expr &rhs) { @@ -515,6 +525,7 @@ class NotOptimizedExpr : public NonConstantExpr { static ref alloc(const ref &src) { ref r(new NotOptimizedExpr(src)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -550,6 +561,7 @@ class UpdateNode { // cache instead of recalc unsigned hashValue; + unsigned heightValue; public: const ref next; @@ -571,11 +583,13 @@ class UpdateNode { int compare(const UpdateNode &b) const; bool equals(const UpdateNode &b) const; unsigned hash() const { return hashValue; } + unsigned height() const { return heightValue; } UpdateNode() = delete; ~UpdateNode() = default; unsigned computeHash(); + unsigned computeHeight(); }; class Array { @@ -622,10 +636,7 @@ class Array { public: bool isSymbolicArray() const { return !isConstantArray(); } - bool isConstantArray() const { - return isa(source) || - isa(source); - } + bool isConstantArray() const { return isa(source); } const std::string getName() const { return source->toString(); } const std::string getIdentifier() const { @@ -670,6 +681,7 @@ class UpdateList { bool operator<(const UpdateList &rhs) const { return compare(rhs) < 0; } unsigned hash() const; + unsigned height() const; }; /// Class representing a one byte read from an array. @@ -686,6 +698,7 @@ class ReadExpr : public NonConstantExpr { static ref alloc(const UpdateList &updates, const ref &index) { ref r(new ReadExpr(updates, index)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -707,6 +720,7 @@ class ReadExpr : public NonConstantExpr { } virtual unsigned computeHash(); + virtual unsigned computeHeight(); private: ReadExpr(const UpdateList &_updates, const ref &_index) @@ -733,12 +747,20 @@ class SelectExpr : public NonConstantExpr { const ref &f) { ref r(new SelectExpr(c, t, f)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } static ref create(ref c, ref t, ref f); - Width getWidth() const { return trueExpr->getWidth(); } + Width getWidth() const { + if (trueExpr->height() < falseExpr->height()) { + return trueExpr->getWidth(); + } else { + return falseExpr->getWidth(); + } + } + Kind getKind() const { return Select; } unsigned getNumKids() const { return numKids; } @@ -797,6 +819,7 @@ class ConcatExpr : public NonConstantExpr { static ref alloc(const ref &l, const ref &r) { ref c(new ConcatExpr(l, r)); c->computeHash(); + c->computeHeight(); return createCachedExpr(c); } @@ -867,6 +890,7 @@ class ExtractExpr : public NonConstantExpr { static ref alloc(const ref &e, unsigned o, Width w) { ref r(new ExtractExpr(e, o, w)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -917,6 +941,7 @@ class NotExpr : public NonConstantExpr { static ref alloc(const ref &e) { ref r(new NotExpr(e)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -990,6 +1015,7 @@ class CastExpr : public NonConstantExpr { static ref alloc(const ref &e, Width w) { \ ref r(new _class_kind##Expr(e, w)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e, Width w); \ @@ -1023,6 +1049,7 @@ CAST_EXPR_CLASS(FPExt) llvm::APFloat::roundingMode rm) { \ ref r(new _class_kind##Expr(e, w, rm)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e, Width w, \ @@ -1069,10 +1096,10 @@ FP_CAST_EXPR_CLASS(SIToFP) static ref alloc(const ref &l, const ref &r) { \ ref res(new _class_kind##Expr(l, r)); \ res->computeHash(); \ + res->computeHeight(); \ return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r); \ - Width getWidth() const { return left->getWidth(); } \ Kind getKind() const { return _class_kind; } \ virtual ref rebuild(ref kids[]) const { \ return create(kids[0], kids[1]); \ @@ -1082,6 +1109,13 @@ FP_CAST_EXPR_CLASS(SIToFP) return E->getKind() == Expr::_class_kind; \ } \ static bool classof(const _class_kind##Expr *) { return true; } \ + Width getWidth() const { \ + if (left->height() < right->height()) { \ + return left->getWidth(); \ + } else { \ + return right->getWidth(); \ + } \ + } \ \ protected: \ virtual int compareContents(const Expr &b) const { \ @@ -1119,11 +1153,19 @@ ARITHMETIC_EXPR_CLASS(AShr) const llvm::APFloat::roundingMode rm) { \ ref res(new _class_kind##Expr(l, r, rm)); \ res->computeHash(); \ + res->computeHeight(); \ return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r, \ llvm::APFloat::roundingMode rm); \ - Width getWidth() const { return left->getWidth(); } \ + Width getWidth() const { \ + if (left->height() < right->height()) { \ + return left->getWidth(); \ + } else { \ + return right->getWidth(); \ + } \ + } \ + \ Kind getKind() const { return _class_kind; } \ virtual ref rebuild(ref kids[]) const { \ return create(kids[0], kids[1], roundingMode); \ @@ -1165,6 +1207,7 @@ FLOAT_ARITHMETIC_EXPR_CLASS(FMin) static ref alloc(const ref &l, const ref &r) { \ ref res(new _class_kind##Expr(l, r)); \ res->computeHash(); \ + res->computeHeight(); \ return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r); \ @@ -1211,6 +1254,7 @@ COMPARISON_EXPR_CLASS(FOGe) static ref alloc(const ref &e) { \ ref r(new _class_kind##Expr(e)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e); \ @@ -1256,6 +1300,7 @@ FP_PRED_EXPR_CLASS(IsSubnormal) const llvm::APFloat::roundingMode rm) { \ ref r(new _class_kind##Expr(e, rm)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e, \ @@ -1302,6 +1347,7 @@ class FAbsExpr : public NonConstantExpr { static ref alloc(const ref &e) { ref r(new FAbsExpr(e)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } static ref create(const ref &e); @@ -1334,6 +1380,7 @@ class FNegExpr : public NonConstantExpr { static ref alloc(const ref &e) { ref r(new FNegExpr(e)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } static ref create(const ref &e); @@ -1440,12 +1487,14 @@ class ConstantExpr : public Expr { static ref alloc(const llvm::APInt &v) { ref r(new ConstantExpr(v)); r->computeHash(); + r->computeHeight(); return r; } static ref alloc(const llvm::APFloat &f) { ref r(new ConstantExpr(f)); r->computeHash(); + r->computeHeight(); return r; } diff --git a/include/klee/Expr/IndependentConstraintSetUnion.h b/include/klee/Expr/IndependentConstraintSetUnion.h new file mode 100644 index 0000000000..c4ce9a4559 --- /dev/null +++ b/include/klee/Expr/IndependentConstraintSetUnion.h @@ -0,0 +1,52 @@ +#ifndef KLEE_INDEPENDENTCONSTRAINTSETUNION_H +#define KLEE_INDEPENDENTCONSTRAINTSETUNION_H + +#include "klee/ADT/Either.h" + +#include "klee/Expr/Assignment.h" +#include "klee/Expr/IndependentSet.h" + +namespace klee { +class IndependentConstraintSetUnion + : public DisjointSetUnion, IndependentConstraintSet, + ExprOrSymcreteHash, ExprOrSymcreteCmp> { +public: + Assignment concretization; + std::vector> constraintQueue; + Assignment updateQueue; + Assignment removeQueue; + +public: + ExprHashMap> concretizedExprs; + +public: + void updateConcretization(const Assignment &delta); + void removeConcretization(const Assignment &remove); + void calculateUpdateConcretizationQueue(); + void calculateRemoveConcretizationQueue(); + void reEvaluateConcretization(const Assignment &newConcretization); + + IndependentConstraintSetUnion getConcretizedVersion(); + IndependentConstraintSetUnion getConcretizedVersion(const Assignment &c); + + IndependentConstraintSetUnion(); + IndependentConstraintSetUnion(const constraints_ty &is, + const SymcreteOrderedSet &os, + const Assignment &c); + IndependentConstraintSetUnion(ref ics); + + void + addIndependentConstraintSetUnion(const IndependentConstraintSetUnion &icsu); + + void getAllDependentConstraintSets( + ref e, std::vector> &result); + void getAllIndependentConstraintSets( + ref e, std::vector> &result); + + void addExpr(ref e); + void addSymcrete(ref s); + void calculateQueue(); +}; +} // namespace klee + +#endif /* KLEE_INDEPENDENTCONSTRAINTSETUNION_H */ diff --git a/include/klee/Expr/IndependentSet.h b/include/klee/Expr/IndependentSet.h index 9173d90678..cbcf9ec752 100644 --- a/include/klee/Expr/IndependentSet.h +++ b/include/klee/Expr/IndependentSet.h @@ -1,9 +1,14 @@ #ifndef KLEE_INDEPENDENTSET_H #define KLEE_INDEPENDENTSET_H +#include "klee/ADT/DisjointSetUnion.h" +#include "klee/ADT/Either.h" +#include "klee/ADT/PersistentMap.h" +#include "klee/ADT/PersistentSet.h" +#include "klee/Expr/Assignment.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprHashMap.h" -#include "klee/Solver/Solver.h" +#include "klee/Expr/Symcrete.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -11,10 +16,24 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/raw_ostream.h" DISABLE_WARNING_POP -#include +#include #include +#include +#include namespace klee { +using ExprOrSymcrete = either; + +struct ExprOrSymcreteHash { + unsigned operator()(const ref &e) const { return e->hash(); } +}; + +struct ExprOrSymcreteCmp { + bool operator()(const ref &a, + const ref &b) const { + return a == b; + } +}; template class DenseSet { typedef std::set set_ty; @@ -42,7 +61,7 @@ template class DenseSet { return modified; } - bool intersects(const DenseSet &b) { + bool intersects(const DenseSet &b) const { for (typename set_ty::iterator it = s.begin(), ie = s.end(); it != ie; ++it) if (b.s.count(*it)) return true; @@ -76,54 +95,91 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, return os; } -class IndependentElementSet { +class IndependentConstraintSet { +private: + using InnerSetUnion = + DisjointSetUnion, IndependentConstraintSet, + ExprOrSymcreteHash, ExprOrSymcreteCmp>; + + void initIndependentConstraintSet(ref e); + void initIndependentConstraintSet(ref s); + public: - typedef std::map> elements_ty; + // All containers need to become persistent to make fast copy and faster + // merge possible map from concretized to normal + typedef PersistentMap> elements_ty; elements_ty elements; // Represents individual elements of array accesses (arr[1]) - std::set - wholeObjects; // Represents symbolically accessed arrays (arr[x]) - constraints_ty exprs; // All expressions (constraints) that are associated - // with this factor - SymcreteOrderedSet symcretes; // All symcretes associated with this factor + PersistentSet + wholeObjects; // Represents symbolically accessed arrays (arr[x]) + PersistentSet> exprs; // All expressions (constraints) that are + // associated with this factor + PersistentSet> + symcretes; // All symcretes associated with this factor + + Assignment concretization; + + InnerSetUnion concretizedSets; + + ref addExpr(ref e) const; + ref + updateConcretization(const Assignment &delta, + ExprHashMap> &changedExprs) const; + ref + removeConcretization(const Assignment &delta, + ExprHashMap> &changedExprs) const; + + void + addValuesToAssignment(const std::vector &objects, + const std::vector> &values, + Assignment &assign) const; + + IndependentConstraintSet(); + explicit IndependentConstraintSet(ref v); + IndependentConstraintSet(const IndependentConstraintSet &ics); + + void print(llvm::raw_ostream &os) const; - IndependentElementSet(); - IndependentElementSet(ref e); - IndependentElementSet(ref s); - IndependentElementSet(const IndependentElementSet &ies); + static bool intersects(ref a, + ref b); - IndependentElementSet &operator=(const IndependentElementSet &ies); + static ref + merge(ref a, + ref b); - void print(llvm::raw_ostream &os) const; + // Extracts which arrays are referenced from a particular independent set. + // Examines both the actual known array accesses arr[1] plus the undetermined + // accesses arr[x].Z + void calculateArrayReferences(std::vector &returnVector) const; - // more efficient when this is the smaller set - bool intersects(const IndependentElementSet &b); + SymcreteOrderedSet getSymcretes() const { + SymcreteOrderedSet a; + for (ref s : symcretes) { + a.insert(s); + } + return a; + } - // returns true iff set is changed by addition - bool add(const IndependentElementSet &b); + constraints_ty getConstraints() const { + constraints_ty a; + for (ref e : exprs) { + a.insert(e); + } + return a; + } + mutable class ReferenceCounter _refCount; }; +void calculateArraysInFactors( + const std::vector> &factors, + ref queryExpr, std::vector &returnVector); + inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, - const IndependentElementSet &ies) { + const IndependentConstraintSet &ies) { ies.print(os); return os; } -// Breaks down a constraint into all of it's individual pieces, returning a -// list of IndependentElementSets or the independent factors. -// -// Caller takes ownership of returned std::list. -std::list * -getAllIndependentConstraintsSets(const Query &query); - -IndependentElementSet getIndependentConstraints(const Query &query, - constraints_ty &result); - -// Extracts which arrays are referenced from a particular independent set. -// Examines both the actual known array accesses arr[1] plus the undetermined -// accesses arr[x]. -void calculateArrayReferences(const IndependentElementSet &ie, - std::vector &returnVector); } // namespace klee #endif /* KLEE_INDEPENDENTSET_H */ diff --git a/include/klee/Expr/Parser/Lexer.h b/include/klee/Expr/Parser/Lexer.h index 8b3fe53a30..dc4c111adc 100644 --- a/include/klee/Expr/Parser/Lexer.h +++ b/include/klee/Expr/Parser/Lexer.h @@ -32,6 +32,8 @@ struct Token { KWFalse, ///< 'false' KWQuery, ///< 'query' KWPath, ///< 'path' + KWDefault, ///< 'default' + KWNull, ///< 'null' KWReserved, ///< fp[0-9]+([.].*)?, i[0-9]+ KWSymbolic, ///< 'symbolic' KWTrue, ///< 'true' diff --git a/include/klee/Expr/Parser/Parser.h b/include/klee/Expr/Parser/Parser.h index 0f6ec291c0..5009125c85 100644 --- a/include/klee/Expr/Parser/Parser.h +++ b/include/klee/Expr/Parser/Parser.h @@ -220,6 +220,8 @@ class Parser { static Parser *Create(const std::string Name, const llvm::MemoryBuffer *MB, ExprBuilder *Builder, ArrayCache *TheArrayCache, KModule *km, bool ClearArrayAfterQuery); + + virtual ArrayCache &getArrayCache() = 0; }; } // namespace expr } // namespace klee diff --git a/include/klee/Expr/Path.h b/include/klee/Expr/Path.h index 48bb63ec47..a556a00213 100644 --- a/include/klee/Expr/Path.h +++ b/include/klee/Expr/Path.h @@ -1,6 +1,8 @@ #ifndef KLEE_PATH_H #define KLEE_PATH_H +#include "klee/ADT/ImmutableList.h" + #include #include #include @@ -16,7 +18,7 @@ using stackframe_ty = std::pair; class Path { public: - using path_ty = std::vector; + using path_ty = ImmutableList; enum class TransitionKind { StepInto, StepOut, None }; struct PathIndex { @@ -38,23 +40,6 @@ class Path { void advance(KInstruction *ki); - friend bool operator==(const Path &lhs, const Path &rhs) { - return lhs.KBlocks == rhs.KBlocks && - lhs.firstInstruction == rhs.firstInstruction && - lhs.lastInstruction == rhs.lastInstruction; - } - friend bool operator!=(const Path &lhs, const Path &rhs) { - return !(lhs == rhs); - } - - friend bool operator<(const Path &lhs, const Path &rhs) { - return lhs.KBlocks < rhs.KBlocks || - (lhs.KBlocks == rhs.KBlocks && - (lhs.firstInstruction < rhs.firstInstruction || - (lhs.firstInstruction == rhs.firstInstruction && - lhs.lastInstruction < rhs.lastInstruction))); - } - unsigned KBlockSize() const; const path_ty &getBlocks() const; unsigned getFirstIndex() const; @@ -64,7 +49,6 @@ class Path { std::vector getStack(bool reversed) const; - std::vector> asFunctionRanges() const; std::string toString() const; static Path concat(const Path &l, const Path &r); @@ -73,7 +57,7 @@ class Path { Path() = default; - Path(unsigned firstInstruction, std::vector kblocks, + Path(unsigned firstInstruction, const path_ty &kblocks, unsigned lastInstruction) : KBlocks(kblocks), firstInstruction(firstInstruction), lastInstruction(lastInstruction) {} diff --git a/include/klee/Expr/SourceBuilder.h b/include/klee/Expr/SourceBuilder.h index 7b57e2f8c9..6869ad0753 100644 --- a/include/klee/Expr/SourceBuilder.h +++ b/include/klee/Expr/SourceBuilder.h @@ -2,6 +2,7 @@ #define KLEE_SOURCEBUILDER_H #include "klee/ADT/Ref.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Module/KModule.h" @@ -12,10 +13,13 @@ class SourceBuilder { SourceBuilder() = delete; static ref - constant(const std::vector> &constantValues); - static ref symbolicSizeConstant(unsigned defaultValue); - static ref symbolicSizeConstantAddress(unsigned defaultValue, - unsigned version); + constant(SparseStorage> constantValues); + + static ref uninitialized(unsigned version, + const KInstruction *allocSite); + static ref + symbolicSizeConstantAddress(unsigned version, const KInstruction *allocSite, + ref size); static ref makeSymbolic(const std::string &name, unsigned version); static ref lazyInitializationAddress(ref pointer); @@ -28,6 +32,7 @@ class SourceBuilder { static ref value(const llvm::Value &_allocSite, int _index, KModule *km); static ref irreproducible(const std::string &name); + static ref alpha(int _index); }; }; // namespace klee diff --git a/include/klee/Expr/SymbolicSource.h b/include/klee/Expr/SymbolicSource.h index be65580f7b..5829855543 100644 --- a/include/klee/Expr/SymbolicSource.h +++ b/include/klee/Expr/SymbolicSource.h @@ -3,11 +3,14 @@ #include "klee/ADT/Ref.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Support/CompilerWarning.h" + DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Argument.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" DISABLE_WARNING_POP @@ -21,6 +24,7 @@ class Array; class Expr; class ConstantExpr; class KModule; +struct KInstruction; class SymbolicSource { protected: @@ -33,7 +37,7 @@ class SymbolicSource { enum Kind { Constant = 3, - SymbolicSizeConstant, + Uninitialied, SymbolicSizeConstantAddress, MakeSymbolic, LazyInitializationContent, @@ -41,7 +45,8 @@ class SymbolicSource { LazyInitializationSize, Instruction, Argument, - Irreproducible + Irreproducible, + Alpha }; public: @@ -63,24 +68,26 @@ class SymbolicSource { class ConstantSource : public SymbolicSource { public: - /// constantValues - The constant initial values for this array, or empty for - /// a symbolic array. If non-empty, this size of this array is equivalent to - /// the array size. - const std::vector> constantValues; + const SparseStorage> constantValues; + + ConstantSource(SparseStorage> _constantValues) + : constantValues(std::move(_constantValues)) { + assert(constantValues.defaultV() && "Constant must be constant!"); + } - ConstantSource(const std::vector> &_constantValues) - : constantValues(_constantValues){}; Kind getKind() const override { return Kind::Constant; } - virtual std::string getName() const override { return "constant"; } - uint64_t size() const { return constantValues.size(); } + + std::string getName() const override { return "constant"; } static bool classof(const SymbolicSource *S) { return S->getKind() == Kind::Constant; } + static bool classof(const ConstantSource *) { return true; } - virtual unsigned computeHash() override; - virtual int internalCompare(const SymbolicSource &b) const override { + unsigned computeHash() override; + + int internalCompare(const SymbolicSource &b) const override { if (getKind() != b.getKind()) { return getKind() < b.getKind() ? -1 : 1; } @@ -92,43 +99,38 @@ class ConstantSource : public SymbolicSource { } }; -class SymbolicSizeConstantSource : public SymbolicSource { +class UninitializedSource : public SymbolicSource { public: - const unsigned defaultValue; - SymbolicSizeConstantSource(unsigned _defaultValue) - : defaultValue(_defaultValue) {} + const unsigned version; + const KInstruction *allocSite; - Kind getKind() const override { return Kind::SymbolicSizeConstant; } - virtual std::string getName() const override { - return "symbolicSizeConstant"; - } + UninitializedSource(unsigned version, const KInstruction *allocSite) + : version(version), allocSite(allocSite) {} + + Kind getKind() const override { return Kind::Uninitialied; } + + std::string getName() const override { return "uninitialized"; } static bool classof(const SymbolicSource *S) { - return S->getKind() == Kind::SymbolicSizeConstant; + return S->getKind() == Kind::Uninitialied; } - static bool classof(const SymbolicSizeConstantSource *) { return true; } - virtual unsigned computeHash() override; + static bool classof(const UninitializedSource *) { return true; } - virtual int internalCompare(const SymbolicSource &b) const override { - if (getKind() != b.getKind()) { - return getKind() < b.getKind() ? -1 : 1; - } - const SymbolicSizeConstantSource &ssb = - static_cast(b); - if (defaultValue != ssb.defaultValue) { - return defaultValue < ssb.defaultValue ? -1 : 1; - } - return 0; - } + unsigned computeHash() override; + + int internalCompare(const SymbolicSource &b) const override; }; class SymbolicSizeConstantAddressSource : public SymbolicSource { public: - const unsigned defaultValue; const unsigned version; - SymbolicSizeConstantAddressSource(unsigned _defaultValue, unsigned _version) - : defaultValue(_defaultValue), version(_version) {} + const KInstruction *allocSite; + ref size; + SymbolicSizeConstantAddressSource(unsigned _version, + const KInstruction *_allocSite, + ref _size) + : version(_version), allocSite(_allocSite), size(_size) {} Kind getKind() const override { return Kind::SymbolicSizeConstantAddress; } virtual std::string getName() const override { @@ -144,20 +146,7 @@ class SymbolicSizeConstantAddressSource : public SymbolicSource { virtual unsigned computeHash() override; - virtual int internalCompare(const SymbolicSource &b) const override { - if (getKind() != b.getKind()) { - return getKind() < b.getKind() ? -1 : 1; - } - const SymbolicSizeConstantAddressSource &ssb = - static_cast(b); - if (defaultValue != ssb.defaultValue) { - return defaultValue < ssb.defaultValue ? -1 : 1; - } - if (version != ssb.version) { - return version < ssb.version ? -1 : 1; - } - return 0; - } + virtual int internalCompare(const SymbolicSource &b) const override; }; class MakeSymbolicSource : public SymbolicSource { @@ -361,6 +350,37 @@ class IrreproducibleSource : public SymbolicSource { } }; +class AlphaSource : public SymbolicSource { +public: + const unsigned index; + + AlphaSource(unsigned _index) : index(_index) {} + Kind getKind() const override { return Kind::Alpha; } + virtual std::string getName() const override { return "alpha"; } + + static bool classof(const SymbolicSource *S) { + return S->getKind() == Kind::Alpha; + } + static bool classof(const AlphaSource *) { return true; } + + virtual unsigned computeHash() override { + unsigned res = getKind(); + hashValue = res ^ (index * SymbolicSource::MAGIC_HASH_CONSTANT); + return hashValue; + } + + virtual int internalCompare(const SymbolicSource &b) const override { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const AlphaSource &amb = static_cast(b); + if (index != amb.index) { + return index < amb.index ? -1 : 1; + } + return 0; + } +}; + } // namespace klee #endif /* KLEE_SYMBOLICSOURCE_H */ diff --git a/include/klee/Expr/Symcrete.h b/include/klee/Expr/Symcrete.h index 6646c4cf16..65b70b20f7 100644 --- a/include/klee/Expr/Symcrete.h +++ b/include/klee/Expr/Symcrete.h @@ -75,6 +75,8 @@ class Symcrete { return id < rhs.id ? -1 : 1; } + unsigned hash() { return id; } + bool operator<(const Symcrete &rhs) const { return compare(rhs) < 0; }; }; diff --git a/include/klee/Module/CodeGraphDistance.h b/include/klee/Module/CodeGraphDistance.h deleted file mode 100644 index 3192344ec4..0000000000 --- a/include/klee/Module/CodeGraphDistance.h +++ /dev/null @@ -1,75 +0,0 @@ -//===-- CodeGraphDistance.h -------------------------------------*- C++ -*-===// -// -// The KLEE Symbolic Virtual Machine -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef KLEE_CODEGRAPHGDISTANCE_H -#define KLEE_CODEGRAPHGDISTANCE_H - -#include "klee/Module/KModule.h" - -#include - -namespace klee { - -class CodeGraphDistance { - - using blockDistanceMap = - std::unordered_map>; - using blockDistanceList = - std::unordered_map>>; - - using functionDistanceMap = - std::unordered_map>; - using functionDistanceList = - std::unordered_map>>; - -private: - blockDistanceMap blockDistance; - blockDistanceMap blockBackwardDistance; - blockDistanceList blockSortedDistance; - blockDistanceList blockSortedBackwardDistance; - - functionDistanceMap functionDistance; - functionDistanceMap functionBackwardDistance; - functionDistanceList functionSortedDistance; - functionDistanceList functionSortedBackwardDistance; - -private: - void calculateDistance(KBlock *bb); - void calculateBackwardDistance(KBlock *bb); - - void calculateDistance(KFunction *kf); - void calculateBackwardDistance(KFunction *kf); - -public: - const std::unordered_map &getDistance(KBlock *kb); - const std::unordered_map & - getBackwardDistance(KBlock *kb); - const std::vector> & - getSortedDistance(KBlock *kb); - const std::vector> & - getSortedBackwardDistance(KBlock *kb); - - const std::unordered_map & - getDistance(KFunction *kf); - const std::unordered_map & - getBackwardDistance(KFunction *kf); - const std::vector> & - getSortedDistance(KFunction *kf); - const std::vector> & - getSortedBackwardDistance(KFunction *kf); - - void getNearestPredicateSatisfying(KBlock *from, KBlockPredicate predicate, - std::set &result); -}; - -} // namespace klee - -#endif /* KLEE_CODEGRAPHGDISTANCE_H */ diff --git a/include/klee/Module/CodeGraphInfo.h b/include/klee/Module/CodeGraphInfo.h new file mode 100644 index 0000000000..549964287a --- /dev/null +++ b/include/klee/Module/CodeGraphInfo.h @@ -0,0 +1,88 @@ +//===-- CodeGraphInfo.h -----------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_CODEGRAPHGDISTANCE_H +#define KLEE_CODEGRAPHGDISTANCE_H + +#include "klee/Module/KModule.h" + +#include + +namespace klee { + +using Block = llvm::BasicBlock; +using BlockDistanceMap = std::unordered_map; +using FunctionDistanceMap = std::unordered_map; +using SortedBlockDistances = std::vector>; +using SortedFunctionDistances = + std::vector>; + +class CodeGraphInfo { + + using blockToDistanceMap = std::unordered_map; + using blockDistanceList = std::unordered_map; + + using functionToDistanceMap = + std::unordered_map; + using functionDistanceList = + std::unordered_map; + + using functionBranchesSet = + std::unordered_map>>; + +private: + blockToDistanceMap blockDistance; + blockToDistanceMap blockBackwardDistance; + std::set blockCycles; + blockDistanceList blockSortedDistance; + blockDistanceList blockSortedBackwardDistance; + + functionToDistanceMap functionDistance; + functionToDistanceMap functionBackwardDistance; + functionDistanceList functionSortedDistance; + functionDistanceList functionSortedBackwardDistance; + + functionBranchesSet functionBranches; + functionBranchesSet functionConditionalBranches; + functionBranchesSet functionBlocks; + +private: + void calculateDistance(Block *bb); + void calculateBackwardDistance(Block *bb); + + void calculateDistance(KFunction *f); + void calculateBackwardDistance(KFunction *f); + + void calculateFunctionBranches(KFunction *kf); + void calculateFunctionConditionalBranches(KFunction *kf); + void calculateFunctionBlocks(KFunction *kf); + +public: + const BlockDistanceMap &getDistance(Block *b); + const BlockDistanceMap &getDistance(KBlock *kb); + const BlockDistanceMap &getBackwardDistance(KBlock *kb); + bool hasCycle(KBlock *kb); + + const FunctionDistanceMap &getDistance(KFunction *kf); + const FunctionDistanceMap &getBackwardDistance(KFunction *kf); + + void getNearestPredicateSatisfying(KBlock *from, KBlockPredicate predicate, + std::set &result); + + const std::map> & + getFunctionBranches(KFunction *kf); + const std::map> & + getFunctionConditionalBranches(KFunction *kf); + const std::map> & + getFunctionBlocks(KFunction *kf); +}; + +} // namespace klee + +#endif /* KLEE_CODEGRAPHGDISTANCE_H */ diff --git a/include/klee/Module/InstructionInfoTable.h b/include/klee/Module/InstructionInfoTable.h deleted file mode 100644 index 8b91c0d8c8..0000000000 --- a/include/klee/Module/InstructionInfoTable.h +++ /dev/null @@ -1,113 +0,0 @@ -//===-- InstructionInfoTable.h ----------------------------------*- C++ -*-===// -// -// The KLEE Symbolic Virtual Machine -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef KLEE_INSTRUCTIONINFOTABLE_H -#define KLEE_INSTRUCTIONINFOTABLE_H - -#include "klee/Support/CompilerWarning.h" -DISABLE_WARNING_PUSH -DISABLE_WARNING_DEPRECATED_DECLARATIONS -#include "llvm/ADT/Optional.h" -#include "llvm/Support/raw_ostream.h" -DISABLE_WARNING_POP - -#include -#include -#include -#include -#include - -namespace llvm { -class Function; -class Instruction; -class Module; -} // namespace llvm - -namespace klee { - -/// @brief InstructionInfo stores debug information for a KInstruction. -struct InstructionInfo { - /// @brief The instruction id. - unsigned id; - /// @brief Line number in source file. - unsigned line; - /// @brief Column number in source file. - unsigned column; - /// @brief Line number in generated assembly.ll. - llvm::Optional assemblyLine; - /// @brief Source file name. - const std::string &file; - -public: - InstructionInfo(unsigned id, const std::string &file, unsigned line, - unsigned column, llvm::Optional assemblyLine) - : id{id}, line{line}, column{column}, - assemblyLine{assemblyLine}, file{file} {} -}; - -/// @brief FunctionInfo stores debug information for a KFunction. -struct FunctionInfo { - /// @brief The function id. - unsigned id; - /// @brief Line number in source file. - unsigned line; - /// @brief Line number in generated assembly.ll. - llvm::Optional assemblyLine; - /// @brief Source file name. - const std::string &file; - -public: - FunctionInfo(unsigned id, const std::string &file, unsigned line, - llvm::Optional assemblyLine) - : id{id}, line{line}, assemblyLine{assemblyLine}, file{file} {} - - FunctionInfo(const FunctionInfo &) = delete; - FunctionInfo &operator=(FunctionInfo const &) = delete; - - FunctionInfo(FunctionInfo &&) = default; -}; - -class InstructionInfoTable { -public: - using Instructions = std::unordered_map< - std::string, - std::unordered_map< - unsigned int, - std::unordered_map>>>; - using LocationToFunctionsMap = - std::unordered_map>; - -private: - std::unordered_map> - infos; - std::unordered_map> - functionInfos; - LocationToFunctionsMap fileNameToFunctions; - std::vector> internedStrings; - std::unordered_set filesNames; - Instructions insts; - -public: - explicit InstructionInfoTable( - const llvm::Module &m, std::unique_ptr assemblyFS, - bool withInstructions = false); - - unsigned getMaxID() const; - const InstructionInfo &getInfo(const llvm::Instruction &) const; - const FunctionInfo &getFunctionInfo(const llvm::Function &) const; - const LocationToFunctionsMap &getFileNameToFunctions() const; - const std::unordered_set &getFilesNames() const; - Instructions getInstructions(); -}; - -} // namespace klee - -#endif /* KLEE_INSTRUCTIONINFOTABLE_H */ diff --git a/include/klee/Module/KInstruction.h b/include/klee/Module/KInstruction.h index 865a752bfd..a4ee2c9c44 100644 --- a/include/klee/Module/KInstruction.h +++ b/include/klee/Module/KInstruction.h @@ -10,16 +10,17 @@ #ifndef KLEE_KINSTRUCTION_H #define KLEE_KINSTRUCTION_H +#include "KModule.h" #include "klee/Config/Version.h" -#include "klee/Module/InstructionInfoTable.h" - #include "klee/Support/CompilerWarning.h" +#include "llvm/IR/Argument.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/DataTypes.h" #include "llvm/Support/raw_ostream.h" DISABLE_WARNING_POP +#include #include namespace llvm { @@ -28,34 +29,98 @@ class Instruction; namespace klee { class Executor; -struct InstructionInfo; class KModule; struct KBlock; +struct KFunction; + +static const unsigned MAGIC_HASH_CONSTANT = 39; /// KInstruction - Intermediate instruction representation used /// during execution. struct KInstruction { + + struct Index { + unsigned long instID; + unsigned long blockID; + unsigned long funcID; + + bool operator==(const Index &other) const { + return std::tie(instID, blockID, funcID) == + std::tie(other.instID, other.blockID, other.funcID); + } + + bool operator<(const Index &other) const { + return std::tie(instID, blockID, funcID) < + std::tie(other.instID, other.blockID, other.funcID); + } + + unsigned hash() const { + unsigned res = instID; + res = res * MAGIC_HASH_CONSTANT + blockID; + res = res * MAGIC_HASH_CONSTANT + funcID; + return res; + } + + void print(llvm::raw_ostream &os) const { + os << "[" << instID << ", " << blockID << ", " << funcID << "]"; + } + }; + llvm::Instruction *inst; - const InstructionInfo *info; /// Value numbers for each operand. -1 is an invalid value, /// otherwise negative numbers are indices (negated and offset by /// 2) into the module constant table and positive numbers are /// register indices. int *operands; - /// Destination register index. - unsigned dest; KBlock *parent; +private: // Instruction index in the basic block - unsigned index; + const unsigned globalIndex; public: - KInstruction() = default; - explicit KInstruction(const KInstruction &ki); + /// Unique index for KFunction and KInstruction inside KModule + /// from 0 to [KFunction + KInstruction] + [[nodiscard]] unsigned getGlobalIndex() const; + /// Instruction index in the basic block + [[nodiscard]] unsigned getIndex() const; + /// Destination register index. + [[nodiscard]] unsigned getDest() const; + + KInstruction(const std::unordered_map + &_instructionToRegisterMap, + llvm::Instruction *_inst, KModule *_km, KBlock *_kb, + unsigned &_globalIndexInc); + + KInstruction() = delete; + explicit KInstruction(const KInstruction &ki) = delete; virtual ~KInstruction(); std::string getSourceLocation() const; - std::string toString() const; + + [[nodiscard]] size_t getLine() const; + [[nodiscard]] size_t getColumn() const; + [[nodiscard]] std::string getSourceFilepath() const; + Index getID() const; + + [[nodiscard]] std::string getSourceLocationString() const; + [[nodiscard]] std::string toString() const; + bool operator==(const KInstruction &other) const { + return getID() == other.getID(); + } + + [[nodiscard]] inline KBlock *getKBlock() const { return parent; } + [[nodiscard]] inline KFunction *getKFunction() const { + return getKBlock()->parent; + } + bool operator<(const KInstruction &other) const { + return getID() < other.getID(); + } + [[nodiscard]] inline KModule *getKModule() const { + return getKFunction()->parent; + } + + unsigned hash() const { return getID().hash(); } }; struct KGEPInstruction : KInstruction { @@ -70,8 +135,14 @@ struct KGEPInstruction : KInstruction { uint64_t offset; public: - KGEPInstruction() = default; - explicit KGEPInstruction(const KGEPInstruction &ki); + KGEPInstruction(const std::unordered_map + &_instructionToRegisterMap, + llvm::Instruction *_inst, KModule *_km, KBlock *_kb, + unsigned &_globalIndexInc) + : KInstruction(_instructionToRegisterMap, _inst, _km, _kb, + _globalIndexInc) {} + KGEPInstruction() = delete; + explicit KGEPInstruction(const KGEPInstruction &ki) = delete; }; } // namespace klee diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index bfd30c019b..dfd00c101f 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -12,7 +12,6 @@ #include "klee/Config/Version.h" #include "klee/Core/Interpreter.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KCallable.h" #include "klee/Support/CompilerWarning.h" @@ -61,20 +60,13 @@ enum KBlockType { Base, Call, Return }; struct KBlock { KFunction *parent; llvm::BasicBlock *basicBlock; - - unsigned numInstructions; KInstruction **instructions; - /// Whether instructions in this function should count as - /// "coverable" for statistics and search heuristics. - bool trackCoverage; - - unsigned id; - public: KBlock(KFunction *, llvm::BasicBlock *, KModule *, - std::unordered_map &, - std::unordered_map &, KInstruction **); + const std::unordered_map &, + KInstruction **, unsigned &globalIndexInc); + KBlock() = delete; KBlock(const KBlock &) = delete; KBlock &operator=(const KBlock &) = delete; virtual ~KBlock() = default; @@ -82,16 +74,16 @@ struct KBlock { virtual KBlockType getKBlockType() const { return KBlockType::Base; } static bool classof(const KBlock *) { return true; } - void handleKInstruction(std::unordered_map - &instructionToRegisterMap, - llvm::Instruction *inst, KModule *km, - KInstruction *ki); + unsigned getNumInstructions() const noexcept { return basicBlock->size(); } KInstruction *getFirstInstruction() const noexcept { return instructions[0]; } KInstruction *getLastInstruction() const noexcept { - return instructions[numInstructions - 1]; + return instructions[getNumInstructions() - 1]; } std::string getLabel() const; std::string toString() const; + + /// Block number in function + [[nodiscard]] uintptr_t getId() const; }; typedef std::function KBlockPredicate; @@ -101,10 +93,11 @@ struct KCallBlock : KBlock { std::set calledFunctions; public: + KCallBlock() = delete; KCallBlock(KFunction *, llvm::BasicBlock *, KModule *, - std::unordered_map &, - std::unordered_map &, - std::set, KInstruction **); + const std::unordered_map &, + std::set, KInstruction **, + unsigned &globalIndexInc); static bool classof(const KCallBlock *) { return true; } static bool classof(const KBlock *E) { return E->getKBlockType() == KBlockType::Call; @@ -118,9 +111,10 @@ struct KCallBlock : KBlock { struct KReturnBlock : KBlock { public: + KReturnBlock() = delete; KReturnBlock(KFunction *, llvm::BasicBlock *, KModule *, - std::unordered_map &, - std::unordered_map &, KInstruction **); + const std::unordered_map &, + KInstruction **, unsigned &globalIndexInc); static bool classof(const KReturnBlock *) { return true; } static bool classof(const KBlock *E) { return E->getKBlockType() == KBlockType::Return; @@ -131,20 +125,14 @@ struct KReturnBlock : KBlock { struct KFunction : public KCallable { private: std::unordered_map labelMap; + const unsigned globalIndex; public: KModule *parent; llvm::Function *function; - - unsigned numArgs, numRegisters; - unsigned id; - - std::unordered_map registerToInstructionMap; - unsigned numInstructions; - unsigned numBlocks; KInstruction **instructions; - bool kleeHandled = false; + [[nodiscard]] KInstruction *getInstructionByRegister(size_t reg) const; std::unordered_map instructionMap; std::vector> blocks; @@ -153,11 +141,16 @@ struct KFunction : public KCallable { std::vector returnKBlocks; std::vector kCallBlocks; - /// Whether instructions in this function should count as - /// "coverable" for statistics and search heuristics. - bool trackCoverage; + /// count of instructions in function + unsigned numInstructions; + [[nodiscard]] size_t getNumArgs() const; + [[nodiscard]] size_t getNumRegisters() const; + unsigned id; + + bool kleeHandled = false; - explicit KFunction(llvm::Function *, KModule *); + explicit KFunction(llvm::Function *, KModule *, unsigned &); + KFunction() = delete; KFunction(const KFunction &) = delete; KFunction &operator=(const KFunction &) = delete; @@ -187,6 +180,27 @@ struct KFunction : public KCallable { static bool classof(const KCallable *callable) { return callable->getKind() == CK_Function; } + + [[nodiscard]] size_t getLine() const; + [[nodiscard]] std::string getSourceFilepath() const; + + /// Unique index for KFunction and KInstruction inside KModule + /// from 0 to [KFunction + KInstruction] + [[nodiscard]] inline unsigned getGlobalIndex() const { return globalIndex; } +}; + +struct KBlockCompare { + bool operator()(const KBlock *a, const KBlock *b) const { + return a->parent->getGlobalIndex() < b->parent->getGlobalIndex() || + (a->parent->getGlobalIndex() == b->parent->getGlobalIndex() && + a->getId() < b->getId()); + } +}; + +struct KFunctionCompare { + bool operator()(const KFunction *a, const KFunction *b) const { + return a->id < b->id; + } }; class KConstant { @@ -206,7 +220,8 @@ class KConstant { class KModule { private: - bool withPosixRuntime; + bool withPosixRuntime; // TODO move to opts + unsigned maxGlobalIndex; public: std::unique_ptr module; @@ -217,19 +232,16 @@ class KModule { std::unordered_map functionMap; std::unordered_map> callMap; std::unordered_map functionNameMap; - std::unordered_map functionIDMap; + [[nodiscard]] unsigned getFunctionId(const llvm::Function *) const; // Functions which escape (may be called indirectly) // XXX change to KFunction std::set escapingFunctions; - std::unordered_set mainModuleFunctions; - - std::unordered_set mainModuleGlobals; - - InstructionInfoTable::Instructions origInfos; + std::set mainModuleFunctions; + std::set mainModuleGlobals; - std::unique_ptr infos; + FLCtoOpcode origInstructions; std::vector constants; std::unordered_map> @@ -241,6 +253,9 @@ class KModule { // Functions which are part of KLEE runtime std::set internalFunctions; + // instruction to assembly.ll line empty if no statistic enabled + std::unordered_map asmLineMap; + // Mark function with functionName as part of the KLEE runtime void addInternalFunction(const char *functionName); // Replace std functions with KLEE intrinsics @@ -287,13 +302,21 @@ class KModule { /// expected by KLEE's Executor hold. void checkModule(); - KBlock *getKBlock(llvm::BasicBlock *bb); + KBlock *getKBlock(const llvm::BasicBlock *bb); bool inMainModule(const llvm::Function &f); bool inMainModule(const llvm::GlobalVariable &v); bool WithPOSIXRuntime() { return withPosixRuntime; } + + std::optional getAsmLine(const uintptr_t ref) const; + std::optional getAsmLine(const llvm::Function *func) const; + std::optional getAsmLine(const llvm::Instruction *inst) const; + + inline unsigned getMaxGlobalIndex() const { return maxGlobalIndex; } + unsigned getGlobalIndex(const llvm::Function *func) const; + unsigned getGlobalIndex(const llvm::Instruction *inst) const; }; } // namespace klee diff --git a/include/klee/Module/LocationInfo.h b/include/klee/Module/LocationInfo.h new file mode 100644 index 0000000000..36ac6bec4d --- /dev/null +++ b/include/klee/Module/LocationInfo.h @@ -0,0 +1,35 @@ +////===-- LocationInfo.h ----------------------------------*- C++ -*-===// +//// +//// The KLEE Symbolic Virtual Machine +//// +//// This file is distributed under the University of Illinois Open Source +//// License. See LICENSE.TXT for details. +//// +////===----------------------------------------------------------------------===// + +#ifndef KLEE_LOCATIONINFO_H +#define KLEE_LOCATIONINFO_H + +#include +#include + +namespace llvm { +class Function; +class Instruction; +class Module; +} // namespace llvm + +namespace klee { + +struct LocationInfo { + std::string file; + size_t line; + size_t column; +}; + +LocationInfo getLocationInfo(const llvm::Function *func); +LocationInfo getLocationInfo(const llvm::Instruction *inst); + +} // namespace klee + +#endif /* KLEE_LOCATIONINFO_H */ diff --git a/include/klee/Module/Target.h b/include/klee/Module/Target.h index 80bf7e0c1d..98eb3c900a 100644 --- a/include/klee/Module/Target.h +++ b/include/klee/Module/Target.h @@ -41,6 +41,9 @@ struct ErrorLocation { unsigned int endLine; optional startColumn; optional endColumn; + + ErrorLocation(const klee::ref &loc); + ErrorLocation(const KInstruction *ki); }; class ReproduceErrorTarget; diff --git a/include/klee/Module/TargetHash.h b/include/klee/Module/TargetHash.h index 2c2c2f81bd..1962ba906c 100644 --- a/include/klee/Module/TargetHash.h +++ b/include/klee/Module/TargetHash.h @@ -31,13 +31,8 @@ struct TargetCmp { bool operator()(const ref &a, const ref &b) const; }; -typedef std::pair Transition; typedef std::pair Branch; -struct TransitionHash { - std::size_t operator()(const Transition &p) const; -}; - struct BranchHash { std::size_t operator()(const Branch &p) const; }; diff --git a/include/klee/Solver/Common.h b/include/klee/Solver/Common.h index 57ebad547d..2a43b9eb67 100644 --- a/include/klee/Solver/Common.h +++ b/include/klee/Solver/Common.h @@ -29,7 +29,7 @@ std::unique_ptr constructSolverChain( std::unique_ptr coreSolver, std::string querySMT2LogPath, std::string baseSolverQuerySMT2LogPath, std::string queryKQueryLogPath, std::string baseSolverQueryKQueryLogPath, - AddressGenerator *addressGenerator); + AddressGenerator *addressGenerator, ArrayCache &arrayCache); } // namespace klee #endif /* KLEE_COMMON_H */ diff --git a/include/klee/Solver/IncompleteSolver.h b/include/klee/Solver/IncompleteSolver.h index 4f47c1cdd6..65dac30c4b 100644 --- a/include/klee/Solver/IncompleteSolver.h +++ b/include/klee/Solver/IncompleteSolver.h @@ -80,6 +80,7 @@ class StagedSolverImpl : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; } // namespace klee diff --git a/include/klee/Solver/Solver.h b/include/klee/Solver/Solver.h index 30b344efec..93fad34f54 100644 --- a/include/klee/Solver/Solver.h +++ b/include/klee/Solver/Solver.h @@ -191,6 +191,10 @@ class Solver { virtual char *getConstraintLog(const Query &query); virtual void setCoreSolverTimeout(time::Span timeout); + + /// @brief Notify the solver that the state with specified id has been + /// terminated + void notifyStateTermination(std::uint32_t id); }; /* *** */ @@ -240,6 +244,14 @@ std::unique_ptr createFastCexSolver(std::unique_ptr s); /// \param s - The underlying solver to use. std::unique_ptr createIndependentSolver(std::unique_ptr s); +/// createAlphaEquivalenceSolver - Create a solver which will change +/// independent queries to their alpha-equvalent version +/// +/// \param s - The underlying solver to use. +/// \param arrayCache - Class to create new arrays. +std::unique_ptr createAlphaEquivalenceSolver(std::unique_ptr s, + ArrayCache &arrayCache); + /// createKQueryLoggingSolver - Create a solver which will forward all queries /// after writing them to the given path in .kquery format. std::unique_ptr createKQueryLoggingSolver(std::unique_ptr s, @@ -264,6 +276,11 @@ std::unique_ptr createCoreSolver(CoreSolverType cst); std::unique_ptr createConcretizingSolver(std::unique_ptr s, AddressGenerator *addressGenerator); + +/// Return a list of all unique symbolic objects referenced by the +/// given Query. +void findSymbolicObjects(const Query &query, + std::vector &results); } // namespace klee #endif /* KLEE_SOLVER_H */ diff --git a/include/klee/Solver/SolverCmdLine.h b/include/klee/Solver/SolverCmdLine.h index 7fbfac0394..e4e5fdcf03 100644 --- a/include/klee/Solver/SolverCmdLine.h +++ b/include/klee/Solver/SolverCmdLine.h @@ -32,6 +32,8 @@ extern llvm::cl::opt UseCexCache; extern llvm::cl::opt UseBranchCache; +extern llvm::cl::opt UseAlphaEquivalence; + extern llvm::cl::opt UseConcretizingSolver; extern llvm::cl::opt UseIndependentSolver; @@ -50,6 +52,8 @@ extern llvm::cl::opt CoreSolverOptimizeDivides; extern llvm::cl::opt UseAssignmentValidatingSolver; +extern llvm::cl::opt MaxSolversApproxTreeInc; + /// The different query logging solvers that can be switched on/off enum QueryLoggingSolverType { ALL_KQUERY, ///< Log all queries in .kquery (KQuery) format @@ -61,10 +65,13 @@ enum QueryLoggingSolverType { extern llvm::cl::bits QueryLoggingOptions; enum CoreSolverType { + BITWUZLA_SOLVER, + BITWUZLA_TREE_SOLVER, STP_SOLVER, METASMT_SOLVER, DUMMY_SOLVER, Z3_SOLVER, + Z3_TREE_SOLVER, NO_SOLVER }; diff --git a/include/klee/Solver/SolverImpl.h b/include/klee/Solver/SolverImpl.h index bd5937ed11..da8e510f22 100644 --- a/include/klee/Solver/SolverImpl.h +++ b/include/klee/Solver/SolverImpl.h @@ -22,7 +22,7 @@ class ExecutionState; class Expr; struct Query; -/// SolverImpl - Abstract base clase for solver implementations. +/// SolverImpl - Abstract base class for solver implementations. class SolverImpl { public: SolverImpl() = default; @@ -119,6 +119,8 @@ class SolverImpl { } virtual void setCoreSolverTimeout(time::Span timeout){}; + + virtual void notifyStateTermination(std::uint32_t id) = 0; }; } // namespace klee diff --git a/include/klee/Solver/SolverUtil.h b/include/klee/Solver/SolverUtil.h index d61c188cc0..9be7d0f2d2 100644 --- a/include/klee/Solver/SolverUtil.h +++ b/include/klee/Solver/SolverUtil.h @@ -5,6 +5,7 @@ #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprHashMap.h" +#include "klee/Expr/IndependentSet.h" #include "klee/System/Time.h" namespace klee { @@ -41,6 +42,9 @@ enum class Validity { True = 1, False = -1, Unknown = 0 }; struct SolverQueryMetaData { /// @brief Costs for all queries issued for this state time::Span queryCost; + + /// @brief Caller state id + std::uint32_t id = 0; }; struct Query { @@ -48,25 +52,36 @@ struct Query { const ConstraintSet constraints; ref expr; - Query(const ConstraintSet &_constraints, ref _expr) - : constraints(_constraints), expr(_expr) {} + /// @brief id of the state initiated this query + const std::uint32_t id; + + Query(const ConstraintSet &_constraints, ref _expr, std::uint32_t _id) + : constraints(_constraints), expr(_expr), id(_id) {} + + /// This constructor should be used *only* if + /// this query is created *not* from some known ExecutionState + /// Otherwise consider using the above constructor + Query(const constraints_ty &cs, ref e) + : Query(ConstraintSet(cs), e, 0) {} Query(const Query &query) - : constraints(query.constraints), expr(query.expr) {} + : constraints(query.constraints), expr(query.expr), id(query.id) {} /// withExpr - Return a copy of the query with the given expression. - Query withExpr(ref _expr) const { return Query(constraints, _expr); } + Query withExpr(ref _expr) const { + return Query(constraints, _expr, id); + } /// withFalse - Return a copy of the query with a false expression. Query withFalse() const { - return Query(constraints, ConstantExpr::alloc(0, Expr::Bool)); + return Query(constraints, Expr::createFalse(), id); } /// negateExpr - Return a copy of the query with the expression negated. Query negateExpr() const { return withExpr(Expr::createIsZero(expr)); } Query withConstraints(const ConstraintSet &_constraints) const { - return Query(_constraints, expr); + return Query(_constraints, expr, id); } /// Get all arrays that figure in the query std::vector gatherArrays() const; @@ -80,6 +95,16 @@ struct Query { (lhs.constraints == rhs.constraints && lhs.expr < rhs.expr); } + void getAllIndependentConstraintsSets( + std::vector> &result) const { + constraints.getAllIndependentConstraintsSets(expr, result); + } + + void getAllDependentConstraintsSets( + std::vector> &result) const { + constraints.getAllDependentConstraintsSets(expr, result); + } + /// Dump query void dump() const; }; @@ -97,11 +122,8 @@ struct ValidityCore { ValidityCore(const constraints_typ &_constraints, ref _expr) : constraints(_constraints), expr(_expr) {} - ValidityCore(const ExprHashSet &_constraints, ref _expr) : expr(_expr) { - for (auto e : _constraints) { - constraints.insert(e); - } - } + ValidityCore(const ExprHashSet &_constraints, ref _expr) + : constraints(_constraints.begin(), _constraints.end()), expr(_expr) {} /// withExpr - Return a copy of the validity core with the given expression. ValidityCore withExpr(ref _expr) const { @@ -117,6 +139,8 @@ struct ValidityCore { /// negated. ValidityCore negateExpr() const { return withExpr(Expr::createIsZero(expr)); } + Query toQuery() const; + /// Dump validity core void dump() const; @@ -220,6 +244,8 @@ class InvalidResponse : public SolverResponse { InvalidResponse(Assignment::bindings_ty &initialValues) : result(initialValues) {} + explicit InvalidResponse() : result() {} + bool tryGetInitialValuesFor( const std::vector &objects, std::vector> &values) const { @@ -228,31 +254,27 @@ class InvalidResponse : public SolverResponse { if (result.bindings.count(object)) { values.push_back(result.bindings.at(object)); } else { - ref constantSize = - dyn_cast(result.evaluate(object->size)); - assert(constantSize); - values.push_back( - SparseStorage(constantSize->getZExtValue(), 0)); + values.push_back(SparseStorage(0)); } } return true; } bool tryGetInitialValues(Assignment::bindings_ty &values) const { - values.insert(result.bindings.begin(), result.bindings.end()); + values = result.bindings; return true; } Assignment initialValuesFor(const std::vector objects) const { std::vector> values; tryGetInitialValuesFor(objects, values); - return Assignment(objects, values, true); + return Assignment(objects, values); } Assignment initialValues() const { Assignment::bindings_ty values; tryGetInitialValues(values); - return Assignment(values, true); + return Assignment(values); } ResponseKind getResponseKind() const { return Invalid; }; @@ -276,15 +298,20 @@ class InvalidResponse : public SolverResponse { return result.bindings < ib.result.bindings; } - bool satisfies(std::set> &key) { - return result.satisfies(key.begin(), key.end()); + bool satisfies(const std::set> &key, bool allowFreeValues = true) { + return result.satisfies(key.begin(), key.end(), allowFreeValues); } - ref evaluate(ref &e) { return result.evaluate(e); } + bool satisfiesOrConstant(const std::set> &key, + bool allowFreeValues = true) { + return result.satisfiesOrConstant(key.begin(), key.end(), allowFreeValues); + } void dump() { result.dump(); } - ref evaluate(ref e) { return (result.evaluate(e)); } + ref evaluate(ref e, bool allowFreeValues = true) { + return (result.evaluate(e, allowFreeValues)); + } }; class UnknownResponse : public SolverResponse { diff --git a/include/klee/Support/ErrorHandling.h b/include/klee/Support/ErrorHandling.h index 4cc57c9744..098293d2e5 100644 --- a/include/klee/Support/ErrorHandling.h +++ b/include/klee/Support/ErrorHandling.h @@ -16,7 +16,7 @@ #endif #endif -#include +#include namespace klee { diff --git a/include/klee/Support/ModuleUtil.h b/include/klee/Support/ModuleUtil.h index 4d385c4c42..7ff0e36bd2 100644 --- a/include/klee/Support/ModuleUtil.h +++ b/include/klee/Support/ModuleUtil.h @@ -39,19 +39,16 @@ bool linkModules(llvm::Module *composite, std::vector> &modules, const unsigned Flags, std::string &errorMsg); -#if defined(__x86_64__) || defined(__i386__) -#define addFunctionReplacement(from, to) \ - {#from "f", #to "f"}, {#from "", #to ""}, { "" #from "l", #to "l" } +void replaceOrRenameFunction(llvm::Module *module, const char *old_name, + const char *new_name); +#if defined(__x86_64__) || defined(__i386__) #define addIntrinsicReplacement(from, to) \ {"llvm." #from ".f32", #to "f"}, {"llvm." #from ".f64", #to}, { \ "llvm." #from ".f80", #to "l" \ } #else -#define addFunctionReplacement(from, to) \ - {#from "f", #to "f"}, { "" #from, "" #to } - #define addIntrinsicReplacement(from, to) \ {"llvm." #from ".f32", #to "f"}, { "llvm." #from ".f64", #to } @@ -62,33 +59,15 @@ bool linkModules(llvm::Module *composite, /// implementations in runtime/klee-fp, but not explicitly replaced here. Should /// we rename them and complete the list? const std::vector> floatReplacements = { - addFunctionReplacement(__isnan, klee_internal_isnan), - addFunctionReplacement(isnan, klee_internal_isnan), - addFunctionReplacement(__isinf, klee_internal_isinf), - addFunctionReplacement(isinf, klee_internal_isinf), - addFunctionReplacement(__fpclassify, klee_internal_fpclassify), - addFunctionReplacement(fpclassify, klee_internal_fpclassify), - addFunctionReplacement(__finite, klee_internal_finite), - addFunctionReplacement(finite, klee_internal_finite), - addFunctionReplacement(sqrt, klee_internal_sqrt), - addFunctionReplacement(fabs, klee_internal_fabs), - addFunctionReplacement(rint, klee_internal_rint), - addFunctionReplacement(round, klee_internal_rint), - addFunctionReplacement(__signbit, klee_internal_signbit), - addIntrinsicReplacement(sqrt, klee_internal_sqrt), - addIntrinsicReplacement(rint, klee_internal_rint), - addIntrinsicReplacement(round, klee_internal_rint), + addIntrinsicReplacement(sqrt, sqrt), + addIntrinsicReplacement(rint, rint), + addIntrinsicReplacement(round, rint), addIntrinsicReplacement(nearbyint, nearbyint), addIntrinsicReplacement(copysign, copysign), - addIntrinsicReplacement(floor, klee_floor), + addIntrinsicReplacement(floor, floor), addIntrinsicReplacement(ceil, ceil)}; -#undef addFunctionReplacement #undef addIntrinsicReplacement -const std::vector> feRoundReplacements{ - {"fegetround", "klee_internal_fegetround"}, - {"fesetround", "klee_internal_fesetround"}}; - /// Return the Function* target of a Call or Invoke instruction, or /// null if it cannot be determined (should be only for indirect /// calls, although complicated constant expressions might be diff --git a/include/klee/Support/OptionCategories.h b/include/klee/Support/OptionCategories.h index c03128f3d9..da1d0d4934 100644 --- a/include/klee/Support/OptionCategories.h +++ b/include/klee/Support/OptionCategories.h @@ -21,6 +21,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS DISABLE_WARNING_POP namespace klee { +extern llvm::cl::OptionCategory TestCompCat; extern llvm::cl::OptionCategory ExecCat; extern llvm::cl::OptionCategory DebugCat; extern llvm::cl::OptionCategory ExecCat; diff --git a/include/klee/Support/PrintContext.h b/include/klee/Support/PrintContext.h index e397367683..5196b9a35f 100644 --- a/include/klee/Support/PrintContext.h +++ b/include/klee/Support/PrintContext.h @@ -72,6 +72,8 @@ class PrintContext { return *this; } + llvm::raw_ostream &getStream() { return os; } + /// Pop the top off the indent stack /// \return The PrintContext object so the method is chainable PrintContext &popIndent() { diff --git a/include/klee/util/APFloatEval.h b/include/klee/Utilities/APFloatEval.h similarity index 100% rename from include/klee/util/APFloatEval.h rename to include/klee/Utilities/APFloatEval.h diff --git a/include/klee/Utilities/Math.h b/include/klee/Utilities/Math.h new file mode 100644 index 0000000000..a7739cadc6 --- /dev/null +++ b/include/klee/Utilities/Math.h @@ -0,0 +1,32 @@ +//===-- Math.h --------------------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_MATH_H +#define KLEE_MATH_H + +#include + +namespace klee { +namespace util { +static unsigned int ulog2(unsigned int val) { + if (val == 0) + return UINT_MAX; + if (val == 1) + return 0; + unsigned int ret = 0; + while (val > 1) { + val >>= 1; + ret++; + } + return ret; +} +} // namespace util +} // namespace klee + +#endif /* KLEE_MATH_H */ diff --git a/lib/ADT/CMakeLists.txt b/lib/ADT/CMakeLists.txt new file mode 100644 index 0000000000..4afa541dd6 --- /dev/null +++ b/lib/ADT/CMakeLists.txt @@ -0,0 +1,16 @@ +#===------------------------------------------------------------------------===# +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +add_library(kleeADT + SparseStorage.cpp +) + +llvm_config(kleeADT "${USE_LLVM_SHARED}" support) +target_include_directories(kleeADT PRIVATE ${KLEE_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}) +target_compile_options(kleeADT PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) +target_compile_definitions(kleeADT PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) diff --git a/lib/ADT/SparseStorage.cpp b/lib/ADT/SparseStorage.cpp new file mode 100644 index 0000000000..1cfe3319b4 --- /dev/null +++ b/lib/ADT/SparseStorage.cpp @@ -0,0 +1,86 @@ +#include "klee/ADT/SparseStorage.h" +#include "klee/Expr/Expr.h" + +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" + +namespace klee { + +template <> +void SparseStorage::print(llvm::raw_ostream &os, + Density d) const { + if (d == Density::Sparse) { + // "Sparse representation" + os << "{"; + bool firstPrinted = false; + auto ordered = calculateOrderedStorage(); + for (const auto &element : ordered) { + if (firstPrinted) { + os << ", "; + } + os << element.first << ": " << llvm::utostr(element.second); + firstPrinted = true; + } + os << "} default: "; + } else { + // "Dense representation" + os << "["; + bool firstPrinted = false; + for (size_t i = 0; i < sizeOfSetRange(); i++) { + if (firstPrinted) { + os << ", "; + } + os << llvm::utostr(load(i)); + firstPrinted = true; + } + os << "] default: "; + } + os << llvm::utostr(defaultValue); +} + +template <> +void SparseStorage>::print(llvm::raw_ostream &os, + Density d) const { + if (d == Density::Sparse) { + // "Sparse representation" + os << "{"; + bool firstPrinted = false; + auto ordered = calculateOrderedStorage(); + for (const auto &element : ordered) { + if (firstPrinted) { + os << ", "; + } + os << element.first << ": "; + if (element.second) { + os << element.second; + } else { + os << "null"; + } + firstPrinted = true; + } + os << "} default: "; + } else { + // "Dense representation" + os << "["; + bool firstPrinted = false; + for (size_t i = 0; i < sizeOfSetRange(); i++) { + if (firstPrinted) { + os << ", "; + } + auto expr = load(i); + if (expr) { + os << expr; + } else { + os << "null"; + } + firstPrinted = true; + } + os << "] default: "; + } + if (defaultValue) { + os << defaultValue; + } else { + os << "null"; + } +} +} // namespace klee diff --git a/lib/Basic/Statistics.cpp b/lib/Basic/Statistics.cpp index 170ea839e0..50d9e8bf1f 100644 --- a/lib/Basic/Statistics.cpp +++ b/lib/Basic/Statistics.cpp @@ -50,7 +50,7 @@ Statistic *StatisticManager::getStatisticByName(const std::string &name) const { return 0; } -StatisticManager *klee::theStatisticManager = 0; +StatisticManager *klee::theStatisticManager = nullptr; static StatisticManager &getStatisticManager() { static StatisticManager sm; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8a0749324a..cc0279a12e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -6,6 +6,7 @@ # License. See LICENSE.TXT for details. # #===------------------------------------------------------------------------===# +add_subdirectory(ADT) add_subdirectory(Basic) add_subdirectory(Support) add_subdirectory(Expr) diff --git a/lib/Core/AddressManager.cpp b/lib/Core/AddressManager.cpp index f763e0d3e0..b0219fb9ea 100644 --- a/lib/Core/AddressManager.cpp +++ b/lib/Core/AddressManager.cpp @@ -25,9 +25,15 @@ void *AddressManager::allocate(ref address, uint64_t size) { } } else { if (sizeLocation == objects.end() || !sizeLocation->second) { - uint64_t newSize = (uint64_t)1 - << (sizeof(size) * CHAR_BIT - - __builtin_clzll(std::max((uint64_t)1, size))); + uint64_t newSize = std::max((uint64_t)1, size); + int clz = __builtin_clzll(std::max((uint64_t)1, newSize)); + int popcount = __builtin_popcountll(std::max((uint64_t)1, newSize)); + if (popcount > 1) { + newSize = (uint64_t)1 << (sizeof(newSize) * CHAR_BIT - clz); + } + if (newSize > maxSize) { + newSize = std::max((uint64_t)1, size); + } assert(!objects.empty()); MemoryObject *mo = objects.begin()->second; newMO = memory->allocate(newSize, mo->isLocal, mo->isGlobal, diff --git a/lib/Core/AddressSpace.cpp b/lib/Core/AddressSpace.cpp index 1d33e574fc..2e1b9593bc 100644 --- a/lib/Core/AddressSpace.cpp +++ b/lib/Core/AddressSpace.cpp @@ -364,30 +364,37 @@ bool AddressSpace::resolve(ExecutionState &state, TimingSolver *solver, // transparently avoid screwing up symbolics (if the byte is symbolic // then its concrete cache byte isn't being used) but is just a hack. -void AddressSpace::copyOutConcretes() { +void AddressSpace::copyOutConcretes(const Assignment &assignment) { for (const auto &object : objects) { auto &mo = object.first; auto &os = object.second; - if (!mo->isUserSpecified && !os->readOnly && os->size != 0) { - copyOutConcrete(mo, os.get()); + if (!mo->isUserSpecified && !os->readOnly && mo->size != 0) { + copyOutConcrete(mo, os.get(), assignment); } } } void AddressSpace::copyOutConcrete(const MemoryObject *mo, - const ObjectState *os) const { + const ObjectState *os, + const Assignment &assignment) const { auto address = reinterpret_cast(mo->address); - std::memcpy(address, os->concreteStore, mo->size); + AssignmentEvaluator ae(assignment, false); + std::vector concreteStore(mo->size); + for (size_t i = 0; i < mo->size; i++) { + auto byte = ae.visit(os->read8(i)); + concreteStore[i] = cast(byte)->getZExtValue(8); + } + std::memcpy(address, concreteStore.data(), mo->size); } -bool AddressSpace::copyInConcretes() { +bool AddressSpace::copyInConcretes(const Assignment &assignment) { for (auto &obj : objects) { const MemoryObject *mo = obj.first; if (!mo->isUserSpecified) { const auto &os = obj.second; - if (!copyInConcrete(mo, os.get(), mo->address)) + if (!copyInConcrete(mo, os.get(), mo->address, assignment)) return false; } } @@ -396,14 +403,23 @@ bool AddressSpace::copyInConcretes() { } bool AddressSpace::copyInConcrete(const MemoryObject *mo, const ObjectState *os, - uint64_t src_address) { + uint64_t src_address, + const Assignment &assignment) { auto address = reinterpret_cast(src_address); - if (memcmp(address, os->concreteStore, mo->size) != 0) { + AssignmentEvaluator ae(assignment, false); + std::vector concreteStore(mo->size); + for (size_t i = 0; i < mo->size; i++) { + auto byte = ae.visit(os->read8(i)); + concreteStore[i] = cast(byte)->getZExtValue(8); + } + if (memcmp(address, concreteStore.data(), mo->size) != 0) { if (os->readOnly) { return false; } else { ObjectState *wos = getWriteable(mo, os); - memcpy(wos->concreteStore, address, mo->size); + for (size_t i = 0; i < mo->size; i++) { + wos->write(i, ConstantExpr::create(address[i], Expr::Int8)); + } } } return true; diff --git a/lib/Core/AddressSpace.h b/lib/Core/AddressSpace.h index 0acd1c1208..11d2de8130 100644 --- a/lib/Core/AddressSpace.h +++ b/lib/Core/AddressSpace.h @@ -13,6 +13,7 @@ #include "Memory.h" #include "klee/ADT/ImmutableMap.h" +#include "klee/Expr/Assignment.h" #include "klee/Expr/Expr.h" #include "klee/System/Time.h" @@ -137,9 +138,10 @@ class AddressSpace { /// actual system memory location they were allocated at. /// Returns the (hypothetical) number of pages needed provided each written /// object occupies (at least) a single page. - void copyOutConcretes(); + void copyOutConcretes(const Assignment &assignment); - void copyOutConcrete(const MemoryObject *mo, const ObjectState *os) const; + void copyOutConcrete(const MemoryObject *mo, const ObjectState *os, + const Assignment &assignment) const; /// \brief Obtain an ObjectState suitable for writing. /// @@ -161,7 +163,7 @@ class AddressSpace { /// /// \retval true The copy succeeded. /// \retval false The copy failed because a read-only object was modified. - bool copyInConcretes(); + bool copyInConcretes(const Assignment &assignment); /// Updates the memory object with the raw memory from the address /// @@ -170,7 +172,7 @@ class AddressSpace { /// @param src_address the address to copy from /// @return bool copyInConcrete(const MemoryObject *mo, const ObjectState *os, - uint64_t src_address); + uint64_t src_address, const Assignment &assignment); }; } // namespace klee diff --git a/lib/Core/CXXTypeSystem/CXXTypeManager.cpp b/lib/Core/CXXTypeSystem/CXXTypeManager.cpp index a171e65a9d..1df8091e9c 100644 --- a/lib/Core/CXXTypeSystem/CXXTypeManager.cpp +++ b/lib/Core/CXXTypeSystem/CXXTypeManager.cpp @@ -201,8 +201,10 @@ static ref getComplexPointerRestrictions( restrictions.addConstraint(innerAlignmentRequirement, {}); } - auto simplified = Simplificator::simplify(restrictions.cs()).simplified; - restrictions.changeCS(simplified); + auto simplified = Simplificator::simplify(restrictions.cs()); + if (simplified.wasSimplified) { + restrictions.changeCS(simplified.simplified); + } for (auto restriction : restrictions.cs()) { if (resultCondition.isNull()) { resultCondition = restriction; diff --git a/lib/Core/DistanceCalculator.cpp b/lib/Core/DistanceCalculator.cpp index 15cf13be42..26aa37350a 100644 --- a/lib/Core/DistanceCalculator.cpp +++ b/lib/Core/DistanceCalculator.cpp @@ -9,7 +9,7 @@ #include "DistanceCalculator.h" #include "ExecutionState.h" -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" #include "klee/Module/Target.h" @@ -56,18 +56,23 @@ DistanceResult DistanceCalculator::getDistance(const ExecutionState &state, DistanceResult DistanceCalculator::getDistance(KBlock *kb, TargetKind kind, KBlock *target) { SpeculativeState specState(kb, kind); - if (distanceResultCache.count(target) == 0 || - distanceResultCache.at(target).count(specState) == 0) { + auto it1 = distanceResultCache.find(target); + if (it1 == distanceResultCache.end()) { + SpeculativeStateToDistanceResultMap m; + it1 = distanceResultCache.emplace(target, std::move(m)).first; + } + auto &m = it1->second; + auto it2 = m.find(specState); + if (it2 == m.end()) { auto result = computeDistance(kb, kind, target); - distanceResultCache[target][specState] = result; + m.emplace(specState, result); + return result; } - return distanceResultCache.at(target).at(specState); + return it2->second; } DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, KBlock *target) const { - const auto &distanceToTargetFunction = - codeGraphDistance.getBackwardDistance(target->parent); weight_type weight = 0; WeightResult res = Miss; bool isInsideFunction = true; @@ -77,7 +82,7 @@ DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, break; case PreTarget: - res = tryGetPreTargetWeight(kb, weight, distanceToTargetFunction, target); + res = tryGetPreTargetWeight(kb, weight, target); isInsideFunction = false; break; @@ -95,35 +100,28 @@ DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, DistanceResult DistanceCalculator::getDistance( const KInstruction *prevPC, const KInstruction *pc, const ExecutionStack::call_stack_ty &frames, KBlock *target) { - weight_type weight = 0; - KBlock *kb = pc->parent; const auto &distanceToTargetFunction = - codeGraphDistance.getBackwardDistance(target->parent); + codeGraphInfo.getBackwardDistance(target->parent); unsigned int minCallWeight = UINT_MAX, minSfNum = UINT_MAX, sfNum = 0; auto sfi = frames.rbegin(), sfe = frames.rend(); bool strictlyAfterKB = sfi != sfe && sfi->kf->parent->inMainModule(*sfi->kf->function); - for (; sfi != sfe; sfi++) { + for (; sfi != sfe; sfi++, sfNum++) { unsigned callWeight; if (distanceInCallGraph(sfi->kf, kb, callWeight, distanceToTargetFunction, target, strictlyAfterKB && sfNum != 0)) { - callWeight *= 2; - callWeight += sfNum; + callWeight = 2 * callWeight + sfNum; if (callWeight < UINT_MAX) { minCallWeight = callWeight; minSfNum = sfNum; + break; } } - if (sfi->caller) { + if (sfi->caller) kb = sfi->caller->parent; - } - sfNum++; - - if (minCallWeight < UINT_MAX) - break; } TargetKind kind = NoneTarget; @@ -140,72 +138,38 @@ DistanceResult DistanceCalculator::getDistance( bool DistanceCalculator::distanceInCallGraph( KFunction *kf, KBlock *origKB, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target, bool strictlyAfterKB) const { - distance = UINT_MAX; - const std::unordered_map &dist = - codeGraphDistance.getDistance(origKB); - KBlock *targetBB = target; - KFunction *targetF = targetBB->parent; - - if (kf == targetF && dist.count(targetBB) != 0) { + const FunctionDistanceMap &distanceToTargetFunction, KBlock *targetKB, + bool strictlyAfterKB) const { + auto &dist = codeGraphInfo.getDistance(origKB->basicBlock); + if (kf == targetKB->parent && dist.count(targetKB->basicBlock)) { distance = 0; return true; } - if (!strictlyAfterKB) - return distanceInCallGraph(kf, origKB, distance, distanceToTargetFunction, - target); - auto min_distance = UINT_MAX; - distance = UINT_MAX; - for (auto bb : successors(origKB->basicBlock)) { - auto kb = kf->blockMap[bb]; - distanceInCallGraph(kf, kb, distance, distanceToTargetFunction, target); - if (distance < min_distance) - min_distance = distance; - } - distance = min_distance; - return distance != UINT_MAX; -} - -bool DistanceCalculator::distanceInCallGraph( - KFunction *kf, KBlock *kb, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const { distance = UINT_MAX; - const std::unordered_map &dist = - codeGraphDistance.getDistance(kb); - - for (auto &kCallBlock : kf->kCallBlocks) { - if (dist.count(kCallBlock) == 0) + bool cannotReachItself = strictlyAfterKB && !codeGraphInfo.hasCycle(origKB); + for (auto kCallBlock : kf->kCallBlocks) { + if (!dist.count(kCallBlock->basicBlock) || + (cannotReachItself && origKB == kCallBlock)) continue; - for (auto &calledFunction : kCallBlock->calledFunctions) { - KFunction *calledKFunction = kf->parent->functionMap[calledFunction]; - if (distanceToTargetFunction.count(calledKFunction) != 0 && - distance > distanceToTargetFunction.at(calledKFunction) + 1) { - distance = distanceToTargetFunction.at(calledKFunction) + 1; - } + for (auto calledFunction : kCallBlock->calledFunctions) { + auto it = distanceToTargetFunction.find(calledFunction); + if (it != distanceToTargetFunction.end() && distance > it->second + 1) + distance = it->second + 1; } } return distance != UINT_MAX; } -WeightResult -DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight, - const std::vector &localTargets, - KBlock *target) const { - KFunction *currentKF = kb->parent; - KBlock *currentKB = kb; - const std::unordered_map &dist = - codeGraphDistance.getDistance(currentKB); +WeightResult DistanceCalculator::tryGetLocalWeight( + KBlock *kb, weight_type &weight, + const std::vector &localTargets) const { + const auto &dist = codeGraphInfo.getDistance(kb); weight = UINT_MAX; - for (auto &end : localTargets) { - if (dist.count(end) > 0) { - unsigned int w = dist.at(end); - weight = std::min(w, weight); - } + for (auto end : localTargets) { + auto it = dist.find(end->basicBlock); + if (it != dist.end()) + weight = std::min(it->second, weight); } if (weight == UINT_MAX) @@ -217,19 +181,18 @@ DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight, return Continue; } -WeightResult DistanceCalculator::tryGetPreTargetWeight( - KBlock *kb, weight_type &weight, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const { +WeightResult DistanceCalculator::tryGetPreTargetWeight(KBlock *kb, + weight_type &weight, + KBlock *target) const { + auto &distanceToTargetFunction = + codeGraphInfo.getBackwardDistance(target->parent); KFunction *currentKF = kb->parent; std::vector localTargets; - for (auto &kCallBlock : currentKF->kCallBlocks) { - for (auto &calledFunction : kCallBlock->calledFunctions) { - KFunction *calledKFunction = - currentKF->parent->functionMap[calledFunction]; - if (distanceToTargetFunction.count(calledKFunction) > 0) { + for (auto kCallBlock : currentKF->kCallBlocks) { + for (auto calledFunction : kCallBlock->calledFunctions) { + if (distanceToTargetFunction.count(calledFunction)) { localTargets.push_back(kCallBlock); + break; } } } @@ -237,7 +200,7 @@ WeightResult DistanceCalculator::tryGetPreTargetWeight( if (localTargets.empty()) return Miss; - WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target); + WeightResult res = tryGetLocalWeight(kb, weight, localTargets); return res == Done ? Continue : res; } @@ -250,7 +213,7 @@ WeightResult DistanceCalculator::tryGetPostTargetWeight(KBlock *kb, if (localTargets.empty()) return Miss; - WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target); + WeightResult res = tryGetLocalWeight(kb, weight, localTargets); return res == Done ? Continue : res; } @@ -258,6 +221,6 @@ WeightResult DistanceCalculator::tryGetTargetWeight(KBlock *kb, weight_type &weight, KBlock *target) const { std::vector localTargets = {target}; - WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target); + WeightResult res = tryGetLocalWeight(kb, weight, localTargets); return res; } diff --git a/lib/Core/DistanceCalculator.h b/lib/Core/DistanceCalculator.h index f0fdd15655..ed6b5170f8 100644 --- a/lib/Core/DistanceCalculator.h +++ b/lib/Core/DistanceCalculator.h @@ -11,13 +11,14 @@ #define KLEE_DISTANCE_CALCULATOR_H #include "ExecutionState.h" +#include "klee/Module/CodeGraphInfo.h" namespace llvm { class BasicBlock; } // namespace llvm namespace klee { -class CodeGraphDistance; +class CodeGraphInfo; class Target; enum WeightResult : std::uint8_t { @@ -45,8 +46,8 @@ struct DistanceResult { class DistanceCalculator { public: - explicit DistanceCalculator(CodeGraphDistance &codeGraphDistance_) - : codeGraphDistance(codeGraphDistance_) {} + explicit DistanceCalculator(CodeGraphInfo &codeGraphInfo_) + : codeGraphInfo(codeGraphInfo_) {} DistanceResult getDistance(const ExecutionState &es, KBlock *target); @@ -97,7 +98,7 @@ class DistanceCalculator { using StatesSet = std::unordered_set; - CodeGraphDistance &codeGraphDistance; + CodeGraphInfo &codeGraphInfo; TargetToSpeculativeStateToDistanceResultMap distanceResultCache; StatesSet localStates; @@ -107,22 +108,14 @@ class DistanceCalculator { KBlock *target) const; bool distanceInCallGraph(KFunction *kf, KBlock *kb, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const; - bool distanceInCallGraph(KFunction *kf, KBlock *kb, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, + const FunctionDistanceMap &distanceToTargetFunction, KBlock *target, bool strictlyAfterKB) const; - WeightResult tryGetLocalWeight(KBlock *kb, weight_type &weight, - const std::vector &localTargets, - KBlock *target) const; WeightResult - tryGetPreTargetWeight(KBlock *kb, weight_type &weight, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const; + tryGetLocalWeight(KBlock *kb, weight_type &weight, + const std::vector &localTargets) const; + WeightResult tryGetPreTargetWeight(KBlock *kb, weight_type &weight, + KBlock *target) const; WeightResult tryGetTargetWeight(KBlock *kb, weight_type &weight, KBlock *target) const; WeightResult tryGetPostTargetWeight(KBlock *kb, weight_type &weight, diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index ddec6ec63b..6c5d4f9128 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -14,7 +14,6 @@ #include "klee/Expr/ArrayExprVisitor.h" #include "klee/Expr/Expr.h" #include "klee/Module/Cell.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" #include "klee/Support/Casting.h" @@ -76,6 +75,7 @@ void ExecutionStack::pushFrame(KInstIterator caller, KFunction *kf) { ++stackBalance; assert(valueStack_.size() == callStack_.size()); assert(valueStack_.size() == infoStack_.size()); + stackSize += kf->getNumRegisters(); } void ExecutionStack::popFrame() { @@ -95,51 +95,47 @@ void ExecutionStack::popFrame() { --stackBalance; assert(valueStack_.size() == callStack_.size()); assert(valueStack_.size() == infoStack_.size()); + stackSize -= kf->getNumRegisters(); } bool CallStackFrame::equals(const CallStackFrame &other) const { return kf == other.kf && caller == other.caller; } -StackFrame::StackFrame(KFunction *kf) : kf(kf), varargs(0) { - locals = new Cell[kf->numRegisters]; +StackFrame::StackFrame(KFunction *kf) : kf(kf), varargs(nullptr) { + locals = new Cell[kf->getNumRegisters()]; } StackFrame::StackFrame(const StackFrame &s) : kf(s.kf), allocas(s.allocas), varargs(s.varargs) { - locals = new Cell[kf->numRegisters]; - for (unsigned i = 0; i < kf->numRegisters; i++) + locals = new Cell[kf->getNumRegisters()]; + for (unsigned i = 0; i < kf->getNumRegisters(); i++) locals[i] = s.locals[i]; } StackFrame::~StackFrame() { delete[] locals; } -CallStackFrame::CallStackFrame(const CallStackFrame &s) - : caller(s.caller), kf(s.kf) {} - InfoStackFrame::InfoStackFrame(KFunction *kf) : kf(kf) {} -InfoStackFrame::InfoStackFrame(const InfoStackFrame &s) - : kf(s.kf), callPathNode(s.callPathNode), - minDistToUncoveredOnReturn(s.minDistToUncoveredOnReturn) {} - /***/ ExecutionState::ExecutionState() : initPC(nullptr), pc(nullptr), prevPC(nullptr), incomingBBIndex(-1), - depth(0), ptreeNode(nullptr), steppedInstructions(0), + depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew(false), - forkDisabled(false), prevHistory_(TargetsHistory::create()), + roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), + coveredNewError(new box(false)), forkDisabled(false), + prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { setID(); } ExecutionState::ExecutionState(KFunction *kf) : initPC(kf->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), - depth(0), ptreeNode(nullptr), steppedInstructions(0), + depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew(false), - forkDisabled(false), prevHistory_(TargetsHistory::create()), + roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), + coveredNewError(new box(false)), forkDisabled(false), + prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); setID(); @@ -147,10 +143,11 @@ ExecutionState::ExecutionState(KFunction *kf) ExecutionState::ExecutionState(KFunction *kf, KBlock *kb) : initPC(kb->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), - depth(0), ptreeNode(nullptr), steppedInstructions(0), + depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew(false), - forkDisabled(false), prevHistory_(TargetsHistory::create()), + roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), + coveredNewError(new box(false)), forkDisabled(false), + prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); setID(); @@ -165,11 +162,11 @@ ExecutionState::ExecutionState(const ExecutionState &state) : initPC(state.initPC), pc(state.pc), prevPC(state.prevPC), stack(state.stack), stackBalance(state.stackBalance), incomingBBIndex(state.incomingBBIndex), depth(state.depth), - level(state.level), transitionLevel(state.transitionLevel), - addressSpace(state.addressSpace), constraints(state.constraints), - targetForest(state.targetForest), pathOS(state.pathOS), - symPathOS(state.symPathOS), coveredLines(state.coveredLines), - symbolics(state.symbolics), resolvedPointers(state.resolvedPointers), + level(state.level), addressSpace(state.addressSpace), + constraints(state.constraints), targetForest(state.targetForest), + pathOS(state.pathOS), symPathOS(state.symPathOS), + coveredLines(state.coveredLines), symbolics(state.symbolics), + resolvedPointers(state.resolvedPointers), cexPreferences(state.cexPreferences), arrayNames(state.arrayNames), steppedInstructions(state.steppedInstructions), steppedMemoryInstructions(state.steppedMemoryInstructions), @@ -178,26 +175,28 @@ ExecutionState::ExecutionState(const ExecutionState &state) unwindingInformation(state.unwindingInformation ? state.unwindingInformation->clone() : nullptr), - coveredNew(state.coveredNew), forkDisabled(state.forkDisabled), - returnValue(state.returnValue), gepExprBases(state.gepExprBases), - prevTargets_(state.prevTargets_), targets_(state.targets_), - prevHistory_(state.prevHistory_), history_(state.history_), - isTargeted_(state.isTargeted_) {} + coveredNew(state.coveredNew), coveredNewError(state.coveredNewError), + forkDisabled(state.forkDisabled), returnValue(state.returnValue), + gepExprBases(state.gepExprBases), prevTargets_(state.prevTargets_), + targets_(state.targets_), prevHistory_(state.prevHistory_), + history_(state.history_), isTargeted_(state.isTargeted_) { + constraints.fork(); + queryMetaData.id = state.id; +} ExecutionState *ExecutionState::branch() { depth++; auto *falseState = new ExecutionState(*this); falseState->setID(); - falseState->coveredNew = false; falseState->coveredLines.clear(); return falseState; } bool ExecutionState::inSymbolics(const MemoryObject *mo) const { - for (auto i : symbolics) { - if (mo->id == i.memoryObject->id) { + for (const auto &symbolic : symbolics) { + if (mo->id == symbolic.memoryObject->id) { return true; } } @@ -257,13 +256,12 @@ void ExecutionState::popFrame() { void ExecutionState::addSymbolic(const MemoryObject *mo, const Array *array, KType *type) { - symbolics.emplace_back(ref(mo), array, type); + symbolics.push_back({mo, array, type}); } ref ExecutionState::findMemoryObject(const Array *array) const { - for (unsigned i = 0; i != symbolics.size(); ++i) { - const auto &symbolic = symbolics[i]; + for (const auto &symbolic : symbolics) { if (array == symbolic.array) { return symbolic.memoryObject; } @@ -366,26 +364,6 @@ void ExecutionState::addUniquePointerResolution(ref address, } } -bool ExecutionState::resolveOnSymbolics(const ref &addr, - IDType &result) const { - uint64_t address = addr->getZExtValue(); - - for (const auto &res : symbolics) { - const auto &mo = res.memoryObject; - // Check if the provided address is between start and end of the object - // [mo->address, mo->address + mo->size) or the object is a 0-sized object. - ref size = cast( - constraints.cs().concretization().evaluate(mo->getSizeExpr())); - if ((size->getZExtValue() == 0 && address == mo->address) || - (address - mo->address < size->getZExtValue())) { - result = mo->id; - return true; - } - } - - return false; -} - /**/ llvm::raw_ostream &klee::operator<<(llvm::raw_ostream &os, @@ -410,13 +388,12 @@ void ExecutionState::dumpStack(llvm::raw_ostream &out) const { const StackFrame &sf = stack.valueStack().at(ri); Function *f = csf.kf->function; - const InstructionInfo &ii = *target->info; out << "\t#" << i; - if (ii.assemblyLine.hasValue()) { - std::stringstream AssStream; - AssStream << std::setw(8) << std::setfill('0') - << ii.assemblyLine.getValue(); - out << AssStream.str(); + auto assemblyLine = target->getKModule()->getAsmLine(target->inst); + if (assemblyLine.has_value()) { + std::stringstream AsmStream; + AsmStream << std::setw(8) << std::setfill('0') << assemblyLine.value(); + out << AsmStream.str(); } out << " in " << f->getName().str() << "("; // Yawn, we could go up and print varargs if we wanted to. @@ -437,8 +414,9 @@ void ExecutionState::dumpStack(llvm::raw_ostream &out) const { } } out << ")"; - if (ii.file != "") - out << " at " << ii.file << ":" << ii.line; + std::string filepath = target->getSourceFilepath(); + if (!filepath.empty()) + out << " at " << filepath << ":" << target->getLine(); out << "\n"; target = csf.caller; } @@ -471,10 +449,7 @@ void ExecutionState::increaseLevel() { if (prevPC->inst->isTerminator() && kmodule->inMainModule(*kf->function)) { auto srcLevel = stack.infoStack().back().multilevel[srcbb].second; stack.infoStack().back().multilevel.replace({srcbb, srcLevel + 1}); - level.insert(srcbb); - } - if (srcbb != dstbb) { - transitionLevel.insert(std::make_pair(srcbb, dstbb)); + level.insert(prevPC->parent); } } @@ -483,7 +458,7 @@ bool ExecutionState::isGEPExpr(ref expr) const { } bool ExecutionState::visited(KBlock *block) const { - return level.count(block->basicBlock) != 0; + return level.count(block) != 0; } bool ExecutionState::reachedTarget(ref target) const { @@ -496,3 +471,9 @@ bool ExecutionState::reachedTarget(ref target) const { return pc == target->getBlock()->getFirstInstruction(); } } + +Query ExecutionState::toQuery(ref head) const { + return Query(constraints.cs(), head, id); +} + +Query ExecutionState::toQuery() const { return toQuery(Expr::createFalse()); } diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index c0bfeb7301..74ba2c67d4 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -12,6 +12,7 @@ #include "AddressSpace.h" +#include "klee/ADT/ImmutableList.h" #include "klee/ADT/ImmutableSet.h" #include "klee/ADT/PersistentMap.h" #include "klee/ADT/PersistentSet.h" @@ -28,6 +29,7 @@ #include "klee/Module/TargetHash.h" #include "klee/Solver/Solver.h" #include "klee/System/Time.h" +#include "klee/Utilities/Math.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -35,6 +37,8 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Function.h" DISABLE_WARNING_POP +#include +#include #include #include #include @@ -53,9 +57,7 @@ struct KBlock; struct KInstruction; class MemoryObject; class PTreeNode; -struct InstructionInfo; class Target; -struct TranstionHash; llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const MemoryMap &mm); @@ -68,7 +70,6 @@ struct CallStackFrame { CallStackFrame(KInstIterator caller_, KFunction *kf_) : caller(caller_), kf(kf_) {} ~CallStackFrame() = default; - CallStackFrame(const CallStackFrame &s); bool equals(const CallStackFrame &other) const; @@ -105,7 +106,6 @@ struct InfoStackFrame { unsigned minDistToUncoveredOnReturn = 0; InfoStackFrame(KFunction *kf); - InfoStackFrame(const InfoStackFrame &s); ~InfoStackFrame() = default; }; @@ -120,6 +120,7 @@ struct ExecutionStack { call_stack_ty callStack_; info_stack_ty infoStack_; call_stack_ty uniqueFrames_; + size_t stackSize = 0; unsigned stackBalance = 0; public: @@ -129,10 +130,12 @@ struct ExecutionStack { inline value_stack_ty &valueStack() { return valueStack_; } inline const value_stack_ty &valueStack() const { return valueStack_; } inline const call_stack_ty &callStack() const { return callStack_; } + inline const info_stack_ty &infoStack() const { return infoStack_; } inline info_stack_ty &infoStack() { return infoStack_; } inline const call_stack_ty &uniqueFrames() const { return uniqueFrames_; } inline unsigned size() const { return callStack_.size(); } + inline size_t stackRegisterSize() const { return stackSize; } inline bool empty() const { return callStack_.empty(); } }; @@ -218,7 +221,8 @@ struct Symbolic { const Array *array; KType *type; Symbolic(ref mo, const Array *a, KType *t) - : memoryObject(mo), array(a), type(t) {} + : memoryObject(std::move(mo)), array(a), type(t) {} + Symbolic(const Symbolic &other) = default; Symbolic &operator=(const Symbolic &other) = default; friend bool operator==(const Symbolic &lhs, const Symbolic &rhs) { @@ -230,9 +234,8 @@ struct Symbolic { struct MemorySubobject { ref address; unsigned size; - MemorySubobject(ref address, unsigned size) + explicit MemorySubobject(ref address, unsigned size) : address(address), size(size) {} - MemorySubobject &operator=(const MemorySubobject &other) = default; }; struct MemorySubobjectHash { @@ -290,8 +293,7 @@ class ExecutionState { std::uint32_t depth = 0; /// @brief Exploration level, i.e., number of times KLEE cycled for this state - std::unordered_set level; - std::unordered_set transitionLevel; + PersistentSet level; /// @brief Address space used by this state (e.g. Global and Heap) AddressSpace addressSpace; @@ -320,16 +322,14 @@ class ExecutionState { TreeOStream symPathOS; /// @brief Set containing which lines in which files are covered by this state - std::map> coveredLines; + std::map> coveredLines; /// @brief Pointer to the process tree of the current state /// Copies of ExecutionState should not copy ptreeNode PTreeNode *ptreeNode = nullptr; /// @brief Ordered list of symbolics: used to generate test cases. - // - // FIXME: Move to a shared list structure (not critical). - std::vector symbolics; + ImmutableList symbolics; /// @brief map from memory accesses to accessed objects and access offsets. ExprHashMap> resolvedPointers; @@ -369,7 +369,8 @@ class ExecutionState { std::uint32_t id = 0; /// @brief Whether a new instruction was covered in this state - bool coveredNew = false; + mutable std::deque>> coveredNew; + mutable ref> coveredNewError; /// @brief Disables forking for this state. Set by user code bool forkDisabled = false; @@ -379,7 +380,7 @@ class ExecutionState { ExprHashMap, llvm::Type *>> gepExprBases; - ReachWithError error = ReachWithError::None; + mutable ReachWithError error = ReachWithError::None; std::atomic terminationReasonType{ HaltExecution::NotHalt}; @@ -431,17 +432,22 @@ class ExecutionState { unsigned size = 0); void addUniquePointerResolution(ref address, const MemoryObject *mo, unsigned size = 0); - bool resolveOnSymbolics(const ref &addr, IDType &result) const; void addConstraint(ref e, const Assignment &c); void addCexPreference(const ref &cond); + Query toQuery(ref head) const; + Query toQuery() const; + void dumpStack(llvm::raw_ostream &out) const; bool visited(KBlock *block) const; std::uint32_t getID() const { return id; }; - void setID() { id = nextID++; }; + void setID() { + id = nextID++; + queryMetaData.id = id; + }; llvm::BasicBlock *getInitPCBlock() const; llvm::BasicBlock *getPrevPCBlock() const; llvm::BasicBlock *getPCBlock() const; @@ -489,19 +495,49 @@ class ExecutionState { bool reachedTarget(ref target) const; static std::uint32_t getLastID() { return nextID - 1; }; - inline bool isStuck(unsigned long long bound) { - KInstruction *prevKI = prevPC; - if (prevKI->inst->isTerminator() && stack.size() > 0) { - auto level = stack.infoStack().back().multilevel[getPCBlock()].second; - return bound && level > bound; + inline bool isCycled(unsigned long long bound) const { + if (bound == 0) + return false; + if (prevPC->inst->isTerminator() && stack.size() > 0) { + auto &ml = stack.infoStack().back().multilevel; + auto level = ml.find(getPCBlock()); + return level != ml.end() && level->second > bound; } if (pc == pc->parent->getFirstInstruction() && pc->parent == pc->parent->parent->entryKBlock) { - auto level = stack.multilevel[stack.callStack().back().kf].second; - return bound && level > bound; + auto level = stack.multilevel.at(stack.callStack().back().kf); + return level > bound; } return false; } + + inline bool isStuck(unsigned long long bound) const { + if (depth == 0) + return false; + return isCycled(bound) && klee::util::ulog2(depth) > bound; + } + + bool isCoveredNew() const { + return !coveredNew.empty() && coveredNew.back()->value; + } + bool isCoveredNewError() const { return coveredNewError->value; } + void coverNew() const { + coveredNew.push_back(new box(true)); + coveredNewError->value = false; + coveredNewError = new box(true); + } + void updateCoveredNew() const { + while (!coveredNew.empty() && !coveredNew.front()->value) { + coveredNew.pop_front(); + } + } + void clearCoveredNew() const { + for (auto signal : coveredNew) { + signal->value = false; + } + coveredNew.clear(); + } + void clearCoveredNewError() const { coveredNewError->value = false; } }; struct ExecutionStateIDCompare { diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 064935305d..8fab82715d 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -32,6 +32,7 @@ #include "TimingSolver.h" #include "TypeManager.h" #include "UserSearcher.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Core/Context.h" #include "klee/ADT/KTest.h" @@ -50,8 +51,7 @@ #include "klee/Expr/IndependentSet.h" #include "klee/Expr/Symcrete.h" #include "klee/Module/Cell.h" -#include "klee/Module/CodeGraphDistance.h" -#include "klee/Module/InstructionInfoTable.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KCallable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" @@ -162,7 +162,7 @@ cl::opt AlignSymbolicPointers("align-symbolic-pointers", cl::desc("Makes symbolic pointers aligned according" "to the used type system (default=true)"), - cl::init(true), cl::cat(ExecCat)); + cl::init(false), cl::cat(ExecCat)); cl::opt ExternCallsCanReturnNull("extern-calls-can-return-null", cl::init(false), @@ -170,6 +170,17 @@ cl::opt "and return null (default=false)"), cl::cat(ExecCat)); +cl::opt OSCopySizeMemoryCheckThreshold( + "os-copy-size-mem-check-threshold", cl::init(10000), + cl::desc("Check memory usage when this amount of bytes dense OS is copied"), + cl::cat(ExecCat)); + +cl::opt StackCopySizeMemoryCheckThreshold( + "stack-copy-size-mem-check-threshold", cl::init(10000), + cl::desc("Check memory usage when state with stack this big (in bytes) is " + "copied"), + cl::cat(ExecCat)); + enum class MockMutableGlobalsPolicy { None, PrimitiveFields, @@ -217,17 +228,34 @@ llvm::cl::opt MinNumberElementsLazyInit( "initialization (default 4)"), llvm::cl::init(4), llvm::cl::cat(LazyInitCat)); +cl::opt FunctionCallReproduce( + "function-call-reproduce", cl::init(""), + cl::desc("Marks mentioned function as target for error-guided mode."), + cl::cat(ExecCat)); + +llvm::cl::opt X86FPAsX87FP80( + "x86FP-as-x87FP80", cl::init(false), + cl::desc("Convert X86 fp values to X87FP80 during computation according to " + "GCC behavior (default=false)"), + cl::cat(ExecCat)); + +cl::opt DumpStatesOnHalt( + "dump-states-on-halt", cl::init(HaltExecution::Reason::Unspecified), + cl::values( + clEnumValN(HaltExecution::Reason::NotHalt, "none", + "Do not dump test cases for all active states on exit."), + clEnumValN(HaltExecution::Reason::UnreachedTarget, "unreached", + "Dump test cases for all active states on exit if error not " + "reached."), + clEnumValN(HaltExecution::Reason::Unspecified, "all", + "Dump test cases for all active states on exit (default)")), + cl::cat(TestGenCat)); } // namespace klee namespace { /*** Test generation options ***/ -cl::opt DumpStatesOnHalt( - "dump-states-on-halt", cl::init(true), - cl::desc("Dump test cases for all active states on exit (default=true)"), - cl::cat(TestGenCat)); - cl::opt OnlyOutputStatesCoveringNew( "only-output-states-covering-new", cl::init(false), cl::desc("Only output test cases covering new code (default=false)"), @@ -239,6 +267,31 @@ cl::opt EmitAllErrors( "(default=false, i.e. one per (error,instruction) pair)"), cl::cat(TestGenCat)); +cl::opt CoverOnTheFly( + "cover-on-the-fly", cl::init(false), + cl::desc("Generate tests cases for each new covered block or branch " + "(default=false)"), + cl::cat(TestGenCat)); + +cl::opt MemoryTriggerCoverOnTheFly( + "mem-trigger-cof", cl::init(false), + cl::desc("Start on the fly tests generation after approaching memory cup" + "(default=false)"), + cl::cat(TestGenCat)); + +cl::opt DelayCoverOnTheFly( + "delay-cover-on-the-fly", cl::init("0s"), + cl::desc("Start on the fly tests generation after the specified duration. " + "Set to 0s to disable (default=0s)"), + cl::cat(TestGenCat)); + +cl::opt UninitMemoryTestMultiplier( + "uninit-memory-test-multiplier", cl::init(6), + cl::desc("Generate additional number of duplicate tests due to " + "irreproducibility of uninitialized memory " + "(default=6)"), + cl::cat(TestGenCat)); + /* Constraint solving options */ cl::opt MaxSymArraySize( @@ -430,6 +483,7 @@ bool allLeafsAreConstant(const ref &expr) { extern llvm::cl::opt MaxConstantAllocationSize; extern llvm::cl::opt MaxSymbolicAllocationSize; extern llvm::cl::opt UseSymbolicSizeAllocation; +extern llvm::cl::opt TrackCoverage; // XXX hack extern "C" unsigned dumpStates, dumpPForest; @@ -455,16 +509,17 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, externalDispatcher(new ExternalDispatcher(ctx)), statsTracker(0), pathWriter(0), symPathWriter(0), specialFunctionHandler(0), timers{time::Span(TimerInterval)}, - guidanceKind(opts.Guidance), codeGraphDistance(new CodeGraphDistance()), - distanceCalculator(new DistanceCalculator(*codeGraphDistance)), - targetCalculator(new TargetCalculator(*codeGraphDistance)), + guidanceKind(opts.Guidance), codeGraphInfo(new CodeGraphInfo()), + distanceCalculator(new DistanceCalculator(*codeGraphInfo)), + targetCalculator(new TargetCalculator(*codeGraphInfo)), targetManager(new TargetManager(guidanceKind, *distanceCalculator, *targetCalculator)), targetedExecutionManager( - new TargetedExecutionManager(*codeGraphDistance, *targetManager)), + new TargetedExecutionManager(*codeGraphInfo, *targetManager)), replayKTest(0), replayPath(0), usingSeeds(0), atMemoryLimit(false), - inhibitForking(false), haltExecution(HaltExecution::NotHalt), - ivcEnabled(false), debugLogBuffer(debugBufferString) { + inhibitForking(false), coverOnTheFly(false), + haltExecution(HaltExecution::NotHalt), ivcEnabled(false), + debugLogBuffer(debugBufferString) { const time::Span maxTime{MaxTime}; if (maxTime) timers.add(std::make_unique(maxTime, [&] { @@ -472,6 +527,13 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, setHaltExecution(HaltExecution::MaxTime); })); + if (CoverOnTheFly && guidanceKind != GuidanceKind::ErrorGuidance) { + const time::Span delayTime{DelayCoverOnTheFly}; + if (delayTime) + timers.add( + std::make_unique(delayTime, [&] { coverOnTheFly = true; })); + } + coreSolverTimeout = time::Span{MaxCoreSolverTime}; if (coreSolverTimeout) UseForkedCoreSolver = true; @@ -491,16 +553,12 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, interpreterHandler->getOutputFilename(SOLVER_QUERIES_SMT2_FILE_NAME), interpreterHandler->getOutputFilename(ALL_QUERIES_KQUERY_FILE_NAME), interpreterHandler->getOutputFilename(SOLVER_QUERIES_KQUERY_FILE_NAME), - addressManager.get()); + addressManager.get(), arrayCache); this->solver = std::make_unique(std::move(solver), optimizer, EqualitySubstitution); initializeSearchOptions(); - if (OnlyOutputStatesCoveringNew && !StatsTracker::useIStats()) - klee_error("To use --only-output-states-covering-new, you need to enable " - "--output-istats."); - if (DebugPrintInstructions.isSet(FILE_ALL) || DebugPrintInstructions.isSet(FILE_COMPACT) || DebugPrintInstructions.isSet(FILE_SRC)) { @@ -524,20 +582,18 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, } } -llvm::Module * -Executor::setModule(std::vector> &userModules, - std::vector> &libsModules, - const ModuleOptions &opts, - const std::unordered_set &mainModuleFunctions, - const std::unordered_set &mainModuleGlobals, - std::unique_ptr origInfos) { +llvm::Module *Executor::setModule( + std::vector> &userModules, + std::vector> &libsModules, + const ModuleOptions &opts, std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions) { assert(!kmodule && !userModules.empty() && "can only register one module"); // XXX gross kmodule = std::make_unique(); // 1.) Link the modules together && 2.) Apply different instrumentation - kmodule->link(userModules, 0); + kmodule->link(userModules, 1); kmodule->instrument(opts); kmodule->link(libsModules, 2); @@ -565,28 +621,42 @@ Executor::setModule(std::vector> &userModules, specialFunctionHandler = new SpecialFunctionHandler(*this); specialFunctionHandler->prepare(preservedFunctions); - preservedFunctions.push_back(opts.EntryPoint.c_str()); - // Preserve the free-standing library calls preservedFunctions.push_back("memset"); preservedFunctions.push_back("memcpy"); preservedFunctions.push_back("memcmp"); preservedFunctions.push_back("memmove"); + for (const auto &p : klee::floatReplacements) { + preservedFunctions.push_back(p.second.c_str()); + } + + if (FunctionCallReproduce != "") { + preservedFunctions.push_back(FunctionCallReproduce.c_str()); + } + + // prevent elimination of the preservedFunctions functions + for (auto pf : preservedFunctions) { + auto f = kmodule->module->getFunction(pf); + if (f) { + f->addFnAttr(Attribute::OptimizeNone); + f->addFnAttr(Attribute::NoInline); + } + } + + // except the entry point + preservedFunctions.push_back(opts.EntryPoint.c_str()); + kmodule->optimiseAndPrepare(opts, preservedFunctions); kmodule->checkModule(); // 4.) Manifest the module - kmodule->mainModuleFunctions.insert(mainModuleFunctions.begin(), - mainModuleFunctions.end()); - kmodule->mainModuleGlobals.insert(mainModuleGlobals.begin(), - mainModuleGlobals.end()); + std::swap(kmodule->mainModuleFunctions, mainModuleFunctions); + std::swap(kmodule->mainModuleGlobals, mainModuleGlobals); kmodule->manifest(interpreterHandler, interpreterOpts.Guidance, StatsTracker::useStatistics()); - if (origInfos) { - kmodule->origInfos = origInfos->getInstructions(); - } + kmodule->origInstructions = origInstructions; specialFunctionHandler->bind(); @@ -615,6 +685,39 @@ Executor::~Executor() { /***/ +ref X87FP80ToFPTrunc(ref arg, Expr::Width type, + llvm::APFloat::roundingMode rm) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = type; + if (Context::get().getPointerWidth() == 32 && arg->getWidth() == Expr::Fl80) { + result = FPTruncExpr::create(arg, resultType, rm); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif + return result; +} + +ref FPToX87FP80Ext(ref arg) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = Expr::Fl80; + if (Context::get().getPointerWidth() == 32) { + result = FPExtExpr::create(arg, resultType); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif + return result; +} + void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os, const Constant *c, unsigned offset) { const auto targetData = kmodule->targetData.get(); @@ -650,6 +753,12 @@ void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os, unsigned StoreBits = targetData->getTypeStoreSizeInBits(c->getType()); ref C = evalConstant(c, state.roundingMode); + if (c->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + C = X87FP80ToFPTrunc(C, getWidthForLLVMType(c->getType()), + state.roundingMode); + } + // Extend the constant if necessary; assert(StoreBits >= C->getWidth() && "Invalid store size!"); if (StoreBits > C->getWidth()) @@ -720,14 +829,29 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { } #ifndef WINDOWS - int *errno_addr = getErrnoLocation(state); + llvm::Type *pointerErrnoAddr = llvm::PointerType::get( llvm::IntegerType::get(m->getContext(), sizeof(*errno_addr) * CHAR_BIT), adressSpaceNum); - MemoryObject *errnoObj = - addExternalObject(state, (void *)errno_addr, - typeSystemManager->getWrappedType(pointerErrnoAddr), - sizeof *errno_addr, false); + MemoryObject *errnoObj = nullptr; + + if (Context::get().getPointerWidth() == 32) { + errnoObj = allocate(state, Expr::createPointer(sizeof(*errno_addr)), false, + true, nullptr, 8); + errnoObj->isFixed = true; + + bindObjectInState(state, errnoObj, + typeSystemManager->getWrappedType(pointerErrnoAddr), + false); + errno_addr = reinterpret_cast(errnoObj->address); + } else { + errno_addr = getErrnoLocation(state); + errnoObj = + addExternalObject(state, (void *)errno_addr, + typeSystemManager->getWrappedType(pointerErrnoAddr), + sizeof *errno_addr, false); + } + // Copy values from and to program space explicitly errnoObj->isUserSpecified = true; #endif @@ -871,7 +995,8 @@ void Executor::initializeGlobalObjects(ExecutionState &state) { for (const GlobalVariable &v : m->globals()) { MemoryObject *mo = globalObjects.find(&v)->second; ObjectState *os = bindObjectInState( - state, mo, typeSystemManager->getWrappedType(v.getType()), false); + state, mo, typeSystemManager->getWrappedType(v.getType()), false, + nullptr); if (v.isDeclaration() && mo->size) { // Program already running -> object already initialized. @@ -905,11 +1030,9 @@ void Executor::initializeGlobalObjects(ExecutionState &state) { if (v.isConstant()) { os->setReadOnly(true); // initialise constant memory that may be used with external calls - state.addressSpace.copyOutConcrete(mo, os); + state.addressSpace.copyOutConcrete(mo, os, {}); } } - } else { - os->initializeToRandom(); } } } @@ -1074,7 +1197,7 @@ ref Executor::maxStaticPctChecks(ExecutionState ¤t, std::string msg("skipping fork and concretizing condition (MaxStatic*Pct " "limit reached) at "); llvm::raw_string_ostream os(msg); - os << current.prevPC->getSourceLocation(); + os << current.prevPC->getSourceLocationString(); klee_warning_once(0, "%s", os.str().c_str()); addConstraint(current, EqExpr::create(value, condition)); @@ -1145,7 +1268,7 @@ Executor::StatePair Executor::fork(ExecutionState ¤t, ref condition, success = solver->mayBeFalse(current.constraints.cs(), condition, mayBeFalse, current.queryMetaData); } - if (success && !mayBeFalse) + if (!success || !mayBeFalse) terminateEverything = true; else res = PartialValidity::MayBeFalse; @@ -1154,7 +1277,7 @@ Executor::StatePair Executor::fork(ExecutionState ¤t, ref condition, bool mayBeTrue; success = solver->mayBeTrue(current.constraints.cs(), condition, mayBeTrue, current.queryMetaData); - if (success && !mayBeTrue) + if (!success || !mayBeTrue) terminateEverything = true; else res = PartialValidity::MayBeTrue; @@ -1405,9 +1528,9 @@ void Executor::addConstraint(ExecutionState &state, ref condition) { if (!concretization.isEmpty()) { // Update memory objects if arrays have affected them. + updateStateWithSymcretes(state, concretization); Assignment delta = state.constraints.cs().concretization().diffWith(concretization); - updateStateWithSymcretes(state, delta); state.addConstraint(condition, delta); } else { state.addConstraint(condition, {}); @@ -1492,8 +1615,8 @@ ref Executor::toConstant(ExecutionState &state, ref e, std::string str; llvm::raw_string_ostream os(str); os << "silently concretizing (reason: " << reason << ") expression " << e - << " to value " << value << " (" << (*(state.pc)).info->file << ":" - << (*(state.pc)).info->line << ")"; + << " to value " << value << " (" << state.pc->getSourceFilepath() << ":" + << state.pc->getLine() << ")"; if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); @@ -1572,10 +1695,13 @@ void Executor::printDebugInstructions(ExecutionState &state) { // [src] src location:asm line:state ID if (!DebugPrintInstructions.isSet(STDERR_COMPACT) && !DebugPrintInstructions.isSet(FILE_COMPACT)) { - (*stream) << " " << state.pc->getSourceLocation() << ':'; + (*stream) << " " << state.pc->getSourceLocationString() << ':'; } - if (state.pc->info->assemblyLine.hasValue()) { - (*stream) << state.pc->info->assemblyLine.getValue() << ':'; + { + auto asmLine = state.pc->getKModule()->getAsmLine(state.pc->inst); + if (asmLine.has_value()) { + (*stream) << asmLine.value() << ':'; + } } (*stream) << state.getID() << ":"; (*stream) << "["; @@ -1920,6 +2046,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, #endif break; } +#ifdef ENABLE_FP case Intrinsic::sqrt: { ref op = eval(ki, 1, state).value; ref result = FSqrtExpr::create(op, state.roundingMode); @@ -1962,6 +2089,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, bindLocal(ki, state, result); break; } +#endif case Intrinsic::fma: case Intrinsic::fmuladd: { @@ -2307,7 +2435,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, const ObjectState *osarg = state.addressSpace.findObject(idObject).second; assert(osarg); - for (unsigned i = 0; i < osarg->size; i++) + for (unsigned i = 0; i < osarg->getObject()->size; i++) os->write(offsets[k] + i, osarg->read8(i)); } if (ati != f->arg_end()) { @@ -2488,6 +2616,11 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { Expr::Width from = result->getWidth(); Expr::Width to = getWidthForLLVMType(t); + if (X86FPAsX87FP80 && t->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + to = Expr::Fl80; + } + if (from != to) { const CallBase &cb = cast(*caller); @@ -2536,11 +2669,17 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { Executor::StatePair branches = fork(state, cond, ifTrueBlock, ifFalseBlock, BranchType::Conditional); + if (branches.first && branches.second) { + maxNewStateStackSize = + std::max(maxNewStateStackSize, + branches.first->stack.stackRegisterSize() * 8); + } + // NOTE: There is a hidden dependency here, markBranchVisited // requires that we still be in the context of the branch // instruction (it reuses its statistic id). Should be cleaned // up with convenient instruction specific data. - if (statsTracker && state.stack.callStack().back().kf->trackCoverage) + if (statsTracker) statsTracker->markBranchVisited(branches.first, branches.second); if (branches.first) @@ -2843,18 +2982,19 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { } else { ref v = eval(ki, 0, state).value; - if (!isa(v) && MockExternalCalls) { - if (ki->inst->getType()->isSized()) { - prepareMockValue(state, "mockExternResult", ki); - } - } else { - ExecutionState *free = &state; - bool hasInvalid = false, first = true; - - /* XXX This is wasteful, no need to do a full evaluate since we - have already got a value. But in the end the caches should - handle it for us, albeit with some overhead. */ - do { + ExecutionState *free = &state; + bool hasInvalid = false, first = true; + + /* XXX This is wasteful, no need to do a full evaluate since we + have already got a value. But in the end the caches should + handle it for us, albeit with some overhead. */ + do { + if (!first && MockExternalCalls) { + free = nullptr; + if (ki->inst->getType()->isSized()) { + prepareMockValue(state, "mockExternResult", ki); + } + } else { v = optimizer.optimizeExpr(v, true); ref value; bool success = solver->getValue(free->constraints.cs(), v, value, @@ -2887,8 +3027,8 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { first = false; free = res.second; timers.invoke(); - } while (free && !haltExecution); - } + } + } while (free && !haltExecution); } break; } @@ -3231,6 +3371,20 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { BitCastInst *bc = cast(ki->inst); llvm::Type *castToType = bc->getType(); + + if (X86FPAsX87FP80 && result->getWidth() == Expr::Fl80 && + !castToType->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = X87FP80ToFPTrunc( + result, getWidthForLLVMType(bc->getOperand(0)->getType()), + state.roundingMode); + } + + if (X86FPAsX87FP80 && castToType->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (castToType->isPointerTy()) { castToType = castToType->getPointerElementType(); } @@ -3608,9 +3762,12 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { ref arg = eval(ki, 0, state).value; if (!fpWidthToSemantics(arg->getWidth()) || !fpWidthToSemantics(resultType)) return terminateStateOnExecError(state, "Unsupported FPTrunc operation"); - if (arg->getWidth() <= resultType) - return terminateStateOnExecError(state, "Invalid FPTrunc"); - ref result = FPTruncExpr::create(arg, resultType, state.roundingMode); + ref result = arg; + if (arg->getWidth() > resultType) + result = FPTruncExpr::create(arg, resultType, state.roundingMode); + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } bindLocal(ki, state, result); break; } @@ -3621,9 +3778,14 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { ref arg = eval(ki, 0, state).value; if (!fpWidthToSemantics(arg->getWidth()) || !fpWidthToSemantics(resultType)) return terminateStateOnExecError(state, "Unsupported FPExt operation"); - if (arg->getWidth() >= resultType) - return terminateStateOnExecError(state, "Invalid FPExt"); - ref result = FPExtExpr::create(arg, resultType); + ref result = arg; + if (arg->getWidth() < resultType) { + // return terminateStateOnExecError(state, "Invalid FPExt"); + result = FPExtExpr::create(arg, resultType); + } + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } bindLocal(ki, state, result); break; } @@ -3657,6 +3819,9 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::UIToFP: { UIToFPInst *fi = cast(i); Expr::Width resultType = getWidthForLLVMType(fi->getType()); + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + resultType = Expr::Fl80; + } ref arg = eval(ki, 0, state).value; const llvm::fltSemantics *semantics = fpWidthToSemantics(resultType); if (!semantics) @@ -3669,6 +3834,9 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::SIToFP: { SIToFPInst *fi = cast(i); Expr::Width resultType = getWidthForLLVMType(fi->getType()); + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + resultType = Expr::Fl80; + } ref arg = eval(ki, 0, state).value; const llvm::fltSemantics *semantics = fpWidthToSemantics(resultType); if (!semantics) @@ -3922,6 +4090,10 @@ void Executor::updateStates(ExecutionState *current) { targetedExecutionManager->update(current, addedStates, removedStates); } + if (targetCalculator) { + targetCalculator->update(current, addedStates, removedStates); + } + if (searcher) { searcher->update(current, addedStates, removedStates); } @@ -4025,13 +4197,24 @@ bool Executor::checkMemoryUsage() { // We need to avoid calling GetTotalMallocUsage() often because it // is O(elts on freelist). This is really bad since we start // to pummel the freelist once we hit the memory cap. - if ((stats::instructions & 0xFFFFU) != 0) // every 65536 instructions + // every 65536 instructions + if ((stats::instructions & 0xFFFFU) != 0 && + maxNewWriteableOSSize < OSCopySizeMemoryCheckThreshold && + maxNewStateStackSize < StackCopySizeMemoryCheckThreshold) return true; // check memory limit const auto mallocUsage = util::GetTotalMallocUsage() >> 20U; const auto mmapUsage = memory->getUsedDeterministicSize() >> 20U; const auto totalUsage = mallocUsage + mmapUsage; + + if (MemoryTriggerCoverOnTheFly && totalUsage > MaxMemory * 0.75) { + klee_warning_once(0, + "enabling cover-on-the-fly (close to memory cap: %luMB)", + totalUsage); + coverOnTheFly = true; + } + atMemoryLimit = totalUsage > MaxMemory; // inhibit forking if (!atMemoryLimit) return true; @@ -4053,7 +4236,7 @@ bool Executor::checkMemoryUsage() { unsigned idx = theRNG.getInt32() % N; // Make two pulls to try and not hit a state that // covered new code. - if (arr[idx]->coveredNew) + if (arr[idx]->isCoveredNew()) idx = theRNG.getInt32() % N; std::swap(arr[idx], arr[N - 1]); @@ -4083,11 +4266,19 @@ void Executor::decreaseConfidenceFromStoppedStates( } void Executor::doDumpStates() { - if (!DumpStatesOnHalt || states.empty()) { + if (DumpStatesOnHalt == HaltExecution::Reason::NotHalt || + (DumpStatesOnHalt == HaltExecution::Reason::UnreachedTarget && + haltExecution == HaltExecution::Reason::ReachedTarget) || + states.empty()) { interpreterHandler->incPathsExplored(states.size()); return; } + if (FunctionCallReproduce != "" && + haltExecution != HaltExecution::Reason::ReachedTarget) { + haltExecution = HaltExecution::UnreachedTarget; + } + klee_message("halting execution, dumping remaining states"); for (const auto &state : pausedStates) terminateStateEarly(*state, "Execution halting (paused state).", @@ -4219,9 +4410,9 @@ void Executor::reportProgressTowardsTargets(std::string prefix, repr << "in function " + target->getBlock()->parent->function->getName().str(); repr << " (lines "; - repr << target->getBlock()->getFirstInstruction()->info->line; + repr << target->getBlock()->getFirstInstruction()->getLine(); repr << " to "; - repr << target->getBlock()->getLastInstruction()->info->line; + repr << target->getBlock()->getLastInstruction()->getLine(); repr << ")"; std::string targetString = repr.str(); klee_message("%s for %s", distance.toString().c_str(), @@ -4260,13 +4451,6 @@ void Executor::run(std::vector initialStates) { while (!states.empty() && !haltExecution) { while (!searcher->empty() && !haltExecution) { ExecutionState &state = searcher->selectState(); - KInstruction *prevKI = state.prevPC; - KFunction *kf = prevKI->parent->parent; - - if (prevKI->inst->isTerminator() && - kmodule->inMainModule(*kf->function)) { - targetCalculator->update(state); - } executeStep(state); } @@ -4325,21 +4509,45 @@ void Executor::initializeTypeManager() { typeSystemManager->initModule(); } +static bool shouldWriteTest(const ExecutionState &state, bool isError = false) { + state.updateCoveredNew(); + bool coveredNew = isError ? state.isCoveredNewError() : state.isCoveredNew(); + return !OnlyOutputStatesCoveringNew || coveredNew; +} + +static std::string terminationTypeFileExtension(StateTerminationType type) { + std::string ret; +#undef TTYPE +#undef TTMARK +#define TTYPE(N, I, S) \ + case StateTerminationType::N: \ + ret = (S); \ + break; +#define TTMARK(N, I) + switch (type) { TERMINATION_TYPES } + return ret; +}; + void Executor::executeStep(ExecutionState &state) { - KInstruction *prevKI = state.prevPC; + KFunction *initKF = state.initPC->parent->parent; + + if (coverOnTheFly && shouldWriteTest(state)) { + state.clearCoveredNew(); + interpreterHandler->processTestCase( + state, nullptr, + terminationTypeFileExtension(StateTerminationType::CoverOnTheFly) + .c_str()); + } + if (targetManager->isTargeted(state) && state.targets().empty()) { terminateStateEarlyAlgorithm(state, "State missed all it's targets.", StateTerminationType::MissedAllTargets); - } else if (prevKI->inst->isTerminator() && MaxCycles && - (state.stack.infoStack() - .back() - .multilevel[state.getPCBlock()] - .second > MaxCycles || - state.stack.multilevel[state.stack.callStack().back().kf].second > - MaxCycles)) { + } else if (state.isCycled(MaxCycles)) { terminateStateEarly(state, "max-cycles exceeded.", StateTerminationType::MaxCycles); } else { + maxNewWriteableOSSize = 0; + maxNewStateStackSize = 0; KInstruction *ki = state.pc; stepInstruction(state); executeInstruction(state, ki); @@ -4358,6 +4566,11 @@ void Executor::executeStep(ExecutionState &state) { // pressure updateStates(nullptr); } + + if (targetCalculator && TrackCoverage != TrackCoverageBy::None && + targetCalculator->isCovered(initKF)) { + haltExecution = HaltExecution::CovCheck; + } } void Executor::targetedRun(ExecutionState &initialState, KBlock *target, @@ -4506,34 +4719,19 @@ void Executor::terminateState(ExecutionState &state, interpreterHandler->incPathsExplored(); state.pc = state.prevPC; - targetCalculator->update(state); + solver->notifyStateTermination(state.id); removedStates.push_back(&state); } -static bool shouldWriteTest(const ExecutionState &state) { - return !OnlyOutputStatesCoveringNew || state.coveredNew; -} - -static std::string terminationTypeFileExtension(StateTerminationType type) { - std::string ret; -#undef TTYPE -#undef TTMARK -#define TTYPE(N, I, S) \ - case StateTerminationType::N: \ - ret = (S); \ - break; -#define TTMARK(N, I) - switch (type) { TERMINATION_TYPES } - return ret; -}; - void Executor::terminateStateOnExit(ExecutionState &state) { auto terminationType = StateTerminationType::Exit; ++stats::terminationExit; - if (shouldWriteTest(state) || (AlwaysOutputSeeds && seedMap.count(&state))) + if (shouldWriteTest(state) || (AlwaysOutputSeeds && seedMap.count(&state))) { + state.clearCoveredNew(); interpreterHandler->processTestCase( state, nullptr, terminationTypeFileExtension(terminationType).c_str()); + } interpreterHandler->incPathsCompleted(); terminateState(state, terminationType); @@ -4550,6 +4748,7 @@ void Executor::terminateStateEarly(ExecutionState &state, const Twine &message, reason == StateTerminationType::MissedAllTargets) && shouldWriteTest(state)) || (AlwaysOutputSeeds && seedMap.count(&state))) { + state.clearCoveredNew(); interpreterHandler->processTestCase( state, (message + "\n").str().c_str(), terminationTypeFileExtension(reason).c_str(), @@ -4574,22 +4773,19 @@ void Executor::terminateStateEarlyUser(ExecutionState &state, terminateStateEarly(state, message, StateTerminationType::SilentExit); } -const InstructionInfo & -Executor::getLastNonKleeInternalInstruction(const ExecutionState &state, - Instruction **lastInstruction) { +const KInstruction * +Executor::getLastNonKleeInternalInstruction(const ExecutionState &state) { // unroll the stack of the applications state and find // the last instruction which is not inside a KLEE internal function - ExecutionStack::call_stack_ty::const_reverse_iterator - it = state.stack.callStack().rbegin(), - itE = state.stack.callStack().rend(); + auto it = state.stack.callStack().rbegin(); + auto itE = state.stack.callStack().rend(); // don't check beyond the outermost function (i.e. main()) itE--; - const InstructionInfo *ii = 0; + const KInstruction *ki = nullptr; if (kmodule->internalFunctions.count(it->kf->function) == 0) { - ii = state.prevPC->info; - *lastInstruction = state.prevPC->inst; + ki = state.prevPC; // Cannot return yet because even though // it->function is not an internal function it might of // been called from an internal function. @@ -4603,21 +4799,19 @@ Executor::getLastNonKleeInternalInstruction(const ExecutionState &state, // function const Function *f = (*it->caller).inst->getParent()->getParent(); if (kmodule->internalFunctions.count(f)) { - ii = 0; + ki = nullptr; continue; } - if (!ii) { - ii = (*it->caller).info; - *lastInstruction = (*it->caller).inst; + if (!ki) { + ki = it->caller; } } - if (!ii) { + if (!ki) { // something went wrong, play safe and return the current instruction info - *lastInstruction = state.prevPC->inst; - return *state.prevPC->info; + return state.prevPC; } - return *ii; + return ki; } bool shouldExitOn(StateTerminationType reason) { @@ -4676,14 +4870,15 @@ void Executor::terminateStateOnError(ExecutionState &state, const char *suffix) { std::string message = messaget.str(); static std::set> emittedErrors; - Instruction *lastInst; - const InstructionInfo &ii = - getLastNonKleeInternalInstruction(state, &lastInst); - - if (EmitAllErrors || - emittedErrors.insert(std::make_pair(lastInst, message)).second) { - if (!ii.file.empty()) { - klee_message("ERROR: %s:%d: %s", ii.file.c_str(), ii.line, + const KInstruction *ki = getLastNonKleeInternalInstruction(state); + Instruction *lastInst = ki->inst; + + if ((EmitAllErrors || + emittedErrors.insert(std::make_pair(lastInst, message)).second) && + shouldWriteTest(state, true)) { + std::string filepath = ki->getSourceFilepath(); + if (!filepath.empty()) { + klee_message("ERROR: %s:%zu: %s", filepath.c_str(), ki->getLine(), message.c_str()); } else { klee_message("ERROR: (location information missing) %s", message.c_str()); @@ -4694,10 +4889,13 @@ void Executor::terminateStateOnError(ExecutionState &state, std::string MsgString; llvm::raw_string_ostream msg(MsgString); msg << "Error: " << message << '\n'; - if (!ii.file.empty()) { - msg << "File: " << ii.file << '\n' << "Line: " << ii.line << '\n'; - if (ii.assemblyLine.hasValue()) { - msg << "assembly.ll line: " << ii.assemblyLine.getValue() << '\n'; + if (!filepath.empty()) { + msg << "File: " << filepath << '\n' << "Line: " << ki->getLine() << '\n'; + { + auto asmLine = ki->getKModule()->getAsmLine(ki->inst); + if (asmLine.has_value()) { + msg << "assembly.ll line: " << asmLine.value() << '\n'; + } } msg << "State: " << state.getID() << '\n'; } @@ -4708,6 +4906,8 @@ void Executor::terminateStateOnError(ExecutionState &state, if (!info_str.empty()) msg << "Info: \n" << info_str; + state.clearCoveredNewError(); + const std::string ext = terminationTypeFileExtension(terminationType); // use user provided suffix from klee_report_error() const char *file_suffix = suffix ? suffix : ext.c_str(); @@ -4786,7 +4986,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, if (i != arguments.size() - 1) os << ", "; } - os << ") at " << state.pc->getSourceLocation(); + os << ") at " << state.pc->getSourceLocationString(); if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); @@ -4827,19 +5027,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, assert(success && "FIXME: Unhandled solver failure"); (void)success; ce->toMemory(&args[wordIndex]); - IDType result; addConstraint(state, EqExpr::create(ce, *ai)); - // Checking to see if the argument is a pointer to something - llvm::Type *argumentType = nullptr; - if (ati != functionType->param_end()) { - argumentType = const_cast(*ati); - } - if (ce->getWidth() == Context::get().getPointerWidth() && - state.addressSpace.resolveOne( - ce, typeSystemManager->getWrappedType(argumentType), result)) { - state.addressSpace.findObject(result).second->flushToConcreteStore( - solver.get(), state); - } wordIndex += (ce->getWidth() + 63) / 64; } else { ref arg = toUnique(state, *ai); @@ -4864,10 +5052,14 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, } // Prepare external memory for invoking the function - state.addressSpace.copyOutConcretes(); + auto arrays = state.constraints.cs().gatherArrays(); + std::vector> values; + solver->getInitialValues(state.constraints.cs(), arrays, values, + state.queryMetaData); + Assignment assignment(arrays, values); + state.addressSpace.copyOutConcretes(assignment); #ifndef WINDOWS // Update external errno state with local state value - int *errno_addr = getErrnoLocation(state); IDType idResult; llvm::Type *pointerErrnoAddr = llvm::PointerType::get( @@ -4905,7 +5097,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, if (i != arguments.size() - 1) os << ", "; } - os << ") at " << state.pc->getSourceLocation(); + os << ") at " << state.pc->getSourceLocationString(); if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); @@ -4937,7 +5129,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, return; } - if (!state.addressSpace.copyInConcretes()) { + if (!state.addressSpace.copyInConcretes(assignment)) { terminateStateOnExecError(state, "external modified read-only object", StateTerminationType::External); return; @@ -4947,7 +5139,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, // Update errno memory object with the errno value from the call int error = externalDispatcher->getLastErrno(); state.addressSpace.copyInConcrete(result.first, result.second, - (uint64_t)&error); + (uint64_t)&error, assignment); #endif Type *resultType = target->inst->getType(); @@ -5026,6 +5218,7 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, KInstruction *target, KType *type, bool zeroMemory, const ObjectState *reallocFrom, size_t allocationAlignment, bool checkOutOfMemory) { + static unsigned allocations = 0; const llvm::Value *allocSite = state.prevPC->inst; if (allocationAlignment == 0) { allocationAlignment = getAllocationAlignment(allocSite); @@ -5067,12 +5260,15 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, if (!mo) { bindLocal(target, state, Expr::createPointer(0)); } else { - ObjectState *os = bindObjectInState(state, mo, type, isLocal); + ref source = nullptr; if (zeroMemory) { - os->initializeToZero(); + source = SourceBuilder::constant( + SparseStorage(ConstantExpr::create(0, Expr::Int8))); } else { - os->initializeToRandom(); + source = SourceBuilder::uninitialized(allocations++, target); } + auto array = makeArray(size, source); + ObjectState *os = bindObjectInState(state, mo, type, isLocal, array); ref address = mo->getBaseExpr(); if (checkOutOfMemory) { @@ -5086,10 +5282,7 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, bindLocal(target, state, address); if (reallocFrom) { - unsigned count = std::min(reallocFrom->size, os->size); - for (unsigned i = 0; i < count; i++) { - os->write(i, reallocFrom->read8(i)); - } + os->write(reallocFrom); state.removePointerResolutions(reallocFrom->getObject()); state.addressSpace.unbindObject(reallocFrom->getObject()); } @@ -5385,13 +5578,18 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, Expr::Width pointerWidthInBits = Context::get().getPointerWidth(); /* Create symbol for array */ + KInstruction *ki = nullptr; + if (!lazyInitializationSource) { + auto inst = cast(allocSite); + ki = kmodule->getKBlock(inst->getParent())->parent->instructionMap[inst]; + } const Array *addressArray = makeArray( Expr::createPointer(pointerWidthInBits / CHAR_BIT), lazyInitializationSource ? SourceBuilder::lazyInitializationAddress(lazyInitializationSource) : SourceBuilder::symbolicSizeConstantAddress( - 0, updateNameVersion(state, "const_arr"))); + updateNameVersion(state, "const_arr"), ki, size)); ref addressExpr = Expr::createTempRead(addressArray, pointerWidthInBits); @@ -5419,18 +5617,19 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, std::vector> symbolicSizesTerms = { ZExtExpr::create(size, pointerWidthInBits)}; - constraints_ty required; - IndependentElementSet eltsClosure = getIndependentConstraints( - Query(state.constraints.cs(), ZExtExpr::create(size, pointerWidthInBits)), - required); + std::vector> factors; + state.toQuery(ZExtExpr::create(size, pointerWidthInBits)) + .getAllDependentConstraintsSets(factors); + /* Collect dependent size symcretes. */ - for (ref symcrete : eltsClosure.symcretes) { - if (isa(symcrete)) { - symbolicSizesTerms.push_back( - ZExtExpr::create(symcrete->symcretized, pointerWidthInBits)); + for (ref ics : factors) { + for (ref symcrete : ics->symcretes) { + if (isa(symcrete)) { + symbolicSizesTerms.push_back( + ZExtExpr::create(symcrete->symcretized, pointerWidthInBits)); + } } } - ref symbolicSizesSum = createNonOverflowingSumExpr(symbolicSizesTerms); std::vector objects; @@ -5441,7 +5640,7 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, return nullptr; } - Assignment assignment(objects, values, true); + Assignment assignment(objects, values); uint64_t sizeMemoryObject = cast(assignment.evaluate(size))->getZExtValue(); @@ -5471,7 +5670,8 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, state.addPointerResolution(addressExpr, mo); } - assignment.bindings[addressArray] = sparseBytesFromValue(mo->address); + assignment.bindings.replace( + {addressArray, sparseBytesFromValue(mo->address)}); state.constraints.addSymcrete(sizeSymcrete, assignment); state.constraints.addSymcrete(addressSymcrete, assignment); @@ -5828,7 +6028,7 @@ void Executor::collectReads( const std::vector &resolvedMemoryObjects, const std::vector &resolveConcretizations, std::vector> &results) { - ref base = address; + ref base = address; // TODO: unused unsigned size = bytes; if (state.isGEPExpr(address)) { base = state.gepExprBases[address].first; @@ -5846,11 +6046,18 @@ void Executor::collectReads( ref result = os->read(mo->getOffsetExpr(address), type); + if (X86FPAsX87FP80 && state.prevPC->inst->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && mo->isGlobal && !os->readOnly && isa(result) && !targetType->getRawType()->isPointerTy()) { result = makeMockValue(state, "mockGlobalValue", result->getWidth()); ObjectState *wos = state.addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->write(mo->getOffsetExpr(address), result); } @@ -5862,6 +6069,16 @@ void Executor::executeMemoryOperation( ExecutionState &estate, bool isWrite, KType *targetType, ref address, ref value /* undef if read */, KInstruction *target /* undef if write */) { + KInstruction *ki = estate.prevPC; + if (X86FPAsX87FP80 && isWrite) { + auto valueOperand = cast(ki->inst)->getValueOperand(); + if (valueOperand->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + value = + X87FP80ToFPTrunc(value, getWidthForLLVMType(valueOperand->getType()), + estate.roundingMode); + } + } Expr::Width type = (isWrite ? value->getWidth() : getWidthForLLVMType(target->inst->getType())); unsigned bytes = Expr::getMinBytesForWidth(type); @@ -5972,13 +6189,13 @@ void Executor::executeMemoryOperation( bool success = solver->getResponse(state->constraints.cs(), inBounds, response, state->queryMetaData); solver->setTimeout(time::Span()); - bool mustBeInBounds = !isa(response); if (!success) { state->pc = state->prevPC; terminateStateOnSolverError(*state, "Query timed out (bounds check)."); return; } + bool mustBeInBounds = !isa(response); if (mustBeInBounds) { if (isa(response)) { addConstraint(*state, inBounds); @@ -5990,6 +6207,8 @@ void Executor::executeMemoryOperation( state->addPointerResolution(address, mo); if (isWrite) { ObjectState *wos = state->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->getDynamicType()->handleMemoryAccess( targetType, mo->getOffsetExpr(address), ConstantExpr::alloc(size, Context::get().getPointerWidth()), true); @@ -6002,6 +6221,11 @@ void Executor::executeMemoryOperation( } else { result = os->read(mo->getOffsetExpr(address), type); + if (X86FPAsX87FP80 && ki->inst->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (interpreterOpts.MakeConcreteSymbolic) result = replaceReadWithSymbolic(*state, result); @@ -6010,6 +6234,8 @@ void Executor::executeMemoryOperation( !targetType->getRawType()->isPointerTy()) { result = makeMockValue(*state, "mockGlobalValue", result->getWidth()); ObjectState *wos = state->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->write(mo->getOffsetExpr(address), result); } @@ -6105,6 +6331,8 @@ void Executor::executeMemoryOperation( const ObjectState *os = op.second; ObjectState *wos = state->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); if (wos->readOnly) { branches = forkInternal(*state, Expr::createIsZero(unboundConditions[i]), @@ -6174,6 +6402,8 @@ void Executor::executeMemoryOperation( if (isWrite) { ObjectState *wos = bound->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->getDynamicType()->handleMemoryAccess( targetType, mo->getOffsetExpr(address), ConstantExpr::alloc(size, Context::get().getPointerWidth()), true); @@ -6186,11 +6416,18 @@ void Executor::executeMemoryOperation( } else { ref result = os->read(mo->getOffsetExpr(address), type); + if (X86FPAsX87FP80 && ki->inst->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && mo->isGlobal && !os->readOnly && isa(result) && !targetType->getRawType()->isPointerTy()) { result = makeMockValue(*bound, "mockGlobalValue", result->getWidth()); ObjectState *wos = bound->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->write(mo->getOffsetExpr(address), result); } @@ -6341,7 +6578,7 @@ void Executor::updateStateWithSymcretes(ExecutionState &state, * assign. We want to update only objects, whose size were changed. */ std::vector> updatedSizeSymcretes; - const Assignment &diffAssignment = + Assignment diffAssignment = state.constraints.cs().concretization().diffWith(assignment); for (const ref &symcrete : state.constraints.cs().symcretes()) { @@ -6368,19 +6605,23 @@ void Executor::updateStateWithSymcretes(ExecutionState &state, continue; } - ObjectPair oldOp = state.addressSpace.findObject(newMO->id); - ref oldMO(oldOp.first); - ref oldOS(oldOp.second); - if (!oldOS) { + ObjectPair op = state.addressSpace.findObject(newMO->id); + + if (!op.second) { continue; } + /* Create a new ObjectState with the new size and new owning memory * object. */ - /* Order of operations critical here. */ - state.addressSpace.unbindObject(oldMO.get()); - state.addressSpace.bindObject(newMO, new ObjectState(newMO, *oldOS.get())); + auto wos = new ObjectState( + *(state.addressSpace.getWriteable(op.first, op.second))); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); + wos->swapObjectHack(newMO); + state.addressSpace.unbindObject(op.first); + state.addressSpace.bindObject(newMO, wos); } } @@ -6409,8 +6650,8 @@ void Executor::executeMakeSymbolic(ExecutionState &state, ObjectState *os = bindObjectInState(state, mo, type, isLocal, array); if (AlignSymbolicPointers) { - if (ref alignmentRestrictions = - type->getContentRestrictions(os->read(0, os->size * CHAR_BIT))) { + if (ref alignmentRestrictions = type->getContentRestrictions( + os->read(0, os->getObject()->size * CHAR_BIT))) { addConstraint(state, alignmentRestrictions); } } @@ -6428,8 +6669,8 @@ void Executor::executeMakeSymbolic(ExecutionState &state, if (!obj) { if (ZeroSeedExtension) { - si.assignment.bindings[array] = - SparseStorage(mo->size, 0); + si.assignment.bindings.replace( + {array, SparseStorage(0)}); } else if (!AllowSeedExtension) { terminateStateOnUserError(state, "ran out of inputs during seeding"); @@ -6449,14 +6690,14 @@ void Executor::executeMakeSymbolic(ExecutionState &state, terminateStateOnUserError(state, msg.str()); break; } else { - SparseStorage &values = - si.assignment.bindings[array]; - values.resize(std::min(mo->size, obj->numBytes)); + SparseStorage values; + if (si.assignment.bindings.find(array) != + si.assignment.bindings.end()) { + values = si.assignment.bindings.at(array); + } values.store(0, obj->bytes, obj->bytes + std::min(obj->numBytes, mo->size)); - if (ZeroSeedExtension) { - values.resize(mo->size); - } + si.assignment.bindings.replace({array, values}); } } } @@ -6591,7 +6832,8 @@ void Executor::clearMemory() { void Executor::runFunctionAsMain(Function *f, int argc, char **argv, char **envp) { - if (guidanceKind == GuidanceKind::ErrorGuidance && + if (FunctionCallReproduce == "" && + guidanceKind == GuidanceKind::ErrorGuidance && (!interpreterOpts.Paths.has_value() || interpreterOpts.Paths->empty())) { klee_warning("No targets found in error-guided mode"); return; @@ -6602,9 +6844,31 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, std::vector states; if (guidanceKind == GuidanceKind::ErrorGuidance) { - auto &paths = interpreterOpts.Paths.value(); - auto prepTargets = targetedExecutionManager->prepareTargets( - kmodule.get(), std::move(paths)); + std::map, + klee::KFunctionCompare> + prepTargets; + if (FunctionCallReproduce == "") { + auto &paths = interpreterOpts.Paths.value(); + prepTargets = targetedExecutionManager->prepareTargets(kmodule.get(), + std::move(paths)); + } else { + /* Find all calls to function specified in .prp file + * and combine them to single target forest */ + auto kfIt = kmodule->functionNameMap.find(FunctionCallReproduce); + if (kfIt == kmodule->functionNameMap.end()) { + klee_warning("%s was eliminated by LLVM passes, so it is unreachable", + FunctionCallReproduce.c_str()); + } else { + auto kCallBlock = kfIt->second->entryKBlock; + KFunction *kEntryFunction = kmodule->functionMap.at(f); + ref forest = new TargetForest(kEntryFunction); + forest->add(ReproduceErrorTarget::create( + {ReachWithError::Reachable}, "", + ErrorLocation(kCallBlock->getFirstInstruction()), kCallBlock)); + prepTargets.emplace(kEntryFunction, forest); + } + } + if (prepTargets.empty()) { klee_warning( "No targets found in error-guided mode after prepare targets"); @@ -6783,7 +7047,7 @@ void Executor::prepareSymbolicValue(ExecutionState &state, void Executor::prepareSymbolicRegister(ExecutionState &state, StackFrame &sf, unsigned regNum) { - KInstruction *allocInst = sf.kf->registerToInstructionMap[regNum]; + KInstruction *allocInst = sf.kf->getInstructionByRegister(regNum); prepareSymbolicValue(state, sf, allocInst); } @@ -6826,7 +7090,7 @@ void Executor::getConstraintLog(const ExecutionState &state, std::string &res, switch (logFormat) { case STP: { - Query query(state.constraints.cs(), ConstantExpr::alloc(0, Expr::Bool)); + auto query = state.toQuery(); char *log = solver->getConstraintLog(query); res = std::string(log); free(log); @@ -6844,7 +7108,7 @@ void Executor::getConstraintLog(const ExecutionState &state, std::string &res, llvm::raw_string_ostream info(Str); ExprSMTLIBPrinter printer; printer.setOutput(info); - Query query(state.constraints.cs(), ConstantExpr::alloc(0, Expr::Bool)); + auto query = state.toQuery(); printer.setQuery(query); printer.generateOutput(); res = info.str(); @@ -6866,7 +7130,7 @@ void Executor::logState(const ExecutionState &state, int id, *f << state.symbolics.size() << " symbolics total. " << "Symbolics:\n"; size_t sc = 0; - for (auto &symbolic : state.symbolics) { + for (const auto &symbolic : state.symbolics) { *f << "Symbolic number " << sc++ << "\n"; *f << "Associated memory object: " << symbolic.memoryObject.get()->id << "\n"; @@ -6880,19 +7144,43 @@ void Executor::logState(const ExecutionState &state, int id, } } -void Executor::setInitializationGraph(const ExecutionState &state, - const Assignment &model, KTest &ktest) { +bool resolveOnSymbolics(const std::vector &symbolics, + const Assignment &assn, + const ref &addr, IDType &result) { + uint64_t address = addr->getZExtValue(); + + for (const auto &res : symbolics) { + const auto &mo = res.memoryObject; + // Check if the provided address is between start and end of the object + // [mo->address, mo->address + mo->size) or the object is a 0-sized object. + ref size = + cast(assn.evaluate(mo->getSizeExpr())); + if ((size->getZExtValue() == 0 && address == mo->address) || + (address - mo->address < size->getZExtValue())) { + result = mo->id; + return true; + } + } + + return false; +} + +void Executor::setInitializationGraph( + const ExecutionState &state, const std::vector &symbolics, + const Assignment &model, KTest &ktest) { std::map> pointers; std::map>> s; ExprHashMap>> resolvedPointers; std::unordered_map> idToSymbolics; - for (const auto &symbolic : state.symbolics) { + for (const auto &symbolic : symbolics) { ref mo = symbolic.memoryObject; idToSymbolics[mo->id] = mo; } - for (const auto &symbolic : state.symbolics) { + const klee::Assignment &assn = state.constraints.cs().concretization(); + + for (const auto &symbolic : symbolics) { KType *symbolicType = symbolic.type; if (!symbolicType->getRawType()) { continue; @@ -6920,7 +7208,7 @@ void Executor::setInitializationGraph(const ExecutionState &state, ref constantAddress = cast(addressInModel); IDType idResult; - if (state.resolveOnSymbolics(constantAddress, idResult)) { + if (resolveOnSymbolics(symbolics, assn, constantAddress, idResult)) { ref mo = idToSymbolics[idResult]; resolvedPointers[address] = std::make_pair(idResult, mo->getOffsetExpr(address)); @@ -6955,15 +7243,17 @@ void Executor::setInitializationGraph(const ExecutionState &state, // The objects have to be symbolic bool pointerFound = false, pointeeFound = false; size_t pointerIndex = 0, pointeeIndex = 0; - for (size_t i = 0; i < state.symbolics.size(); i++) { - if (state.symbolics[i].memoryObject == pointerResolution.first) { + size_t i = 0; + for (auto &symbolic : symbolics) { + if (symbolic.memoryObject == pointerResolution.first) { pointerIndex = i; pointerFound = true; } - if (state.symbolics[i].memoryObject->id == pointer.second.first) { + if (symbolic.memoryObject->id == pointer.second.first) { pointeeIndex = i; pointeeFound = true; } + ++i; } if (pointerFound && pointeeFound) { ref offset = model.evaluate(pointerResolution.second); @@ -6998,7 +7288,7 @@ Assignment Executor::computeConcretization(const ConstraintSet &constraints, ref condition, SolverQueryMetaData &queryMetaData) { Assignment concretization; - if (Query(constraints, condition).containsSymcretes()) { + if (Query(constraints, condition, queryMetaData.id).containsSymcretes()) { ref response; solver->setTimeout(coreSolverTimeout); bool success = solver->getResponse( @@ -7012,6 +7302,32 @@ Assignment Executor::computeConcretization(const ConstraintSet &constraints, return concretization; } +bool isReproducible(const klee::Symbolic &symb) { + auto arr = symb.array; + bool bad = IrreproducibleSource::classof(arr->source.get()); + if (auto liSource = dyn_cast(arr->source.get())) { + std::vector arrays; + findObjects(liSource->pointer, arrays); + for (auto innerArr : arrays) { + bad |= IrreproducibleSource::classof(innerArr->source.get()); + } + } + if (bad) + klee_warning_once(arr->source.get(), + "A irreproducible symbolic %s reaches a test", + arr->getIdentifier().c_str()); + return !bad; +} + +bool isUninitialized(const klee::Array *array) { + bool bad = isa(array->source); + if (bad) + klee_warning_once(array->source.get(), + "A uninitialized array %s reaches a test", + array->getIdentifier().c_str()); + return bad; +} + bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); @@ -7024,34 +7340,61 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { // the preferred constraints. See test/Features/PreferCex.c for // an example) While this process can be very expensive, it can // also make understanding individual test cases much easier. - for (auto &pi : state.cexPreferences) { - bool mustBeTrue; - // Attempt to bound byte to constraints held in cexPreferences - bool success = - solver->mustBeTrue(extendedConstraints.cs(), Expr::createIsZero(pi), - mustBeTrue, state.queryMetaData); - // If it isn't possible to add the condition without making the entire - // list UNSAT, then just continue to the next condition - if (!success) - break; - // If the particular constraint operated on in this iteration through - // the loop isn't implied then add it to the list of constraints. - if (!mustBeTrue) { - Assignment concretization = computeConcretization( - extendedConstraints.cs(), pi, state.queryMetaData); - - if (!concretization.isEmpty()) { - extendedConstraints.addConstraint(pi, concretization); - } else { - extendedConstraints.addConstraint(pi, {}); + const size_t cexPreferencesBound = 16; + if (state.cexPreferences.size() > cexPreferencesBound) { + klee_warning_once(0, "skipping cex preffering (size of restrictons > %zu).", + cexPreferencesBound); + } else { + for (auto &pi : state.cexPreferences) { + bool mustBeTrue; + // Attempt to bound byte to constraints held in cexPreferences + bool success = + solver->mustBeTrue(extendedConstraints.cs(), Expr::createIsZero(pi), + mustBeTrue, state.queryMetaData); + // If it isn't possible to add the condition without making the entire + // list UNSAT, then just continue to the next condition + if (!success) + break; + // If the particular constraint operated on in this iteration through + // the loop isn't implied then add it to the list of constraints. + if (!mustBeTrue) { + Assignment concretization = computeConcretization( + extendedConstraints.cs(), pi, state.queryMetaData); + + if (!concretization.isEmpty()) { + extendedConstraints.addConstraint(pi, concretization); + } else { + extendedConstraints.addConstraint(pi, {}); + } } } } + std::vector allObjects; + findSymbolicObjects(state.constraints.cs().cs().begin(), + state.constraints.cs().cs().end(), allObjects); + std::vector uninitObjects; + std::copy_if(allObjects.begin(), allObjects.end(), + std::back_inserter(uninitObjects), isUninitialized); + + std::vector symbolics; + std::copy_if(state.symbolics.begin(), state.symbolics.end(), + std::back_inserter(symbolics), isReproducible); + + // we cannot be sure that an irreproducible state proves the presence of an + // error + if (uninitObjects.size() > 0 || state.symbolics.size() != symbolics.size()) { + state.error = ReachWithError::None; + } else if (FunctionCallReproduce != "" && + state.error == ReachWithError::Reachable) { + setHaltExecution(HaltExecution::ReachedTarget); + } + std::vector> values; std::vector objects; - for (unsigned i = 0; i != state.symbolics.size(); ++i) - objects.push_back(state.symbolics[i].array); + for (auto &symbolic : symbolics) { + objects.push_back(symbolic.array); + } bool success = solver->getInitialValues(extendedConstraints.cs(), objects, values, state.queryMetaData); solver->setTimeout(time::Span()); @@ -7062,34 +7405,41 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { return false; } - res.objects = new KTestObject[state.symbolics.size()]; - res.numObjects = state.symbolics.size(); + res.numObjects = symbolics.size(); + res.objects = new KTestObject[res.numObjects]; + res.uninitCoeff = uninitObjects.size() * UninitMemoryTestMultiplier; - for (unsigned i = 0; i != state.symbolics.size(); ++i) { - auto mo = state.symbolics[i].memoryObject; - KTestObject *o = &res.objects[i]; - o->name = const_cast(mo->name.c_str()); - o->address = mo->address; - o->numBytes = values[i].size(); - o->bytes = new unsigned char[o->numBytes]; - std::copy(values[i].begin(), values[i].end(), o->bytes); - o->numPointers = 0; - o->pointers = nullptr; + { + size_t i = 0; + // Remove mo->size, evaluate size expr in array + for (auto &symbolic : symbolics) { + auto mo = symbolic.memoryObject; + KTestObject *o = &res.objects[i]; + o->name = const_cast(mo->name.c_str()); + o->address = mo->address; + o->numBytes = mo->size; + o->bytes = new unsigned char[o->numBytes]; + for (size_t j = 0; j < mo->size; j++) { + o->bytes[j] = values[i].load(j); + } + o->numPointers = 0; + o->pointers = nullptr; + i++; + } } - Assignment model = Assignment(objects, values, true); + Assignment model = Assignment(objects, values); for (auto binding : state.constraints.cs().concretization().bindings) { model.bindings.insert(binding); } - setInitializationGraph(state, model, res); + setInitializationGraph(state, symbolics, model, res); return true; } -void Executor::getCoveredLines( - const ExecutionState &state, - std::map> &res) { +void Executor::getCoveredLines(const ExecutionState &state, + std::map> &res) { res = state.coveredLines; } @@ -7125,6 +7475,8 @@ void Executor::doImpliedValueConcretization(ExecutionState &state, ref e, assert(!os->readOnly && "not possible? read only object with static read?"); ObjectState *wos = state.addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->write(CE, it->second); } } @@ -7248,9 +7600,9 @@ void Executor::dumpStates() { sfIt != sf_ie; ++sfIt) { *os << "('" << sfIt->kf->function->getName().str() << "',"; if (next == es->stack.callStack().end()) { - *os << es->prevPC->info->line << "), "; + *os << es->prevPC->getLine() << "), "; } else { - *os << next->caller->info->line << "), "; + *os << next->caller->getLine() << "), "; ++next; } } @@ -7259,15 +7611,15 @@ void Executor::dumpStates() { InfoStackFrame &sf = es->stack.infoStack().back(); uint64_t md2u = computeMinDistToUncovered(es->pc, sf.minDistToUncoveredOnReturn); - uint64_t icnt = theStatisticManager->getIndexedValue(stats::instructions, - es->pc->info->id); + uint64_t icnt = theStatisticManager->getIndexedValue( + stats::instructions, es->pc->getGlobalIndex()); uint64_t cpicnt = sf.callPathNode->statistics.getValue(stats::instructions); *os << "{"; *os << "'depth' : " << es->depth << ", "; *os << "'queryCost' : " << es->queryMetaData.queryCost << ", "; - *os << "'coveredNew' : " << es->coveredNew << ", "; + *os << "'coveredNew' : " << es->isCoveredNew() << ", "; *os << "'instsSinceCovNew' : " << es->instsSinceCovNew << ", "; *os << "'md2u' : " << md2u << ", "; *os << "'icnt' : " << icnt << ", "; diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index d66ff5986f..0f8d8eaf69 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -72,13 +72,12 @@ namespace klee { class AddressManager; class Array; struct Cell; -class CodeGraphDistance; +class CodeGraphInfo; class DistanceCalculator; class ExecutionState; class ExternalDispatcher; class Expr; template class ExprHashMap; -class InstructionInfoTable; class KCallable; struct KFunction; struct KInstruction; @@ -122,6 +121,11 @@ class Executor : public Interpreter { RNG theRNG; private: + int *errno_addr; + + size_t maxNewWriteableOSSize = 0; + size_t maxNewStateStackSize = 0; + using SetOfStates = std::set; /* Set of Intrinsic::ID. Plain type is used here to avoid including llvm in * the header */ @@ -146,7 +150,7 @@ class Executor : public Interpreter { TimerGroup timers; std::unique_ptr processForest; GuidanceKind guidanceKind; - std::unique_ptr codeGraphDistance; + std::unique_ptr codeGraphInfo; std::unique_ptr distanceCalculator; std::unique_ptr targetCalculator; std::unique_ptr targetManager; @@ -207,6 +211,9 @@ class Executor : public Interpreter { /// Disables forking, set by client. \see setInhibitForking() bool inhibitForking; + /// Should it generate test cases for each new covered block or branch + bool coverOnTheFly; + /// Signals the executor to halt execution at the next instruction /// step. HaltExecution::Reason haltExecution = HaltExecution::NotHalt; @@ -286,7 +293,7 @@ class Executor : public Interpreter { ObjectState *bindObjectInState(ExecutionState &state, const MemoryObject *mo, KType *dynamicType, bool IsAlloca, - const Array *array = 0); + const Array *array = nullptr); /// Resolve a pointer to the memory objects it could point to the /// start of, forking execution when necessary and generating errors @@ -480,7 +487,7 @@ class Executor : public Interpreter { ref readDest(ExecutionState &state, StackFrame &frame, const KInstruction *target) { - unsigned index = target->dest; + unsigned index = target->getDest(); ref reg = frame.locals[index].value; if (!reg) { prepareSymbolicRegister(state, frame, index); @@ -494,7 +501,7 @@ class Executor : public Interpreter { } Cell &getDestCell(const StackFrame &frame, const KInstruction *target) { - return frame.locals[target->dest]; + return frame.locals[target->getDest()]; } const Cell &eval(const KInstruction *ki, unsigned index, @@ -565,10 +572,9 @@ class Executor : public Interpreter { const MemoryObject *mo = nullptr) const; // Determines the \param lastInstruction of the \param state which is not KLEE - // internal and returns its InstructionInfo - const InstructionInfo & - getLastNonKleeInternalInstruction(const ExecutionState &state, - llvm::Instruction **lastInstruction); + // internal and returns its KInstruction + const KInstruction * + getLastNonKleeInternalInstruction(const ExecutionState &state); /// Remove state from queue and delete state void terminateState(ExecutionState &state, @@ -727,9 +733,9 @@ class Executor : public Interpreter { setModule(std::vector> &userModules, std::vector> &libsModules, const ModuleOptions &opts, - const std::unordered_set &mainModuleFunctions, - const std::unordered_set &mainModuleGlobals, - std::unique_ptr origInfos) override; + std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, + FLCtoOpcode &&origInstructions) override; void useSeeds(const std::vector *seeds) override { usingSeeds = seeds; @@ -776,6 +782,8 @@ class Executor : public Interpreter { haltExecution = value; } + HaltExecution::Reason getHaltExecution() override { return haltExecution; } + void setInhibitForking(bool value) override { inhibitForking = value; } void prepareForEarlyExit() override; @@ -791,6 +799,7 @@ class Executor : public Interpreter { Interpreter::LogType logFormat = Interpreter::STP) override; void setInitializationGraph(const ExecutionState &state, + const std::vector &symbolics, const Assignment &model, KTest &tc); void logState(const ExecutionState &state, int id, @@ -798,9 +807,8 @@ class Executor : public Interpreter { bool getSymbolicSolution(const ExecutionState &state, KTest &res) override; - void getCoveredLines( - const ExecutionState &state, - std::map> &res) override; + void getCoveredLines(const ExecutionState &state, + std::map> &res) override; void getBlockPath(const ExecutionState &state, std::string &blockPath) override; diff --git a/lib/Core/ExecutorUtil.cpp b/lib/Core/ExecutorUtil.cpp index 467982c81f..ce19fa74bf 100644 --- a/lib/Core/ExecutorUtil.cpp +++ b/lib/Core/ExecutorUtil.cpp @@ -35,6 +35,39 @@ DISABLE_WARNING_POP using namespace llvm; namespace klee { +extern llvm::cl::opt X86FPAsX87FP80; +ref X87FP80ToFPTrunc(ref arg, Expr::Width type, + llvm::APFloat::roundingMode rm) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = type; + if (Context::get().getPointerWidth() == 32 && arg->getWidth() == Expr::Fl80) { + result = FPTruncExpr::create(arg, resultType, rm); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif // ENABLE_FP + return result; +} + +ref FPToX87FP80Ext(ref arg) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = Expr::Fl80; + if (Context::get().getPointerWidth() == 32) { + result = FPExtExpr::create(arg, resultType); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif // ENABLE_FP + return result; +} ref Executor::evalConstant(const Constant *c, llvm::APFloat::roundingMode rm, @@ -51,7 +84,12 @@ ref Executor::evalConstant(const Constant *c, if (const ConstantInt *ci = dyn_cast(c)) { return ConstantExpr::alloc(ci->getValue()); } else if (const ConstantFP *cf = dyn_cast(c)) { - return ConstantExpr::alloc(cf->getValueAPF()); + ref result = ConstantExpr::alloc(cf->getValueAPF()); + if (X86FPAsX87FP80 && c->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = cast(FPToX87FP80Ext(result)); + } + return result; } else if (const GlobalValue *gv = dyn_cast(c)) { auto it = globalAddresses.find(gv); assert(it != globalAddresses.end()); @@ -134,7 +172,7 @@ ref Executor::evalConstant(const Constant *c, std::string msg("Cannot handle constant "); llvm::raw_string_ostream os(msg); os << "'" << *c << "' at location " - << (ki ? ki->getSourceLocation() : "[unknown]"); + << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); } } @@ -261,7 +299,7 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, std::string msg( "Division/modulo by zero during constant folding at location "); llvm::raw_string_ostream os(msg); - os << (ki ? ki->getSourceLocation() : "[unknown]"); + os << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); } break; @@ -271,7 +309,7 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, if (op2->getLimitedValue() >= op1->getWidth()) { std::string msg("Overshift during constant folding at location "); llvm::raw_string_ostream os(msg); - os << (ki ? ki->getSourceLocation() : "[unknown]"); + os << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); } } @@ -282,7 +320,7 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, switch (ce->getOpcode()) { default: os << "'" << *ce << "' at location " - << (ki ? ki->getSourceLocation() : "[unknown]"); + << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); case Instruction::Trunc: @@ -317,8 +355,22 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, return op1->LShr(op2); case Instruction::AShr: return op1->AShr(op2); - case Instruction::BitCast: - return op1; + case Instruction::BitCast: { + ref result = op1; + + if (X86FPAsX87FP80 && result->getWidth() == Expr::Fl80 && + !ce->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = cast( + X87FP80ToFPTrunc(result, getWidthForLLVMType(type), rm)); + } + + if (X86FPAsX87FP80 && ce->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = cast(FPToX87FP80Ext(result)); + } + return result; + } case Instruction::IntToPtr: return op1->ZExt(getWidthForLLVMType(type)); diff --git a/lib/Core/ImpliedValue.cpp b/lib/Core/ImpliedValue.cpp index 8841ffab3c..81d3e3faf8 100644 --- a/lib/Core/ImpliedValue.cpp +++ b/lib/Core/ImpliedValue.cpp @@ -203,8 +203,8 @@ void ImpliedValue::checkForImpliedValues(Solver *S, ref e, std::set> readsSet(reads.begin(), reads.end()); reads = std::vector>(readsSet.begin(), readsSet.end()); - ConstraintSet assumption; - assumption.addConstraint(EqExpr::create(e, value), {}); + constraints_ty assumption; + assumption.insert(EqExpr::create(e, value)); // obscure... we need to make sure that all the read indices are // bounds checked. if we don't do this we can end up constructing @@ -212,11 +212,8 @@ void ImpliedValue::checkForImpliedValues(Solver *S, ref e, // bounds indices which will not get picked up. this is of utmost // importance if we are being backed by the CexCachingSolver. - for (std::vector>::iterator i = reads.begin(), ie = reads.end(); - i != ie; ++i) { - ReadExpr *re = i->get(); - assumption.addConstraint(UltExpr::create(re->index, re->updates.root->size), - {}); + for (const auto &re : reads) { + assumption.insert(UltExpr::create(re->index, re->updates.root->size)); } for (const auto &var : reads) { diff --git a/lib/Core/Memory.cpp b/lib/Core/Memory.cpp index f85ea95b3b..16a49c6938 100644 --- a/lib/Core/Memory.cpp +++ b/lib/Core/Memory.cpp @@ -39,14 +39,6 @@ DISABLE_WARNING_POP using namespace llvm; using namespace klee; -namespace { -cl::opt - UseConstantArrays("use-constant-arrays", - cl::desc("Use constant arrays instead of updates when " - "possible (default=true)\n"), - cl::init(true), cl::cat(SolvingCat)); -} - /***/ IDType MemoryObject::counter = 1; @@ -81,99 +73,21 @@ void MemoryObject::getAllocInfo(std::string &result) const { /***/ -ObjectState::ObjectState(const MemoryObject *mo, KType *dt) - : copyOnWriteOwner(0), object(mo), concreteStore(new uint8_t[mo->size]), - concreteMask(nullptr), knownSymbolics(nullptr), unflushedMask(nullptr), - updates(nullptr, nullptr), lastUpdate(nullptr), dynamicType(dt), - size(mo->size), readOnly(false) { - if (!UseConstantArrays) { - static unsigned id = 0; - const Array *array = getArrayCache()->CreateArray( - mo->getSizeExpr(), SourceBuilder::makeSymbolic("tmp_arr", ++id)); - updates = UpdateList(array, 0); - } - memset(concreteStore, 0, size); -} - ObjectState::ObjectState(const MemoryObject *mo, const Array *array, KType *dt) - : copyOnWriteOwner(0), object(mo), concreteStore(new uint8_t[mo->size]), - concreteMask(nullptr), knownSymbolics(nullptr), unflushedMask(nullptr), - updates(array, nullptr), lastUpdate(nullptr), dynamicType(dt), - size(mo->size), readOnly(false) { - makeSymbolic(); - memset(concreteStore, 0, size); -} - -ObjectState::ObjectState(const ObjectState &os) - : copyOnWriteOwner(0), object(os.object), - concreteStore(new uint8_t[os.size]), - concreteMask(os.concreteMask ? new BitArray(*os.concreteMask, os.size) - : nullptr), - knownSymbolics(nullptr), - unflushedMask(os.unflushedMask ? new BitArray(*os.unflushedMask, os.size) - : nullptr), - updates(os.updates), wasZeroInitialized(os.wasZeroInitialized), - lastUpdate(os.lastUpdate), dynamicType(os.dynamicType), size(os.size), - readOnly(os.readOnly) { - if (os.knownSymbolics) { - knownSymbolics = new ref[size]; - for (unsigned i = 0; i < size; i++) - knownSymbolics[i] = os.knownSymbolics[i]; - } + : copyOnWriteOwner(0), object(mo), knownSymbolics(nullptr), + unflushedMask(false), updates(array, nullptr), lastUpdate(nullptr), + size(array->size), dynamicType(dt), readOnly(false) {} - memcpy(concreteStore, os.concreteStore, size * sizeof(*concreteStore)); -} - -ObjectState::ObjectState(const MemoryObject *mo, const ObjectState &os) - : copyOnWriteOwner(0), object(mo), concreteStore(new uint8_t[mo->size]), - concreteMask(os.concreteMask ? new BitArray(*os.concreteMask, mo->size) - : nullptr), - knownSymbolics(nullptr), - unflushedMask(os.unflushedMask ? new BitArray(*os.unflushedMask, mo->size) - : nullptr), - updates(os.updates), wasZeroInitialized(os.wasZeroInitialized), - lastUpdate(os.lastUpdate), dynamicType(os.getDynamicType()), - size(mo->size), readOnly(os.readOnly) { - /* This constructor should be used when we extend or truncate the memory - for MemoryObject and want to leave content from previous ObjectState. Maybe - it is good to make it a method, not a constructor. */ - unsigned copyingRange = std::min(size, os.size); - - if (os.knownSymbolics) { - knownSymbolics = new ref[size]; - for (unsigned i = 0; i < copyingRange; ++i) { - knownSymbolics[i] = os.knownSymbolics[i]; - } - } - - if (updates.root && - (isa_and_nonnull(updates.root->source) || - isa_and_nonnull( - updates.root->source))) { - /* As now we cannot make only a part of object symbolic, - we will mark all remain bytes as symbolic. */ - for (unsigned i = copyingRange; i < size; ++i) { - markByteSymbolic(i); - setKnownSymbolic(i, 0); - markByteFlushed(i); - } - } - - memcpy(concreteStore, os.concreteStore, - copyingRange * sizeof(*concreteStore)); - // FIXME: 0xAB is a magical number here... Move to constant. - memset(reinterpret_cast(concreteStore) + - copyingRange * sizeof(*concreteStore), - os.wasZeroInitialized ? 0 : 0xAB, - (size - copyingRange) * sizeof(*concreteStore)); -} +ObjectState::ObjectState(const MemoryObject *mo, KType *dt) + : copyOnWriteOwner(0), object(mo), knownSymbolics(nullptr), + unflushedMask(false), updates(nullptr, nullptr), lastUpdate(nullptr), + size(mo->getSizeExpr()), dynamicType(dt), readOnly(false) {} -ObjectState::~ObjectState() { - delete concreteMask; - delete unflushedMask; - delete[] knownSymbolics; - delete[] concreteStore; -} +ObjectState::ObjectState(const ObjectState &os) + : copyOnWriteOwner(0), object(os.object), knownSymbolics(os.knownSymbolics), + unflushedMask(os.unflushedMask), updates(os.updates), + lastUpdate(os.lastUpdate), size(os.size), dynamicType(os.dynamicType), + readOnly(os.readOnly) {} ArrayCache *ObjectState::getArrayCache() const { assert(object && "object was NULL"); @@ -184,248 +98,66 @@ ArrayCache *ObjectState::getArrayCache() const { const UpdateList &ObjectState::getUpdates() const { // Constant arrays are created lazily. - if (!updates.root) { - // Collect the list of writes, with the oldest writes first. - - // FIXME: We should be able to do this more efficiently, we just need to be - // careful to get the interaction with the cache right. In particular we - // should avoid creating UpdateNode instances we never use. - unsigned NumWrites = updates.head ? updates.head->getSize() : 0; - std::vector, ref>> Writes(NumWrites); - const auto *un = updates.head.get(); - for (unsigned i = NumWrites; i != 0; un = un->next.get()) { - --i; - Writes[i] = std::make_pair(un->index, un->value); - } - - /* For objects of symbolic size we will leave last constant - sizes for every index and create constant array (in terms of - Z3 solver) filled with zeros. This part is required for reads - from unitialzed memory. */ - std::vector> Contents(size); - - // Initialize to zeros. - for (unsigned i = 0, e = size; i != e; ++i) - Contents[i] = ConstantExpr::create(0, Expr::Int8); - - // Pull off as many concrete writes as we can. - unsigned Begin = 0, End = Writes.size(); - for (; Begin != End; ++Begin) { - // Push concrete writes into the constant array. - ConstantExpr *Index = dyn_cast(Writes[Begin].first); - if (!Index) - break; - - ConstantExpr *Value = dyn_cast(Writes[Begin].second); - if (!Value) - break; - - Contents[Index->getZExtValue()] = Value; - } - static unsigned id = 0; - std::string arrayName = "const_arr" + llvm::utostr(++id); - const Array *array = nullptr; - - if (object->hasSymbolicSize()) { - /* Extend updates with last written non-zero constant values. - ConstantValues must be empty in constant array. */ - array = getArrayCache()->CreateArray( - object->getSizeExpr(), SourceBuilder::symbolicSizeConstant(0)); - updates = UpdateList(array, 0); - for (unsigned idx = 0; idx < size; ++idx) { - if (!Contents[idx]->getZExtValue()) { - updates.extend(ConstantExpr::create(idx, Expr::Int32), Contents[idx]); + if (auto sizeExpr = dyn_cast(size)) { + auto size = sizeExpr->getZExtValue(); + if (knownSymbolics.storage().size() == size) { + SparseStorage> values( + ConstantExpr::create(0, Expr::Int8)); + UpdateList symbolicUpdates = UpdateList(nullptr, nullptr); + for (unsigned i = 0; i < size; i++) { + auto value = knownSymbolics.load(i); + assert(value); + if (isa(value)) { + values.store(i, cast(value)); + } else { + symbolicUpdates.extend(ConstantExpr::create(i, Expr::Int32), value); } } - } else { - array = getArrayCache()->CreateArray(object->getSizeExpr(), - SourceBuilder::constant(Contents)); - updates = UpdateList(array, 0); - } - - // Apply the remaining (non-constant) writes. - for (; Begin != End; ++Begin) - updates.extend(Writes[Begin].first, Writes[Begin].second); - } - - return updates; -} - -void ObjectState::flushToConcreteStore(TimingSolver *solver, - const ExecutionState &state) const { - for (unsigned i = 0; i < size; i++) { - if (isByteKnownSymbolic(i)) { - ref ce; - bool success = solver->getValue(state.constraints.cs(), read8(i), ce, - state.queryMetaData); - if (!success) - klee_warning("Solver timed out when getting a value for external call, " - "byte %p+%u will have random value", - (void *)object->address, i); - else - ce->toMemory(concreteStore + i); - } - } -} - -void ObjectState::makeConcrete() { - delete concreteMask; - delete unflushedMask; - delete[] knownSymbolics; - concreteMask = nullptr; - unflushedMask = nullptr; - knownSymbolics = nullptr; -} - -void ObjectState::makeSymbolic() { - assert(!updates.head && - "XXX makeSymbolic of objects with symbolic values is unsupported"); - // XXX simplify this, can just delete various arrays I guess - for (unsigned i = 0; i < size; i++) { - markByteSymbolic(i); - setKnownSymbolic(i, 0); - markByteFlushed(i); - } -} - -void ObjectState::initializeToZero() { - makeConcrete(); - wasZeroInitialized = true; - memset(concreteStore, 0, size); -} - -void ObjectState::initializeToRandom() { - makeConcrete(); - wasZeroInitialized = false; - memset(concreteStore, 0xAB, size); -} - -/* -Cache Invariants --- -isByteKnownSymbolic(i) => !isByteConcrete(i) -isByteConcrete(i) => !isByteKnownSymbolic(i) -isByteUnflushed(i) => (isByteConcrete(i) || isByteKnownSymbolic(i)) - */ - -void ObjectState::fastRangeCheckOffset(ref offset, unsigned *base_r, - unsigned *size_r) const { - *base_r = 0; - *size_r = size; -} - -void ObjectState::flushRangeForRead(unsigned rangeBase, - unsigned rangeSize) const { - if (!unflushedMask) - unflushedMask = new BitArray(size, true); - - for (unsigned offset = rangeBase; offset < rangeBase + rangeSize; offset++) { - if (isByteUnflushed(offset)) { - if (isByteConcrete(offset)) { - updates.extend(ConstantExpr::create(offset, Expr::Int32), - ConstantExpr::create(concreteStore[offset], Expr::Int8)); - } else { - assert(isByteKnownSymbolic(offset) && - "invalid bit set in unflushedMask"); - updates.extend(ConstantExpr::create(offset, Expr::Int32), - knownSymbolics[offset]); - } - - unflushedMask->unset(offset); + auto array = getArrayCache()->CreateArray( + sizeExpr, SourceBuilder::constant(values)); + updates = UpdateList(array, symbolicUpdates.head); + knownSymbolics.reset(); + unflushedMask.reset(); } } -} - -void ObjectState::flushRangeForWrite(unsigned rangeBase, unsigned rangeSize) { - if (!unflushedMask) - unflushedMask = new BitArray(size, true); - - for (unsigned offset = rangeBase; offset < rangeBase + rangeSize; offset++) { - if (isByteUnflushed(offset)) { - if (isByteConcrete(offset)) { - updates.extend(ConstantExpr::create(offset, Expr::Int32), - ConstantExpr::create(concreteStore[offset], Expr::Int8)); - markByteSymbolic(offset); - } else { - assert(isByteKnownSymbolic(offset) && - "invalid bit set in unflushedMask"); - updates.extend(ConstantExpr::create(offset, Expr::Int32), - knownSymbolics[offset]); - setKnownSymbolic(offset, 0); - } - unflushedMask->unset(offset); - } else { - // flushed bytes that are written over still need - // to be marked out - if (isByteConcrete(offset)) { - markByteSymbolic(offset); - } else if (isByteKnownSymbolic(offset)) { - setKnownSymbolic(offset, 0); - } - } + if (!updates.root) { + SparseStorage> values( + ConstantExpr::create(0, Expr::Int8)); + auto array = + getArrayCache()->CreateArray(size, SourceBuilder::constant(values)); + updates = UpdateList(array, updates.head); } -} -bool ObjectState::isByteConcrete(unsigned offset) const { - return !concreteMask || concreteMask->get(offset); -} - -bool ObjectState::isByteUnflushed(unsigned offset) const { - return !unflushedMask || unflushedMask->get(offset); -} - -bool ObjectState::isByteKnownSymbolic(unsigned offset) const { - return knownSymbolics && knownSymbolics[offset].get(); -} + assert(updates.root); -void ObjectState::markByteConcrete(unsigned offset) { - if (concreteMask) - concreteMask->set(offset); -} - -void ObjectState::markByteSymbolic(unsigned offset) { - if (!concreteMask) - concreteMask = new BitArray(size, true); - concreteMask->unset(offset); -} - -void ObjectState::markByteUnflushed(unsigned offset) { - if (unflushedMask) - unflushedMask->set(offset); + return updates; } -void ObjectState::markByteFlushed(unsigned offset) { - if (!unflushedMask) { - unflushedMask = new BitArray(size, false); - } else { - unflushedMask->unset(offset); +void ObjectState::flushForRead() const { + for (const auto &unflushed : unflushedMask.storage()) { + auto offset = unflushed.first; + auto value = knownSymbolics.load(offset); + assert(value); + updates.extend(ConstantExpr::create(offset, Expr::Int32), value); } + unflushedMask.reset(false); } -void ObjectState::setKnownSymbolic(unsigned offset, - Expr *value /* can be null */) { - if (knownSymbolics) { - knownSymbolics[offset] = value; - } else { - if (value) { - knownSymbolics = new ref[size]; - knownSymbolics[offset] = value; - } - } +void ObjectState::flushForWrite() { + flushForRead(); + // The write is symbolic offset and might overwrite any byte + knownSymbolics.reset(nullptr); } /***/ ref ObjectState::read8(unsigned offset) const { - if (isByteConcrete(offset)) { - return ConstantExpr::create(concreteStore[offset], Expr::Int8); - } else if (isByteKnownSymbolic(offset)) { - return knownSymbolics[offset]; + if (auto byte = knownSymbolics.load(offset)) { + return byte; } else { - assert(!isByteUnflushed(offset) && "unflushed byte without cache value"); - + assert(!unflushedMask.load(offset) && "unflushed byte without cache value"); return ReadExpr::create(getUpdates(), ConstantExpr::create(offset, Expr::Int32)); } @@ -434,11 +166,9 @@ ref ObjectState::read8(unsigned offset) const { ref ObjectState::read8(ref offset) const { assert(!isa(offset) && "constant offset passed to symbolic read8"); - unsigned base, size; - fastRangeCheckOffset(offset, &base, &size); - flushRangeForRead(base, size); + flushForRead(); - if (size > 4096) { + if (object && object->size > 4096) { std::string allocInfo; object->getAllocInfo(allocInfo); klee_warning_once( @@ -446,19 +176,15 @@ ref ObjectState::read8(ref offset) const { "Symbolic memory access will send the following array of %d bytes to " "the constraint solver -- large symbolic arrays may cause significant " "performance issues: %s", - size, allocInfo.c_str()); + object->size, allocInfo.c_str()); } return ReadExpr::create(getUpdates(), ZExtExpr::create(offset, Expr::Int32)); } void ObjectState::write8(unsigned offset, uint8_t value) { - // assert(read_only == false && "writing to read-only object!"); - concreteStore[offset] = value; - setKnownSymbolic(offset, 0); - - markByteConcrete(offset); - markByteUnflushed(offset); + knownSymbolics.store(offset, ConstantExpr::create(value, Expr::Int8)); + unflushedMask.store(offset, true); } void ObjectState::write8(unsigned offset, ref value) { @@ -466,21 +192,17 @@ void ObjectState::write8(unsigned offset, ref value) { if (ConstantExpr *CE = dyn_cast(value)) { write8(offset, (uint8_t)CE->getZExtValue(8)); } else { - setKnownSymbolic(offset, value.get()); - - markByteSymbolic(offset); - markByteUnflushed(offset); + knownSymbolics.store(offset, value); + unflushedMask.store(offset, true); } } void ObjectState::write8(ref offset, ref value) { assert(!isa(offset) && "constant offset passed to symbolic write8"); - unsigned base, size; - fastRangeCheckOffset(offset, &base, &size); - flushRangeForWrite(base, size); + flushForWrite(); - if (size > 4096) { + if (object && object->size > 4096) { std::string allocInfo; object->getAllocInfo(allocInfo); klee_warning_once( @@ -488,12 +210,19 @@ void ObjectState::write8(ref offset, ref value) { "Symbolic memory access will send the following array of %d bytes to " "the constraint solver -- large symbolic arrays may cause significant " "performance issues: %s", - size, allocInfo.c_str()); + object->size, allocInfo.c_str()); } updates.extend(ZExtExpr::create(offset, Expr::Int32), value); } +void ObjectState::write(ref os) { + knownSymbolics = os->knownSymbolics; + unflushedMask = os->unflushedMask; + updates = UpdateList(updates.root, os->updates.head); + lastUpdate = os->lastUpdate; +} + /***/ ref ObjectState::read(ref offset, Expr::Width width) const { @@ -642,14 +371,13 @@ void ObjectState::print() const { llvm::errs() << "-- ObjectState --\n"; llvm::errs() << "\tMemoryObject ID: " << object->id << "\n"; llvm::errs() << "\tRoot Object: " << updates.root << "\n"; - llvm::errs() << "\tSize: " << size << "\n"; + llvm::errs() << "\tSize: " << object->size << "\n"; llvm::errs() << "\tBytes:\n"; - for (unsigned i = 0; i < size; i++) { + for (unsigned i = 0; i < object->size; i++) { llvm::errs() << "\t\t[" << i << "]" - << " concrete? " << isByteConcrete(i) << " known-sym? " - << isByteKnownSymbolic(i) << " unflushed? " - << isByteUnflushed(i) << " = "; + << " known? " << !knownSymbolics.load(i).isNull() + << " unflushed? " << unflushedMask.load(i) << " = "; ref e = read8(i); llvm::errs() << e << "\n"; } diff --git a/lib/Core/Memory.h b/lib/Core/Memory.h index e43e4d015b..6d3bb3b987 100644 --- a/lib/Core/Memory.h +++ b/lib/Core/Memory.h @@ -12,6 +12,8 @@ #include "MemoryManager.h" #include "TimingSolver.h" +#include "klee/ADT/Ref.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Core/Context.h" #include "klee/Expr/Assignment.h" @@ -125,7 +127,7 @@ class MemoryObject { /// Get an identifying string for this allocation. void getAllocInfo(std::string &result) const; - void setName(std::string name) const { this->name = name; } + void setName(const std::string &_name) const { this->name = _name; } void updateTimestamp() const { this->timestamp = time++; } @@ -209,57 +211,46 @@ class ObjectState { ref object; - /// @brief Holds all known concrete bytes - uint8_t *concreteStore; - - /// @brief concreteMask[byte] is set if byte is known to be concrete - BitArray *concreteMask; - - /// knownSymbolics[byte] holds the symbolic expression for byte, - /// if byte is known to be symbolic - ref *knownSymbolics; + /// knownSymbolics[byte] holds the expression for byte, + /// if byte is known + mutable SparseStorage, OptionalRefEq> knownSymbolics; /// unflushedMask[byte] is set if byte is unflushed /// mutable because may need flushed during read of const - mutable BitArray *unflushedMask; + mutable SparseStorage unflushedMask; // mutable because we may need flush during read of const mutable UpdateList updates; - bool wasZeroInitialized = true; - ref lastUpdate; + ref size; + KType *dynamicType; public: - unsigned size; - bool readOnly; public: - /// Create a new object state for the given memory object with concrete - /// contents. The initial contents are undefined, it is the callers - /// responsibility to initialize the object contents appropriately. + /// Create a new object state for the given memory + // For objects in memory + ObjectState(const MemoryObject *mo, const Array *array, KType *dt); ObjectState(const MemoryObject *mo, KType *dt); - /// Create a new object state for the given memory object with symbolic - /// contents. - ObjectState(const MemoryObject *mo, const Array *array, KType *dt); - ObjectState(const MemoryObject *mo, const ObjectState &os); + // For symbolic objects not in memory (hack) ObjectState(const ObjectState &os); - ~ObjectState(); + ~ObjectState() = default; const MemoryObject *getObject() const { return object.get(); } void setReadOnly(bool ro) { readOnly = ro; } - /// Make contents all concrete and zero - void initializeToZero(); + size_t getSparseStorageEntries() { + return knownSymbolics.storage().size() + unflushedMask.storage().size(); + } - /// Make contents all concrete and random - void initializeToRandom(); + void swapObjectHack(MemoryObject *mo) { object = mo; } ref read(ref offset, Expr::Width width) const; ref read(unsigned offset, Expr::Width width) const; @@ -267,6 +258,7 @@ class ObjectState { void write(unsigned offset, ref value); void write(ref offset, ref value); + void write(ref os); void write8(unsigned offset, uint8_t value); void write16(unsigned offset, uint16_t value); @@ -274,13 +266,6 @@ class ObjectState { void write64(unsigned offset, uint64_t value); void print() const; - /* - Looks at all the symbolic bytes of this object, gets a value for them - from the solver and puts them in the concreteStore. - */ - void flushToConcreteStore(TimingSolver *solver, - const ExecutionState &state) const; - bool isAccessableFrom(KType *) const; KType *getDynamicType() const; @@ -290,31 +275,12 @@ class ObjectState { void makeConcrete(); - void makeSymbolic(); - ref read8(ref offset) const; void write8(unsigned offset, ref value); void write8(ref offset, ref value); - void fastRangeCheckOffset(ref offset, unsigned *base_r, - unsigned *size_r) const; - void flushRangeForRead(unsigned rangeBase, unsigned rangeSize) const; - void flushRangeForWrite(unsigned rangeBase, unsigned rangeSize); - - /// isByteConcrete ==> !isByteKnownSymbolic - bool isByteConcrete(unsigned offset) const; - - /// isByteKnownSymbolic ==> !isByteConcrete - bool isByteKnownSymbolic(unsigned offset) const; - - /// isByteUnflushed(i) => (isByteConcrete(i) || isByteKnownSymbolic(i)) - bool isByteUnflushed(unsigned offset) const; - - void markByteConcrete(unsigned offset); - void markByteSymbolic(unsigned offset); - void markByteFlushed(unsigned offset); - void markByteUnflushed(unsigned offset); - void setKnownSymbolic(unsigned offset, Expr *value); + void flushForRead() const; + void flushForWrite(); ArrayCache *getArrayCache() const; }; diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp index 30adeb8ce7..f42f798141 100644 --- a/lib/Core/Searcher.cpp +++ b/lib/Core/Searcher.cpp @@ -19,13 +19,13 @@ #include "klee/ADT/DiscretePDF.h" #include "klee/ADT/RNG.h" #include "klee/ADT/WeightedQueue.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" #include "klee/Module/Target.h" #include "klee/Statistics/Statistics.h" #include "klee/Support/ErrorHandling.h" #include "klee/System/Time.h" +#include "klee/Utilities/Math.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -48,8 +48,8 @@ using namespace llvm; ExecutionState &DFSSearcher::selectState() { return *states.back(); } void DFSSearcher::update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) { + const StateIterable &addedStates, + const StateIterable &removedStates) { // insert states states.insert(states.end(), addedStates.begin(), addedStates.end()); @@ -74,8 +74,8 @@ void DFSSearcher::printName(llvm::raw_ostream &os) { os << "DFSSearcher\n"; } ExecutionState &BFSSearcher::selectState() { return *states.front(); } void BFSSearcher::update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) { + const StateIterable &addedStates, + const StateIterable &removedStates) { // update current state // Assumption: If new states were added KLEE forked, therefore states evolved. // constraints were added to the current state, it evolved. @@ -115,9 +115,9 @@ ExecutionState &RandomSearcher::selectState() { return *states[theRNG.getInt32() % states.size()]; } -void RandomSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void RandomSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // insert states states.insert(states.end(), addedStates.begin(), addedStates.end()); @@ -137,21 +137,6 @@ void RandomSearcher::printName(llvm::raw_ostream &os) { /// -static unsigned int ulog2(unsigned int val) { - if (val == 0) - return UINT_MAX; - if (val == 1) - return 0; - unsigned int ret = 0; - while (val > 1) { - val >>= 1; - ret++; - } - return ret; -} - -/// - TargetedSearcher::~TargetedSearcher() {} bool TargetedSearcher::empty() { return states->empty(); } @@ -168,9 +153,9 @@ TargetedSearcher::TargetedSearcher(ref target, ExecutionState &TargetedSearcher::selectState() { return *states->choose(0); } -void TargetedSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void TargetedSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // update current if (current && std::find(removedStates.begin(), removedStates.end(), @@ -190,13 +175,14 @@ weight_type TargetedSearcher::getWeight(ExecutionState *es) { KBlock *kb = es->pc->parent; KInstruction *ki = es->pc; weight_type weight; - if (!target->shouldFailOnThisTarget() && kb->numInstructions && + if (!target->shouldFailOnThisTarget() && kb->getNumInstructions() && !isa(kb) && kb->getFirstInstruction() != ki && states->tryGetWeight(es, weight)) { return weight; } auto distRes = distanceCalculator.getDistance(*es, target->getBlock()); - weight = ulog2(distRes.weight + es->steppedMemoryInstructions + 1); // [0, 32) + weight = klee::util::ulog2(distRes.weight + es->steppedMemoryInstructions + + 1); // [0, 32) if (!distRes.isInsideFunction) { weight += 32; // [32, 64) } @@ -207,12 +193,12 @@ weight_type TargetedSearcher::getWeight(ExecutionState *es) { ExecutionState &GuidedSearcher::selectState() { unsigned size = historiesAndTargets.size(); - index = theRNG.getInt32() % (size + 1); + interleave ^= 1; ExecutionState *state = nullptr; - if (index == size) { + if (interleave || !size) { state = &baseSearcher->selectState(); } else { - index = index % size; + index = theRNG.getInt32() % size; auto &historyTargetPair = historiesAndTargets[index]; ref history = historyTargetPair.first; ref target = historyTargetPair.second; @@ -225,9 +211,9 @@ ExecutionState &GuidedSearcher::selectState() { return *state; } -void GuidedSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void GuidedSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { if (current) { ref history = current->history(); @@ -389,8 +375,8 @@ double WeightedRandomSearcher::getWeight(ExecutionState *es) { case RP: return std::pow(0.5, es->depth); case InstCount: { - uint64_t count = theStatisticManager->getIndexedValue(stats::instructions, - es->pc->info->id); + uint64_t count = theStatisticManager->getIndexedValue( + stats::instructions, es->pc->getGlobalIndex()); double inv = 1. / std::max((uint64_t)1, count); return inv * inv; } @@ -422,9 +408,9 @@ double WeightedRandomSearcher::getWeight(ExecutionState *es) { } } -void WeightedRandomSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void WeightedRandomSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // update current if (current && updateWeights && @@ -515,11 +501,11 @@ ExecutionState &RandomPathSearcher::selectState() { return *n->state; } -void RandomPathSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void RandomPathSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // insert states - for (auto &es : addedStates) { + for (auto es : addedStates) { PTreeNode *pnode = es->ptreeNode, *parent = pnode->parent; PTreeNodePtr &root = processForest.getPTrees().at(pnode->getTreeID())->root; PTreeNodePtr *childPtr; @@ -619,9 +605,9 @@ ExecutionState &BatchingSearcher::selectState() { return *lastState; } -void BatchingSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void BatchingSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // drop memoized state if it is marked for deletion if (std::find(removedStates.begin(), removedStates.end(), lastState) != removedStates.end()) @@ -641,63 +627,106 @@ void BatchingSearcher::printName(llvm::raw_ostream &os) { /// -IterativeDeepeningTimeSearcher::IterativeDeepeningTimeSearcher( - Searcher *baseSearcher) - : baseSearcher{baseSearcher} {}; +class TimeMetric final : public IterativeDeepeningSearcher::Metric { + time::Point startTime; + time::Span time{time::seconds(1)}; + +public: + void selectState() final { startTime = time::getWallTime(); } + bool exceeds(const ExecutionState &state) const final { + return time::getWallTime() - startTime > time; + } + void increaseLimit() final { + time *= 2U; + klee_message("increased time budget to %f seconds", time.toSeconds()); + } +}; + +class MaxCyclesMetric final : public IterativeDeepeningSearcher::Metric { +public: + using ty = unsigned long long; + +private: + ty maxCycles; + +public: + explicit MaxCyclesMetric(ty maxCycles) : maxCycles(maxCycles){}; + explicit MaxCyclesMetric() : MaxCyclesMetric(1ULL){}; + + bool exceeds(const ExecutionState &state) const final { + return state.isCycled(maxCycles); + } + void increaseLimit() final { + maxCycles *= 4ULL; + klee_message("increased max-cycles to %llu", maxCycles); + } +}; + +IterativeDeepeningSearcher::IterativeDeepeningSearcher( + Searcher *baseSearcher, TargetManagerSubscriber *tms, + HaltExecution::Reason m) + : baseSearcher{baseSearcher}, tms{tms} { + switch (m) { + case HaltExecution::Reason::MaxTime: + metric = std::make_unique(); + return; + case HaltExecution::Reason::MaxCycles: + metric = std::make_unique(); + return; + default: + klee_error("Illegal metric for iterative deepening searcher: %d", m); + } +} -ExecutionState &IterativeDeepeningTimeSearcher::selectState() { +ExecutionState &IterativeDeepeningSearcher::selectState() { ExecutionState &res = baseSearcher->selectState(); - startTime = time::getWallTime(); + metric->selectState(); return res; } -void IterativeDeepeningTimeSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void IterativeDeepeningSearcher::update( + const TargetHistoryTargetPairToStatesMap &added, + const TargetHistoryTargetPairToStatesMap &removed) { + if (!tms) + return; + added.setWithout(&pausedStates); + removed.setWithout(&pausedStates); + tms->update(added, removed); + added.clearWithout(); + removed.clearWithout(); +} - const auto elapsed = time::getWallTime() - startTime; +void IterativeDeepeningSearcher::update(ExecutionState *current, + const StateIterable &added, + const StateIterable &removed) { + removed.setWithout(&pausedStates); + baseSearcher->update(current, added, removed); + removed.clearWithout(); - // update underlying searcher (filter paused states unknown to underlying - // searcher) - if (!removedStates.empty()) { - std::vector alt = removedStates; - for (const auto state : removedStates) { - auto it = pausedStates.find(state); - if (it != pausedStates.end()) { - pausedStates.erase(it); - alt.erase(std::remove(alt.begin(), alt.end(), state), alt.end()); - } - } - baseSearcher->update(current, addedStates, alt); - } else { - baseSearcher->update(current, addedStates, removedStates); - } + for (auto state : removed) + pausedStates.erase(state); - // update current: pause if time exceeded if (current && - std::find(removedStates.begin(), removedStates.end(), current) == - removedStates.end() && - elapsed > time) { + std::find(removed.begin(), removed.end(), current) == removed.end() && + metric->exceeds(*current)) { pausedStates.insert(current); baseSearcher->update(nullptr, {}, {current}); } // no states left in underlying searcher: fill with paused states - if (baseSearcher->empty()) { - time *= 2U; - klee_message("increased time budget to %f\n", time.toSeconds()); - std::vector ps(pausedStates.begin(), pausedStates.end()); - baseSearcher->update(nullptr, ps, std::vector()); + if (baseSearcher->empty() && !pausedStates.empty()) { + metric->increaseLimit(); + baseSearcher->update(nullptr, pausedStates, {}); pausedStates.clear(); } } -bool IterativeDeepeningTimeSearcher::empty() { +bool IterativeDeepeningSearcher::empty() { return baseSearcher->empty() && pausedStates.empty(); } -void IterativeDeepeningTimeSearcher::printName(llvm::raw_ostream &os) { - os << "IterativeDeepeningTimeSearcher\n"; +void IterativeDeepeningSearcher::printName(llvm::raw_ostream &os) { + os << "IterativeDeepeningSearcher\n"; } /// @@ -716,9 +745,9 @@ ExecutionState &InterleavedSearcher::selectState() { return s->selectState(); } -void InterleavedSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void InterleavedSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // update underlying searchers for (auto &searcher : searchers) diff --git a/lib/Core/Searcher.h b/lib/Core/Searcher.h index 0a6c734f73..f0b7e8d2b5 100644 --- a/lib/Core/Searcher.h +++ b/lib/Core/Searcher.h @@ -63,9 +63,8 @@ class Searcher { /// \param current The currently selected state for exploration. /// \param addedStates The newly branched states with `current` as common /// ancestor. \param removedStates The states that will be terminated. - virtual void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) = 0; + virtual void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) = 0; /// \return True if no state left for exploration, False otherwise virtual bool empty() = 0; @@ -96,9 +95,8 @@ class DFSSearcher final : public Searcher { public: ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -112,9 +110,8 @@ class BFSSearcher final : public Searcher { public: ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -127,9 +124,8 @@ class RandomSearcher final : public Searcher { public: explicit RandomSearcher(RNG &rng); ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -148,9 +144,8 @@ class TargetedSearcher final : public Searcher { ~TargetedSearcher() override; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -160,17 +155,10 @@ class GuidedSearcher final : public Searcher, public TargetManagerSubscriber { using TargetHistoryTargetPairHashMap = std::unordered_map; - - using TargetHistoryTargetPair = - std::pair, ref>; using TargetHistoryTargetPairToSearcherMap = std::unordered_map, TargetHistoryTargetHash, TargetHistoryTargetCmp>; - using StatesVector = std::vector; - using TargetHistoryTargetPairToStatesMap = - std::unordered_map; using TargetForestHisoryTargetVector = std::vector; using TargetForestHistoryTargetSet = std::unordered_set baseAddedStates; @@ -204,9 +193,8 @@ class GuidedSearcher final : public Searcher, public TargetManagerSubscriber { theRNG(rng) {} ~GuidedSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; void update(const TargetHistoryTargetPairToStatesMap &added, const TargetHistoryTargetPairToStatesMap &removed) override; void updateTargets(ExecutionState *current); @@ -245,9 +233,8 @@ class WeightedRandomSearcher final : public Searcher { ~WeightedRandomSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -282,9 +269,8 @@ class RandomPathSearcher final : public Searcher { ~RandomPathSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -316,33 +302,45 @@ class BatchingSearcher final : public Searcher { ~BatchingSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; -/// IterativeDeepeningTimeSearcher implements time-based deepening. States -/// are selected from an underlying searcher. When a state reaches its time -/// limit it is paused (removed from underlying searcher). When the underlying -/// searcher runs out of states, the time budget is increased and all paused +/// IterativeDeepeningSearcher implements a metric-based deepening. States +/// are selected from an underlying searcher. When a state exceeds its metric +/// limit, it is paused (removed from underlying searcher). When the underlying +/// searcher runs out of states, the metric limit is increased and all paused /// states are revived (added to underlying searcher). -class IterativeDeepeningTimeSearcher final : public Searcher { +class IterativeDeepeningSearcher final : public Searcher, + public TargetManagerSubscriber { +public: + struct Metric { + virtual ~Metric() = default; + virtual void selectState(){}; + virtual bool exceeds(const ExecutionState &state) const = 0; + virtual void increaseLimit() = 0; + }; + +private: std::unique_ptr baseSearcher; - time::Point startTime; - time::Span time{time::seconds(1)}; + TargetManagerSubscriber *tms; + std::unique_ptr metric; std::set pausedStates; public: /// \param baseSearcher The underlying searcher (takes ownership). - explicit IterativeDeepeningTimeSearcher(Searcher *baseSearcher); - ~IterativeDeepeningTimeSearcher() override = default; + explicit IterativeDeepeningSearcher(Searcher *baseSearcher, + TargetManagerSubscriber *tms, + HaltExecution::Reason metric); + ~IterativeDeepeningSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; + void update(const TargetHistoryTargetPairToStatesMap &added, + const TargetHistoryTargetPairToStatesMap &removed) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -360,9 +358,8 @@ class InterleavedSearcher final : public Searcher { ~InterleavedSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; diff --git a/lib/Core/SeedInfo.cpp b/lib/Core/SeedInfo.cpp index 143baae61e..bea2a646a8 100644 --- a/lib/Core/SeedInfo.cpp +++ b/lib/Core/SeedInfo.cpp @@ -107,7 +107,9 @@ void SeedInfo::patchSeed(const ExecutionState &state, ref condition, solver->getValue(required, read, value, state.queryMetaData); assert(success && "FIXME: Unhandled solver failure"); (void)success; - it2->second.store(i, value->getZExtValue(8)); + auto s = it2->second; + s.store(i, value->getZExtValue(8)); + assignment.bindings.replace({it2->first, s}); required.addConstraint( EqExpr::create( read, ConstantExpr::alloc(it2->second.load(i), Expr::Int8)), @@ -151,7 +153,9 @@ void SeedInfo::patchSeed(const ExecutionState &state, ref condition, solver->getValue(required, read, value, state.queryMetaData); assert(success && "FIXME: Unhandled solver failure"); (void)success; - it->second.store(i, value->getZExtValue(8)); + auto s = it->second; + s.store(i, value->getZExtValue(8)); + assignment.bindings.replace({it->first, s}); required.addConstraint( EqExpr::create(read, ConstantExpr::alloc(it->second.load(i), Expr::Int8)), diff --git a/lib/Core/SeedInfo.h b/lib/Core/SeedInfo.h index a513665fdb..ee84133bc3 100644 --- a/lib/Core/SeedInfo.h +++ b/lib/Core/SeedInfo.h @@ -32,8 +32,7 @@ class SeedInfo { std::set used; public: - explicit SeedInfo(KTest *_input) - : assignment(true), input(_input), inputPosition(0) {} + explicit SeedInfo(KTest *_input) : input(_input), inputPosition(0) {} KTestObject *getNextInput(const MemoryObject *mo, bool byName); diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index 1d3e07b85f..a9d7457a88 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -734,7 +734,8 @@ void SpecialFunctionHandler::handleErrnoLocation( "invalid number of arguments to __errno_location/__error"); #ifndef WINDOWS - int *errno_addr = executor.getErrnoLocation(state); + // int *errno_addr = executor.getErrnoLocation(state); + int *errno_addr = executor.errno_addr; #else int *errno_addr = nullptr; #endif @@ -920,7 +921,7 @@ void SpecialFunctionHandler::handleMakeSymbolic( assert(success && "FIXME: Unhandled solver failure"); if (res) { - uint64_t sid = 0; + uint64_t sid = 0; // TODO: unused variable if (state.arrayNames.count(name)) { sid = state.arrayNames[name]; } diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp index 372c6fc61b..c2b9b4769d 100644 --- a/lib/Core/StatsTracker.cpp +++ b/lib/Core/StatsTracker.cpp @@ -13,9 +13,9 @@ #include "klee/Config/Version.h" #include "klee/Core/TerminationTypes.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Solver/SolverStats.h" #include "klee/Statistics/Statistics.h" #include "klee/Support/ErrorHandling.h" @@ -233,27 +233,25 @@ StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename, } if (useStatistics() || userSearcherRequiresMD2U()) - theStatisticManager->useIndexedStats(km->infos->getMaxID()); + theStatisticManager->useIndexedStats(km->getMaxGlobalIndex()); for (auto &kfp : km->functions) { KFunction *kf = kfp.get(); - kf->trackCoverage = 1; for (unsigned i = 0; i < kf->numInstructions; ++i) { KInstruction *ki = kf->instructions[i]; if (OutputIStats) { - unsigned id = ki->info->id; + unsigned id = ki->getGlobalIndex(); theStatisticManager->setIndex(id); - if (kf->trackCoverage && instructionIsCoverable(ki->inst)) + if (instructionIsCoverable(ki->inst)) { ++stats::uncoveredInstructions; + } } - if (kf->trackCoverage) { - if (BranchInst *bi = dyn_cast(ki->inst)) - if (!bi->isUnconditional()) - numBranches++; - } + if (BranchInst *bi = dyn_cast(ki->inst)) + if (!bi->isUnconditional()) + numBranches++; } } @@ -393,25 +391,24 @@ void StatsTracker::stepInstruction(ExecutionState &es) { } Instruction *inst = es.pc->inst; - const InstructionInfo &ii = *es.pc->info; - InfoStackFrame &sf = es.stack.infoStack().back(); - theStatisticManager->setIndex(ii.id); + const KInstruction *ki = es.pc; + auto &sf = es.stack.infoStack().back(); + theStatisticManager->setIndex(ki->getGlobalIndex()); if (UseCallPaths) theStatisticManager->setContext(&sf.callPathNode->statistics); if (es.instsSinceCovNew) ++es.instsSinceCovNew; - if (sf.kf->trackCoverage && instructionIsCoverable(inst)) { + if (instructionIsCoverable(inst)) { if (!theStatisticManager->getIndexedValue(stats::coveredInstructions, - ii.id)) { + ki->getGlobalIndex())) { // Checking for actual stoppoints avoids inconsistencies due // to line number propogation. // // FIXME: This trick no longer works, we should fix this in the line // number propogation. - es.coveredLines[&ii.file].insert(ii.line); - es.coveredNew = true; + es.coveredLines[ki->getSourceFilepath()].insert(ki->getLine()); es.instsSinceCovNew = 1; ++stats::coveredInstructions; stats::uncoveredInstructions += (uint64_t)-1; @@ -480,7 +477,6 @@ void StatsTracker::markBranchVisited(ExecutionState *visitedTrue, uint64_t hasFalse = theStatisticManager->getIndexedValue(stats::falseBranches, id); if (visitedTrue && !hasTrue) { - visitedTrue->coveredNew = true; visitedTrue->instsSinceCovNew = 1; ++stats::trueBranches; if (hasFalse) { @@ -491,7 +487,6 @@ void StatsTracker::markBranchVisited(ExecutionState *visitedTrue, hasTrue = 1; } if (visitedFalse && !hasFalse) { - visitedFalse->coveredNew = true; visitedFalse->instsSinceCovNew = 1; ++stats::falseBranches; if (hasTrue) { @@ -698,8 +693,8 @@ void StatsTracker::updateStateStatistics(uint64_t addend) { ie = executor.states.end(); it != ie; ++it) { ExecutionState &state = **it; - const InstructionInfo &ii = *state.pc->info; - theStatisticManager->incrementIndexedValue(stats::states, ii.id, addend); + theStatisticManager->incrementIndexedValue( + stats::states, state.pc->getGlobalIndex(), addend); if (UseCallPaths) state.stack.infoStack().back().callPathNode->statistics.incrementValue( stats::states, addend); @@ -768,66 +763,70 @@ void StatsTracker::writeIStats() { of << "ob=" << llvm::sys::path::filename(objectFilename).str() << "\n"; - for (Module::iterator fnIt = m->begin(), fn_ie = m->end(); fnIt != fn_ie; - ++fnIt) { - if (!fnIt->isDeclaration()) { + for (auto &fn : *m) { + if (!fn.isDeclaration()) { // Always try to write the filename before the function name, as otherwise // KCachegrind can create two entries for the function, one with an // unnamed file and one without. - Function *fn = &*fnIt; - const FunctionInfo &ii = executor.kmodule->infos->getFunctionInfo(*fn); - if (ii.file != sourceFile) { - of << "fl=" << ii.file << "\n"; - sourceFile = ii.file; + auto fnlFile = getLocationInfo(&fn).file; + if (fnlFile != sourceFile) { + of << "fl=" << fnlFile << "\n"; + sourceFile = fnlFile; } - of << "fn=" << fnIt->getName().str() << "\n"; - for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); - bbIt != bb_ie; ++bbIt) { - for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); - it != ie; ++it) { - Instruction *instr = &*it; - const InstructionInfo &ii = executor.kmodule->infos->getInfo(*instr); - unsigned index = ii.id; - if (ii.file != sourceFile) { - of << "fl=" << ii.file << "\n"; - sourceFile = ii.file; + of << "fn=" << fn.getName().str() << "\n"; + for (auto &bb : fn) { + for (auto &instr : bb) { + Instruction *instrPtr = &instr; + + auto instrLI = getLocationInfo(instrPtr); + + unsigned index = executor.kmodule->getGlobalIndex(instrPtr); + if (instrLI.file != sourceFile) { + of << "fl=" << instrLI.file << "\n"; + sourceFile = instrLI.file; } - assert(ii.assemblyLine.hasValue()); - of << ii.assemblyLine.getValue() << " "; + { + auto asmLine = executor.kmodule->getAsmLine(instrPtr); + assert(asmLine.has_value()); + of << asmLine.value() << " "; + } - of << ii.line << " "; + of << instrLI.line << " "; for (unsigned i = 0; i < nStats; i++) if (istatsMask.test(i)) of << sm.getIndexedValue(sm.getStatistic(i), index) << " "; of << "\n"; if (UseCallPaths && - (isa(instr) || isa(instr))) { - CallSiteSummaryTable::iterator it = callSiteStats.find(instr); + (isa(instrPtr) || isa(instrPtr))) { + CallSiteSummaryTable::iterator it = callSiteStats.find(instrPtr); if (it != callSiteStats.end()) { - for (auto fit = it->second.begin(), fie = it->second.end(); - fit != fie; ++fit) { - const Function *f = fit->first; - CallSiteInfo &csi = fit->second; - const FunctionInfo &fii = - executor.kmodule->infos->getFunctionInfo(*f); - - if (fii.file != "" && fii.file != sourceFile) - of << "cfl=" << fii.file << "\n"; + for (auto &fit : it->second) { + const Function *f = fit.first; + CallSiteInfo &csi = fit.second; + auto fli = getLocationInfo(f); + if (fli.file != "" && fli.file != sourceFile) + of << "cfl=" << fli.file << "\n"; of << "cfn=" << f->getName().str() << "\n"; of << "calls=" << csi.count << " "; - assert(fii.assemblyLine.hasValue()); - of << fii.assemblyLine.getValue() << " "; + { + auto asmLine = executor.kmodule->getAsmLine(f); + assert(asmLine.has_value()); + of << asmLine.value() << " "; + } - of << fii.line << "\n"; + of << fli.line << "\n"; - assert(ii.assemblyLine.hasValue()); - of << ii.assemblyLine.getValue() << " "; + { + auto asmLine = executor.kmodule->getAsmLine(instrPtr); + assert(asmLine.has_value()); + of << asmLine.value() << " "; + } - of << ii.line << " "; + of << instrLI.line << " "; for (unsigned i = 0; i < nStats; i++) { if (istatsMask.test(i)) { Statistic &s = sm.getStatistic(i); @@ -892,12 +891,12 @@ uint64_t klee::computeMinDistToUncovered(const KInstruction *ki, uint64_t minDistAtRA) { StatisticManager &sm = *theStatisticManager; if (minDistAtRA == 0) { // unreachable on return, best is local - return sm.getIndexedValue(stats::minDistToUncovered, ki->info->id); + return sm.getIndexedValue(stats::minDistToUncovered, ki->getGlobalIndex()); } else { uint64_t minDistLocal = - sm.getIndexedValue(stats::minDistToUncovered, ki->info->id); + sm.getIndexedValue(stats::minDistToUncovered, ki->getGlobalIndex()); uint64_t distToReturn = - sm.getIndexedValue(stats::minDistToReturn, ki->info->id); + sm.getIndexedValue(stats::minDistToReturn, ki->getGlobalIndex()); if (distToReturn == 0) { // return unreachable, best is local return minDistLocal; @@ -913,7 +912,6 @@ void StatsTracker::computeReachableUncovered() { KModule *km = executor.kmodule.get(); const auto m = km->module.get(); static bool init = true; - const InstructionInfoTable &infos = *km->infos; StatisticManager &sm = *theStatisticManager; if (init) { @@ -976,11 +974,10 @@ void StatsTracker::computeReachableUncovered() { // Not sure if I should bother to preorder here. XXX I should. for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); bbIt != bb_ie; ++bbIt) { - for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); - it != ie; ++it) { - Instruction *inst = &*it; + for (auto &it : *bbIt) { + Instruction *inst = ⁢ instructions.push_back(inst); - unsigned id = infos.getInfo(*inst).id; + unsigned id = km->getGlobalIndex(inst); sm.setIndexedValue(stats::minDistToReturn, id, isa(inst)); } } @@ -992,9 +989,8 @@ void StatsTracker::computeReachableUncovered() { bool changed; do { changed = false; - for (auto it = instructions.begin(), ie = instructions.end(); it != ie; - ++it) { - Instruction *inst = *it; + for (auto &instruction : instructions) { + Instruction *inst = instruction; unsigned bestThrough = 0; if (isa(inst) || isa(inst)) { @@ -1014,15 +1010,15 @@ void StatsTracker::computeReachableUncovered() { } if (bestThrough) { - unsigned id = infos.getInfo(*(*it)).id; + unsigned id = km->getGlobalIndex(instruction); uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToReturn, id); - std::vector succs = getSuccs(*it); + std::vector succs = getSuccs(instruction); for (std::vector::iterator it2 = succs.begin(), ie = succs.end(); it2 != ie; ++it2) { uint64_t dist = sm.getIndexedValue(stats::minDistToReturn, - infos.getInfo(*(*it2)).id); + km->getGlobalIndex(*it2)); if (dist) { uint64_t val = bestThrough + dist; if (best == 0 || val < best) @@ -1058,7 +1054,7 @@ void StatsTracker::computeReachableUncovered() { for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); it != ie; ++it) { Instruction *inst = &*it; - unsigned id = infos.getInfo(*inst).id; + unsigned id = km->getGlobalIndex(inst); instructions.push_back(inst); sm.setIndexedValue( stats::minDistToUncovered, id, @@ -1073,29 +1069,24 @@ void StatsTracker::computeReachableUncovered() { bool changed; do { changed = false; - for (std::vector::iterator it = instructions.begin(), - ie = instructions.end(); - it != ie; ++it) { - Instruction *inst = *it; + for (auto inst : instructions) { uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToUncovered, - infos.getInfo(*inst).id); + km->getGlobalIndex(inst)); unsigned bestThrough = 0; if (isa(inst) || isa(inst)) { std::vector &targets = callTargets[inst]; - for (std::vector::iterator fnIt = targets.begin(), - ie = targets.end(); - fnIt != ie; ++fnIt) { - uint64_t dist = functionShortestPath[*fnIt]; + for (auto &target : targets) { + uint64_t dist = functionShortestPath[target]; if (dist) { dist = 1 + dist; // count instruction itself if (bestThrough == 0 || dist < bestThrough) bestThrough = dist; } - if (!(*fnIt)->isDeclaration()) { + if (!target->isDeclaration()) { uint64_t calleeDist = sm.getIndexedValue( - stats::minDistToUncovered, infos.getFunctionInfo(*(*fnIt)).id); + stats::minDistToUncovered, km->getGlobalIndex(target)); if (calleeDist) { calleeDist = 1 + calleeDist; // count instruction itself if (best == 0 || calleeDist < best) @@ -1109,11 +1100,9 @@ void StatsTracker::computeReachableUncovered() { if (bestThrough) { std::vector succs = getSuccs(inst); - for (std::vector::iterator it2 = succs.begin(), - ie = succs.end(); - it2 != ie; ++it2) { + for (auto &succ : succs) { uint64_t dist = sm.getIndexedValue(stats::minDistToUncovered, - infos.getInfo(*(*it2)).id); + km->getGlobalIndex(succ)); if (dist) { uint64_t val = bestThrough + dist; if (best == 0 || val < best) @@ -1123,7 +1112,7 @@ void StatsTracker::computeReachableUncovered() { } if (best != cur) { - sm.setIndexedValue(stats::minDistToUncovered, infos.getInfo(*inst).id, + sm.setIndexedValue(stats::minDistToUncovered, km->getGlobalIndex(inst), best); changed = true; } diff --git a/lib/Core/StatsTracker.h b/lib/Core/StatsTracker.h index be0f39ae5b..52a85d560c 100644 --- a/lib/Core/StatsTracker.h +++ b/lib/Core/StatsTracker.h @@ -27,7 +27,6 @@ class raw_fd_ostream; namespace klee { class ExecutionState; class Executor; -class InstructionInfoTable; class InterpreterHandler; struct KInstruction; struct InfoStackFrame; diff --git a/lib/Core/TargetCalculator.cpp b/lib/Core/TargetCalculator.cpp index c2340e4af2..36c23a9026 100644 --- a/lib/Core/TargetCalculator.cpp +++ b/lib/Core/TargetCalculator.cpp @@ -11,7 +11,7 @@ #include "ExecutionState.h" -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" #include "klee/Module/Target.h" #include "klee/Module/TargetHash.h" @@ -22,120 +22,157 @@ using namespace llvm; using namespace klee; -namespace klee { -llvm::cl::opt TargetCalculatorMode( - "target-calculator-kind", cl::desc("Specifiy the target calculator mode."), - cl::values( - clEnumValN(TargetCalculateBy::Default, "default", - "Looks for the closest uncovered block."), - clEnumValN( - TargetCalculateBy::Blocks, "blocks", - "Looks for the closest uncovered block by state blocks history."), - clEnumValN(TargetCalculateBy::Transitions, "transitions", - "Looks for the closest uncovered block by state transitions " - "history.")), - cl::init(TargetCalculateBy::Default), cl::cat(ExecCat)); -} // namespace klee +llvm::cl::opt TrackCoverage( + "track-coverage", cl::desc("Specifiy the track coverage mode."), + cl::values(clEnumValN(TrackCoverageBy::None, "none", "Not track coverage."), + clEnumValN(TrackCoverageBy::Blocks, "blocks", + "Track only covered block."), + clEnumValN(TrackCoverageBy::Branches, "branches", + "Track only covered conditional branches."), + clEnumValN(TrackCoverageBy::All, "all", "Track all.")), + cl::init(TrackCoverageBy::None), cl::cat(ExecCat)); void TargetCalculator::update(const ExecutionState &state) { Function *initialFunction = state.getInitPCBlock()->getParent(); - switch (TargetCalculatorMode) { - case TargetCalculateBy::Default: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.getInitPCBlock()); - if (state.prevPC == state.prevPC->parent->getLastInstruction()) { - coveredBlocks[state.getPrevPCBlock()->getParent()].insert( - state.getPrevPCBlock()); + + if (state.prevPC == state.prevPC->parent->getLastInstruction() && + !fullyCoveredFunctions.count(state.prevPC->parent->parent)) { + auto &fBranches = getCoverageTargets(state.prevPC->parent->parent); + + if (!coveredFunctionsInBranches.count(state.prevPC->parent->parent)) { + if (fBranches.count(state.prevPC->parent) != 0) { + if (!coveredBranches[state.prevPC->parent->parent].count( + state.prevPC->parent)) { + state.coverNew(); + coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; + } + if (!fBranches.at(state.prevPC->parent).empty()) { + unsigned index = 0; + for (auto succ : successors(state.getPrevPCBlock())) { + if (succ == state.getPCBlock()) { + if (!coveredBranches[state.prevPC->parent->parent] + [state.prevPC->parent] + .count(index)) { + state.coverNew(); + coveredBranches[state.prevPC->parent->parent] + [state.prevPC->parent] + .insert(index); + } + break; + } + ++index; + } + } + } + if (getCoverageTargets(state.prevPC->parent->parent) == + coveredBranches[state.prevPC->parent->parent]) { + coveredFunctionsInBranches.insert(state.prevPC->parent->parent); + } } - if (state.prevPC == state.prevPC->parent->getLastInstruction()) { - unsigned index = 0; - coveredBranches[state.getPrevPCBlock()->getParent()] - [state.getPrevPCBlock()]; - for (auto succ : successors(state.getPrevPCBlock())) { - if (succ == state.getPCBlock()) { - coveredBranches[state.getPrevPCBlock()->getParent()] - [state.getPrevPCBlock()] - .insert(index); - break; + if (!fullyCoveredFunctions.count(state.prevPC->parent->parent) && + coveredFunctionsInBranches.count(state.prevPC->parent->parent)) { + bool covered = true; + std::set fnsTaken; + std::deque fns; + fns.push_back(state.prevPC->parent->parent); + + while (!fns.empty() && covered) { + KFunction *currKF = fns.front(); + fnsTaken.insert(currKF); + for (auto &kcallBlock : currKF->kCallBlocks) { + if (kcallBlock->calledFunctions.size() == 1) { + auto calledFunction = *kcallBlock->calledFunctions.begin(); + KFunction *calledKFunction = state.prevPC->parent->parent->parent + ->functionMap[calledFunction]; + if (calledKFunction->numInstructions != 0 && + coveredFunctionsInBranches.count(calledKFunction) == 0 && + !getCoverageTargets(calledKFunction).empty()) { + covered = false; + break; + } + if (!fnsTaken.count(calledKFunction) && + fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions != 0) { + fns.push_back(calledKFunction); + } + } } - ++index; + fns.pop_front(); + } + + if (covered) { + fullyCoveredFunctions.insert(state.prevPC->parent->parent); } } - break; - - case TargetCalculateBy::Blocks: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.level.begin(), state.level.end()); - break; - - case TargetCalculateBy::Transitions: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.level.begin(), state.level.end()); - transitionsHistory[initialFunction][state.getPrevPCBlock()].insert( - state.transitionLevel.begin(), state.transitionLevel.end()); - break; } } -bool TargetCalculator::differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target) { - std::vector diff; - std::set left(state.level.begin(), state.level.end()); - std::set right(history.at(target->basicBlock).begin(), - history.at(target->basicBlock).end()); - std::set_difference(left.begin(), left.end(), right.begin(), right.end(), - std::inserter(diff, diff.begin())); - return diff.empty(); +void TargetCalculator::update( + ExecutionState *current, const std::vector &addedStates, + const std::vector &removedStates) { + if (current && (std::find(removedStates.begin(), removedStates.end(), + current) == removedStates.end())) { + localStates.insert(current); + } + for (const auto state : addedStates) { + localStates.insert(state); + } + for (const auto state : removedStates) { + localStates.insert(state); + } + for (auto state : localStates) { + KFunction *kf = state->prevPC->parent->parent; + KModule *km = kf->parent; + if (state->prevPC->inst->isTerminator() && + km->inMainModule(*kf->function)) { + update(*state); + } + } + localStates.clear(); } -bool TargetCalculator::differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target) { - std::vector diff; - std::set left(state.transitionLevel.begin(), - state.transitionLevel.end()); - std::set right(history.at(target->basicBlock).begin(), - history.at(target->basicBlock).end()); - std::set_difference(left.begin(), left.end(), right.begin(), right.end(), - std::inserter(diff, diff.begin())); - return diff.empty(); +const std::map> & +TargetCalculator::getCoverageTargets(KFunction *kf) { + switch (TrackCoverage) { + case TrackCoverageBy::Blocks: + return codeGraphInfo.getFunctionBlocks(kf); + case TrackCoverageBy::Branches: + return codeGraphInfo.getFunctionConditionalBranches(kf); + case TrackCoverageBy::None: + case TrackCoverageBy::All: + return codeGraphInfo.getFunctionBranches(kf); + + default: + assert(0 && "not implemented"); + } } bool TargetCalculator::uncoveredBlockPredicate(ExecutionState *state, KBlock *kblock) { Function *initialFunction = state->getInitPCBlock()->getParent(); - std::unordered_map &history = - blocksHistory[initialFunction]; - std::unordered_map - &transitionHistory = transitionsHistory[initialFunction]; bool result = false; - switch (TargetCalculatorMode) { - case TargetCalculateBy::Default: { - if (coveredBranches[kblock->parent->function].count(kblock->basicBlock) == - 0) { + + auto &fBranches = getCoverageTargets(kblock->parent); + + if (fBranches.count(kblock) != 0 || isa(kblock)) { + if (coveredBranches[kblock->parent].count(kblock) == 0) { result = true; } else { - auto &cb = coveredBranches[kblock->parent->function][kblock->basicBlock]; - result = - kblock->basicBlock->getTerminator()->getNumSuccessors() > cb.size(); - } - break; - } - case TargetCalculateBy::Blocks: { - if (history[kblock->basicBlock].size() != 0) { - result = !differenceIsEmpty(*state, history, kblock); - } - break; - } - case TargetCalculateBy::Transitions: { - if (history[kblock->basicBlock].size() != 0) { - result = !differenceIsEmpty(*state, transitionHistory, kblock); + auto &cb = coveredBranches[kblock->parent][kblock]; + if (isa(kblock) && + cast(kblock)->calledFunctions.size() == 1) { + auto calledFunction = + *cast(kblock)->calledFunctions.begin(); + KFunction *calledKFunction = + kblock->parent->parent->functionMap[calledFunction]; + result = fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions; + } + if (fBranches.at(kblock) != cb) { + result |= + kblock->basicBlock->getTerminator()->getNumSuccessors() > cb.size(); + } } - break; - } } return result; @@ -146,6 +183,10 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { const KModule &module = *state.pc->parent->parent->parent; KFunction *kf = module.functionMap.at(bb->getParent()); KBlock *kb = kf->blockMap[bb]; + kb = !isa(kb) || (kb->getLastInstruction() != state.pc) + ? kb + : kf->blockMap[state.pc->parent->basicBlock->getTerminator() + ->getSuccessor(0)]; for (auto sfi = state.stack.callStack().rbegin(), sfe = state.stack.callStack().rend(); sfi != sfe; sfi++) { @@ -155,32 +196,62 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { using std::placeholders::_1; KBlockPredicate func = std::bind(&TargetCalculator::uncoveredBlockPredicate, this, &state, _1); - codeGraphDistance.getNearestPredicateSatisfying(kb, func, blocks); + codeGraphInfo.getNearestPredicateSatisfying(kb, func, blocks); if (!blocks.empty()) { TargetHashSet targets; for (auto block : blocks) { - if (coveredBranches[block->parent->function].count(block->basicBlock) == - 0) { - targets.insert(ReachBlockTarget::create(block, true)); - } else { - auto &cb = - coveredBranches[block->parent->function][block->basicBlock]; - for (unsigned index = 0; - index < block->basicBlock->getTerminator()->getNumSuccessors(); - ++index) { - if (!cb.count(index)) - targets.insert(CoverBranchTarget::create(block, index)); + auto &fBranches = getCoverageTargets(block->parent); + + if (fBranches.count(block) != 0 || isa(block)) { + if (coveredBranches[block->parent].count(block) == 0) { + targets.insert(ReachBlockTarget::create(block, false)); + } else { + auto &cb = coveredBranches[block->parent][block]; + bool notCoveredFunction = false; + if (isa(block) && + cast(block)->calledFunctions.size() == 1) { + auto calledFunction = + *cast(block)->calledFunctions.begin(); + KFunction *calledKFunction = + block->parent->parent->functionMap[calledFunction]; + notCoveredFunction = + fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions; + } + if (notCoveredFunction) { + targets.insert(ReachBlockTarget::create(block, true)); + } else { + if (fBranches.at(block) != cb) { + for (unsigned index = 0; + index < + block->basicBlock->getTerminator()->getNumSuccessors(); + ++index) { + if (!cb.count(index)) + targets.insert(CoverBranchTarget::create(block, index)); + } + } + } } } } + assert(!targets.empty()); return targets; } if (sfi->caller) { kb = sfi->caller->parent; + + kb = !isa(kb) || (kb->getLastInstruction() != sfi->caller) + ? kb + : kf->blockMap[sfi->caller->parent->basicBlock->getTerminator() + ->getSuccessor(0)]; } } return {}; } + +bool TargetCalculator::isCovered(KFunction *kf) const { + return fullyCoveredFunctions.count(kf) != 0; +} diff --git a/lib/Core/TargetCalculator.h b/lib/Core/TargetCalculator.h index 7369519afd..f337b879fd 100644 --- a/lib/Core/TargetCalculator.h +++ b/lib/Core/TargetCalculator.h @@ -32,60 +32,50 @@ DISABLE_WARNING_POP #include namespace klee { -class CodeGraphDistance; +class CodeGraphInfo; class ExecutionState; -struct TransitionHash; -enum TargetCalculateBy { Default, Blocks, Transitions }; +enum class TrackCoverageBy { None, Blocks, Branches, All }; -typedef std::pair Transition; typedef std::pair Branch; class TargetCalculator { - typedef std::unordered_set VisitedBlocks; - typedef std::unordered_set VisitedTransitions; + using StatesSet = std::unordered_set; + + typedef std::unordered_set VisitedBlocks; typedef std::unordered_set VisitedBranches; enum HistoryKind { Blocks, Transitions }; - typedef std::unordered_map< - llvm::Function *, std::unordered_map> - BlocksHistory; - typedef std::unordered_map< - llvm::Function *, - std::unordered_map> - TransitionsHistory; - - typedef std::unordered_map< - llvm::Function *, - std::unordered_map>> + typedef std::unordered_map>> CoveredBranches; - typedef std::unordered_map CoveredBlocks; + typedef std::unordered_set CoveredFunctionsBranches; + + void update(const ExecutionState &state); public: - TargetCalculator(CodeGraphDistance &codeGraphDistance) - : codeGraphDistance(codeGraphDistance) {} + TargetCalculator(CodeGraphInfo &codeGraphInfo) + : codeGraphInfo(codeGraphInfo) {} - void update(const ExecutionState &state); + void update(ExecutionState *current, + const std::vector &addedStates, + const std::vector &removedStates); TargetHashSet calculate(ExecutionState &state); + bool isCovered(KFunction *kf) const; + private: - CodeGraphDistance &codeGraphDistance; - BlocksHistory blocksHistory; - TransitionsHistory transitionsHistory; + CodeGraphInfo &codeGraphInfo; CoveredBranches coveredBranches; - CoveredBlocks coveredBlocks; - - bool differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target); - bool differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target); + CoveredFunctionsBranches coveredFunctionsInBranches; + CoveredFunctionsBranches fullyCoveredFunctions; + StatesSet localStates; + + const std::map> & + getCoverageTargets(KFunction *kf); bool uncoveredBlockPredicate(ExecutionState *state, KBlock *kblock); }; diff --git a/lib/Core/TargetManager.cpp b/lib/Core/TargetManager.cpp index 58579130fb..9dcaedcd86 100644 --- a/lib/Core/TargetManager.cpp +++ b/lib/Core/TargetManager.cpp @@ -41,7 +41,11 @@ void TargetManager::updateDone(ExecutionState &state, ref target) { setHistory(state, stateTargetForest.getHistory()); if (guidance == Interpreter::GuidanceKind::CoverageGuidance || target->shouldFailOnThisTarget()) { - reachedTargets.insert(target); + if (target->shouldFailOnThisTarget() || + !isa(target->getBlock())) { + reachedTargets.insert(target); + } + for (auto es : states) { if (isTargeted(*es)) { auto &esTargetForest = targetForest(*es); @@ -112,7 +116,7 @@ void TargetManager::updateReached(ExecutionState &state) { if (state.getPrevPCBlock()->getTerminator()->getNumSuccessors() == 0) { target = ReachBlockTarget::create(state.prevPC->parent, true); - } else { + } else if (!isa(state.prevPC->parent)) { unsigned index = 0; for (auto succ : successors(state.getPrevPCBlock())) { if (succ == state.getPCBlock()) { @@ -270,9 +274,23 @@ bool TargetManager::isReachedTarget(const ExecutionState &state, } if (target->shouldFailOnThisTarget()) { - if (state.pc->parent == target->getBlock()) { - if (cast(target)->isTheSameAsIn(state.prevPC) && - cast(target)->isThatError(state.error)) { + bool found = true; + auto possibleInstruction = state.prevPC; + int i = state.stack.size() - 1; + + while (!cast(target)->isTheSameAsIn( + possibleInstruction)) { // TODO: target->getBlock() == + // possibleInstruction should also be checked, + // but more smartly + if (i <= 0) { + found = false; + break; + } + possibleInstruction = state.stack.callStack().at(i).caller; + i--; + } + if (found) { + if (cast(target)->isThatError(state.error)) { result = Done; } else { result = Continue; diff --git a/lib/Core/TargetManager.h b/lib/Core/TargetManager.h index 3d3188b1f6..ba2dea9ab3 100644 --- a/lib/Core/TargetManager.h +++ b/lib/Core/TargetManager.h @@ -25,15 +25,131 @@ namespace klee { class TargetCalculator; -class TargetManagerSubscriber { +using TargetHistoryTargetPair = + std::pair, ref>; +using StatesVector = std::vector; +using StateSet = std::set; + +class StateIterable final { +private: + using v = ExecutionState *; + const StatesVector *self; + mutable const StateSet *without = nullptr; + using vec_it = StatesVector::const_iterator; + bool shouldDestruct; + + class it : public std::iterator { + vec_it self; + const vec_it ie; + const StateSet *without = nullptr; + void goUntilRealNode() { + if (!without) + return; + for (; self != ie; self++) { + if (!without->count(*self)) + return; + } + } + + public: + it(vec_it i, vec_it ie, const StateSet *without) + : self(i), ie(ie), without(without) { + goUntilRealNode(); + } + bool operator==(const it &other) const noexcept { + return self == other.self; + }; + bool operator!=(const it &other) const noexcept { + return self != other.self; + }; + it &operator++() noexcept { + if (self != ie) { + self++; + goUntilRealNode(); + } + return *this; + } + v operator*() const noexcept { return *self; } + }; + +public: + StateIterable() : self(new StatesVector()), shouldDestruct(true) {} + StateIterable(v s) : self(new StatesVector({s})), shouldDestruct(true) {} + StateIterable(const StatesVector &v, const StateSet *without) + : self(&v), without(without), shouldDestruct(false) {} + StateIterable(const StatesVector &v) : StateIterable(v, nullptr) {} + StateIterable(const StateSet &s) + : self(new StatesVector(s.begin(), s.end())), shouldDestruct(true) {} + ~StateIterable() { + if (shouldDestruct) + delete self; + } + bool empty() const noexcept { + return without ? begin() == end() : self->empty(); + } + it begin() const noexcept { return it(self->begin(), self->end(), without); } + it end() const noexcept { return it(self->end(), self->end(), without); } + + void setWithout(const StateSet *w) const { without = w; } + void clearWithout() const { without = nullptr; } +}; + +class TargetHistoryTargetPairToStatesMap final { +private: + using k = TargetHistoryTargetPair; + using cv = StateIterable; + using p = std::pair; + using v = StatesVector; + using t = + std::unordered_map; + using map_it = t::iterator; + using map_cit = t::const_iterator; + t self; + mutable const StateSet *without = nullptr; + + class it : public std::iterator { + protected: + map_cit self; + const StateSet *without = nullptr; + + public: + it(map_cit i, const StateSet *without) : self(i), without(without) {} + bool operator==(const it &other) const noexcept { + return self == other.self; + }; + bool operator!=(const it &other) const noexcept { + return self != other.self; + }; + it &operator++() noexcept { + self++; + return *this; + } + p operator*() const noexcept { + return std::make_pair(self->first, StateIterable(self->second, without)); + } + }; + public: - using TargetHistoryTargetPair = - std::pair, ref>; - using StatesVector = std::vector; - using TargetHistoryTargetPairToStatesMap = - std::unordered_map; + inline v &operator[](const k &__k) { return self[__k]; } + inline v &operator[](k &&__k) { return self[std::move(__k)]; } + inline v &at(const k &__k) { return self.at(__k); } + inline map_it begin() noexcept { return self.begin(); } + inline map_it end() noexcept { return self.end(); } + + inline const cv at(const k &__k) const { + cv result = self.at(__k); + result.setWithout(without); + return result; + } + inline it begin() const noexcept { return it(self.begin(), without); }; + inline it end() const noexcept { return it(self.end(), without); }; + + void setWithout(const StateSet *w) const { without = w; } + void clearWithout() const { without = nullptr; } +}; +class TargetManagerSubscriber { +public: virtual ~TargetManagerSubscriber() = default; /// Selects a state for further exploration. @@ -47,12 +163,6 @@ class TargetManager { using StatesSet = std::unordered_set; using StateToDistanceMap = std::unordered_map>; - using TargetHistoryTargetPair = - std::pair, ref>; - using StatesVector = std::vector; - using TargetHistoryTargetPairToStatesMap = - std::unordered_map; using TargetForestHistoryTargetSet = std::unordered_set; diff --git a/lib/Core/TargetedExecutionManager.cpp b/lib/Core/TargetedExecutionManager.cpp index 25357773ae..ab4b67f3df 100644 --- a/lib/Core/TargetedExecutionManager.cpp +++ b/lib/Core/TargetedExecutionManager.cpp @@ -14,7 +14,7 @@ #include "ExecutionState.h" #include "klee/Core/TerminationTypes.h" -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" #include "klee/Support/ErrorHandling.h" @@ -318,24 +318,27 @@ TargetedExecutionManager::LocationToBlocks TargetedExecutionManager::prepareAllLocations(KModule *kmodule, Locations &locations) const { LocationToBlocks locToBlocks; - const auto &infos = kmodule->infos; + std::unordered_map> + fileNameToFunctions; + + for (const auto &kfunc : kmodule->functions) { + fileNameToFunctions[kfunc->getSourceFilepath()].insert(kfunc->function); + } + for (auto it = locations.begin(); it != locations.end(); ++it) { auto loc = *it; - for (const auto &fileName : infos->getFilesNames()) { - if (kmodule->origInfos.count(fileName) == 0) { + for (const auto &[fileName, origInstsInFile] : kmodule->origInstructions) { + if (kmodule->origInstructions.count(fileName) == 0) { continue; } if (!loc->isInside(fileName)) { continue; } - const auto &relatedFunctions = - infos->getFileNameToFunctions().at(fileName); + const auto &relatedFunctions = fileNameToFunctions.at(fileName); for (const auto func : relatedFunctions) { const auto kfunc = kmodule->functionMap[func]; - const auto &fi = infos->getFunctionInfo(*kfunc->function); - const auto &origInstsInFile = kmodule->origInfos.at(fi.file); for (const auto &kblock : kfunc->blocks) { auto b = kblock.get(); @@ -375,19 +378,19 @@ bool TargetedExecutionManager::canReach(const ref &from, return true; } - const auto &blockDist = codeGraphDistance.getDistance(fromBlock); - if (blockDist.count(toBlock) != 0) { + const auto &blockDist = codeGraphInfo.getDistance(fromBlock); + if (blockDist.count(toBlock->basicBlock) != 0) { return true; } } else { - const auto &funcDist = codeGraphDistance.getDistance(fromKf); - if (funcDist.count(toKf) != 0) { + const auto &funcDist = codeGraphInfo.getDistance(fromKf); + if (funcDist.count(toKf->function) != 0) { return true; } const auto &backwardFuncDist = - codeGraphDistance.getBackwardDistance(fromKf); - if (backwardFuncDist.count(toKf) != 0) { + codeGraphInfo.getBackwardDistance(fromKf); + if (backwardFuncDist.count(toKf->function) != 0) { return true; } } @@ -449,7 +452,7 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( if (i == j) { continue; } - const auto &funcDist = codeGraphDistance.getDistance(resKf); + const auto &funcDist = codeGraphInfo.getDistance(resKf); std::vector currKFs; for (auto block : locToBlocks[result.locations[j]]) { @@ -461,9 +464,9 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( KFunction *curKf = nullptr; for (size_t m = 0; m < currKFs.size() && !curKf; ++m) { curKf = currKFs.at(m); - if (funcDist.count(curKf) == 0) { - const auto &curFuncDist = codeGraphDistance.getDistance(curKf); - if (curFuncDist.count(resKf) == 0) { + if (funcDist.count(curKf->function) == 0) { + const auto &curFuncDist = codeGraphInfo.getDistance(curKf); + if (curFuncDist.count(resKf->function) == 0) { curKf = nullptr; } else { i = j; @@ -490,13 +493,12 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( return resKf; } -std::map, - TargetedExecutionManager::KFunctionLess> +std::map, KFunctionCompare> TargetedExecutionManager::prepareTargets(KModule *kmodule, SarifReport paths) { Locations locations = collectAllLocations(paths); LocationToBlocks locToBlocks = prepareAllLocations(kmodule, locations); - std::map, KFunctionLess> whitelists; + std::map, KFunctionCompare> whitelists; for (auto &result : paths.results) { bool isFullyResolved = tryResolveLocations(result, locToBlocks); @@ -524,12 +526,13 @@ TargetedExecutionManager::prepareTargets(KModule *kmodule, SarifReport paths) { void TargetedExecutionManager::reportFalseNegative(ExecutionState &state, ReachWithError error) { klee_warning("100.00%% %s False Negative at: %s", getErrorString(error), - state.prevPC->getSourceLocation().c_str()); + state.prevPC->getSourceLocationString().c_str()); } bool TargetedExecutionManager::reportTruePositive(ExecutionState &state, ReachWithError error) { bool atLeastOneReported = false; + state.error = error; for (auto target : state.targetForest.getTargets()) { if (!target->shouldFailOnThisTarget()) continue; @@ -539,27 +542,10 @@ bool TargetedExecutionManager::reportTruePositive(ExecutionState &state, reportedTraces.count(errorTarget->getId())) continue; - /// The following code checks if target is a `call ...` instruction and we - /// failed somewhere *inside* call - auto possibleInstruction = state.prevPC; - int i = state.stack.size() - 1; - bool found = true; - - while (!errorTarget->isTheSameAsIn( - possibleInstruction)) { // TODO: target->getBlock() == - // possibleInstruction should also be checked, - // but more smartly - if (i <= 0) { - found = false; - break; - } - possibleInstruction = state.stack.callStack().at(i).caller; - i--; - } - if (!found) + if (!targetManager.isReachedTarget(state, errorTarget)) { continue; + } - state.error = error; atLeastOneReported = true; assert(!errorTarget->isReported); if (errorTarget->isThatError(ReachWithError::Reachable)) { diff --git a/lib/Core/TargetedExecutionManager.h b/lib/Core/TargetedExecutionManager.h index 7d5b285d41..e5f72e935b 100644 --- a/lib/Core/TargetedExecutionManager.h +++ b/lib/Core/TargetedExecutionManager.h @@ -60,7 +60,7 @@ extern llvm::cl::opt TimerInterval; extern llvm::cl::opt MaxCycles; -class CodeGraphDistance; +class CodeGraphInfo; class TargetedHaltsOnTraces { using HaltTypeToConfidence = @@ -96,12 +96,6 @@ class TargetedExecutionManager { using StatesSet = std::unordered_set; using TargetToStateUnorderedSetMap = TargetHashMap; - using Instructions = std::unordered_map< - std::string, - std::unordered_map< - unsigned int, - std::unordered_map>>>; - std::unordered_set brokenTraces; std::unordered_set reportedTraces; @@ -116,22 +110,16 @@ class TargetedExecutionManager { KFunction *tryResolveEntryFunction(const Result &result, LocationToBlocks &locToBlocks) const; - CodeGraphDistance &codeGraphDistance; + CodeGraphInfo &codeGraphInfo; TargetManager &targetManager; StatesSet localStates; public: - struct KFunctionLess { - bool operator()(const KFunction *a, const KFunction *b) const { - return a->id < b->id; - } - }; - - explicit TargetedExecutionManager(CodeGraphDistance &codeGraphDistance_, + explicit TargetedExecutionManager(CodeGraphInfo &codeGraphInfo_, TargetManager &targetManager_) - : codeGraphDistance(codeGraphDistance_), targetManager(targetManager_) {} + : codeGraphInfo(codeGraphInfo_), targetManager(targetManager_) {} ~TargetedExecutionManager() = default; - std::map, KFunctionLess> + std::map, KFunctionCompare> prepareTargets(KModule *kmodule, SarifReport paths); void reportFalseNegative(ExecutionState &state, ReachWithError error); diff --git a/lib/Core/TimingSolver.cpp b/lib/Core/TimingSolver.cpp index edae9a3a5b..91d1d57e9c 100644 --- a/lib/Core/TimingSolver.cpp +++ b/lib/Core/TimingSolver.cpp @@ -44,11 +44,11 @@ bool TimingSolver::evaluate(const ConstraintSet &constraints, ref expr, ref queryResult; ref negatedQueryResult; + Query query(constraints, expr, metaData.id); bool success = produceValidityCore - ? solver->evaluate(Query(constraints, expr), queryResult, - negatedQueryResult) - : solver->evaluate(Query(constraints, expr), result); + ? solver->evaluate(query, queryResult, negatedQueryResult) + : solver->evaluate(query, result); if (success && produceValidityCore) { if (isa(queryResult) && @@ -91,12 +91,12 @@ bool TimingSolver::tryGetUnique(const ConstraintSet &constraints, ref e, e = optimizer.optimizeExpr(e, true); TimerStatIncrementer timer(stats::solverTime); - if (!solver->getValue(Query(constraints, e), value)) { + if (!solver->getValue(Query(constraints, e, metaData.id), value)) { return false; } ref cond = EqExpr::create(e, value); cond = optimizer.optimizeExpr(cond, false); - if (!solver->mustBeTrue(Query(constraints, cond), isTrue)) { + if (!solver->mustBeTrue(Query(constraints, cond, metaData.id), isTrue)) { return false; } if (isTrue) { @@ -125,11 +125,11 @@ bool TimingSolver::mustBeTrue(const ConstraintSet &constraints, ref expr, expr = Simplificator::simplifyExpr(constraints, expr).simplified; ValidityCore validityCore; + Query query(constraints, expr, metaData.id); bool success = produceValidityCore - ? solver->getValidityCore(Query(constraints, expr), - validityCore, result) - : solver->mustBeTrue(Query(constraints, expr), result); + ? solver->getValidityCore(query, validityCore, result) + : solver->mustBeTrue(query, result); metaData.queryCost += timer.delta(); @@ -178,7 +178,8 @@ bool TimingSolver::getValue(const ConstraintSet &constraints, ref expr, if (simplifyExprs) expr = Simplificator::simplifyExpr(constraints, expr).simplified; - bool success = solver->getValue(Query(constraints, expr), result); + bool success = + solver->getValue(Query(constraints, expr, metaData.id), result); metaData.queryCost += timer.delta(); @@ -201,8 +202,8 @@ bool TimingSolver::getMinimalUnsignedValue(const ConstraintSet &constraints, if (simplifyExprs) expr = Simplificator::simplifyExpr(constraints, expr).simplified; - bool success = - solver->getMinimalUnsignedValue(Query(constraints, expr), result); + bool success = solver->getMinimalUnsignedValue( + Query(constraints, expr, metaData.id), result); metaData.queryCost += timer.delta(); @@ -220,15 +221,11 @@ bool TimingSolver::getInitialValues( TimerStatIncrementer timer(stats::solverTime); ref queryResult; + Query query(constraints, Expr::createFalse(), metaData.id); - bool success = - produceValidityCore - ? solver->check( - Query(constraints, ConstantExpr::alloc(0, Expr::Bool)), - queryResult) - : solver->getInitialValues( - Query(constraints, ConstantExpr::alloc(0, Expr::Bool)), objects, - result); + bool success = produceValidityCore + ? solver->check(query, queryResult) + : solver->getInitialValues(query, objects, result); if (success && produceValidityCore && isa(queryResult)) { success = queryResult->tryGetInitialValuesFor(objects, result); @@ -251,22 +248,22 @@ bool TimingSolver::evaluate(const ConstraintSet &constraints, ref expr, auto simplified = simplification.simplified; auto dependency = simplification.dependency; if (auto CE = dyn_cast(simplified)) { + Query query(constraints, simplified, metaData.id); if (CE->isTrue()) { queryResult = new ValidResponse(ValidityCore(dependency, expr)); - return solver->check(Query(constraints, simplified).negateExpr(), - negatedQueryResult); + return solver->check(query.negateExpr(), negatedQueryResult); } else { negatedQueryResult = new ValidResponse( ValidityCore(dependency, Expr::createIsZero(expr))); - return solver->check(Query(constraints, simplified), queryResult); + return solver->check(query, queryResult); } } else { expr = simplified; } } - bool success = solver->evaluate(Query(constraints, expr), queryResult, - negatedQueryResult); + bool success = solver->evaluate(Query(constraints, expr, metaData.id), + queryResult, negatedQueryResult); metaData.queryCost += timer.delta(); @@ -300,8 +297,8 @@ bool TimingSolver::getValidityCore(const ConstraintSet &constraints, } } - bool success = - solver->getValidityCore(Query(constraints, expr), validityCore, result); + bool success = solver->getValidityCore(Query(constraints, expr, metaData.id), + validityCore, result); metaData.queryCost += timer.delta(); @@ -334,7 +331,8 @@ bool TimingSolver::getResponse(const ConstraintSet &constraints, ref expr, } } - bool success = solver->check(Query(constraints, expr), queryResult); + bool success = + solver->check(Query(constraints, expr, metaData.id), queryResult); metaData.queryCost += timer.delta(); @@ -346,8 +344,12 @@ TimingSolver::getRange(const ConstraintSet &constraints, ref expr, SolverQueryMetaData &metaData, time::Span timeout) { ++stats::queries; TimerStatIncrementer timer(stats::solverTime); - auto query = Query(constraints, expr); + Query query(constraints, expr, metaData.id); auto result = solver->getRange(query, timeout); metaData.queryCost += timer.delta(); return result; } + +void TimingSolver::notifyStateTermination(std::uint32_t id) { + solver->notifyStateTermination(id); +} diff --git a/lib/Core/TimingSolver.h b/lib/Core/TimingSolver.h index fbf65c4a56..7692d50377 100644 --- a/lib/Core/TimingSolver.h +++ b/lib/Core/TimingSolver.h @@ -49,6 +49,10 @@ class TimingSolver { return solver->getConstraintLog(query); } + /// @brief Notify the solver that the state with specified id has been + /// terminated + void notifyStateTermination(std::uint32_t id); + bool evaluate(const ConstraintSet &, ref, PartialValidity &result, SolverQueryMetaData &metaData, bool produceValidityCore = false); diff --git a/lib/Core/TypeManager.cpp b/lib/Core/TypeManager.cpp index c6e00f2f82..c053d449fa 100644 --- a/lib/Core/TypeManager.cpp +++ b/lib/Core/TypeManager.cpp @@ -37,6 +37,12 @@ KType *TypeManager::getWrappedType(llvm::Type *type) { if (typesMap.count(type) == 0) { types.emplace_back(new KType(type, this)); typesMap.emplace(type, types.back().get()); + if (type && type->isPointerTy()) { + getWrappedType(type->getPointerElementType()); + } + if (type && type->isArrayTy()) { + getWrappedType(type->getArrayElementType()); + } } return typesMap[type]; } @@ -61,15 +67,21 @@ void TypeManager::initTypesFromStructs() { * and pull types to top. */ - std::vector collectedStructTypes = - parent->module->getIdentifiedStructTypes(); - for (auto &structType : collectedStructTypes) { + for (auto &structType : parent->module->getIdentifiedStructTypes()) { getWrappedType(structType); } + std::unordered_set collectedStructTypes; + for (const auto &it : typesMap) { + if (llvm::StructType *itStruct = + llvm::dyn_cast(it.first)) { + collectedStructTypes.insert(itStruct); + } + } + for (auto &typesToOffsets : typesMap) { if (llvm::isa(typesToOffsets.first)) { - collectedStructTypes.emplace_back( + collectedStructTypes.insert( llvm::cast(typesToOffsets.first)); } } @@ -141,20 +153,13 @@ void TypeManager::initTypesFromGlobals() { */ void TypeManager::initTypesFromInstructions() { for (auto &function : *(parent->module)) { - auto kf = parent->functionMap[&function]; - for (auto &BasicBlock : function) { - unsigned numInstructions = kf->blockMap[&BasicBlock]->numInstructions; - KBlock *kb = kf->blockMap[&BasicBlock]; - - for (unsigned i = 0; i < numInstructions; ++i) { - llvm::Instruction *inst = kb->instructions[i]->inst; - + for (auto &inst : BasicBlock) { /* Register return type */ - getWrappedType(inst->getType()); + getWrappedType(inst.getType()); /* Register types for arguments */ - for (auto opb = inst->op_begin(), ope = inst->op_end(); opb != ope; + for (auto opb = inst.op_begin(), ope = inst.op_end(); opb != ope; ++opb) { getWrappedType((*opb)->getType()); } diff --git a/lib/Core/UserSearcher.cpp b/lib/Core/UserSearcher.cpp index 8de5273052..59674a84f7 100644 --- a/lib/Core/UserSearcher.cpp +++ b/lib/Core/UserSearcher.cpp @@ -55,11 +55,17 @@ cl::list CoreSearch( clEnumValN(Searcher::NURS_QC, "nurs:qc", "use NURS with Query-Cost")), cl::cat(SearchCat)); -cl::opt UseIterativeDeepeningTimeSearch( - "use-iterative-deepening-time-search", - cl::desc( - "Use iterative deepening time search (experimental) (default=false)"), - cl::init(false), cl::cat(SearchCat)); +cl::opt UseIterativeDeepeningSearch( + "use-iterative-deepening-search", + cl::desc("Use iterative deepening search based on metric (experimental) " + "(default=unspecified)"), + cl::values(clEnumValN(HaltExecution::Reason::Unspecified, "unspecified", + "Do not use iterative deepening search (default)"), + clEnumValN(HaltExecution::Reason::MaxTime, "max-time", + "metric is maximum time"), + clEnumValN(HaltExecution::Reason::MaxCycles, "max-cycles", + "metric is maximum cycles")), + cl::init(HaltExecution::Reason::Unspecified), cl::cat(SearchCat)); cl::opt UseBatchingSearch( "use-batching-search", @@ -172,16 +178,22 @@ Searcher *klee::constructUserSearcher(Executor &executor, BatchInstructions); } - if (UseIterativeDeepeningTimeSearch) { - searcher = new IterativeDeepeningTimeSearcher(searcher); - } - + TargetManagerSubscriber *tms = nullptr; if (executor.guidanceKind != Interpreter::GuidanceKind::NoGuidance) { searcher = new GuidedSearcher(searcher, *executor.distanceCalculator, executor.theRNG); - executor.targetManager->subscribe(*static_cast(searcher)); + tms = static_cast(searcher); } + if (UseIterativeDeepeningSearch != HaltExecution::Reason::Unspecified) { + searcher = new IterativeDeepeningSearcher(searcher, tms, + UseIterativeDeepeningSearch); + tms = static_cast(searcher); + } + + if (tms) + executor.targetManager->subscribe(*tms); + llvm::raw_ostream &os = executor.getHandler().getInfoStream(); os << "BEGIN searcher description\n"; diff --git a/lib/Expr/APFloatEval.cpp b/lib/Expr/APFloatEval.cpp index a1f49b28f9..49ae758d1c 100644 --- a/lib/Expr/APFloatEval.cpp +++ b/lib/Expr/APFloatEval.cpp @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#include "klee/util/APFloatEval.h" +#include "klee/Utilities/APFloatEval.h" #include "klee/Config/Version.h" #include "klee/Support/CompilerWarning.h" diff --git a/lib/Expr/AlphaBuilder.cpp b/lib/Expr/AlphaBuilder.cpp new file mode 100644 index 0000000000..13fb00073f --- /dev/null +++ b/lib/Expr/AlphaBuilder.cpp @@ -0,0 +1,95 @@ +//===-- AlphaBuilder.cpp ---------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Expr/AlphaBuilder.h" +#include "klee/Expr/ArrayCache.h" +#include "klee/Expr/SourceBuilder.h" + +#include + +namespace klee { + +const Array *AlphaBuilder::visitArray(const Array *arr) { + if (!reverse && alphaArrayMap.find(arr) == alphaArrayMap.end()) { + ref source = arr->source; + ref size = visit(arr->getSize()); + + if (!arr->isConstantArray()) { + source = SourceBuilder::alpha(index); + index++; + alphaArrayMap[arr] = arrayCache.CreateArray( + size, source, arr->getDomain(), arr->getRange()); + reverseAlphaArrayMap[alphaArrayMap[arr]] = arr; + } else if (size != arr->getSize()) { + alphaArrayMap[arr] = arrayCache.CreateArray( + size, source, arr->getDomain(), arr->getRange()); + reverseAlphaArrayMap[alphaArrayMap[arr]] = arr; + } else { + alphaArrayMap[arr] = arr; + reverseAlphaArrayMap[arr] = arr; + } + } + if (reverse) { + return reverseAlphaArrayMap[arr]; + } else { + return alphaArrayMap[arr]; + } +} + +UpdateList AlphaBuilder::visitUpdateList(UpdateList u) { + const Array *root = visitArray(u.root); + std::vector> updates; + + for (auto un = u.head; un; un = un->next) { + updates.push_back(un); + } + + updates.push_back(nullptr); + + for (int i = updates.size() - 2; i >= 0; i--) { + ref index = visit(updates[i]->index); + ref value = visit(updates[i]->value); + updates[i] = new UpdateNode(updates[i + 1], index, value); + } + return UpdateList(root, updates[0]); +} + +ExprVisitor::Action AlphaBuilder::visitRead(const ReadExpr &re) { + ref v = visit(re.index); + UpdateList u = visitUpdateList(re.updates); + ref e = ReadExpr::create(u, v); + return Action::changeTo(e); +} + +AlphaBuilder::AlphaBuilder(ArrayCache &_arrayCache) : arrayCache(_arrayCache) {} + +constraints_ty AlphaBuilder::visitConstraints(constraints_ty cs) { + constraints_ty result; + for (auto arg : cs) { + ref v = visit(arg); + reverseExprMap[v] = arg; + reverseExprMap[Expr::createIsZero(v)] = Expr::createIsZero(arg); + result.insert(v); + } + return result; +} +ref AlphaBuilder::build(ref v) { + ref e = visit(v); + reverseExprMap[e] = v; + reverseExprMap[Expr::createIsZero(e)] = Expr::createIsZero(v); + return e; +} +ref AlphaBuilder::reverseBuild(ref v) { + reverse = true; + ref e = visit(v); + reverse = false; + return e; +} + +} // namespace klee diff --git a/lib/Expr/ArrayCache.cpp b/lib/Expr/ArrayCache.cpp index afea585300..3962278f6c 100644 --- a/lib/Expr/ArrayCache.cpp +++ b/lib/Expr/ArrayCache.cpp @@ -11,41 +11,25 @@ ArrayCache::~ArrayCache() { ai != e; ++ai) { delete *ai; } - for (ArrayPtrVec::iterator ai = concreteArrays.begin(), - e = concreteArrays.end(); - ai != e; ++ai) { - delete *ai; - } } const Array *ArrayCache::CreateArray(ref _size, ref _source, Expr::Width _domain, Expr::Width _range) { - const Array *array = new Array(_size, _source, _domain, _range, getNextID()); - if (array->isSymbolicArray()) { - std::pair success = - cachedSymbolicArrays.insert(array); - if (success.second) { - // Cache miss - return array; - } - // Cache hit - delete array; - array = *(success.first); - assert(array->isSymbolicArray() && - "Cached symbolic array is no longer symbolic"); - return array; - } else { - // Treat every constant array as distinct so we never cache them - assert(array->isConstantArray()); - concreteArrays.push_back(array); // For deletion later + auto id = allocatedCount[_source->getKind()]; + const Array *array = new Array(_size, _source, _domain, _range, id); + std::pair success = + cachedSymbolicArrays.insert(array); + if (success.second) { + // Cache miss + allocatedCount[_source->getKind()]++; return array; } -} - -unsigned ArrayCache::getNextID() const { - return cachedSymbolicArrays.size() + concreteArrays.size(); + // Cache hit + delete array; + array = *(success.first); + return array; } } // namespace klee diff --git a/lib/Expr/ArrayExprOptimizer.cpp b/lib/Expr/ArrayExprOptimizer.cpp index d67bd3ddbd..205685fdd6 100644 --- a/lib/Expr/ArrayExprOptimizer.cpp +++ b/lib/Expr/ArrayExprOptimizer.cpp @@ -198,6 +198,7 @@ bool ExprOptimizer::computeIndexes(array2idx_ty &arrays, const ref &e, // For each constant array found for (auto &element : arrays) { const Array *arr = element.first; + auto arraySize = cast(arr->size)->getZExtValue(); assert(arr->isConstantArray() && "Array is not concrete"); assert(element.second.size() == 1 && "Multiple indexes on the same array"); @@ -224,8 +225,7 @@ bool ExprOptimizer::computeIndexes(array2idx_ty &arrays, const ref &e, // For each concrete value 'i' stored in the array if (ref constantSource = cast(arr->source)) { - for (size_t aIdx = 0; aIdx < constantSource->constantValues.size(); - aIdx += width) { + for (size_t aIdx = 0; aIdx < arraySize; aIdx += width) { auto *a = new Assignment(); std::vector objects; std::vector> values; @@ -302,7 +302,8 @@ ref ExprOptimizer::getSelectOptExpr( std::vector> arrayConstValues; if (ref constantSource = dyn_cast(read->updates.root->source)) { - arrayConstValues = constantSource->constantValues; + arrayConstValues = + constantSource->constantValues.getFirstNIndexes(size); } for (auto it = us.rbegin(); it != us.rend(); it++) { const UpdateNode *un = *it; @@ -377,7 +378,8 @@ ref ExprOptimizer::getSelectOptExpr( std::vector> arrayConstValues; if (ref constantSource = dyn_cast(read->updates.root->source)) { - arrayConstValues = constantSource->constantValues; + arrayConstValues = + constantSource->constantValues.getFirstNIndexes(size); } if (arrayConstValues.size() < size) { // We need to "force" initialization of the values diff --git a/lib/Expr/Assignment.cpp b/lib/Expr/Assignment.cpp index d43db33870..860f1a0a50 100644 --- a/lib/Expr/Assignment.cpp +++ b/lib/Expr/Assignment.cpp @@ -20,17 +20,26 @@ void Assignment::dump() const { llvm::errs() << "No bindings\n"; return; } - for (bindings_ty::const_iterator i = bindings.begin(), e = bindings.end(); - i != e; ++i) { - llvm::errs() << (*i).first->getName() << "\n["; - for (int j = 0, k = (*i).second.size(); j < k; ++j) - llvm::errs() << (int)(*i).second.load(j) << ","; - llvm::errs() << "]\n"; + for (bindings_ty::iterator i = bindings.begin(), e = bindings.end(); i != e; + ++i) { + llvm::errs() << (*i).first->getName() << "\n"; + Density d = + ((*i).second.storage().size() * 2 < (*i).second.sizeOfSetRange()) + ? Density::Sparse + : Density::Dense; + (*i).second.print(llvm::errs(), d); + llvm::errs() << "\n"; } } -ConstraintSet Assignment::createConstraintsFromAssignment() const { - ConstraintSet result; +void Assignment::addIndependentAssignment(const Assignment &b) { + for (auto it : b) { + bindings.insert(it); + } +} + +constraints_ty Assignment::createConstraintsFromAssignment() const { + constraints_ty result; for (const auto &binding : bindings) { const auto &array = binding.first; const auto &values = binding.second; @@ -41,17 +50,15 @@ ConstraintSet Assignment::createConstraintsFromAssignment() const { uint64_t arraySize = arrayConstantSize->getZExtValue(); if (arraySize <= 8 && array->getRange() == Expr::Int8) { ref e = Expr::createTempRead(array, arraySize * array->getRange()); - result.addConstraint(EqExpr::create(e, evaluate(e)), {}); + result.insert(EqExpr::create(e, evaluate(e))); } else { for (unsigned arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex) { unsigned char value = values.load(arrayIndex); - result.addConstraint( - EqExpr::create( - ReadExpr::create( - UpdateList(array, 0), - ConstantExpr::alloc(arrayIndex, array->getDomain())), - ConstantExpr::alloc(value, array->getRange())), - {}); + result.insert(EqExpr::create( + ReadExpr::create( + UpdateList(array, 0), + ConstantExpr::alloc(arrayIndex, array->getDomain())), + ConstantExpr::alloc(value, array->getRange()))); } } } @@ -59,7 +66,7 @@ ConstraintSet Assignment::createConstraintsFromAssignment() const { } Assignment Assignment::diffWith(const Assignment &other) const { - Assignment diffAssignment(allowFreeValues); + Assignment diffAssignment; for (const auto &it : other) { if (bindings.count(it.first) == 0 || bindings.at(it.first) != it.second) { diffAssignment.bindings.insert(it); @@ -87,10 +94,12 @@ std::vector> Assignment::values() const { } Assignment Assignment::part(const SymcreteOrderedSet &symcretes) const { - Assignment ret(allowFreeValues); + Assignment ret; for (auto symcrete : symcretes) { for (auto array : symcrete->dependentArrays()) { - ret.bindings.insert({array, bindings.at(array)}); + if (bindings.find(array) != bindings.end()) { + ret.bindings.insert({array, bindings.at(array)}); + } } } return ret; diff --git a/lib/Expr/CMakeLists.txt b/lib/Expr/CMakeLists.txt index b7ca4e0124..6167bbf721 100644 --- a/lib/Expr/CMakeLists.txt +++ b/lib/Expr/CMakeLists.txt @@ -7,6 +7,7 @@ # #===------------------------------------------------------------------------===# add_library(kleaverExpr + AlphaBuilder.cpp APFloatEval.cpp ArrayCache.cpp ArrayExprOptimizer.cpp @@ -22,6 +23,7 @@ add_library(kleaverExpr ExprSMTLIBPrinter.cpp ExprUtil.cpp ExprVisitor.cpp + IndependentConstraintSetUnion.cpp IndependentSet.cpp Path.cpp SourceBuilder.cpp @@ -31,6 +33,10 @@ add_library(kleaverExpr Updates.cpp ) +target_link_libraries(kleaverExpr PRIVATE + kleeADT +) + llvm_config(kleaverExpr "${USE_LLVM_SHARED}" support) target_include_directories(kleaverExpr PRIVATE ${KLEE_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}) target_compile_options(kleaverExpr PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index 802a75bea4..b88c204555 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -15,6 +15,7 @@ #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" #include "klee/Expr/ExprVisitor.h" +#include "klee/Expr/IndependentSet.h" #include "klee/Expr/Path.h" #include "klee/Expr/Symcrete.h" #include "klee/Module/KModule.h" @@ -181,18 +182,48 @@ class ExprReplaceVisitor3 : public ExprVisitor { ConstraintSet::ConstraintSet(constraints_ty cs, symcretes_ty symcretes, Assignment concretization) - : _constraints(cs), _symcretes(symcretes), _concretization(concretization) { + : _constraints(cs), _symcretes(symcretes), _concretization(concretization), + _independentElements(new IndependentConstraintSetUnion( + _constraints, _symcretes, _concretization)) {} + +ConstraintSet::ConstraintSet(ref ics) + : _constraints(ics->getConstraints()), _symcretes(ics->getSymcretes()), + _concretization(ics->concretization), + _independentElements(new IndependentConstraintSetUnion(ics)) {} + +ConstraintSet::ConstraintSet( + const std::vector> &factors) + : _independentElements(new IndependentConstraintSetUnion( + _constraints, _symcretes, _concretization)) { + for (auto ics : factors) { + constraints_ty constraints = ics->getConstraints(); + SymcreteOrderedSet symcretes = ics->getSymcretes(); + IndependentConstraintSetUnion icsu(ics); + _constraints.insert(constraints.begin(), constraints.end()); + _symcretes.insert(symcretes.begin(), symcretes.end()); + _concretization.addIndependentAssignment(ics->concretization); + _independentElements->addIndependentConstraintSetUnion(icsu); + } } -ConstraintSet::ConstraintSet() : _concretization(Assignment(true)) {} +ConstraintSet::ConstraintSet(constraints_ty cs) : ConstraintSet(cs, {}, {}) {} + +ConstraintSet::ConstraintSet() + : _independentElements(new IndependentConstraintSetUnion()) {} + +void ConstraintSet::fork() { + _independentElements = std::make_shared( + IndependentConstraintSetUnion(*_independentElements)); +} void ConstraintSet::addConstraint(ref e, const Assignment &delta) { _constraints.insert(e); - // Update bindings - for (auto i : delta.bindings) { - _concretization.bindings[i.first] = i.second; + for (auto &i : delta.bindings) { + _concretization.bindings.replace({i.first, i.second}); } + _independentElements->updateConcretization(delta); + _independentElements->addExpr(e); } IDType Symcrete::idCounter = 0; @@ -200,9 +231,14 @@ IDType Symcrete::idCounter = 0; void ConstraintSet::addSymcrete(ref s, const Assignment &concretization) { _symcretes.insert(s); + _independentElements->addSymcrete(s); + Assignment dependentConcretization; for (auto i : s->dependentArrays()) { - _concretization.bindings[i] = concretization.bindings.at(i); + _concretization.bindings.replace({i, concretization.bindings.at(i)}); + dependentConcretization.bindings.replace( + {i, concretization.bindings.at(i)}); } + _independentElements->updateConcretization(dependentConcretization); } bool ConstraintSet::isSymcretized(ref expr) const { @@ -217,9 +253,34 @@ bool ConstraintSet::isSymcretized(ref expr) const { void ConstraintSet::rewriteConcretization(const Assignment &a) { for (auto i : a.bindings) { if (concretization().bindings.count(i.first)) { - _concretization.bindings[i.first] = i.second; + _concretization.bindings.replace({i.first, i.second}); } } + _independentElements->updateConcretization(a); +} + +ConstraintSet ConstraintSet::getConcretizedVersion() const { + ConstraintSet cs; + cs._independentElements = std::make_shared( + _independentElements->getConcretizedVersion()); + + for (auto &e : cs._independentElements->is()) { + if (isa(e)) { + cs._constraints.insert(cast(e)->value()); + } + } + return cs; +} + +ConstraintSet ConstraintSet::getConcretizedVersion( + const Assignment &newConcretization) const { + ConstraintSet cs; + cs._independentElements = std::make_shared( + _independentElements->getConcretizedVersion(newConcretization)); + for (auto &e : cs._independentElements->is()) { + cs._constraints.insert(cast(e)->value()); + } + return cs; } void ConstraintSet::print(llvm::raw_ostream &os) const { @@ -240,12 +301,21 @@ void ConstraintSet::print(llvm::raw_ostream &os) const { void ConstraintSet::dump() const { this->print(llvm::errs()); } -void ConstraintSet::changeCS(constraints_ty &cs) { _constraints = cs; } +void ConstraintSet::changeCS(constraints_ty &cs) { + _constraints = cs; + _independentElements = std::make_shared( + IndependentConstraintSetUnion(_constraints, _symcretes, _concretization)); +} const constraints_ty &ConstraintSet::cs() const { return _constraints; } const symcretes_ty &ConstraintSet::symcretes() const { return _symcretes; } +const IndependentConstraintSetUnion & +ConstraintSet::independentElements() const { + return *_independentElements; +} + const Path &PathConstraints::path() const { return _path; } const ExprHashMap &PathConstraints::indexes() const { @@ -271,9 +341,7 @@ PathConstraints::orderedCS() const { void PathConstraints::advancePath(KInstruction *ki) { _path.advance(ki); } -void PathConstraints::advancePath(const Path &path) { - _path = Path::concat(_path, path); -} +void PathConstraints::fork() { constraints.fork(); } ExprHashSet PathConstraints::addConstraint(ref e, const Assignment &delta, Path::PathIndex currIndex) { @@ -293,7 +361,9 @@ ExprHashSet PathConstraints::addConstraint(ref e, const Assignment &delta, added.insert(expr); pathIndexes.insert({expr, currIndex}); _simplificationMap[expr].insert(expr); - orderedConstraints[currIndex].insert(expr); + auto indexConstraints = orderedConstraints[currIndex].second; + indexConstraints.insert(expr); + orderedConstraints.replace({currIndex, indexConstraints}); constraints.addConstraint(expr, delta); } } @@ -301,10 +371,12 @@ ExprHashSet PathConstraints::addConstraint(ref e, const Assignment &delta, if (RewriteEqualities != RewriteEqualitiesPolicy::None) { auto simplified = Simplificator::simplify(constraints.cs(), RewriteEqualities); - constraints.changeCS(simplified.simplified); + if (simplified.wasSimplified) { + constraints.changeCS(simplified.simplified); - _simplificationMap = Simplificator::composeExprDependencies( - _simplificationMap, simplified.dependency); + _simplificationMap = Simplificator::composeExprDependencies( + _simplificationMap, simplified.dependency); + } } return added; @@ -328,29 +400,6 @@ void PathConstraints::rewriteConcretization(const Assignment &a) { constraints.rewriteConcretization(a); } -PathConstraints PathConstraints::concat(const PathConstraints &l, - const PathConstraints &r) { - // TODO : How to handle symcretes and concretization? - PathConstraints path = l; - path._path = Path::concat(l._path, r._path); - auto offset = l._path.KBlockSize(); - for (const auto &i : r._original) { - path._original.insert(i); - auto index = r.pathIndexes.at(i); - index.block += offset; - path.pathIndexes.insert({i, index}); - path.orderedConstraints[index].insert(i); - } - for (const auto &i : r.constraints.cs()) { - path.constraints.addConstraint(i, {}); - if (r._simplificationMap.count(i)) { - path._simplificationMap.insert({i, r._simplificationMap.at(i)}); - } - } - // Run the simplificator on the newly constructed set? - return path; -} - Simplificator::ExprResult Simplificator::simplifyExpr(const constraints_ty &constraints, const ref &expr) { @@ -362,27 +411,23 @@ Simplificator::simplifyExpr(const constraints_ty &constraints, for (auto &constraint : constraints) { if (const EqExpr *ee = dyn_cast(constraint)) { - ref left = ee->left; - ref right = ee->right; - if (right < left) { - left = ee->right; - right = ee->left; - } - if (isa(ee->left)) { - equalities.insert(std::make_pair(ee->right, ee->left)); - equalitiesParents.insert({ee->right, constraint}); - } else { - equalities.insert(std::make_pair(constraint, Expr::createTrue())); - equalities.insert(std::make_pair(right, left)); - equalitiesParents.insert({constraint, constraint}); - equalitiesParents.insert({right, constraint}); + ref small = ee->left; + ref big = ee->right; + if (!isa(small)) { + auto hr = big->height(), hl = small->height(); + if (hr < hl || (hr == hl && big < small)) + std::swap(small, big); + equalities.emplace(constraint, Expr::createTrue()); + equalitiesParents.emplace(constraint, constraint); } + equalities.emplace(big, small); + equalitiesParents.emplace(big, constraint); } else { - equalities.insert(std::make_pair(constraint, Expr::createTrue())); - equalitiesParents.insert({constraint, constraint}); + equalities.emplace(constraint, Expr::createTrue()); + equalitiesParents.emplace(constraint, constraint); if (const NotExpr *ne = dyn_cast(constraint)) { - equalities.insert(std::make_pair(ne->expr, Expr::createFalse())); - equalitiesParents.insert({ne->expr, constraint}); + equalities.emplace(ne->expr, Expr::createFalse()); + equalitiesParents.emplace(ne->expr, constraint); } } } @@ -409,6 +454,7 @@ Simplificator::simplify(const constraints_ty &constraints, dependencies.insert({constraint, {constraint}}); } + bool actuallyChanged = false; bool changed = true; while (changed) { changed = false; @@ -441,6 +487,7 @@ Simplificator::simplify(const constraints_ty &constraints, currentDependencies[part].insert(constraint); } if (constraint != simplifiedConstraint || andsSplit.size() > 1) { + actuallyChanged = true; changed = true; } } @@ -454,7 +501,7 @@ Simplificator::simplify(const constraints_ty &constraints, simplified.erase(ConstantExpr::createTrue()); dependencies.erase(ConstantExpr::createTrue()); - return {simplified, dependencies}; + return {simplified, dependencies, actuallyChanged}; } Simplificator::Replacements @@ -523,6 +570,18 @@ Simplificator::composeExprDependencies(const ExprHashMap &upper, return result; } +void ConstraintSet::getAllIndependentConstraintsSets( + ref queryExpr, + std::vector> &result) const { + _independentElements->getAllIndependentConstraintSets(queryExpr, result); +} + +void ConstraintSet::getAllDependentConstraintsSets( + ref queryExpr, + std::vector> &result) const { + _independentElements->getAllDependentConstraintSets(queryExpr, result); +} + std::vector ConstraintSet::gatherArrays() const { std::vector arrays; findObjects(_constraints.begin(), _constraints.end(), arrays); diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index e34239682a..90f2380709 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -16,7 +16,7 @@ #include "klee/Support/ErrorHandling.h" #include "klee/Support/OptionCategories.h" #include "klee/Support/RoundingModeUtil.h" -#include "klee/util/APFloatEval.h" +#include "klee/Utilities/APFloatEval.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -153,11 +153,13 @@ int Expr::compare(const Expr &b, ExprEquivSet &equivs) const { return 0; Kind ak = getKind(), bk = b.getKind(); - if (ak != bk) - return (ak < bk) ? -1 : 1; + int kc = (ak > bk) - (ak < bk); + if (kc) + return kc; - if (hashValue != b.hashValue) - return (hashValue < b.hashValue) ? -1 : 1; + int hc = (hashValue > b.hashValue) - (hashValue < b.hashValue); + if (hc) + return hc; if (int res = compareContents(b)) return res; @@ -260,6 +262,18 @@ unsigned Expr::computeHash() { return hashValue; } +unsigned Expr::computeHeight() { + unsigned maxKidHeight = 0; + + int n = getNumKids(); + for (int i = 0; i < n; i++) { + maxKidHeight = std::max(maxKidHeight, getKid(i)->height()); + } + + heightValue = maxKidHeight + 1; + return heightValue; +} + unsigned ConstantExpr::computeHash() { Expr::Width w = getWidth(); if (w <= 64) @@ -290,6 +304,11 @@ unsigned ReadExpr::computeHash() { return hashValue; } +unsigned ReadExpr::computeHeight() { + heightValue = std::max(index->height(), updates.height()) + 1; + return heightValue; +} + unsigned NotExpr::computeHash() { hashValue = expr->hash() * Expr::MAGIC_HASH_CONSTANT * Expr::Not; return hashValue; @@ -1465,22 +1484,7 @@ Array::Array(ref _size, ref _source, Expr::Width _domain, Expr::Width _range, unsigned _id) : size(_size), source(_source), domain(_domain), range(_range), id(_id) { ref constantSize = dyn_cast(size); - assert( - (!isa(_source) || - cast(_source)->size() == constantSize->getZExtValue()) && - "Invalid size for constant array!"); computeHash(); -#ifndef NDEBUG - if (isa(_source)) { - for (const ref * - it = cast(_source)->constantValues.data(), - *end = cast(_source)->constantValues.data() + - cast(_source)->constantValues.size(); - it != end; ++it) - assert((*it)->getWidth() == getRange() && - "Invalid initial constant value!"); - } -#endif // NDEBUG std::set allArrays = _source->getRelatedArrays(); std::vector sizeArrays; @@ -1529,6 +1533,22 @@ ref ReadExpr::create(const UpdateList &ul, ref index) { } } + // So that we return weird stuff like reads from consts that should have + // simplified to constant exprs if we read beyond size boundary. + if (auto source = dyn_cast(ul.root->source)) { + if (auto arraySizeExpr = dyn_cast(ul.root->size)) { + if (auto indexExpr = dyn_cast(index)) { + auto arraySize = arraySizeExpr->getZExtValue(); + auto concreteIndex = indexExpr->getZExtValue(); + if (concreteIndex >= arraySize) { + return ReadExpr::alloc(ul, index); + } + } + } else { + return ReadExpr::alloc(ul, index); + } + } + if (isa(ul.root->source) && !updateListHasSymbolicWrites) { // No updates with symbolic index to a constant array have been found if (ConstantExpr *CE = dyn_cast(index)) { @@ -1536,9 +1556,8 @@ ref ReadExpr::create(const UpdateList &ul, ref index) { ref constantSource = cast(ul.root->source); uint64_t concreteIndex = CE->getZExtValue(); - uint64_t size = constantSource->constantValues.size(); - if (concreteIndex < size) { - return constantSource->constantValues[concreteIndex]; + if (auto value = constantSource->constantValues.load(concreteIndex)) { + return value; } } } @@ -1635,21 +1654,6 @@ ref ConcatExpr::create(const ref &l, const ref &r) { if (ConstantExpr *rCE = dyn_cast(r)) return lCE->Concat(rCE); - if (isa(l) || isa(r)) { - if (SelectExpr *se = dyn_cast(l)) { - if (isa(se->trueExpr)) { - return SelectExpr::create(se->cond, ConcatExpr::create(se->trueExpr, r), - ConcatExpr::create(se->falseExpr, r)); - } - } - if (SelectExpr *se = dyn_cast(r)) { - if (isa(se->trueExpr)) { - return SelectExpr::create(se->cond, ConcatExpr::create(l, se->trueExpr), - ConcatExpr::create(l, se->falseExpr)); - } - } - } - // Merge contiguous Extracts if (ExtractExpr *ee_left = dyn_cast(l)) { if (ExtractExpr *ee_right = dyn_cast(r)) { @@ -1707,11 +1711,6 @@ ref ExtractExpr::create(ref expr, unsigned off, Width w) { } else if (ConstantExpr *CE = dyn_cast(expr)) { return CE->Extract(off, w); } else if (SelectExpr *se = dyn_cast(expr)) { - if (isa(se->trueExpr)) { - return SelectExpr::create(se->cond, - ExtractExpr::create(se->trueExpr, off, w), - ExtractExpr::create(se->falseExpr, off, w)); - } } else { // Extract(Concat) if (ConcatExpr *ce = dyn_cast(expr)) { @@ -1822,9 +1821,13 @@ ref FPTruncExpr::create(const ref &e, Width w, return e; } else if (ConstantExpr *CE = dyn_cast(e)) { return CE->FPTrunc(w, rm); - } else { - return FPTruncExpr::alloc(e, w, rm); + } else if (FPExtExpr *ExtE = dyn_cast(e)) { + if (ExtE->src->getWidth() == w) { + return ExtE->src; + } } + + return FPTruncExpr::alloc(e, w, rm); } ref FPToUIExpr::create(const ref &e, Width w, @@ -2271,12 +2274,14 @@ static ref TryConstArrayOpt(const ref &cl, ReadExpr *rd) { // for now, just assume standard "flushing" of a concrete array, // where the concrete array has one update for each index, in order + auto arraySize = dyn_cast(rd->updates.root->size); + assert(arraySize); + auto size = arraySize->getZExtValue(); ref res = ConstantExpr::alloc(0, Expr::Bool); if (ref constantSource = dyn_cast(rd->updates.root->source)) { - for (unsigned i = 0, e = constantSource->constantValues.size(); i != e; - ++i) { - if (cl == constantSource->constantValues[i]) { + for (unsigned i = 0, e = size; i != e; ++i) { + if (cl == constantSource->constantValues.load(i)) { // Arbitrary maximum on the size of disjunction. if (++numMatches > 100) return EqExpr_create(cl, rd); diff --git a/lib/Expr/ExprEvaluator.cpp b/lib/Expr/ExprEvaluator.cpp index bcadb59156..418640769a 100644 --- a/lib/Expr/ExprEvaluator.cpp +++ b/lib/Expr/ExprEvaluator.cpp @@ -32,15 +32,10 @@ ExprVisitor::Action ExprEvaluator::evalRead(const UpdateList &ul, if (ref constantSource = dyn_cast(ul.root->source)) { - if (index < constantSource->constantValues.size()) { - return Action::changeTo(constantSource->constantValues[index]); + if (auto value = constantSource->constantValues.load(index)) { + return Action::changeTo(value); } } - if (ref symbolicSizeConstantSource = - dyn_cast(ul.root->source)) { - return Action::changeTo(ConstantExpr::create( - symbolicSizeConstantSource->defaultValue, ul.root->getRange())); - } return Action::changeTo(getInitialValue(*ul.root, index)); } diff --git a/lib/Expr/ExprPPrinter.cpp b/lib/Expr/ExprPPrinter.cpp index bde8d30d6d..5ffba87725 100644 --- a/lib/Expr/ExprPPrinter.cpp +++ b/lib/Expr/ExprPPrinter.cpp @@ -385,19 +385,16 @@ class PPrinter : public ExprPPrinter { void printSource(ref source, PrintContext &PC) { PC << "("; PC << source->getName() << " "; + if (auto s = dyn_cast(source)) { - PC << " ["; - for (unsigned i = 0; i < s->constantValues.size(); i++) { - PC << s->constantValues[i]; - if (i != s->constantValues.size() - 1) { - PC << " "; - } - } - PC << "]"; - } else if (auto s = dyn_cast(source)) { - PC << s->defaultValue; + s->constantValues.print(PC.getStream(), Density::Sparse); } else if (auto s = dyn_cast(source)) { - PC << s->defaultValue << " " << s->version; + PC << s->version << " "; + s->allocSite->getID().print(PC.getStream()); + PC << " " << s->size; + } else if (auto s = dyn_cast(source)) { + PC << s->version << " "; + s->allocSite->getID().print(PC.getStream()); } else if (auto s = dyn_cast(source)) { PC << s->name << " " << s->version; } else if (auto s = dyn_cast(source)) { @@ -409,10 +406,12 @@ class PPrinter : public ExprPPrinter { auto kf = s->km->functionMap.at(s->allocSite.getFunction()); auto ki = kf->instructionMap.at(&s->allocSite); auto kb = ki->parent; - PC << ki->index << " " << kb->getLabel() << " " << kf->getName().str() - << " " << s->index; + PC << ki->getIndex() << " " << kb->getLabel() << " " + << kf->getName().str() << " " << s->index; } else if (auto s = dyn_cast(source)) { PC << s->name; + } else if (auto s = dyn_cast(source)) { + PC << s->index; } else { assert(0 && "Not implemented"); } diff --git a/lib/Expr/ExprSMTLIBPrinter.cpp b/lib/Expr/ExprSMTLIBPrinter.cpp index e1a9b9aa89..ea0315ce4e 100644 --- a/lib/Expr/ExprSMTLIBPrinter.cpp +++ b/lib/Expr/ExprSMTLIBPrinter.cpp @@ -557,7 +557,11 @@ namespace { struct ArrayPtrsByName { bool operator()(const Array *a1, const Array *a2) const { - return a1->id < a2->id; + if (a1->source->getKind() != a2->source->getKind()) { + return a1->source->getKind() < a2->source->getKind(); + } else { + return a1->id < a2->id; + } } }; @@ -613,14 +617,8 @@ void ExprSMTLIBPrinter::printArrayDeclarations() { << " " << array->getDomain() << ") )"; printSeperator(); - if (ref symbolicSizeConstantSource = - dyn_cast(array->source)) { - printConstant(ConstantExpr::create( - symbolicSizeConstantSource->defaultValue, array->getRange())); - } else if (ref constantSource = - cast(array->source)) { - printConstant(constantSource->constantValues[byteIndex]); - } + auto source = dyn_cast(array->source); + printConstant(source->constantValues.load(byteIndex)); p->popIndent(); printSeperator(); diff --git a/lib/Expr/IndependentConstraintSetUnion.cpp b/lib/Expr/IndependentConstraintSetUnion.cpp new file mode 100644 index 0000000000..b2c67e5a14 --- /dev/null +++ b/lib/Expr/IndependentConstraintSetUnion.cpp @@ -0,0 +1,193 @@ +#include "klee/Expr/IndependentConstraintSetUnion.h" + +namespace klee { + +IndependentConstraintSetUnion::IndependentConstraintSetUnion() {} + +IndependentConstraintSetUnion::IndependentConstraintSetUnion( + const constraints_ty &is, const SymcreteOrderedSet &os, + const Assignment &c) { + for (ref e : is) { + addExpr(e); + } + for (ref s : os) { + addSymcrete(s); + } + updateConcretization(c); +} + +IndependentConstraintSetUnion::IndependentConstraintSetUnion( + ref ics) { + auto exprs = ics->exprs; + for (ref e : exprs) { + auto v = ref(new ExprOrSymcrete::left(e)); + rank.insert_or_assign(v, 0); + internalStorage.insert(v); + } + + for (ref s : ics->symcretes) { + auto v = ref(new ExprOrSymcrete::right(s)); + rank.insert_or_assign(v, 0); + internalStorage.insert(v); + } + + if (internalStorage.size() == 0) { + return; + } + + auto &first = *(internalStorage.begin()); + for (auto &e : internalStorage) { + parent.insert_or_assign(e, first); + } + rank.insert_or_assign(first, 1); + roots.insert(first); + disjointSets.insert_or_assign(first, ics); + concretization = ics->concretization; +} + +void IndependentConstraintSetUnion::addIndependentConstraintSetUnion( + const IndependentConstraintSetUnion &icsu) { + add(icsu); + concretization.addIndependentAssignment(icsu.concretization); + updateQueue.addIndependentAssignment(icsu.updateQueue); + removeQueue.addIndependentAssignment(icsu.removeQueue); + constraintQueue.insert(constraintQueue.begin(), icsu.constraintQueue.begin(), + icsu.constraintQueue.end()); +} + +void IndependentConstraintSetUnion::updateConcretization( + const Assignment &delta) { + for (auto &it : delta.bindings) { + updateQueue.bindings.replace({it.first, it.second}); + removeQueue.bindings.remove(it.first); + } +} + +void IndependentConstraintSetUnion::removeConcretization( + const Assignment &remove) { + for (auto &it : remove.bindings) { + removeQueue.bindings.replace({it.first, it.second}); + updateQueue.bindings.remove(it.first); + } +} + +void IndependentConstraintSetUnion::calculateUpdateConcretizationQueue() { + for (auto &e : roots) { + ref ics = disjointSets.at(e); + Assignment part = updateQueue.part(ics->getSymcretes()); + ics = ics->updateConcretization(part, concretizedExprs); + disjointSets.insert_or_assign(e, ics); + } + for (auto &it : updateQueue.bindings) { + concretization.bindings.replace({it.first, it.second}); + } +} + +void IndependentConstraintSetUnion::calculateRemoveConcretizationQueue() { + for (auto &e : roots) { + ref ics = disjointSets.at(e); + Assignment part = removeQueue.part(ics->getSymcretes()); + ics = ics->removeConcretization(part, concretizedExprs); + disjointSets.insert_or_assign(e, ics); + } + for (auto &it : removeQueue.bindings) { + concretization.bindings.remove(it.first); + } +} + +void IndependentConstraintSetUnion::reEvaluateConcretization( + const Assignment &newConcretization) { + Assignment delta; + Assignment removed; + for (const auto &it : concretization) { + if (newConcretization.bindings.count(it.first) == 0) { + removed.bindings.insert(it); + } else if (newConcretization.bindings.at(it.first) != it.second) { + delta.bindings.insert(*(newConcretization.bindings.find(it.first))); + } + } + updateConcretization(delta); + removeConcretization(removed); +} + +void IndependentConstraintSetUnion::getAllIndependentConstraintSets( + ref e, std::vector> &result) { + calculateQueue(); + ref compare = + new IndependentConstraintSet(new ExprOrSymcrete::left(e)); + for (auto &r : roots) { + ref ics = disjointSets.at(r); + if (!IndependentConstraintSet::intersects(ics, compare)) { + result.push_back(ics); + } + } +} + +void IndependentConstraintSetUnion::getAllDependentConstraintSets( + ref e, std::vector> &result) { + calculateQueue(); + ref compare = + new IndependentConstraintSet(new ExprOrSymcrete::left(e)); + for (auto &r : roots) { + ref ics = disjointSets.at(r); + if (IndependentConstraintSet::intersects(ics, compare)) { + result.push_back(ics); + } + } +} + +void IndependentConstraintSetUnion::addExpr(ref e) { + constraintQueue.push_back(new ExprOrSymcrete::left(e)); +} + +void IndependentConstraintSetUnion::addSymcrete(ref s) { + constraintQueue.push_back(new ExprOrSymcrete::right(s)); +} + +IndependentConstraintSetUnion +IndependentConstraintSetUnion::getConcretizedVersion() { + calculateQueue(); + IndependentConstraintSetUnion icsu; + for (auto &i : roots) { + ref root = disjointSets.at(i); + if (root->concretization.bindings.empty()) { + for (ref expr : root->exprs) { + icsu.addValue(new ExprOrSymcrete::left(expr)); + } + } else { + icsu.add(root->concretizedSets); + } + icsu.concretization.addIndependentAssignment(root->concretization); + } + icsu.concretizedExprs = concretizedExprs; + icsu.calculateQueue(); + return icsu; +} + +IndependentConstraintSetUnion +IndependentConstraintSetUnion::getConcretizedVersion( + const Assignment &newConcretization) { + calculateQueue(); + IndependentConstraintSetUnion icsu = *this; + icsu.reEvaluateConcretization(newConcretization); + icsu.calculateQueue(); + return icsu.getConcretizedVersion(); +} + +void IndependentConstraintSetUnion::calculateQueue() { + calculateUpdateConcretizationQueue(); + calculateRemoveConcretizationQueue(); + while (!constraintQueue.empty()) { + addValue(constraintQueue[constraintQueue.size() - 1]); + constraintQueue.pop_back(); + } + calculateUpdateConcretizationQueue(); + calculateRemoveConcretizationQueue(); + // Calculations are done twice for constraints already in dsu and for newly + // added constraints. Because IndependentSet update and remove concretization + // functions work only with difference between new and old concretization, no + // extra work is done + removeQueue.bindings = Assignment::bindings_ty(); + updateQueue.bindings = Assignment::bindings_ty(); +} +} // namespace klee diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index d4fade9ef1..888dc52fdd 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -1,6 +1,7 @@ #include "klee/Expr/IndependentSet.h" #include "klee/ADT/Ref.h" +#include "klee/Expr/Assignment.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" @@ -15,10 +16,122 @@ #include namespace klee { +ref +IndependentConstraintSet::updateConcretization( + const Assignment &delta, ExprHashMap> &concretizedExprs) const { + ref ics = new IndependentConstraintSet(*this); + if (delta.bindings.size() == 0) { + return ics; + } + for (auto &i : delta.bindings) { + ics->concretization.bindings.replace({i.first, i.second}); + } + InnerSetUnion DSU; + for (ref i : exprs) { + ref e = ics->concretization.evaluate(i); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + concretizedExprs[i] = e; + DSU.addValue(new ExprOrSymcrete::left(e)); + } + for (ref s : symcretes) { + ref e = EqExpr::create(ics->concretization.evaluate(s->symcretized), + s->symcretized); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprOrSymcrete::left(e)); + } + auto concretizationConstraints = + ics->concretization.createConstraintsFromAssignment(); + for (ref e : concretizationConstraints) { + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprOrSymcrete::left(e)); + } + ics->concretizedSets = DSU; + return ics; +} + +ref +IndependentConstraintSet::removeConcretization( + const Assignment &delta, ExprHashMap> &concretizedExprs) const { + ref ics = new IndependentConstraintSet(*this); + if (delta.bindings.size() == 0) { + return ics; + } + for (auto &i : delta.bindings) { + ics->concretization.bindings.remove(i.first); + } + InnerSetUnion DSU; + for (ref i : exprs) { + ref e = ics->concretization.evaluate(i); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + concretizedExprs[i] = e; + DSU.addValue(new ExprOrSymcrete::left(e)); + } + for (ref s : symcretes) { + ref e = EqExpr::create(ics->concretization.evaluate(s->symcretized), + s->symcretized); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprOrSymcrete::left(e)); + } + auto concretizationConstraints = + ics->concretization.createConstraintsFromAssignment(); + for (ref e : concretizationConstraints) { + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprOrSymcrete::left(e)); + } -IndependentElementSet::IndependentElementSet() {} + ics->concretizedSets = DSU; + return ics; +} -IndependentElementSet::IndependentElementSet(ref e) { +void IndependentConstraintSet::addValuesToAssignment( + const std::vector &objects, + const std::vector> &values, + Assignment &assign) const { + for (unsigned i = 0; i < objects.size(); i++) { + if (assign.bindings.count(objects[i])) { + SparseStorage value = assign.bindings.at(objects[i]); + DenseSet ds = (elements.find(objects[i]))->second; + for (std::set::iterator it2 = ds.begin(); it2 != ds.end(); + it2++) { + unsigned index = *it2; + value.store(index, values[i].load(index)); + } + assign.bindings.replace({objects[i], value}); + } else { + assign.bindings.replace({objects[i], values[i]}); + } + } +} + +IndependentConstraintSet::IndependentConstraintSet() {} + +IndependentConstraintSet::IndependentConstraintSet(ref v) { + if (isa(v)) { + initIndependentConstraintSet(cast(v)->value()); + } else { + initIndependentConstraintSet(cast(v)->value()); + } +} + +void IndependentConstraintSet::initIndependentConstraintSet(ref e) { exprs.insert(e); // Track all reads in the program. Determines whether reads are // concrete or symbolic. If they are symbolic, "collapses" array @@ -39,25 +152,25 @@ IndependentElementSet::IndependentElementSet(ref e) { if (ConstantExpr *CE = dyn_cast(re->index)) { // if index constant, then add to set of constraints operating // on that array (actually, don't add constraint, just set index) - DenseSet &dis = elements[array]; + DenseSet dis; + if (elements.find(array) != elements.end()) { + dis = (elements.find(array))->second; + } dis.add((unsigned)CE->getZExtValue(32)); + elements.replace({array, dis}); } else { elements_ty::iterator it2 = elements.find(array); if (it2 != elements.end()) - elements.erase(it2); + elements.remove(it2->first); wholeObjects.insert(array); } } } } -IndependentElementSet::IndependentElementSet(ref s) { +void IndependentConstraintSet::initIndependentConstraintSet(ref s) { symcretes.insert(s); - for (Symcrete &dependentSymcrete : s->dependentSymcretes()) { - symcretes.insert(ref(&dependentSymcrete)); - } - // Track all reads in the program. Determines whether reads are // concrete or symbolic. If they are symbolic, "collapses" array // by adding it to wholeObjects. Otherwise, creates a mapping of @@ -93,35 +206,33 @@ IndependentElementSet::IndependentElementSet(ref s) { if (ConstantExpr *CE = dyn_cast(re->index)) { // if index constant, then add to set of constraints operating // on that array (actually, don't add constraint, just set index) - DenseSet &dis = elements[array]; + DenseSet dis; + if (elements.find(array) != elements.end()) { + dis = (elements.find(array))->second; + } dis.add((unsigned)CE->getZExtValue(32)); + elements.replace({array, dis}); } else { elements_ty::iterator it2 = elements.find(array); if (it2 != elements.end()) - elements.erase(it2); + elements.remove(it2->first); wholeObjects.insert(array); } } } } -IndependentElementSet::IndependentElementSet(const IndependentElementSet &ies) - : elements(ies.elements), wholeObjects(ies.wholeObjects), exprs(ies.exprs) { -} - -IndependentElementSet & -IndependentElementSet::operator=(const IndependentElementSet &ies) { - elements = ies.elements; - wholeObjects = ies.wholeObjects; - exprs = ies.exprs; - return *this; -} +IndependentConstraintSet::IndependentConstraintSet( + const IndependentConstraintSet &ics) + : elements(ics.elements), wholeObjects(ics.wholeObjects), exprs(ics.exprs), + symcretes(ics.symcretes), concretization(ics.concretization), + concretizedSets(ics.concretizedSets) {} -void IndependentElementSet::print(llvm::raw_ostream &os) const { +void IndependentConstraintSet::print(llvm::raw_ostream &os) const { os << "{"; bool first = true; - for (std::set::iterator it = wholeObjects.begin(), - ie = wholeObjects.end(); + for (PersistentSet::iterator it = wholeObjects.begin(), + ie = wholeObjects.end(); it != ie; ++it) { const Array *array = *it; @@ -133,7 +244,7 @@ void IndependentElementSet::print(llvm::raw_ostream &os) const { os << "MO" << array->getIdentifier(); } - for (elements_ty::const_iterator it = elements.begin(), ie = elements.end(); + for (elements_ty::iterator it = elements.begin(), ie = elements.end(); it != ie; ++it) { const Array *array = it->first; const DenseSet &dis = it->second; @@ -149,218 +260,155 @@ void IndependentElementSet::print(llvm::raw_ostream &os) const { os << "}"; } -// more efficient when this is the smaller set -bool IndependentElementSet::intersects(const IndependentElementSet &b) { +bool IndependentConstraintSet::intersects( + ref a, + ref b) { + if (a->wholeObjects.size() + a->elements.size() > + b->wholeObjects.size() + b->elements.size()) { + std::swap(a, b); + } // If there are any symbolic arrays in our query that b accesses - for (std::set::iterator it = wholeObjects.begin(), - ie = wholeObjects.end(); + for (PersistentSet::iterator it = a->wholeObjects.begin(), + ie = a->wholeObjects.end(); it != ie; ++it) { const Array *array = *it; - if (b.wholeObjects.count(array) || - b.elements.find(array) != b.elements.end()) + if (b->wholeObjects.count(array) || + b->elements.find(array) != b->elements.end()) return true; } - for (elements_ty::iterator it = elements.begin(), ie = elements.end(); + for (elements_ty::iterator it = a->elements.begin(), ie = a->elements.end(); it != ie; ++it) { const Array *array = it->first; // if the array we access is symbolic in b - if (b.wholeObjects.count(array)) + if (b->wholeObjects.count(array)) return true; - elements_ty::const_iterator it2 = b.elements.find(array); + elements_ty::iterator it2 = b->elements.find(array); // if any of the elements we access are also accessed by b - if (it2 != b.elements.end()) { - if (it->second.intersects(it2->second)) + if (it2 != b->elements.end()) { + if (it->second.intersects(it2->second)) { return true; + } } } // No need to check symcretes here, arrays must be sufficient. return false; } -// returns true iff set is changed by addition -bool IndependentElementSet::add(const IndependentElementSet &b) { - for (auto expr : b.exprs) { - exprs.insert(expr); - } +ref +IndependentConstraintSet::merge(ref A, + ref B) { + ref a = new IndependentConstraintSet(*A); + ref b = new IndependentConstraintSet(*B); - for (const ref &symcrete : b.symcretes) { - symcretes.insert(symcrete); + if (a->wholeObjects.size() + a->elements.size() < + b->wholeObjects.size() + b->elements.size()) { + std::swap(a, b); + } + for (ref expr : b->exprs) { + a->exprs.insert(expr); + } + for (const ref &symcrete : b->symcretes) { + a->symcretes.insert(symcrete); } - bool modified = false; - for (std::set::const_iterator it = b.wholeObjects.begin(), - ie = b.wholeObjects.end(); + for (PersistentSet::iterator it = b->wholeObjects.begin(), + ie = b->wholeObjects.end(); it != ie; ++it) { const Array *array = *it; - elements_ty::iterator it2 = elements.find(array); - if (it2 != elements.end()) { - modified = true; - elements.erase(it2); - wholeObjects.insert(array); + elements_ty::iterator it2 = a->elements.find(array); + if (it2 != a->elements.end()) { + a->elements.remove(it2->first); + a->wholeObjects.insert(array); } else { - if (!wholeObjects.count(array)) { - modified = true; - wholeObjects.insert(array); + if (!a->wholeObjects.count(array)) { + a->wholeObjects.insert(array); } } } - for (elements_ty::const_iterator it = b.elements.begin(), - ie = b.elements.end(); + for (elements_ty::iterator it = b->elements.begin(), ie = b->elements.end(); it != ie; ++it) { const Array *array = it->first; - if (!wholeObjects.count(array)) { - elements_ty::iterator it2 = elements.find(array); - if (it2 == elements.end()) { - modified = true; - elements.insert(*it); + if (!a->wholeObjects.count(array)) { + elements_ty::iterator it2 = a->elements.find(array); + if (it2 == a->elements.end()) { + a->elements.insert(*it); } else { - // Now need to see if there are any (z=?)'s - if (it2->second.add(it->second)) - modified = true; + DenseSet dis = it2->second; + dis.add(it->second); + a->elements.replace({array, dis}); } } } - return modified; -} - -// Breaks down a constraint into all of it's individual pieces, returning a -// list of IndependentElementSets or the independent factors. -// -// Caller takes ownership of returned std::list. -std::list * -getAllIndependentConstraintsSets(const Query &query) { - std::list *factors = - new std::list(); - ConstantExpr *CE = dyn_cast(query.expr); - if (CE) { - assert(CE && CE->isFalse() && - "the expr should always be false and " - "therefore not included in factors"); - } else { - ref neg = Expr::createIsZero(query.expr); - factors->push_back(IndependentElementSet(neg)); - } - - for (const auto &constraint : query.constraints.cs()) { - // iterate through all the previously separated constraints. Until we - // actually return, factors is treated as a queue of expressions to be - // evaluated. If the queue property isn't maintained, then the exprs - // could be returned in an order different from how they came it, negatively - // affecting later stages. - factors->push_back(IndependentElementSet(constraint)); - } - - for (const auto &symcrete : query.constraints.symcretes()) { - factors->push_back(IndependentElementSet(symcrete)); - } - - bool doneLoop = false; - do { - doneLoop = true; - std::list *done = - new std::list; - while (factors->size() > 0) { - IndependentElementSet current = factors->front(); - factors->pop_front(); - // This list represents the set of factors that are separate from current. - // Those that are not inserted into this list (queue) intersect with - // current. - std::list *keep = - new std::list; - while (factors->size() > 0) { - IndependentElementSet compare = factors->front(); - factors->pop_front(); - if (current.intersects(compare)) { - if (current.add(compare)) { - // Means that we have added (z=y)added to (x=y) - // Now need to see if there are any (z=?)'s - doneLoop = false; - } - } else { - keep->push_back(compare); - } + b->addValuesToAssignment(b->concretization.keys(), b->concretization.values(), + a->concretization); + + if (!a->concretization.bindings.empty()) { + InnerSetUnion DSU; + for (ref i : a->exprs) { + ref e = a->concretization.evaluate(i); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; } - done->push_back(current); - delete factors; - factors = keep; + DSU.addValue(new ExprOrSymcrete::left(e)); + } + for (ref s : a->symcretes) { + ref e = EqExpr::create(a->concretization.evaluate(s->symcretized), + s->symcretized); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprOrSymcrete::left(e)); + } + auto concretizationConstraints = + a->concretization.createConstraintsFromAssignment(); + for (ref e : concretizationConstraints) { + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprOrSymcrete::left(e)); } - delete factors; - factors = done; - } while (!doneLoop); - - return factors; -} - -IndependentElementSet getIndependentConstraints(const Query &query, - constraints_ty &result) { - IndependentElementSet eltsClosure(query.expr); - std::vector, IndependentElementSet>> worklist; - - for (const auto &constraint : query.constraints.cs()) - worklist.push_back( - std::make_pair(constraint, IndependentElementSet(constraint))); - for (const ref &symcrete : query.constraints.symcretes()) { - worklist.push_back( - std::make_pair(symcrete->symcretized, IndependentElementSet(symcrete))); + a->concretizedSets = DSU; } - // XXX This should be more efficient (in terms of low level copy stuff). - bool done = false; - do { - done = true; - std::vector, IndependentElementSet>> newWorklist; - for (std::vector, IndependentElementSet>>::iterator - it = worklist.begin(), - ie = worklist.end(); - it != ie; ++it) { - if (it->second.intersects(eltsClosure)) { - if (eltsClosure.add(it->second)) - done = false; - result.insert(it->first); - // Means that we have added (z=y)added to (x=y) - // Now need to see if there are any (z=?)'s - } else { - newWorklist.push_back(*it); - } - } - worklist.swap(newWorklist); - } while (!done); - - // KLEE_DEBUG( - // std::set> reqset(result.begin(), result.end()); - // errs() << "--\n"; errs() << "Q: " << query.expr << "\n"; - // errs() << "\telts: " << IndependentElementSet(query.expr) << "\n"; - // int i = 0; for (const auto &constraint - // : query.constraints) { - // errs() << "C" << i++ << ": " << constraint; - // errs() << " " - // << (reqset.count(constraint) ? "(required)" : "(independent)") - // << "\n"; - // errs() << "\telts: " << IndependentElementSet(constraint) << "\n"; - // } errs() << "elts closure: " - // << eltsClosure << "\n";); - - return eltsClosure; + return a; } -void calculateArrayReferences(const IndependentElementSet &ie, - std::vector &returnVector) { +void IndependentConstraintSet::calculateArrayReferences( + std::vector &returnVector) const { std::set thisSeen; - for (std::map>::const_iterator it = - ie.elements.begin(); - it != ie.elements.end(); it++) { + for (IndependentConstraintSet::elements_ty::iterator it = elements.begin(); + it != elements.end(); ++it) { thisSeen.insert(it->first); } - for (std::set::iterator it = ie.wholeObjects.begin(); - it != ie.wholeObjects.end(); it++) { - assert(*it); + for (PersistentSet::iterator it = wholeObjects.begin(); + it != wholeObjects.end(); ++it) { thisSeen.insert(*it); } for (std::set::iterator it = thisSeen.begin(); - it != thisSeen.end(); it++) { + it != thisSeen.end(); ++it) { returnVector.push_back(*it); } } +void calculateArraysInFactors( + const std::vector> &factors, + ref queryExpr, std::vector &returnVector) { + std::set returnSet; + for (ref ics : factors) { + std::vector result; + ics->calculateArrayReferences(result); + returnSet.insert(result.begin(), result.end()); + } + std::vector result; + ref queryExprSet = + new IndependentConstraintSet(new ExprOrSymcrete::left(queryExpr)); + queryExprSet->calculateArrayReferences(result); + returnSet.insert(result.begin(), result.end()); + returnVector.insert(returnVector.begin(), returnSet.begin(), returnSet.end()); +} + } // namespace klee diff --git a/lib/Expr/Lexer.cpp b/lib/Expr/Lexer.cpp index 9be58ae5ce..acbb29b9dc 100644 --- a/lib/Expr/Lexer.cpp +++ b/lib/Expr/Lexer.cpp @@ -54,6 +54,10 @@ const char *Token::getKindName() const { return "KWQuery"; case KWPath: return "KWPath"; + case KWDefault: + return "KWDefault"; + case KWNull: + return "KWNull"; case KWReserved: return "KWReserved"; case KWSymbolic: @@ -180,6 +184,8 @@ Token &Lexer::SetIdentifierTokenKind(Token &Result) { return SetTokenKind(Result, Token::KWTrue); if (memcmp("path", Result.start, 4) == 0) return SetTokenKind(Result, Token::KWPath); + if (memcmp("null", Result.start, 4) == 0) + return SetTokenKind(Result, Token::KWNull); break; case 5: @@ -199,6 +205,8 @@ Token &Lexer::SetIdentifierTokenKind(Token &Result) { case 7: if (memcmp("declare", Result.start, 7) == 0) return SetTokenKind(Result, Token::KWReserved); + if (memcmp("default", Result.start, 7) == 0) + return SetTokenKind(Result, Token::KWDefault); break; case 8: diff --git a/lib/Expr/Parser.cpp b/lib/Expr/Parser.cpp index b072cec826..a144437fd8 100644 --- a/lib/Expr/Parser.cpp +++ b/lib/Expr/Parser.cpp @@ -280,6 +280,8 @@ class ParserImpl : public Parser { } } + ArrayCache &getArrayCache() { return *TheArrayCache; } + /*** Grammar productions ****/ /* Top level decls */ @@ -322,7 +324,6 @@ class ParserImpl : public Parser { SourceResult ParseSource(); SourceResult ParseConstantSource(); - SourceResult ParseSymbolicSizeConstantSource(); SourceResult ParseSymbolicSizeConstantAddressSource(); SourceResult ParseMakeSymbolicSource(); SourceResult ParseLazyInitializationContentSource(); @@ -330,6 +331,7 @@ class ParserImpl : public Parser { SourceResult ParseLazyInitializationSizeSource(); SourceResult ParseInstructionSource(); SourceResult ParseArgumentSource(); + SourceResult ParseAlphaSource(); /*** Diagnostics ***/ @@ -483,8 +485,6 @@ SourceResult ParserImpl::ParseSource() { SourceResult source; if (type == "constant") { source = ParseConstantSource(); - } else if (type == "symbolicSizeConstant") { - source = ParseSymbolicSizeConstantSource(); } else if (type == "symbolicSizeConstantAddress") { source = ParseSymbolicSizeConstantAddressSource(); } else if (type == "makeSymbolic") { @@ -501,6 +501,8 @@ SourceResult ParserImpl::ParseSource() { } else if (type == "argument") { assert(km); source = ParseArgumentSource(); + } else if (type == "alpha") { + source = ParseAlphaSource(); } else { assert(0); } @@ -509,39 +511,69 @@ SourceResult ParserImpl::ParseSource() { } SourceResult ParserImpl::ParseConstantSource() { - std::vector> Values; - ConsumeLSquare(); - while (Tok.kind != Token::RSquare) { - if (Tok.kind == Token::EndOfFile) { - Error("unexpected end of file."); - assert(0); + std::unordered_map> storage; + ref defaultValue = nullptr; + + if (Tok.kind == Token::LSquare) { + ConsumeLSquare(); + unsigned index = 0; + while (Tok.kind != Token::RSquare) { + if (Tok.kind == Token::EndOfFile) { + Error("unexpected end of file."); + assert(0); + } + ExprResult Res = ParseNumber(8).get(); // Should be Range Type + storage.insert({index, cast(Res.get())}); + if (Tok.kind == Token::Comma) { + ConsumeExpectedToken(Token::Comma); + } + index++; } - - ExprResult Res = ParseNumber(8); // Should be Range Type - if (Res.isValid()) - Values.push_back(cast(Res.get())); + ConsumeRSquare(); + } else if (Tok.kind == Token::LBrace) { + ConsumeExpectedToken(Token::LBrace); + while (Tok.kind != Token::RBrace) { + if (Tok.kind == Token::EndOfFile) { + Error("unexpected end of file."); + assert(0); + } + ExprResult Index = ParseNumber(64).get(); + ConsumeExpectedToken(Token::Colon); + ExprResult Res = ParseNumber(8).get(); // Should be Range Type + storage.insert({cast(Index.get())->getZExtValue(), + cast(Res.get())}); + if (Tok.kind == Token::Comma) { + ConsumeExpectedToken(Token::Comma); + } + } + ConsumeExpectedToken(Token::RBrace); + } else { + assert(0 && "Parsing error"); } - ConsumeRSquare(); - return SourceBuilder::constant(Values); -} -SourceResult ParserImpl::ParseSymbolicSizeConstantSource() { - auto valueExpr = ParseNumber(64).get(); - if (auto ce = dyn_cast(valueExpr)) { - return SourceBuilder::symbolicSizeConstant(ce->getZExtValue()); + ConsumeExpectedToken(Token::KWDefault); + ConsumeExpectedToken(Token::Colon); + + if (Tok.kind != Token::KWNull) { + ExprResult DV = ParseNumber(8).get(); // Should be Range Type + defaultValue = cast(DV.get()); } else { - assert(0); + ConsumeExpectedToken(Token::KWNull); } + + SparseStorage> Values(storage, defaultValue); + return SourceBuilder::constant(Values); } SourceResult ParserImpl::ParseSymbolicSizeConstantAddressSource() { - auto valueExpr = ParseNumber(64).get(); - auto versionExpr = ParseNumber(64).get(); - auto value = dyn_cast(valueExpr); - auto version = dyn_cast(versionExpr); - assert(value && version); - return SourceBuilder::symbolicSizeConstantAddress(value->getZExtValue(), - version->getZExtValue()); + assert(0 && "unimplemented"); + // auto valueExpr = ParseNumber(64).get(); + // auto versionExpr = ParseNumber(64).get(); + // auto value = dyn_cast(valueExpr); + // auto version = dyn_cast(versionExpr); + // assert(value && version); + // return SourceBuilder::symbolicSizeConstantAddress(value->getZExtValue(), + // version->getZExtValue()); } SourceResult ParserImpl::ParseMakeSymbolicSource() { @@ -599,6 +631,12 @@ SourceResult ParserImpl::ParseInstructionSource() { return SourceBuilder::instruction(*KI->inst, index, km); } +SourceResult ParserImpl::ParseAlphaSource() { + auto indexExpr = ParseNumber(64).get(); + auto index = dyn_cast(indexExpr)->getZExtValue(); + return SourceBuilder::alpha(index); +} + /// ParseCommandDecl - Parse a command declaration. The lexer should /// be positioned at the opening '('. /// diff --git a/lib/Expr/Path.cpp b/lib/Expr/Path.cpp index 7b578aa30c..829e73b374 100644 --- a/lib/Expr/Path.cpp +++ b/lib/Expr/Path.cpp @@ -15,8 +15,8 @@ using namespace llvm; void Path::advance(KInstruction *ki) { if (KBlocks.empty()) { - firstInstruction = ki->index; - lastInstruction = ki->index; + firstInstruction = ki->getIndex(); + lastInstruction = ki->getIndex(); KBlocks.push_back(ki->parent); return; } @@ -24,8 +24,7 @@ void Path::advance(KInstruction *ki) { if (ki->parent != lastBlock) { KBlocks.push_back(ki->parent); } - lastInstruction = ki->index; - return; + lastInstruction = ki->getIndex(); } unsigned Path::KBlockSize() const { return KBlocks.size(); } @@ -40,67 +39,6 @@ Path::PathIndex Path::getCurrentIndex() const { return {KBlocks.size() - 1, lastInstruction}; } -std::vector Path::getStack(bool reversed) const { - std::vector stack; - for (unsigned i = 0; i < KBlocks.size(); i++) { - auto current = reversed ? KBlocks[KBlocks.size() - 1 - i] : KBlocks[i]; - // Previous for reversed is the next - KBlock *prev = nullptr; - if (i != 0) { - prev = reversed ? KBlocks[KBlocks.size() - i] : KBlocks[i - 1]; - } - if (i == 0) { - stack.push_back({nullptr, current->parent}); - continue; - } - if (reversed) { - auto kind = getTransitionKind(current, prev); - if (kind == TransitionKind::StepInto) { - if (!stack.empty()) { - stack.pop_back(); - } - } else if (kind == TransitionKind::StepOut) { - assert(isa(prev)); - stack.push_back({prev->getFirstInstruction(), current->parent}); - } - } else { - auto kind = getTransitionKind(prev, current); - if (kind == TransitionKind::StepInto) { - stack.push_back({prev->getFirstInstruction(), current->parent}); - } else if (kind == TransitionKind::StepOut) { - if (!stack.empty()) { - stack.pop_back(); - } - } - } - } - return stack; -} - -std::vector> -Path::asFunctionRanges() const { - assert(!KBlocks.empty()); - std::vector> ranges; - BlockRange range{0, 0}; - KFunction *function = KBlocks[0]->parent; - for (unsigned i = 1; i < KBlocks.size(); i++) { - if (getTransitionKind(KBlocks[i - 1], KBlocks[i]) == TransitionKind::None) { - if (i == KBlocks.size() - 1) { - range.last = i; - ranges.push_back({function, range}); - return ranges; - } else { - continue; - } - } - range.last = i - 1; - ranges.push_back({function, range}); - range.first = i; - function = KBlocks[i]->parent; - } - llvm_unreachable("asFunctionRanges reached the end of the for!"); -} - Path Path::concat(const Path &l, const Path &r) { Path path = l; for (auto block : r.KBlocks) { @@ -113,11 +51,16 @@ Path Path::concat(const Path &l, const Path &r) { std::string Path::toString() const { std::string blocks = ""; unsigned depth = 0; - for (unsigned i = 0; i < KBlocks.size(); i++) { - auto current = KBlocks[i]; + std::vector KBlocksVector; + KBlocksVector.reserve(KBlocks.size()); + for (auto kblock : KBlocks) { + KBlocksVector.push_back(kblock); + } + for (size_t i = 0; i < KBlocksVector.size(); i++) { + auto current = KBlocksVector[i]; KBlock *prev = nullptr; if (i != 0) { - prev = KBlocks[i - 1]; + prev = KBlocksVector[i - 1]; } auto kind = i == 0 ? TransitionKind::StepInto : getTransitionKind(prev, current); diff --git a/lib/Expr/SourceBuilder.cpp b/lib/Expr/SourceBuilder.cpp index a667a19ba2..866f89da6d 100644 --- a/lib/Expr/SourceBuilder.cpp +++ b/lib/Expr/SourceBuilder.cpp @@ -1,4 +1,5 @@ #include "klee/Expr/SourceBuilder.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Expr/Expr.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Module/KModule.h" @@ -6,23 +7,23 @@ using namespace klee; ref -SourceBuilder::constant(const std::vector> &constantValues) { +SourceBuilder::constant(SparseStorage> constantValues) { ref r(new ConstantSource(constantValues)); r->computeHash(); return r; } -ref SourceBuilder::symbolicSizeConstant(unsigned defaultValue) { - ref r(new SymbolicSizeConstantSource(defaultValue)); +ref +SourceBuilder::uninitialized(unsigned version, const KInstruction *allocSite) { + ref r(new UninitializedSource(version, allocSite)); r->computeHash(); return r; } -ref -SourceBuilder::symbolicSizeConstantAddress(unsigned defaultValue, - unsigned version) { +ref SourceBuilder::symbolicSizeConstantAddress( + unsigned version, const KInstruction *allocSite, ref size) { ref r( - new SymbolicSizeConstantAddressSource(defaultValue, version)); + new SymbolicSizeConstantAddressSource(version, allocSite, size)); r->computeHash(); return r; } @@ -86,4 +87,10 @@ ref SourceBuilder::irreproducible(const std::string &name) { ref r(new IrreproducibleSource(name + llvm::utostr(++id))); r->computeHash(); return r; -} \ No newline at end of file +} + +ref SourceBuilder::alpha(int _index) { + ref r(new AlphaSource(_index)); + r->computeHash(); + return r; +} diff --git a/lib/Expr/SymbolicSource.cpp b/lib/Expr/SymbolicSource.cpp index 0e7f8b1086..1f78147c2b 100644 --- a/lib/Expr/SymbolicSource.cpp +++ b/lib/Expr/SymbolicSource.cpp @@ -46,27 +46,74 @@ std::set LazyInitializationSource::getRelatedArrays() const { } unsigned ConstantSource::computeHash() { - unsigned res = 0; - for (unsigned i = 0, e = constantValues.size(); i != e; ++i) { - res = - (res * SymbolicSource::MAGIC_HASH_CONSTANT) + constantValues[i]->hash(); + auto defaultV = constantValues.defaultV(); + auto ordered = constantValues.calculateOrderedStorage(); + + unsigned res = (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + + (defaultV ? defaultV->hash() : 0); + + for (auto kv : ordered) { + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + kv.first; + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + kv.second->hash(); } - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + getKind(); + hashValue = res; return hashValue; } -unsigned SymbolicSizeConstantSource::computeHash() { - unsigned res = - (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + defaultValue; +unsigned UninitializedSource::computeHash() { + unsigned res = getKind(); + res = res * SymbolicSource::MAGIC_HASH_CONSTANT + version; + res = res * SymbolicSource::MAGIC_HASH_CONSTANT + allocSite->hash(); hashValue = res; return hashValue; } +int UninitializedSource::internalCompare(const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const UninitializedSource &ub = static_cast(b); + + if (version != ub.version) { + return version < ub.version ? -1 : 1; + } + + if (allocSite != ub.allocSite) { + return allocSite->getGlobalIndex() < ub.allocSite->getGlobalIndex() ? -1 + : 1; + } + + return 0; +} + +int SymbolicSizeConstantAddressSource::internalCompare( + const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const SymbolicSizeConstantAddressSource &ub = + static_cast(b); + + if (version != ub.version) { + return version < ub.version ? -1 : 1; + } + if (size != ub.size) { + return size < ub.size ? -1 : 1; + } + if (allocSite != ub.allocSite) { + return allocSite->getGlobalIndex() < ub.allocSite->getGlobalIndex() ? -1 + : 1; + } + + return 0; +} + unsigned SymbolicSizeConstantAddressSource::computeHash() { - unsigned res = - (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + defaultValue; - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + version; + unsigned res = getKind(); + res = res * MAGIC_HASH_CONSTANT + version; + res = res * MAGIC_HASH_CONSTANT + allocSite->hash(); + res = res * MAGIC_HASH_CONSTANT + size->hash(); hashValue = res; return hashValue; } @@ -98,9 +145,8 @@ int ArgumentSource::internalCompare(const SymbolicSource &b) const { assert(km == ab.km); auto parent = allocSite.getParent(); auto bParent = ab.allocSite.getParent(); - if (km->functionIDMap.at(parent) != km->functionIDMap.at(bParent)) { - return km->functionIDMap.at(parent) < km->functionIDMap.at(bParent) ? -1 - : 1; + if (km->getFunctionId(parent) != km->getFunctionId(bParent)) { + return km->getFunctionId(parent) < km->getFunctionId(bParent) ? -1 : 1; } if (allocSite.getArgNo() != ab.allocSite.getArgNo()) { return allocSite.getArgNo() < ab.allocSite.getArgNo() ? -1 : 1; @@ -118,21 +164,14 @@ int InstructionSource::internalCompare(const SymbolicSource &b) const { } assert(km == ib.km); auto function = allocSite.getParent()->getParent(); - auto bFunction = ib.allocSite.getParent()->getParent(); - if (km->functionIDMap.at(function) != km->functionIDMap.at(bFunction)) { - return km->functionIDMap.at(function) < km->functionIDMap.at(bFunction) ? -1 - : 1; - } auto kf = km->functionMap.at(function); - auto block = allocSite.getParent(); - auto bBlock = ib.allocSite.getParent(); - if (kf->blockMap[block]->id != kf->blockMap[bBlock]->id) { - return kf->blockMap[block]->id < kf->blockMap[bBlock]->id ? -1 : 1; - } - if (kf->instructionMap[&allocSite]->index != - kf->instructionMap[&ib.allocSite]->index) { - return kf->instructionMap[&allocSite]->index < - kf->instructionMap[&ib.allocSite]->index + auto bfunction = ib.allocSite.getParent()->getParent(); + auto bkf = km->functionMap.at(bfunction); + + if (kf->instructionMap[&allocSite]->getGlobalIndex() != + bkf->instructionMap[&ib.allocSite]->getGlobalIndex()) { + return kf->instructionMap[&allocSite]->getGlobalIndex() < + bkf->instructionMap[&ib.allocSite]->getGlobalIndex() ? -1 : 1; } @@ -142,8 +181,7 @@ int InstructionSource::internalCompare(const SymbolicSource &b) const { unsigned ArgumentSource::computeHash() { unsigned res = (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + index; auto parent = allocSite.getParent(); - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - km->functionIDMap.at(parent); + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + km->getFunctionId(parent); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + allocSite.getArgNo(); hashValue = res; return hashValue; @@ -154,11 +192,12 @@ unsigned InstructionSource::computeHash() { auto function = allocSite.getParent()->getParent(); auto kf = km->functionMap.at(function); auto block = allocSite.getParent(); + res = + (res * SymbolicSource::MAGIC_HASH_CONSTANT) + km->getFunctionId(function); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - km->functionIDMap.at(function); - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + kf->blockMap[block]->id; + kf->blockMap[block]->getId(); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - kf->instructionMap[&allocSite]->index; + kf->instructionMap[&allocSite]->getIndex(); hashValue = res; return hashValue; } diff --git a/lib/Expr/Updates.cpp b/lib/Expr/Updates.cpp index 6b740e3a72..b7bbad8cbc 100644 --- a/lib/Expr/Updates.cpp +++ b/lib/Expr/Updates.cpp @@ -25,6 +25,7 @@ UpdateNode::UpdateNode(const ref &_next, const ref &_index, "Update value should be 8-bit wide."); */ computeHash(); + computeHeight(); size = next ? next->size + 1 : 1; } @@ -45,6 +46,14 @@ unsigned UpdateNode::computeHash() { return hashValue; } +unsigned UpdateNode::computeHeight() { + unsigned maxHeight = next ? next->height() : 0; + maxHeight = std::max(maxHeight, index->height()); + maxHeight = std::max(maxHeight, value->height()); + heightValue = maxHeight; + return heightValue; +} + /// UpdateList::UpdateList(const Array *_root, const ref &_head) @@ -95,3 +104,5 @@ unsigned UpdateList::hash() const { res = (res * Expr::MAGIC_HASH_CONSTANT) + head->hash(); return res; } + +unsigned UpdateList::height() const { return head ? head->height() : 0; } diff --git a/lib/Module/CMakeLists.txt b/lib/Module/CMakeLists.txt index 0bdb2e67eb..bca27a10ea 100644 --- a/lib/Module/CMakeLists.txt +++ b/lib/Module/CMakeLists.txt @@ -8,10 +8,11 @@ #===------------------------------------------------------------------------===# set(KLEE_MODULE_COMPONENT_SRCS CallSplitter.cpp + CallRemover.cpp Checks.cpp - CodeGraphDistance.cpp + CodeGraphInfo.cpp FunctionAlias.cpp - InstructionInfoTable.cpp + LocationInfo.cpp InstructionOperandTypeCheckPass.cpp IntrinsicCleaner.cpp KInstruction.cpp diff --git a/lib/Module/CallRemover.cpp b/lib/Module/CallRemover.cpp new file mode 100644 index 0000000000..7c94f6d26e --- /dev/null +++ b/lib/Module/CallRemover.cpp @@ -0,0 +1,37 @@ +//===-- CallRemover.cpp----------------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Passes.h" +#include + +namespace klee { + +using namespace llvm; + +char CallRemover::ID; + +bool CallRemover::runOnModule(llvm::Module &M) { + std::vector badFuncs = {"llvm.dbg.declare", "llvm.dbg.label", + "llvm.dbg.value"}; + + for (const auto &f : badFuncs) { + auto Declare = M.getFunction(f); + if (!Declare) + continue; + while (!Declare->use_empty()) { + auto CI = cast(Declare->user_back()); + assert(CI->use_empty() && "deleted function must have void result"); + CI->eraseFromParent(); + } + Declare->eraseFromParent(); + } + + return true; +} +} // namespace klee diff --git a/lib/Module/CallSplitter.cpp b/lib/Module/CallSplitter.cpp index 4c4a71c4f3..a90e17516d 100644 --- a/lib/Module/CallSplitter.cpp +++ b/lib/Module/CallSplitter.cpp @@ -1,5 +1,4 @@ -//===-- CallSplitter.cpp -//-------------------------------------------------------===// +//===-- CallSplitter.cpp --------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -46,8 +45,9 @@ bool CallSplitter::runOnFunction(Function &F) { if (callInst != firstInst) { fbb = fbb->splitBasicBlock(callInst); } - if (isa(afterCallInst) && - cast(afterCallInst)->isUnconditional()) { + if ((isa(afterCallInst) && + cast(afterCallInst)->isUnconditional()) || + isa(afterCallInst)) { break; } fbb = fbb->splitBasicBlock(afterCallInst); diff --git a/lib/Module/CodeGraphDistance.cpp b/lib/Module/CodeGraphDistance.cpp deleted file mode 100644 index 54839c6cd3..0000000000 --- a/lib/Module/CodeGraphDistance.cpp +++ /dev/null @@ -1,202 +0,0 @@ -//===-- CodeGraphDistance.cpp -//---------------------------------------------------===// -// -// The KLEE Symbolic Virtual Machine -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "klee/Module/CodeGraphDistance.h" - -#include "klee/Support/CompilerWarning.h" -DISABLE_WARNING_PUSH -DISABLE_WARNING_DEPRECATED_DECLARATIONS -#include "llvm/IR/CFG.h" -DISABLE_WARNING_POP - -#include -#include - -using namespace klee; - -void CodeGraphDistance::calculateDistance(KBlock *bb) { - auto blockMap = bb->parent->blockMap; - std::unordered_map &dist = blockDistance[bb]; - std::vector> &sort = blockSortedDistance[bb]; - std::deque nodes; - nodes.push_back(bb); - dist[bb] = 0; - sort.push_back({bb, 0}); - while (!nodes.empty()) { - KBlock *currBB = nodes.front(); - for (auto const &succ : successors(currBB->basicBlock)) { - if (dist.count(blockMap[succ]) == 0) { - dist[blockMap[succ]] = dist[currBB] + 1; - sort.push_back({blockMap[succ], dist[currBB] + 1}); - nodes.push_back(blockMap[succ]); - } - } - nodes.pop_front(); - } -} - -void CodeGraphDistance::calculateBackwardDistance(KBlock *bb) { - auto blockMap = bb->parent->blockMap; - std::unordered_map &bdist = blockBackwardDistance[bb]; - std::vector> &bsort = - blockSortedBackwardDistance[bb]; - std::deque nodes; - nodes.push_back(bb); - bdist[bb] = 0; - bsort.push_back({bb, 0}); - while (!nodes.empty()) { - KBlock *currBB = nodes.front(); - for (auto const &pred : predecessors(currBB->basicBlock)) { - if (bdist.count(blockMap[pred]) == 0) { - bdist[blockMap[pred]] = bdist[currBB] + 1; - bsort.push_back({blockMap[pred], bdist[currBB] + 1}); - nodes.push_back(blockMap[pred]); - } - } - nodes.pop_front(); - } -} - -void CodeGraphDistance::calculateDistance(KFunction *kf) { - auto &functionMap = kf->parent->functionMap; - std::unordered_map &dist = functionDistance[kf]; - std::vector> &sort = - functionSortedDistance[kf]; - std::deque nodes; - nodes.push_back(kf); - dist[kf] = 0; - sort.push_back({kf, 0}); - while (!nodes.empty()) { - KFunction *currKF = nodes.front(); - for (auto &callBlock : currKF->kCallBlocks) { - for (auto &calledFunction : callBlock->calledFunctions) { - if (!calledFunction || calledFunction->isDeclaration()) { - continue; - } - KFunction *callKF = functionMap[calledFunction]; - if (dist.count(callKF) == 0) { - dist[callKF] = dist[currKF] + 1; - sort.push_back({callKF, dist[currKF] + 1}); - nodes.push_back(callKF); - } - } - } - nodes.pop_front(); - } -} - -void CodeGraphDistance::calculateBackwardDistance(KFunction *kf) { - auto &functionMap = kf->parent->functionMap; - auto &callMap = kf->parent->callMap; - std::unordered_map &bdist = - functionBackwardDistance[kf]; - std::vector> &bsort = - functionSortedBackwardDistance[kf]; - std::deque nodes; - nodes.push_back(kf); - bdist[kf] = 0; - bsort.push_back({kf, 0}); - while (!nodes.empty()) { - KFunction *currKF = nodes.front(); - for (auto &cf : callMap[currKF->function]) { - if (cf->isDeclaration()) { - continue; - } - KFunction *callKF = functionMap[cf]; - if (bdist.count(callKF) == 0) { - bdist[callKF] = bdist[currKF] + 1; - bsort.push_back({callKF, bdist[currKF] + 1}); - nodes.push_back(callKF); - } - } - nodes.pop_front(); - } -} - -const std::unordered_map & -CodeGraphDistance::getDistance(KBlock *kb) { - if (blockDistance.count(kb) == 0) - calculateDistance(kb); - return blockDistance.at(kb); -} - -const std::unordered_map & -CodeGraphDistance::getBackwardDistance(KBlock *kb) { - if (blockBackwardDistance.count(kb) == 0) - calculateBackwardDistance(kb); - return blockBackwardDistance.at(kb); -} - -const std::vector> & -CodeGraphDistance::getSortedDistance(KBlock *kb) { - if (blockDistance.count(kb) == 0) - calculateDistance(kb); - return blockSortedDistance.at(kb); -} - -const std::vector> & -CodeGraphDistance::getSortedBackwardDistance(KBlock *kb) { - if (blockBackwardDistance.count(kb) == 0) - calculateBackwardDistance(kb); - return blockSortedBackwardDistance.at(kb); -} - -const std::unordered_map & -CodeGraphDistance::getDistance(KFunction *kf) { - if (functionDistance.count(kf) == 0) - calculateDistance(kf); - return functionDistance.at(kf); -} - -const std::unordered_map & -CodeGraphDistance::getBackwardDistance(KFunction *kf) { - if (functionBackwardDistance.count(kf) == 0) - calculateBackwardDistance(kf); - return functionBackwardDistance.at(kf); -} - -const std::vector> & -CodeGraphDistance::getSortedDistance(KFunction *kf) { - if (functionDistance.count(kf) == 0) - calculateDistance(kf); - return functionSortedDistance.at(kf); -} - -const std::vector> & -CodeGraphDistance::getSortedBackwardDistance(KFunction *kf) { - if (functionBackwardDistance.count(kf) == 0) - calculateBackwardDistance(kf); - return functionSortedBackwardDistance.at(kf); -} - -void CodeGraphDistance::getNearestPredicateSatisfying( - KBlock *from, KBlockPredicate predicate, std::set &result) { - std::set visited; - - auto blockMap = from->parent->blockMap; - std::deque nodes; - nodes.push_back(from); - - while (!nodes.empty()) { - KBlock *currBB = nodes.front(); - visited.insert(currBB); - - if (predicate(currBB) && currBB != from) { - result.insert(currBB); - } else { - for (auto const &succ : successors(currBB->basicBlock)) { - if (visited.count(blockMap[succ]) == 0) { - nodes.push_back(blockMap[succ]); - } - } - } - nodes.pop_front(); - } -} diff --git a/lib/Module/CodeGraphInfo.cpp b/lib/Module/CodeGraphInfo.cpp new file mode 100644 index 0000000000..71bb259ee1 --- /dev/null +++ b/lib/Module/CodeGraphInfo.cpp @@ -0,0 +1,236 @@ +//===-- CodeGraphInfo.cpp -------------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Module/CodeGraphInfo.h" + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/IR/CFG.h" +DISABLE_WARNING_POP + +#include +#include + +using namespace klee; + +void CodeGraphInfo::calculateDistance(Block *bb) { + auto &dist = blockDistance[bb]; + auto &sort = blockSortedDistance[bb]; + std::deque nodes; + nodes.push_back(bb); + dist[bb] = 0; + sort.push_back({bb, 0}); + bool hasCycle = false; + for (; !nodes.empty(); nodes.pop_front()) { + auto currBB = nodes.front(); + for (auto succ : successors(currBB)) { + if (succ == bb) { + hasCycle = true; + continue; + } + if (dist.count(succ)) + continue; + auto d = dist[currBB] + 1; + dist.emplace(succ, d); + sort.push_back({succ, d}); + nodes.push_back(succ); + } + } + if (hasCycle) + blockCycles.insert(bb); +} + +void CodeGraphInfo::calculateBackwardDistance(Block *bb) { + auto &bdist = blockBackwardDistance[bb]; + auto &bsort = blockSortedBackwardDistance[bb]; + std::deque nodes; + nodes.push_back(bb); + bdist[bb] = 0; + bsort.push_back({bb, 0}); + while (!nodes.empty()) { + auto currBB = nodes.front(); + for (auto const &pred : predecessors(currBB)) { + if (bdist.count(pred) == 0) { + bdist[pred] = bdist[currBB] + 1; + bsort.push_back({pred, bdist[currBB] + 1}); + nodes.push_back(pred); + } + } + nodes.pop_front(); + } +} + +void CodeGraphInfo::calculateDistance(KFunction *kf) { + auto f = kf->function; + auto &functionMap = kf->parent->functionMap; + auto &dist = functionDistance[f]; + auto &sort = functionSortedDistance[f]; + std::deque nodes; + nodes.push_back(kf); + dist[f] = 0; + sort.push_back({f, 0}); + while (!nodes.empty()) { + auto currKF = nodes.front(); + for (auto callBlock : currKF->kCallBlocks) { + for (auto calledFunction : callBlock->calledFunctions) { + if (!calledFunction || calledFunction->isDeclaration()) + continue; + if (dist.count(calledFunction) == 0) { + auto d = dist[currKF->function] + 1; + dist[calledFunction] = d; + sort.emplace_back(calledFunction, d); + auto callKF = functionMap[calledFunction]; + nodes.push_back(callKF); + } + } + } + nodes.pop_front(); + } +} + +void CodeGraphInfo::calculateBackwardDistance(KFunction *kf) { + auto f = kf->function; + auto &callMap = kf->parent->callMap; + auto &bdist = functionBackwardDistance[f]; + auto &bsort = functionSortedBackwardDistance[f]; + std::deque nodes = {f}; + bdist[f] = 0; + bsort.emplace_back(f, 0); + for (; !nodes.empty(); nodes.pop_front()) { + auto currKF = nodes.front(); + for (auto cf : callMap[currKF]) { + if (cf->isDeclaration()) + continue; + auto it = bdist.find(cf); + if (it == bdist.end()) { + auto d = bdist[currKF] + 1; + bdist.emplace_hint(it, cf, d); + bsort.emplace_back(cf, d); + nodes.push_back(cf); + } + } + } +} + +void CodeGraphInfo::calculateFunctionBranches(KFunction *kf) { + std::map> &fbranches = functionBranches[kf]; + for (auto &kb : kf->blocks) { + fbranches[kb.get()]; + for (unsigned branch = 0; + branch < kb->basicBlock->getTerminator()->getNumSuccessors(); + ++branch) { + fbranches[kb.get()].insert(branch); + } + } +} +void CodeGraphInfo::calculateFunctionConditionalBranches(KFunction *kf) { + std::map> &fbranches = + functionConditionalBranches[kf]; + for (auto &kb : kf->blocks) { + if (kb->basicBlock->getTerminator()->getNumSuccessors() > 1) { + fbranches[kb.get()]; + for (unsigned branch = 0; + branch < kb->basicBlock->getTerminator()->getNumSuccessors(); + ++branch) { + fbranches[kb.get()].insert(branch); + } + } + } +} +void CodeGraphInfo::calculateFunctionBlocks(KFunction *kf) { + std::map> &fbranches = functionBlocks[kf]; + for (auto &kb : kf->blocks) { + fbranches[kb.get()]; + } +} + +const BlockDistanceMap &CodeGraphInfo::getDistance(Block *b) { + if (blockDistance.count(b) == 0) + calculateDistance(b); + return blockDistance.at(b); +} + +bool CodeGraphInfo::hasCycle(KBlock *kb) { + auto b = kb->basicBlock; + if (!blockDistance.count(b)) + calculateDistance(b); + return blockCycles.count(b); +} + +const BlockDistanceMap &CodeGraphInfo::getDistance(KBlock *kb) { + return getDistance(kb->basicBlock); +} + +const BlockDistanceMap &CodeGraphInfo::getBackwardDistance(KBlock *kb) { + if (blockBackwardDistance.count(kb->basicBlock) == 0) + calculateBackwardDistance(kb->basicBlock); + return blockBackwardDistance.at(kb->basicBlock); +} + +const FunctionDistanceMap &CodeGraphInfo::getDistance(KFunction *kf) { + auto f = kf->function; + if (functionDistance.count(f) == 0) + calculateDistance(kf); + return functionDistance.at(f); +} + +const FunctionDistanceMap &CodeGraphInfo::getBackwardDistance(KFunction *kf) { + auto f = kf->function; + if (functionBackwardDistance.count(f) == 0) + calculateBackwardDistance(kf); + return functionBackwardDistance.at(f); +} + +void CodeGraphInfo::getNearestPredicateSatisfying(KBlock *from, + KBlockPredicate predicate, + std::set &result) { + std::set visited; + + auto blockMap = from->parent->blockMap; + std::deque nodes; + nodes.push_back(from); + + while (!nodes.empty()) { + KBlock *currBB = nodes.front(); + visited.insert(currBB); + + if (predicate(currBB) && currBB != from) { + result.insert(currBB); + } else { + for (auto succ : successors(currBB->basicBlock)) { + if (visited.count(blockMap[succ]) == 0) { + nodes.push_back(blockMap[succ]); + } + } + } + nodes.pop_front(); + } +} + +const std::map> & +CodeGraphInfo::getFunctionBranches(KFunction *kf) { + if (functionBranches.count(kf) == 0) + calculateFunctionBranches(kf); + return functionBranches.at(kf); +} + +const std::map> & +CodeGraphInfo::getFunctionConditionalBranches(KFunction *kf) { + if (functionConditionalBranches.count(kf) == 0) + calculateFunctionConditionalBranches(kf); + return functionConditionalBranches.at(kf); +} + +const std::map> & +CodeGraphInfo::getFunctionBlocks(KFunction *kf) { + if (functionBlocks.count(kf) == 0) + calculateFunctionBlocks(kf); + return functionBlocks.at(kf); +} diff --git a/lib/Module/InstructionInfoTable.cpp b/lib/Module/InstructionInfoTable.cpp deleted file mode 100644 index ee66e91cbf..0000000000 --- a/lib/Module/InstructionInfoTable.cpp +++ /dev/null @@ -1,230 +0,0 @@ -//===-- InstructionInfoTable.cpp ------------------------------------------===// -// -// The KLEE Symbolic Virtual Machine -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "klee/Module/InstructionInfoTable.h" -#include "klee/Config/Version.h" - -#include "klee/Support/CompilerWarning.h" -DISABLE_WARNING_PUSH -DISABLE_WARNING_DEPRECATED_DECLARATIONS -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/AssemblyAnnotationWriter.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Linker/Linker.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -DISABLE_WARNING_POP - -#include -#include -#include - -using namespace klee; - -class InstructionToLineAnnotator : public llvm::AssemblyAnnotationWriter { -private: - std::unordered_map mapping = {}; - -public: - void emitInstructionAnnot(const llvm::Instruction *i, - llvm::formatted_raw_ostream &os) override { - os.flush(); - mapping.emplace(reinterpret_cast(i), os.getLine() + 1); - } - - void emitFunctionAnnot(const llvm::Function *f, - llvm::formatted_raw_ostream &os) override { - os.flush(); - mapping.emplace(reinterpret_cast(f), os.getLine() + 1); - } - - std::unordered_map getMapping() const { return mapping; } -}; - -static std::unordered_map -buildInstructionToLineMap(const llvm::Module &m, - std::unique_ptr assemblyFS) { - - InstructionToLineAnnotator a; - - m.print(*assemblyFS, &a); - assemblyFS->flush(); - - return a.getMapping(); -} - -class DebugInfoExtractor { - std::vector> &internedStrings; - std::unordered_map lineTable; - - const llvm::Module &module; - bool withAsm = false; - -public: - DebugInfoExtractor( - std::vector> &_internedStrings, - const llvm::Module &_module, - std::unique_ptr assemblyFS) - : internedStrings(_internedStrings), module(_module) { - if (assemblyFS) { - withAsm = true; - lineTable = buildInstructionToLineMap(module, std::move(assemblyFS)); - } - } - - std::string &getInternedString(const std::string &s) { - auto found = std::find_if(internedStrings.begin(), internedStrings.end(), - [&s](const std::unique_ptr &item) { - return *item.get() == s; - }); - if (found != internedStrings.end()) - return *found->get(); - - auto newItem = std::unique_ptr(new std::string(s)); - auto result = newItem.get(); - - internedStrings.emplace_back(std::move(newItem)); - return *result; - } - - std::unique_ptr getFunctionInfo(const llvm::Function &Func) { - llvm::Optional asmLine; - if (withAsm) { - asmLine = lineTable.at(reinterpret_cast(&Func)); - } - auto dsub = Func.getSubprogram(); - - if (dsub != nullptr) { - auto path = dsub->getFilename(); - return std::make_unique(FunctionInfo( - 0, getInternedString(path.str()), dsub->getLine(), asmLine)); - } - - // Fallback: Mark as unknown - return std::make_unique( - FunctionInfo(0, getInternedString(""), 0, asmLine)); - } - - std::unique_ptr - getInstructionInfo(const llvm::Instruction &Inst, const FunctionInfo *f) { - llvm::Optional asmLine; - if (withAsm) { - asmLine = lineTable.at(reinterpret_cast(&Inst)); - } - - // Retrieve debug information associated with instruction - auto dl = Inst.getDebugLoc(); - - // Check if a valid debug location is assigned to the instruction. - if (dl.get() != nullptr) { - auto full_path = dl.get()->getFilename(); - auto line = dl.getLine(); - auto column = dl.getCol(); - - // Still, if the line is unknown, take the context of the instruction to - // narrow it down - if (line == 0) { - if (auto LexicalBlock = - llvm::dyn_cast(dl.getScope())) { - line = LexicalBlock->getLine(); - column = LexicalBlock->getColumn(); - } - } - return std::make_unique(InstructionInfo( - 0, getInternedString(full_path.str()), line, column, asmLine)); - } - - if (f != nullptr) - // If nothing found, use the surrounding function - return std::make_unique( - InstructionInfo(0, f->file, f->line, 0, asmLine)); - // If nothing found, use the surrounding function - return std::make_unique( - InstructionInfo(0, getInternedString(""), 0, 0, asmLine)); - } -}; - -InstructionInfoTable::InstructionInfoTable( - const llvm::Module &m, std::unique_ptr assemblyFS, - bool withInstructions) { - // Generate all debug instruction information - DebugInfoExtractor DI(internedStrings, m, std::move(assemblyFS)); - - for (const auto &Func : m) { - auto F = DI.getFunctionInfo(Func); - auto FR = F.get(); - functionInfos.emplace(&Func, std::move(F)); - - for (auto it = llvm::inst_begin(Func), ie = llvm::inst_end(Func); it != ie; - ++it) { - auto instr = &*it; - auto instInfo = DI.getInstructionInfo(*instr, FR); - if (withInstructions) { - insts[instInfo->file][instInfo->line][instInfo->column].insert( - instr->getOpcode()); - } - filesNames.insert(instInfo->file); - fileNameToFunctions[instInfo->file].insert(&Func); - infos.emplace(instr, std::move(instInfo)); - } - } - - // Make sure that every item has a unique ID - size_t idCounter = 0; - for (auto &item : infos) - item.second->id = idCounter++; - for (auto &item : functionInfos) - item.second->id = idCounter++; -} - -unsigned InstructionInfoTable::getMaxID() const { - return infos.size() + functionInfos.size(); -} - -const InstructionInfo & -InstructionInfoTable::getInfo(const llvm::Instruction &inst) const { - auto it = infos.find(&inst); - if (it == infos.end()) - llvm::report_fatal_error("invalid instruction, not present in " - "initial module!"); - return *it->second.get(); -} - -const FunctionInfo & -InstructionInfoTable::getFunctionInfo(const llvm::Function &f) const { - auto found = functionInfos.find(&f); - if (found == functionInfos.end()) - llvm::report_fatal_error("invalid instruction, not present in " - "initial module!"); - - return *found->second.get(); -} - -const InstructionInfoTable::LocationToFunctionsMap & -InstructionInfoTable::getFileNameToFunctions() const { - return fileNameToFunctions; -} - -const std::unordered_set & -InstructionInfoTable::getFilesNames() const { - return filesNames; -} - -InstructionInfoTable::Instructions InstructionInfoTable::getInstructions() { - return std::move(insts); -} diff --git a/lib/Module/KInstruction.cpp b/lib/Module/KInstruction.cpp index f7159c4bd6..09497d344c 100644 --- a/lib/Module/KInstruction.cpp +++ b/lib/Module/KInstruction.cpp @@ -9,11 +9,15 @@ #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/ADT/StringExtras.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include +#include DISABLE_WARNING_POP #include @@ -23,17 +27,95 @@ using namespace klee; /***/ +static int getOperandNum( + Value *v, + const std::unordered_map &instructionToRegisterMap, + KModule *km, KInstruction *ki) { + if (Instruction *inst = dyn_cast(v)) { + return instructionToRegisterMap.at(inst); + } else if (Argument *a = dyn_cast(v)) { + return a->getArgNo(); + } else if (isa(v) || isa(v) || + isa(v)) { + return -1; + } else { + assert(isa(v)); + Constant *c = cast(v); + return -(km->getConstantID(c, ki) + 2); + } +} + +KInstruction::KInstruction( + const std::unordered_map + &_instructionToRegisterMap, + llvm::Instruction *_inst, KModule *_km, KBlock *_kb, + unsigned &_globalIndexInc) + : inst(_inst), parent(_kb), globalIndex(_globalIndexInc++) { + if (isa(inst) || isa(inst)) { + const llvm::CallBase &cs = cast(*inst); + Value *val = cs.getCalledOperand(); + unsigned numArgs = cs.arg_size(); + operands = new int[numArgs + 1]; + operands[0] = getOperandNum(val, _instructionToRegisterMap, _km, this); + for (unsigned j = 0; j < numArgs; j++) { + Value *v = cs.getArgOperand(j); + operands[j + 1] = getOperandNum(v, _instructionToRegisterMap, _km, this); + } + } else { + unsigned numOperands = inst->getNumOperands(); + operands = new int[numOperands]; + for (unsigned j = 0; j < numOperands; j++) { + Value *v = inst->getOperand(j); + operands[j] = getOperandNum(v, _instructionToRegisterMap, _km, this); + } + } +} + KInstruction::~KInstruction() { delete[] operands; } -std::string KInstruction::getSourceLocation() const { - if (!info->file.empty()) - return info->file + ":" + std::to_string(info->line) + " " + - std::to_string(info->column); - else +size_t KInstruction::getLine() const { + auto locationInfo = getLocationInfo(inst); + return locationInfo.line; +} + +size_t KInstruction::getColumn() const { + auto locationInfo = getLocationInfo(inst); + return locationInfo.column; +} + +std::string KInstruction::getSourceFilepath() const { + auto locationInfo = getLocationInfo(inst); + return locationInfo.file; +} + +std::string KInstruction::getSourceLocationString() const { + std::string filePath = getSourceFilepath(); + if (!filePath.empty()) { + // TODO change format to file:line:column + return filePath + ":" + std::to_string(getLine()) + " " + + std::to_string(getColumn()); + } else { return "[no debug info]"; + } } std::string KInstruction::toString() const { - return llvm::utostr(index) + " at " + parent->toString() + " (" + + return llvm::utostr(getIndex()) + " at " + parent->toString() + " (" + inst->getOpcodeName() + ")"; } + +unsigned KInstruction::getGlobalIndex() const { return globalIndex; } + +unsigned KInstruction::getIndex() const { + return getGlobalIndex() - getKFunction()->getGlobalIndex() - + getKBlock()->getId() - 1; +} + +unsigned KInstruction::getDest() const { + return parent->parent->getNumArgs() + getIndex() + + (parent->instructions - parent->parent->instructions); +} + +KInstruction::Index KInstruction::getID() const { + return {getGlobalIndex(), parent->getId(), parent->parent->id}; +} diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 2ab1059a8f..64e1d3037c 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -14,9 +14,9 @@ #include "klee/Config/Version.h" #include "klee/Core/Interpreter.h" #include "klee/Module/Cell.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Support/Debug.h" #include "klee/Support/ErrorHandling.h" #include "klee/Support/ModuleUtil.h" @@ -26,6 +26,7 @@ DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Bitcode/BitcodeWriter.h" +#include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -37,6 +38,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Verifier.h" #include "llvm/Linker/Linker.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_os_ostream.h" #include "llvm/Support/raw_ostream.h" @@ -46,7 +48,9 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Transforms/Utils/Cloning.h" DISABLE_WARNING_POP +#include #include +#include using namespace llvm; using namespace klee; @@ -113,6 +117,11 @@ cl::opt cl::desc("Split each call in own basic block (default=true)"), cl::init(true), cl::cat(klee::ModuleCat)); +static cl::opt + StripUnwantedCalls("strip-unwanted-calls", + cl::desc("Strip all unwanted calls (llvm.dbg.* stuff)"), + cl::init(false), cl::cat(klee::ModuleCat)); + cl::opt SplitReturns( "split-returns", cl::desc("Split each return in own basic block (default=true)"), @@ -226,19 +235,6 @@ bool KModule::link(std::vector> &modules, return true; } -void KModule::replaceFunction(const std::unique_ptr &m, - const char *original, const char *replacement) { - llvm::Function *originalFunc = m->getFunction(original); - llvm::Function *replacementFunc = m->getFunction(replacement); - if (!originalFunc) - return; - klee_message("Replacing function \"%s\" with \"%s\"", original, replacement); - assert(replacementFunc && "Replacement function not found"); - assert(!(replacementFunc->isDeclaration()) && "replacement must have body"); - originalFunc->replaceAllUsesWith(replacementFunc); - originalFunc->eraseFromParent(); -} - void KModule::instrument(const Interpreter::ModuleOptions &opts) { // Inject checks prior to optimization... we also perform the // invariant transformations that we will end up doing later so that @@ -292,12 +288,10 @@ void KModule::optimiseAndPrepare( if (opts.WithFPRuntime) { if (UseKleeFloatInternals) { for (const auto &p : klee::floatReplacements) { - replaceFunction(module, p.first.c_str(), p.second.c_str()); + replaceOrRenameFunction(module.get(), p.first.c_str(), + p.second.c_str()); } } - for (const auto &p : klee::feRoundReplacements) { - replaceFunction(module, p.first.c_str(), p.second.c_str()); - } } // Needs to happen after linking (since ctors/dtors can be modified) @@ -328,6 +322,8 @@ void KModule::optimiseAndPrepare( pm3.add(createScalarizerPass()); pm3.add(new PhiCleanerPass()); pm3.add(new FunctionAliasPass()); + if (StripUnwantedCalls) + pm3.add(new CallRemover()); if (SplitCalls) { pm3.add(new CallSplitter()); } @@ -337,6 +333,38 @@ void KModule::optimiseAndPrepare( pm3.run(*module); } +class InstructionToLineAnnotator : public llvm::AssemblyAnnotationWriter { +private: + std::unordered_map mapping = {}; + +public: + void emitInstructionAnnot(const llvm::Instruction *i, + llvm::formatted_raw_ostream &os) override { + os.flush(); + mapping.emplace(reinterpret_cast(i), os.getLine() + 1); + } + + void emitFunctionAnnot(const llvm::Function *f, + llvm::formatted_raw_ostream &os) override { + os.flush(); + mapping.emplace(reinterpret_cast(f), os.getLine() + 1); + } + + std::unordered_map getMapping() const { return mapping; } +}; + +static std::unordered_map +buildInstructionToLineMap(const llvm::Module &m, + std::unique_ptr assemblyFS) { + + InstructionToLineAnnotator a; + + m.print(*assemblyFS, &a); + assemblyFS->flush(); + + return a.getMapping(); +} + void KModule::manifest(InterpreterHandler *ih, Interpreter::GuidanceKind guidance, bool forceSourceOutput) { @@ -351,32 +379,21 @@ void KModule::manifest(InterpreterHandler *ih, std::unique_ptr assemblyFS; if (OutputSource || forceSourceOutput) { assemblyFS = ih->openOutputFile("assembly.ll"); + asmLineMap = buildInstructionToLineMap(*module, std::move(assemblyFS)); } - infos = - std::make_unique(*module, std::move(assemblyFS)); } std::vector declarations; unsigned functionID = 0; + maxGlobalIndex = 0; for (auto &Function : module->functions()) { if (Function.isDeclaration()) { declarations.push_back(&Function); } - auto kf = std::unique_ptr(new KFunction(&Function, this)); + auto kf = std::make_unique(&Function, this, maxGlobalIndex); - llvm::Function *function = &Function; - for (auto &BasicBlock : *function) { - unsigned numInstructions = kf->blockMap[&BasicBlock]->numInstructions; - KBlock *kb = kf->blockMap[&BasicBlock]; - for (unsigned i = 0; i < numInstructions; ++i) { - KInstruction *ki = kb->instructions[i]; - ki->info = &infos->getInfo(*ki->inst); - } - } - - functionIDMap.insert({&Function, functionID}); kf->id = functionID; functionID++; functionNameMap.insert({kf->getName().str(), kf.get()}); @@ -397,7 +414,7 @@ void KModule::manifest(InterpreterHandler *ih, } for (auto &kfp : functions) { - for (auto kcb : kfp.get()->kCallBlocks) { + for (auto kcb : kfp->kCallBlocks) { bool isInlineAsm = false; const CallBase &cs = cast(*kcb->kcallInstruction->inst); if (isa(cs.getCalledOperand())) { @@ -405,12 +422,12 @@ void KModule::manifest(InterpreterHandler *ih, } if (kcb->calledFunctions.empty() && !isInlineAsm && (guidance != Interpreter::GuidanceKind::ErrorGuidance || - !inMainModule(*kfp.get()->function))) { + !inMainModule(*kfp->function))) { kcb->calledFunctions.insert(escapingFunctions.begin(), escapingFunctions.end()); } - for (auto &calledFunction : kcb->calledFunctions) { - callMap[calledFunction].insert(kfp.get()->function); + for (auto calledFunction : kcb->calledFunctions) { + callMap[calledFunction].insert(kfp->function); } } } @@ -426,6 +443,19 @@ void KModule::manifest(InterpreterHandler *ih, } } +std::optional KModule::getAsmLine(const uintptr_t ref) const { + if (!asmLineMap.empty()) { + return asmLineMap.at(ref); + } + return std::nullopt; +} +std::optional KModule::getAsmLine(const llvm::Function *func) const { + return getAsmLine(reinterpret_cast(func)); +} +std::optional KModule::getAsmLine(const llvm::Instruction *inst) const { + return getAsmLine(reinterpret_cast(inst)); +} + void KModule::checkModule() { InstructionOperandTypeCheckPass *operandTypeCheckPass = new InstructionOperandTypeCheckPass(); @@ -444,7 +474,7 @@ void KModule::checkModule() { } } -KBlock *KModule::getKBlock(llvm::BasicBlock *bb) { +KBlock *KModule::getKBlock(const llvm::BasicBlock *bb) { return functionMap[bb->getParent()]->blockMap[bb]; } @@ -502,6 +532,18 @@ unsigned KModule::getConstantID(Constant *c, KInstruction *ki) { return id; } +unsigned KModule::getFunctionId(const llvm::Function *func) const { + return functionMap.at(func)->id; +} +unsigned KModule::getGlobalIndex(const llvm::Function *func) const { + return functionMap.at(func)->getGlobalIndex(); +} +unsigned KModule::getGlobalIndex(const llvm::Instruction *inst) const { + return functionMap.at(inst->getFunction()) + ->instructionMap.at(inst) + ->getGlobalIndex(); +} + /***/ KConstant::KConstant(llvm::Constant *_ct, unsigned _id, KInstruction *_ki) { @@ -510,76 +552,25 @@ KConstant::KConstant(llvm::Constant *_ct, unsigned _id, KInstruction *_ki) { ki = _ki; } -/***/ - -static int getOperandNum( - Value *v, - std::unordered_map &instructionToRegisterMap, - KModule *km, KInstruction *ki) { - if (Instruction *inst = dyn_cast(v)) { - return instructionToRegisterMap[inst]; - } else if (Argument *a = dyn_cast(v)) { - return a->getArgNo(); - } else if (isa(v) || isa(v) || - isa(v)) { - return -1; - } else { - assert(isa(v)); - Constant *c = cast(v); - return -(km->getConstantID(c, ki) + 2); - } -} - -void KBlock::handleKInstruction( - std::unordered_map &instructionToRegisterMap, - llvm::Instruction *inst, KModule *km, KInstruction *ki) { - ki->parent = this; - ki->inst = inst; - ki->dest = instructionToRegisterMap[inst]; - if (isa(inst) || isa(inst)) { - const CallBase &cs = cast(*inst); - Value *val = cs.getCalledOperand(); - unsigned numArgs = cs.arg_size(); - ki->operands = new int[numArgs + 1]; - ki->operands[0] = getOperandNum(val, instructionToRegisterMap, km, ki); - for (unsigned j = 0; j < numArgs; j++) { - Value *v = cs.getArgOperand(j); - ki->operands[j + 1] = getOperandNum(v, instructionToRegisterMap, km, ki); - } - } else { - unsigned numOperands = inst->getNumOperands(); - ki->operands = new int[numOperands]; - for (unsigned j = 0; j < numOperands; j++) { - Value *v = inst->getOperand(j); - ki->operands[j] = getOperandNum(v, instructionToRegisterMap, km, ki); - } - } -} - -KFunction::KFunction(llvm::Function *_function, KModule *_km) - : KCallable(CK_Function), parent(_km), function(_function), - numArgs(function->arg_size()), numInstructions(0), numBlocks(0), - entryKBlock(nullptr), trackCoverage(true) { +KFunction::KFunction(llvm::Function *_function, KModule *_km, + unsigned &globalIndexInc) + : KCallable(CK_Function), globalIndex(globalIndexInc++), parent(_km), + function(_function), entryKBlock(nullptr), numInstructions(0) { for (auto &BasicBlock : *function) { numInstructions += BasicBlock.size(); - numBlocks++; } instructions = new KInstruction *[numInstructions]; std::unordered_map instructionToRegisterMap; // Assign unique instruction IDs to each basic block unsigned n = 0; // The first arg_size() registers are reserved for formals. - unsigned rnum = numArgs; - for (llvm::Function::iterator bbit = function->begin(), - bbie = function->end(); - bbit != bbie; ++bbit) { - for (llvm::BasicBlock::iterator it = bbit->begin(), ie = bbit->end(); - it != ie; ++it) - instructionToRegisterMap[&*it] = rnum++; + unsigned rnum = getNumArgs(); + for (auto &bb : *function) { + for (auto &instr : bb) { + instructionToRegisterMap[&instr] = rnum++; + } } - numRegisters = rnum; - unsigned blockID = 0; for (llvm::Function::iterator bbit = function->begin(), bbie = function->end(); bbit != bbie; ++bbit) { @@ -594,32 +585,42 @@ KFunction::KFunction(llvm::Function *_function, KModule *_km) if (f) { calledFunctions.insert(f); } - KCallBlock *ckb = new KCallBlock( - this, &*bbit, parent, instructionToRegisterMap, - registerToInstructionMap, calledFunctions, &instructions[n]); + auto *ckb = + new KCallBlock(this, &*bbit, parent, instructionToRegisterMap, + calledFunctions, &instructions[n], globalIndexInc); kCallBlocks.push_back(ckb); kb = ckb; } else if (SplitReturns && isa(lit)) { kb = new KReturnBlock(this, &*bbit, parent, instructionToRegisterMap, - registerToInstructionMap, &instructions[n]); + &instructions[n], globalIndexInc); returnKBlocks.push_back(kb); - } else + } else { kb = new KBlock(this, &*bbit, parent, instructionToRegisterMap, - registerToInstructionMap, &instructions[n]); - for (unsigned i = 0; i < kb->numInstructions; i++, n++) { + &instructions[n], globalIndexInc); + } + for (unsigned i = 0, ie = kb->getNumInstructions(); i < ie; i++, n++) { instructionMap[instructions[n]->inst] = instructions[n]; } - kb->id = blockID++; blockMap[&*bbit] = kb; blocks.push_back(std::unique_ptr(kb)); } - if (numBlocks > 0) { + if (blocks.size() > 0) { assert(function->begin() != function->end()); entryKBlock = blockMap[&*function->begin()]; } } +size_t KFunction::getLine() const { + auto locationInfo = getLocationInfo(function); + return locationInfo.line; +} + +std::string KFunction::getSourceFilepath() const { + auto locationInfo = getLocationInfo(function); + return locationInfo.file; +} + KFunction::~KFunction() { for (unsigned i = 0; i < numInstructions; ++i) delete instructions[i]; @@ -628,47 +629,39 @@ KFunction::~KFunction() { KBlock::KBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, - std::unordered_map &instructionToRegisterMap, - std::unordered_map ®isterToInstructionMap, - KInstruction **instructionsKF) - : parent(_kfunction), basicBlock(block), numInstructions(0), - trackCoverage(true) { - numInstructions += block->size(); + const std::unordered_map &instructionToRegisterMap, + KInstruction **instructionsKF, unsigned &globalIndexInc) + : parent(_kfunction), basicBlock(block) { instructions = instructionsKF; - unsigned i = 0; - for (llvm::BasicBlock::iterator it = block->begin(), ie = block->end(); - it != ie; ++it) { + for (auto &it : *block) { KInstruction *ki; - switch (it->getOpcode()) { + switch (it.getOpcode()) { case Instruction::GetElementPtr: case Instruction::InsertValue: case Instruction::ExtractValue: - ki = new KGEPInstruction(); + ki = new KGEPInstruction(instructionToRegisterMap, &it, km, this, + globalIndexInc); break; default: - ki = new KInstruction(); + ki = new KInstruction(instructionToRegisterMap, &it, km, this, + globalIndexInc); break; } - - Instruction *inst = &*it; - handleKInstruction(instructionToRegisterMap, inst, km, ki); - ki->index = i; - instructions[i++] = ki; - registerToInstructionMap[instructionToRegisterMap[&*it]] = ki; + instructions[ki->getIndex()] = ki; } } KCallBlock::KCallBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, - std::unordered_map &instructionToRegisterMap, - std::unordered_map ®isterToInstructionMap, - std::set _calledFunctions, KInstruction **instructionsKF) + const std::unordered_map &instructionToRegisterMap, + std::set _calledFunctions, KInstruction **instructionsKF, + unsigned &globalIndexInc) : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, - registerToInstructionMap, instructionsKF), + instructionsKF, globalIndexInc), kcallInstruction(this->instructions[0]), - calledFunctions(_calledFunctions) {} + calledFunctions(std::move(_calledFunctions)) {} bool KCallBlock::intrinsic() const { if (calledFunctions.size() != 1) { @@ -695,11 +688,10 @@ KFunction *KCallBlock::getKFunction() const { KReturnBlock::KReturnBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, - std::unordered_map &instructionToRegisterMap, - std::unordered_map ®isterToInstructionMap, - KInstruction **instructionsKF) + const std::unordered_map &instructionToRegisterMap, + KInstruction **instructionsKF, unsigned &globalIndexInc) : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, - registerToInstructionMap, instructionsKF) {} + instructionsKF, globalIndexInc) {} std::string KBlock::getLabel() const { std::string _label; @@ -712,3 +704,13 @@ std::string KBlock::getLabel() const { std::string KBlock::toString() const { return getLabel() + " in function " + parent->function->getName().str(); } + +uintptr_t KBlock::getId() const { return instructions - parent->instructions; } + +KInstruction *KFunction::getInstructionByRegister(size_t reg) const { + return instructions[reg - function->arg_size()]; +} +size_t KFunction::getNumArgs() const { return function->arg_size(); } +size_t KFunction::getNumRegisters() const { + return function->arg_size() + numInstructions; +} diff --git a/lib/Module/LocationInfo.cpp b/lib/Module/LocationInfo.cpp new file mode 100644 index 0000000000..274a55e25d --- /dev/null +++ b/lib/Module/LocationInfo.cpp @@ -0,0 +1,63 @@ +//===-- LocationInfo.cpp ------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Module/LocationInfo.h" +#include "klee/Support/CompilerWarning.h" + +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/AssemblyAnnotationWriter.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/FormattedStream.h" +DISABLE_WARNING_POP + +namespace klee { + +LocationInfo getLocationInfo(const llvm::Function *func) { + const auto dsub = func->getSubprogram(); + + if (dsub != nullptr) { + auto path = dsub->getFilename(); + return {path.str(), dsub->getLine(), 0}; // TODO why not use column here? + } + + return {"", 0, 0}; +} + +LocationInfo getLocationInfo(const llvm::Instruction *inst) { + // Retrieve debug information associated with instruction + const auto &dl = inst->getDebugLoc(); + + // Check if a valid debug location is assigned to the instruction. + if (dl.get() != nullptr) { + auto full_path = dl->getFilename(); + auto line = dl.getLine(); + auto column = dl.getCol(); + + // Still, if the line is unknown, take the context of the instruction to + // narrow it down + if (line == 0) { + if (auto LexicalBlock = + llvm::dyn_cast(dl.getScope())) { + line = LexicalBlock->getLine(); + column = LexicalBlock->getColumn(); + } + } + return {full_path.str(), line, column}; + } + + return getLocationInfo(inst->getParent()->getParent()); +} + +} // namespace klee diff --git a/lib/Module/ModuleUtil.cpp b/lib/Module/ModuleUtil.cpp index e64d628e71..d23e41a607 100644 --- a/lib/Module/ModuleUtil.cpp +++ b/lib/Module/ModuleUtil.cpp @@ -367,3 +367,19 @@ bool klee::loadFileAsOneModule( } return res; } + +void klee::replaceOrRenameFunction(llvm::Module *module, const char *old_name, + const char *new_name) { + Function *new_function, *old_function; + new_function = module->getFunction(new_name); + old_function = module->getFunction(old_name); + if (old_function) { + if (new_function) { + old_function->replaceAllUsesWith(new_function); + old_function->eraseFromParent(); + } else { + old_function->setName(new_name); + assert(old_function->getName() == new_name); + } + } +} \ No newline at end of file diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp index dd97353391..e087ed2208 100644 --- a/lib/Module/Optimize.cpp +++ b/lib/Module/Optimize.cpp @@ -75,6 +75,15 @@ static cl::opt static cl::alias A1("S", cl::desc("Alias for --strip-debug"), cl::aliasopt(StripDebug)); +static cl::opt DeleteDeadLoops("delete-dead-loops", + cl::desc("Use LoopDeletionPass"), + cl::init(true), cl::cat(klee::ModuleCat)); + +static cl::opt + OptimizeAggressive("optimize-aggressive", + cl::desc("Use aggressive optimization passes"), + cl::init(true), cl::cat(klee::ModuleCat)); + // A utility function that adds a pass to the pass manager but will also add // a verifier pass after if we're supposed to verify. static inline void addPass(legacy::PassManager &PM, Pass *P) { @@ -131,8 +140,9 @@ static void AddStandardCompilePasses(legacy::PassManager &PM) { addPass(PM, createLoopUnswitchPass()); // Unswitch loops. // FIXME : Removing instcombine causes nestedloop regression. addPass(PM, createInstructionCombiningPass()); - addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars - addPass(PM, createLoopDeletionPass()); // Delete dead loops + addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars + if (DeleteDeadLoops) + addPass(PM, createLoopDeletionPass()); // Delete dead loops addPass(PM, createLoopUnrollPass()); // Unroll small loops addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller addPass(PM, createGVNPass()); // Remove redundancies @@ -144,43 +154,12 @@ static void AddStandardCompilePasses(legacy::PassManager &PM) { addPass(PM, createInstructionCombiningPass()); addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores - addPass(PM, createAggressiveDCEPass()); // Delete dead instructions addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs addPass(PM, createStripDeadPrototypesPass()); // Get rid of dead prototypes addPass(PM, createConstantMergePass()); // Merge dup global constants } -/// Optimize - Perform link time optimizations. This will run the scalar -/// optimizations, any loaded plugin-optimization modules, and then the -/// inter-procedural optimizations if applicable. -void Optimize(Module *M, llvm::ArrayRef preservedFunctions) { - - // Instantiate the pass manager to organize the passes. - legacy::PassManager Passes; - - // If we're verifying, start off with a verification pass. - if (VerifyEach) - Passes.add(createVerifierPass()); - - // DWD - Run the opt standard pass list as well. - AddStandardCompilePasses(Passes); - - // Now that composite has been compiled, scan through the module, looking - // for a main function. If main is defined, mark all other functions - // internal. - if (!DisableInternalize) { - auto PreserveFunctions = [=](const GlobalValue &GV) { - StringRef GVName = GV.getName(); - - for (const char *fun : preservedFunctions) - if (GVName.equals(fun)) - return true; - - return false; - }; - ModulePass *pass = createInternalizePass(PreserveFunctions); - addPass(Passes, pass); - } +static void AddNonStandardCompilePasses(legacy::PassManager &Passes) { // Propagate constants at call sites into the functions they call. This // opens opportunities for globalopt (and inlining) by substituting function @@ -252,6 +231,43 @@ void Optimize(Module *M, llvm::ArrayRef preservedFunctions) { addPass(Passes, createCFGSimplificationPass()); addPass(Passes, createAggressiveDCEPass()); addPass(Passes, createGlobalDCEPass()); +} + +/// Optimize - Perform link time optimizations. This will run the scalar +/// optimizations, any loaded plugin-optimization modules, and then the +/// inter-procedural optimizations if applicable. +void Optimize(Module *M, llvm::ArrayRef preservedFunctions) { + + // Instantiate the pass manager to organize the passes. + legacy::PassManager Passes; + + // If we're verifying, start off with a verification pass. + if (VerifyEach) + Passes.add(createVerifierPass()); + + // DWD - Run the opt standard pass list as well. + AddStandardCompilePasses(Passes); + + // Now that composite has been compiled, scan through the module, looking + // for a main function. If main is defined, mark all other functions + // internal. + if (!DisableInternalize) { + auto PreserveFunctions = [=](const GlobalValue &GV) { + StringRef GVName = GV.getName(); + + for (const char *fun : preservedFunctions) + if (GVName.equals(fun)) + return true; + + return false; + }; + ModulePass *pass = createInternalizePass(PreserveFunctions); + addPass(Passes, pass); + } + + if (OptimizeAggressive) { + AddNonStandardCompilePasses(Passes); + } // Run our queue of passes all at once now, efficiently. Passes.run(*M); diff --git a/lib/Module/Passes.h b/lib/Module/Passes.h index 76499428df..01983e0b85 100644 --- a/lib/Module/Passes.h +++ b/lib/Module/Passes.h @@ -206,6 +206,14 @@ class CallSplitter : public llvm::FunctionPass { bool runOnFunction(llvm::Function &F) override; }; +/// Remove unwanted calls +class CallRemover : public llvm::ModulePass { +public: + static char ID; + CallRemover() : llvm::ModulePass(ID) {} + bool runOnModule(llvm::Module &M) override; +}; + class ReturnSplitter : public llvm::FunctionPass { public: static char ID; diff --git a/lib/Module/SarifReport.cpp b/lib/Module/SarifReport.cpp index 075ce32417..6cc323a87a 100644 --- a/lib/Module/SarifReport.cpp +++ b/lib/Module/SarifReport.cpp @@ -326,20 +326,22 @@ bool Location::isInside(const std::string &name) const { } bool Location::isInside(KBlock *block, const Instructions &origInsts) const { - auto first = block->getFirstInstruction()->info; - auto last = block->getLastInstruction()->info; + auto first = block->getFirstInstruction(); + auto last = block->getLastInstruction(); if (!startColumn.has_value()) { - if (first->line > endLine) + if (first->getLine() > endLine) return false; - return startLine <= last->line; // and `first <= line` from above + return startLine <= last->getLine(); // and `first <= line` from above } else { - for (size_t i = 0; i < block->numInstructions; ++i) { - auto inst = block->instructions[i]->info; + for (unsigned i = 0, ie = block->getNumInstructions(); i < ie; ++i) { + auto inst = block->instructions[i]; auto opCode = block->instructions[i]->inst->getOpcode(); if (!isa(block->instructions[i]->inst) && - inst->line <= endLine && inst->line >= startLine && - inst->column <= *endColumn && inst->column >= *startColumn && - origInsts.at(inst->line).at(inst->column).count(opCode) != 0) { + inst->getLine() <= endLine && inst->getLine() >= startLine && + inst->getColumn() <= *endColumn && + inst->getColumn() >= *startColumn && + origInsts.at(inst->getLine()).at(inst->getColumn()).count(opCode) != + 0) { return true; } } diff --git a/lib/Module/Target.cpp b/lib/Module/Target.cpp index 633d27f2a6..d2dde07919 100644 --- a/lib/Module/Target.cpp +++ b/lib/Module/Target.cpp @@ -10,7 +10,7 @@ #include "klee/Module/Target.h" #include "klee/Module/TargetHash.h" -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" #include @@ -26,6 +26,15 @@ llvm::cl::opt LocationAccuracy( cl::desc("Check location with line and column accuracy (default=false)")); } +ErrorLocation::ErrorLocation(const klee::ref &loc) + : startLine(loc->startLine), endLine(loc->endLine), + startColumn(loc->startColumn), endColumn(loc->endColumn) {} + +ErrorLocation::ErrorLocation(const KInstruction *ki) { + startLine = (endLine = ki->getLine()); + startColumn = (endColumn = ki->getLine()); +} + std::string ReproduceErrorTarget::toString() const { std::ostringstream repr; repr << "Target " << getId() << ": "; @@ -93,11 +102,11 @@ ref CoverBranchTarget::create(KBlock *_block, unsigned _branchCase) { bool ReproduceErrorTarget::isTheSameAsIn(const KInstruction *instr) const { const auto &errLoc = loc; - return instr->info->line >= errLoc.startLine && - instr->info->line <= errLoc.endLine && + return instr->getLine() >= errLoc.startLine && + instr->getLine() <= errLoc.endLine && (!LocationAccuracy || !errLoc.startColumn.has_value() || - (instr->info->column >= *errLoc.startColumn && - instr->info->column <= *errLoc.endColumn)); + (instr->getColumn() >= *errLoc.startColumn && + instr->getColumn() <= *errLoc.endColumn)); } int Target::compare(const Target &b) const { return internalCompare(b); } @@ -117,8 +126,8 @@ int ReachBlockTarget::internalCompare(const Target &b) const { if (block->parent->id != other.block->parent->id) { return block->parent->id < other.block->parent->id ? -1 : 1; } - if (block->id != other.block->id) { - return block->id < other.block->id ? -1 : 1; + if (block->getId() != other.block->getId()) { + return block->getId() < other.block->getId() ? -1 : 1; } if (atEnd != other.atEnd) { @@ -137,8 +146,8 @@ int CoverBranchTarget::internalCompare(const Target &b) const { if (block->parent->id != other.block->parent->id) { return block->parent->id < other.block->parent->id ? -1 : 1; } - if (block->id != other.block->id) { - return block->id < other.block->id ? -1 : 1; + if (block->getId() != other.block->getId()) { + return block->getId() < other.block->getId() ? -1 : 1; } if (branchCase != other.branchCase) { @@ -161,8 +170,8 @@ int ReproduceErrorTarget::internalCompare(const Target &b) const { if (block->parent->id != other.block->parent->id) { return block->parent->id < other.block->parent->id ? -1 : 1; } - if (block->id != other.block->id) { - return block->id < other.block->id ? -1 : 1; + if (block->getId() != other.block->getId()) { + return block->getId() < other.block->getId() ? -1 : 1; } if (errors.size() != other.errors.size()) { diff --git a/lib/Module/TargetForest.cpp b/lib/Module/TargetForest.cpp index 0a95f3754f..cb2f8a907e 100644 --- a/lib/Module/TargetForest.cpp +++ b/lib/Module/TargetForest.cpp @@ -117,11 +117,8 @@ void TargetForest::Layer::addTrace( for (auto block : it->second) { ref target = nullptr; if (i == result.locations.size() - 1) { - target = ReproduceErrorTarget::create( - result.errors, result.id, - ErrorLocation{loc->startLine, loc->endLine, loc->startColumn, - loc->endColumn}, - block); + target = ReproduceErrorTarget::create(result.errors, result.id, + ErrorLocation(loc), block); } else { target = ReachBlockTarget::create(block); } diff --git a/lib/Module/TargetHash.cpp b/lib/Module/TargetHash.cpp index 7f5b9be2eb..f7c3010689 100644 --- a/lib/Module/TargetHash.cpp +++ b/lib/Module/TargetHash.cpp @@ -22,11 +22,6 @@ bool TargetCmp::operator()(const ref &a, const ref &b) const { return a == b; } -std::size_t TransitionHash::operator()(const Transition &p) const { - return reinterpret_cast(p.first) * 31 + - reinterpret_cast(p.second); -} - std::size_t BranchHash::operator()(const Branch &p) const { return reinterpret_cast(p.first) * 31 + p.second; } diff --git a/lib/Solver/AlphaEquivalenceSolver.cpp b/lib/Solver/AlphaEquivalenceSolver.cpp new file mode 100644 index 0000000000..d8b6011c78 --- /dev/null +++ b/lib/Solver/AlphaEquivalenceSolver.cpp @@ -0,0 +1,239 @@ +//===-- AlphaEquivalenceSolver.cpp-----------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Expr/SymbolicSource.h" +#include "klee/Solver/SolverUtil.h" + +#include "klee/Solver/Solver.h" + +#include "klee/Expr/AlphaBuilder.h" +#include "klee/Expr/Assignment.h" +#include "klee/Expr/Constraints.h" +#include "klee/Expr/ExprHashMap.h" +#include "klee/Solver/SolverImpl.h" +#include "klee/Support/Debug.h" + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +DISABLE_WARNING_POP + +using namespace klee; +using namespace llvm; + +class AlphaEquivalenceSolver : public SolverImpl { +private: + std::unique_ptr solver; + ArrayCache &arrayCache; + +public: + AlphaEquivalenceSolver(std::unique_ptr solver, + ArrayCache &_arrayCache) + : solver(std::move(solver)), arrayCache(_arrayCache) {} + + bool computeTruth(const Query &, bool &isValid); + bool computeValidity(const Query &, PartialValidity &result); + bool computeValue(const Query &, ref &result); + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution); + bool check(const Query &query, ref &result); + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid); + SolverRunStatus getOperationStatusCode(); + char *getConstraintLog(const Query &); + void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); + ValidityCore changeVersion(const ValidityCore &validityCore, + AlphaBuilder &builder); + std::vector + changeVersion(const std::vector &objects, + AlphaBuilder &builder); + Assignment + changeVersion(const std::vector &objects, + const std::vector> &values, + const ArrayCache::ArrayHashMap &reverse); + Assignment + changeVersion(const Assignment &a, + const ArrayCache::ArrayHashMap &reverse); + ref changeVersion(ref res, + AlphaBuilder &builder); +}; + +ValidityCore +AlphaEquivalenceSolver::changeVersion(const ValidityCore &validityCore, + AlphaBuilder &builder) { + ValidityCore reverseValidityCore; + if (isa(validityCore.expr)) { + reverseValidityCore.expr = validityCore.expr; + } else { + reverseValidityCore.expr = builder.reverseBuild(validityCore.expr); + } + for (auto e : validityCore.constraints) { + reverseValidityCore.constraints.insert(builder.reverseBuild(e)); + } + return reverseValidityCore; +} + +Assignment AlphaEquivalenceSolver::changeVersion( + const std::vector &objects, + const std::vector> &values, + const ArrayCache::ArrayHashMap &reverse) { + std::vector reverseObjects; + std::vector> reverseValues; + for (size_t i = 0; i < objects.size(); i++) { + if (reverse.count(objects.at(i)) != 0) { + reverseObjects.push_back(reverse.at(objects.at(i))); + reverseValues.push_back(values.at(i)); + } + } + return Assignment(reverseObjects, reverseValues); +} + +std::vector +AlphaEquivalenceSolver::changeVersion(const std::vector &objects, + AlphaBuilder &builder) { + std::vector reverseObjects; + for (size_t i = 0; i < objects.size(); i++) { + reverseObjects.push_back(builder.buildArray(objects.at(i))); + } + return reverseObjects; +} + +Assignment AlphaEquivalenceSolver::changeVersion( + const Assignment &a, + const ArrayCache::ArrayHashMap &reverse) { + std::vector objects = a.keys(); + std::vector> values = a.values(); + return changeVersion(objects, values, reverse); +} + +ref +AlphaEquivalenceSolver::changeVersion(ref res, + AlphaBuilder &builder) { + ref reverseRes; + if (!isa(res) && !isa(res)) { + return res; + } + + if (isa(res)) { + Assignment a = cast(res)->initialValues(); + a = changeVersion(a, builder.reverseAlphaArrayMap); + reverseRes = new InvalidResponse(a.bindings); + } else { + ValidityCore validityCore; + res->tryGetValidityCore(validityCore); + validityCore = changeVersion(validityCore, builder); + reverseRes = new ValidResponse(validityCore); + } + return reverseRes; +} + +bool AlphaEquivalenceSolver::computeValidity(const Query &query, + PartialValidity &result) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + return solver->impl->computeValidity( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + result); +} + +bool AlphaEquivalenceSolver::computeTruth(const Query &query, bool &isValid) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + return solver->impl->computeTruth( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + isValid); +} + +bool AlphaEquivalenceSolver::computeValue(const Query &query, + ref &result) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + return solver->impl->computeValue( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + result); +} + +bool AlphaEquivalenceSolver::computeInitialValues( + const Query &query, const std::vector &objects, + std::vector> &values, bool &hasSolution) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + const std::vector newObjects = changeVersion(objects, builder); + + if (!solver->impl->computeInitialValues( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + newObjects, values, hasSolution)) { + return false; + } + return true; +} + +bool AlphaEquivalenceSolver::check(const Query &query, + ref &result) { + AlphaBuilder builder(arrayCache); + + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + if (!solver->impl->check( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + result)) { + return false; + } + + result = changeVersion(result, builder); + return true; +} + +bool AlphaEquivalenceSolver::computeValidityCore(const Query &query, + ValidityCore &validityCore, + bool &isValid) { + AlphaBuilder builder(arrayCache); + + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.build(query.expr); + if (!solver->impl->computeValidityCore( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + validityCore, isValid)) { + return false; + } + validityCore = changeVersion(validityCore, builder); + return true; +} + +SolverImpl::SolverRunStatus AlphaEquivalenceSolver::getOperationStatusCode() { + return solver->impl->getOperationStatusCode(); +} + +char *AlphaEquivalenceSolver::getConstraintLog(const Query &query) { + return solver->impl->getConstraintLog(query); +} + +void AlphaEquivalenceSolver::setCoreSolverTimeout(time::Span timeout) { + solver->impl->setCoreSolverTimeout(timeout); +} + +void AlphaEquivalenceSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + +std::unique_ptr +klee::createAlphaEquivalenceSolver(std::unique_ptr s, + ArrayCache &arrayCache) { + return std::make_unique( + std::make_unique(std::move(s), arrayCache)); +} diff --git a/lib/Solver/AssignmentValidatingSolver.cpp b/lib/Solver/AssignmentValidatingSolver.cpp index dde0f1a23d..8284f0502e 100644 --- a/lib/Solver/AssignmentValidatingSolver.cpp +++ b/lib/Solver/AssignmentValidatingSolver.cpp @@ -44,6 +44,7 @@ class AssignmentValidatingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; // TODO: use computeInitialValues for all queries for more stress testing @@ -65,9 +66,8 @@ void AssignmentValidatingSolver::validateAssigment( std::vector> &values) { // Use `_allowFreeValues` so that if we are missing an assignment // we can't compute a constant and flag this as a problem. - Assignment assignment(objects, values, /*_allowFreeValues=*/true); + Assignment assignment(objects, values); // Check computed assignment satisfies query - assert(!query.containsSymcretes()); for (const auto &constraint : query.constraints.cs()) { ref constraintEvaluated = assignment.evaluate(constraint); ConstantExpr *CE = dyn_cast(constraintEvaluated); @@ -142,14 +142,8 @@ bool AssignmentValidatingSolver::check(const Query &query, return true; } - ExprHashSet expressions; - assert(!query.containsSymcretes()); - expressions.insert(query.constraints.cs().begin(), - query.constraints.cs().end()); - expressions.insert(query.expr); - std::vector objects; - findSymbolicObjects(expressions.begin(), expressions.end(), objects); + findSymbolicObjects(query, objects); std::vector> values; assert(isa(result)); @@ -170,14 +164,13 @@ void AssignmentValidatingSolver::dumpAssignmentQuery( const Query &query, const Assignment &assignment) { // Create a Query that is augmented with constraints that // enforce the given assignment. - auto constraints = assignment.createConstraintsFromAssignment(); + ConstraintSet constraints(assignment.createConstraintsFromAssignment()); // Add Constraints from `query` - assert(!query.containsSymcretes()); for (const auto &constraint : query.constraints.cs()) constraints.addConstraint(constraint, {}); - Query augmentedQuery(constraints, query.expr); + Query augmentedQuery = query.withConstraints(constraints); // Ask the solver for the log for this query. char *logText = solver->getConstraintLog(augmentedQuery); @@ -198,6 +191,10 @@ void AssignmentValidatingSolver::setCoreSolverTimeout(time::Span timeout) { return solver->impl->setCoreSolverTimeout(timeout); } +void AssignmentValidatingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + std::unique_ptr createAssignmentValidatingSolver(std::unique_ptr s) { return std::make_unique( diff --git a/lib/Solver/BitwuzlaBuilder.cpp b/lib/Solver/BitwuzlaBuilder.cpp new file mode 100644 index 0000000000..2c47a1440a --- /dev/null +++ b/lib/Solver/BitwuzlaBuilder.cpp @@ -0,0 +1,1314 @@ +//===-- BitwuzlaBuilder.cpp ---------------------------------*- C++ -*-====// +//-*-====// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "klee/Config/config.h" + +#ifdef ENABLE_BITWUZLA + +#include "BitwuzlaBuilder.h" +#include "BitwuzlaHashConfig.h" +#include "klee/ADT/Bits.h" + +#include "klee/Expr/Expr.h" +#include "klee/Solver/Solver.h" +#include "klee/Solver/SolverStats.h" +#include "klee/Support/ErrorHandling.h" + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +DISABLE_WARNING_POP + +namespace klee { + +BitwuzlaArrayExprHash::~BitwuzlaArrayExprHash() {} + +void BitwuzlaArrayExprHash::clear() { + _update_node_hash.clear(); + _array_hash.clear(); +} + +void BitwuzlaArrayExprHash::clearUpdates() { _update_node_hash.clear(); } + +BitwuzlaBuilder::BitwuzlaBuilder(bool autoClearConstructCache) + : autoClearConstructCache(autoClearConstructCache) {} + +BitwuzlaBuilder::~BitwuzlaBuilder() { + _arr_hash.clearUpdates(); + clearSideConstraints(); +} + +Sort BitwuzlaBuilder::getBoolSort() { + // FIXME: cache these + return mk_bool_sort(); +} + +Sort BitwuzlaBuilder::getBvSort(unsigned width) { + // FIXME: cache these + return mk_bv_sort(width); +} + +Sort BitwuzlaBuilder::getArraySort(Sort domainSort, Sort rangeSort) { + // FIXME: cache these + return mk_array_sort(domainSort, rangeSort); +} + +Term BitwuzlaBuilder::buildFreshBoolConst() { return mk_const(getBoolSort()); } + +Term BitwuzlaBuilder::buildArray(const char *name, unsigned indexWidth, + unsigned valueWidth) { + Sort domainSort = getBvSort(indexWidth); + Sort rangeSort = getBvSort(valueWidth); + Sort t = getArraySort(domainSort, rangeSort); + return mk_const(t, std::string(name)); +} + +Term BitwuzlaBuilder::buildConstantArray(const char *name, unsigned indexWidth, + unsigned valueWidth, unsigned value) { + Sort domainSort = getBvSort(indexWidth); + Sort rangeSort = getBvSort(valueWidth); + return mk_const_array(getArraySort(domainSort, rangeSort), + bvConst32(valueWidth, value)); +} + +Term BitwuzlaBuilder::getTrue() { return mk_true(); } + +Term BitwuzlaBuilder::getFalse() { return mk_false(); } + +Term BitwuzlaBuilder::bvOne(unsigned width) { + return mk_bv_one(getBvSort(width)); +} +Term BitwuzlaBuilder::bvZero(unsigned width) { + return mk_bv_zero(getBvSort(width)); +} +Term BitwuzlaBuilder::bvMinusOne(unsigned width) { + return bvZExtConst(width, (uint64_t)-1); +} +Term BitwuzlaBuilder::bvConst32(unsigned width, uint32_t value) { + if (width < 32) { + value &= ((1 << width) - 1); + } + return mk_bv_value_uint64(getBvSort(width), value); +} +Term BitwuzlaBuilder::bvConst64(unsigned width, uint64_t value) { + if (width < 64) { + value &= ((uint64_t(1) << width) - 1); + } + return mk_bv_value_uint64(getBvSort(width), value); +} +Term BitwuzlaBuilder::bvZExtConst(unsigned width, uint64_t value) { + if (width <= 64) { + return bvConst64(width, value); + } + std::vector terms = {bvConst64(64, value)}; + for (width -= 64; width > 64; width -= 64) { + terms.push_back(bvConst64(64, 0)); + } + terms.push_back(bvConst64(width, 0)); + return mk_term(Kind::BV_CONCAT, terms); +} + +Term BitwuzlaBuilder::bvSExtConst(unsigned width, uint64_t value) { + if (width <= 64) { + return bvConst64(width, value); + } + + Sort t = getBvSort(width - 64); + if (value >> 63) { + return mk_term(Kind::BV_CONCAT, + {bvMinusOne(width - 64), bvConst64(64, value)}); + } + return mk_term(Kind::BV_CONCAT, {bvZero(width - 64), bvConst64(64, value)}); +} + +Term BitwuzlaBuilder::bvBoolExtract(Term expr, int bit) { + return mk_term(Kind::EQUAL, {bvExtract(expr, bit, bit), bvOne(1)}); +} + +Term BitwuzlaBuilder::bvExtract(Term expr, unsigned top, unsigned bottom) { + return mk_term(Kind::BV_EXTRACT, {castToBitVector(expr)}, {top, bottom}); +} + +Term BitwuzlaBuilder::eqExpr(Term a, Term b) { + // Handle implicit bitvector/float coercision + Sort aSort = a.sort(); + Sort bSort = b.sort(); + + if (aSort.is_bool() && bSort.is_fp()) { + // Coerce `b` to be a bitvector + b = castToBitVector(b); + } + + if (aSort.is_fp() && bSort.is_bool()) { + // Coerce `a` to be a bitvector + a = castToBitVector(a); + } + return mk_term(Kind::EQUAL, {a, b}); +} + +// logical right shift +Term BitwuzlaBuilder::bvRightShift(Term expr, unsigned shift) { + Term exprAsBv = castToBitVector(expr); + unsigned width = getBVLength(exprAsBv); + + if (shift == 0) { + return expr; + } else if (shift >= width) { + return bvZero(width); // Overshift to zero + } else { + return mk_term(Kind::BV_SHR, {exprAsBv, bvConst32(width, shift)}); + } +} + +// logical left shift +Term BitwuzlaBuilder::bvLeftShift(Term expr, unsigned shift) { + Term exprAsBv = castToBitVector(expr); + unsigned width = getBVLength(exprAsBv); + + if (shift == 0) { + return expr; + } else if (shift >= width) { + return bvZero(width); // Overshift to zero + } else { + return mk_term(Kind::BV_SHL, {exprAsBv, bvConst32(width, shift)}); + } +} + +// left shift by a variable amount on an expression of the specified width +Term BitwuzlaBuilder::bvVarLeftShift(Term expr, Term shift) { + Term exprAsBv = castToBitVector(expr); + Term shiftAsBv = castToBitVector(shift); + + unsigned width = getBVLength(exprAsBv); + Term res = mk_term(Kind::BV_SHL, {exprAsBv, shiftAsBv}); + + // If overshifting, shift to zero + Term ex = bvLtExpr(shiftAsBv, bvConst32(getBVLength(shiftAsBv), width)); + res = iteExpr(ex, res, bvZero(width)); + return res; +} + +// logical right shift by a variable amount on an expression of the specified +// width +Term BitwuzlaBuilder::bvVarRightShift(Term expr, Term shift) { + Term exprAsBv = castToBitVector(expr); + Term shiftAsBv = castToBitVector(shift); + + unsigned width = getBVLength(exprAsBv); + Term res = mk_term(Kind::BV_SHR, {exprAsBv, shiftAsBv}); + + // If overshifting, shift to zero + Term ex = bvLtExpr(shiftAsBv, bvConst32(getBVLength(shiftAsBv), width)); + res = iteExpr(ex, res, bvZero(width)); + return res; +} + +// arithmetic right shift by a variable amount on an expression of the specified +// width +Term BitwuzlaBuilder::bvVarArithRightShift(Term expr, Term shift) { + Term exprAsBv = castToBitVector(expr); + Term shiftAsBv = castToBitVector(shift); + + unsigned width = getBVLength(exprAsBv); + + Term res = mk_term(Kind::BV_ASHR, {exprAsBv, shiftAsBv}); + + // If overshifting, shift to zero + Term ex = bvLtExpr(shiftAsBv, bvConst32(getBVLength(shiftAsBv), width)); + res = iteExpr(ex, res, bvZero(width)); + return res; +} + +Term BitwuzlaBuilder::notExpr(Term expr) { return mk_term(Kind::NOT, {expr}); } +Term BitwuzlaBuilder::andExpr(Term lhs, Term rhs) { + return mk_term(Kind::AND, {lhs, rhs}); +} +Term BitwuzlaBuilder::orExpr(Term lhs, Term rhs) { + return mk_term(Kind::OR, {lhs, rhs}); +} +Term BitwuzlaBuilder::iffExpr(Term lhs, Term rhs) { + return mk_term(Kind::IFF, {lhs, rhs}); +} + +Term BitwuzlaBuilder::bvNotExpr(Term expr) { + return mk_term(Kind::BV_NOT, {castToBitVector(expr)}); +} + +Term BitwuzlaBuilder::bvAndExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_AND, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvOrExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_OR, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvXorExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_XOR, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvSignExtend(Term src, unsigned width) { + Term srcAsBv = castToBitVector(src); + unsigned src_width = srcAsBv.sort().bv_size(); + assert(src_width <= width && "attempted to extend longer data"); + + if (width <= 64) { + return mk_term(Kind::BV_SIGN_EXTEND, {srcAsBv}, {width - src_width}); + } + + Term signBit = bvBoolExtract(srcAsBv, src_width - 1); + Term zeroExtended = + mk_term(Kind::BV_CONCAT, {bvZero(width - src_width), src}); + Term oneExtended = + mk_term(Kind::BV_CONCAT, {bvMinusOne(width - src_width), src}); + + return mk_term(Kind::ITE, {signBit, oneExtended, zeroExtended}); +} + +Term BitwuzlaBuilder::writeExpr(Term array, Term index, Term value) { + return mk_term(Kind::ARRAY_STORE, {array, index, value}); +} + +Term BitwuzlaBuilder::readExpr(Term array, Term index) { + return mk_term(Kind::ARRAY_SELECT, {array, index}); +} + +unsigned BitwuzlaBuilder::getBVLength(Term expr) { + if (!expr.sort().is_bv()) { + klee_error("getBVLength() accepts only bitvector, given %s", + expr.sort().str().c_str()); + } + return expr.sort().bv_size(); +} + +Term BitwuzlaBuilder::iteExpr(Term condition, Term whenTrue, Term whenFalse) { + // Handle implicit bitvector/float coercision + Sort whenTrueSort = whenTrue.sort(); + Sort whenFalseSort = whenFalse.sort(); + + if (whenTrueSort.is_bv() && whenFalseSort.is_fp()) { + // Coerce `whenFalse` to be a bitvector + whenFalse = castToBitVector(whenFalse); + } + + if (whenTrueSort.is_fp() && whenFalseSort.is_bv()) { + // Coerce `whenTrue` to be a bitvector + whenTrue = castToBitVector(whenTrue); + } + return mk_term(Kind::ITE, {condition, whenTrue, whenFalse}); +} + +Term BitwuzlaBuilder::bvLtExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_ULT, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvLeExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_ULE, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::sbvLtExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_SLT, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::sbvLeExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_SLE, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::constructAShrByConstant(Term expr, unsigned shift, + Term isSigned) { + Term exprAsBv = castToBitVector(expr); + unsigned width = getBVLength(exprAsBv); + + if (shift == 0) { + return exprAsBv; + } else if (shift >= width) { + return bvZero(width); // Overshift to zero + } else { + // FIXME: Is this really the best way to interact with Bitwuzla? + Term signed_term = + mk_term(Kind::BV_CONCAT, + {bvMinusOne(shift), bvExtract(exprAsBv, width - 1, shift)}); + Term unsigned_term = bvRightShift(exprAsBv, shift); + + return mk_term(Kind::ITE, {isSigned, signed_term, unsigned_term}); + } +} + +Term BitwuzlaBuilder::getInitialArray(const Array *root) { + assert(root); + Term array_expr; + bool hashed = _arr_hash.lookupArrayExpr(root, array_expr); + + if (!hashed) { + // Unique arrays by name, so we make sure the name is unique by + // using the size of the array hash as a counter. + std::string unique_id = llvm::utostr(_arr_hash._array_hash.size()); + std::string unique_name = root->getIdentifier() + unique_id; + + auto source = dyn_cast(root->source); + auto value = (source ? source->constantValues.defaultV() : nullptr); + if (source) { + assert(value); + } + + if (source && !isa(root->size)) { + array_expr = buildConstantArray(unique_name.c_str(), root->getDomain(), + root->getRange(), value->getZExtValue(8)); + } else { + array_expr = + buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); + } + + if (source) { + if (auto constSize = dyn_cast(root->size)) { + std::vector array_assertions; + for (size_t i = 0; i < constSize->getZExtValue(); i++) { + auto value = source->constantValues.load(i); + // construct(= (select i root) root->value[i]) to be asserted in + // BitwuzlaSolver.cpp + int width_out; + Term array_value = construct(value, &width_out); + assert(width_out == (int)root->getRange() && + "Value doesn't match root range"); + array_assertions.push_back( + eqExpr(readExpr(array_expr, bvConst32(root->getDomain(), i)), + array_value)); + } + constant_array_assertions[root] = std::move(array_assertions); + } else { + for (auto &[index, value] : source->constantValues.storage()) { + int width_out; + Term array_value = construct(value, &width_out); + assert(width_out == (int)root->getRange() && + "Value doesn't match root range"); + array_expr = writeExpr( + array_expr, bvConst32(root->getDomain(), index), array_value); + } + } + } + + _arr_hash.hashArrayExpr(root, array_expr); + } + + return array_expr; +} + +Term BitwuzlaBuilder::getInitialRead(const Array *root, unsigned index) { + return readExpr(getInitialArray(root), bvConst32(32, index)); +} + +Term BitwuzlaBuilder::getArrayForUpdate(const Array *root, + const UpdateNode *un) { + // Iterate over the update nodes, until we find a cached version of the node, + // or no more update nodes remain + Term un_expr; + std::vector update_nodes; + for (; un && !_arr_hash.lookupUpdateNodeExpr(un, un_expr); + un = un->next.get()) { + update_nodes.push_back(un); + } + if (!un) { + un_expr = getInitialArray(root); + } + // `un_expr` now holds an expression for the array - either from cache or by + // virtue of being the initial array expression + + // Create and cache solver expressions based on the update nodes starting from + // the oldest + for (const auto &un : + llvm::make_range(update_nodes.crbegin(), update_nodes.crend())) { + un_expr = + writeExpr(un_expr, construct(un->index, 0), construct(un->value, 0)); + + _arr_hash.hashUpdateNodeExpr(un, un_expr); + } + + return un_expr; +} + +Term BitwuzlaBuilder::construct(ref e, int *width_out) { + if (!BitwuzlaHashConfig::UseConstructHashBitwuzla || isa(e)) { + return constructActual(e, width_out); + } else { + ExprHashMap>::iterator it = constructed.find(e); + if (it != constructed.end()) { + if (width_out) + *width_out = it->second.second; + return it->second.first; + } else { + int width; + if (!width_out) + width_out = &width; + Term res = constructActual(e, width_out); + constructed.insert(std::make_pair(e, std::make_pair(res, *width_out))); + return res; + } + } +} + +void BitwuzlaBuilder::FPCastWidthAssert(int *width_out, char const *msg) { + assert(&(ConstantExpr::widthToFloatSemantics(*width_out)) != + &(llvm::APFloat::Bogus()) && + msg); +} + +/** if *width_out!=1 then result is a bitvector, +otherwise it is a bool */ +Term BitwuzlaBuilder::constructActual(ref e, int *width_out) { + + int width; + if (!width_out) + width_out = &width; + ++stats::queryConstructs; + switch (e->getKind()) { + case Expr::Constant: { + ConstantExpr *CE = cast(e); + *width_out = CE->getWidth(); + + // Coerce to bool if necessary. + if (*width_out == 1) + return CE->isTrue() ? getTrue() : getFalse(); + + Term Res; + if (*width_out <= 32) { + // Fast path. + Res = bvConst32(*width_out, CE->getZExtValue(32)); + } else if (*width_out <= 64) { + // Fast path. + Res = bvConst64(*width_out, CE->getZExtValue()); + } else { + llvm::SmallString<129> CEUValue; + CE->getAPValue().toStringUnsigned(CEUValue); + Res = mk_bv_value(mk_bv_sort(CE->getWidth()), CEUValue.str().str(), 10); + } + // Coerce to float if necesary + if (CE->isFloat()) { + Res = castToFloat(Res); + } + return Res; + } + + // Special + case Expr::NotOptimized: { + NotOptimizedExpr *noe = cast(e); + return construct(noe->src, width_out); + } + + case Expr::Read: { + ReadExpr *re = cast(e); + assert(re && re->updates.root); + *width_out = re->updates.root->getRange(); + return readExpr(getArrayForUpdate(re->updates.root, re->updates.head.get()), + construct(re->index, 0)); + } + + case Expr::Select: { + SelectExpr *se = cast(e); + Term cond = construct(se->cond, 0); + Term tExpr = construct(se->trueExpr, width_out); + Term fExpr = construct(se->falseExpr, width_out); + return iteExpr(cond, tExpr, fExpr); + } + + case Expr::Concat: { + ConcatExpr *ce = cast(e); + unsigned numKids = ce->getNumKids(); + std::vector term_args; + term_args.reserve(numKids); + + for (unsigned i = 0; i < numKids; ++i) { + term_args.push_back(construct(ce->getKid(i), 0)); + } + + *width_out = ce->getWidth(); + return mk_term(Kind::BV_CONCAT, term_args); + } + + case Expr::Extract: { + ExtractExpr *ee = cast(e); + Term src = construct(ee->expr, width_out); + *width_out = ee->getWidth(); + if (*width_out == 1) { + return bvBoolExtract(src, ee->offset); + } else { + return bvExtract(src, ee->offset + *width_out - 1, ee->offset); + } + } + + // Casting + + case Expr::ZExt: { + int srcWidth; + CastExpr *ce = cast(e); + Term src = construct(ce->src, &srcWidth); + *width_out = ce->getWidth(); + if (srcWidth == 1) { + return iteExpr(src, bvOne(*width_out), bvZero(*width_out)); + } else { + assert(*width_out > srcWidth && "Invalid width_out"); + return mk_term(Kind::BV_CONCAT, + {bvZero(*width_out - srcWidth), castToBitVector(src)}); + } + } + + case Expr::SExt: { + int srcWidth; + CastExpr *ce = cast(e); + Term src = construct(ce->src, &srcWidth); + *width_out = ce->getWidth(); + if (srcWidth == 1) { + return iteExpr(src, bvMinusOne(*width_out), bvZero(*width_out)); + } else { + return bvSignExtend(src, *width_out); + } + } + + case Expr::FPExt: { + int srcWidth; + FPExtExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPExt width"); + assert(*width_out >= srcWidth && "Invalid FPExt"); + // Just use any arounding mode here as we are extending + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term( + Kind::FP_TO_FP_FROM_FP, + {getRoundingModeSort(llvm::APFloat::rmNearestTiesToEven), src}, + {out_widths.first, out_widths.second}); + } + + case Expr::FPTrunc: { + int srcWidth; + FPTruncExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPTrunc width"); + assert(*width_out <= srcWidth && "Invalid FPTrunc"); + + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term( + Kind::FP_TO_FP_FROM_FP, + {getRoundingModeSort(llvm::APFloat::rmNearestTiesToEven), src}, + {out_widths.first, out_widths.second}); + } + + case Expr::FPToUI: { + int srcWidth; + FPToUIExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPToUI width"); + return mk_term(Kind::FP_TO_UBV, + {getRoundingModeSort(ce->roundingMode), src}, + {ce->getWidth()}); + } + + case Expr::FPToSI: { + int srcWidth; + FPToSIExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPToSI width"); + return mk_term(Kind::FP_TO_SBV, + {getRoundingModeSort(ce->roundingMode), src}, + {ce->getWidth()}); + } + + case Expr::UIToFP: { + int srcWidth; + UIToFPExpr *ce = cast(e); + Term src = castToBitVector(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid UIToFP width"); + + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term(Kind::FP_TO_FP_FROM_UBV, + {getRoundingModeSort(ce->roundingMode), src}, + {out_widths.first, out_widths.second}); + } + + case Expr::SIToFP: { + int srcWidth; + SIToFPExpr *ce = cast(e); + Term src = castToBitVector(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid SIToFP width"); + + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term(Kind::FP_TO_FP_FROM_SBV, + {getRoundingModeSort(ce->roundingMode), src}, + {out_widths.first, out_widths.second}); + } + + // Arithmetic + case Expr::Add: { + AddExpr *ae = cast(e); + Term left = castToBitVector(construct(ae->left, width_out)); + Term right = castToBitVector(construct(ae->right, width_out)); + assert(*width_out != 1 && "uncanonicalized add"); + Term result = mk_term(Kind::BV_ADD, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::Sub: { + SubExpr *se = cast(e); + Term left = castToBitVector(construct(se->left, width_out)); + Term right = castToBitVector(construct(se->right, width_out)); + assert(*width_out != 1 && "uncanonicalized sub"); + Term result = mk_term(Kind::BV_SUB, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::Mul: { + MulExpr *me = cast(e); + Term right = castToBitVector(construct(me->right, width_out)); + assert(*width_out != 1 && "uncanonicalized mul"); + Term left = castToBitVector(construct(me->left, width_out)); + Term result = mk_term(Kind::BV_MUL, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::UDiv: { + UDivExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + assert(*width_out != 1 && "uncanonicalized udiv"); + + if (ConstantExpr *CE = dyn_cast(de->right)) { + if (CE->getWidth() <= 64) { + uint64_t divisor = CE->getZExtValue(); + if (bits64::isPowerOfTwo(divisor)) + return bvRightShift(left, bits64::indexOfSingleBit(divisor)); + } + } + + Term right = castToBitVector(construct(de->right, width_out)); + Term result = mk_term(Kind::BV_UDIV, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::SDiv: { + SDivExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + assert(*width_out != 1 && "uncanonicalized sdiv"); + Term right = castToBitVector(construct(de->right, width_out)); + Term result = mk_term(Kind::BV_SDIV, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::URem: { + URemExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + assert(*width_out != 1 && "uncanonicalized urem"); + + if (ConstantExpr *CE = dyn_cast(de->right)) { + if (CE->getWidth() <= 64) { + uint64_t divisor = CE->getZExtValue(); + + if (bits64::isPowerOfTwo(divisor)) { + int bits = bits64::indexOfSingleBit(divisor); + assert(bits >= 0 && "bit index cannot be negative"); + assert(bits64::indexOfSingleBit(divisor) < INT32_MAX); + + // special case for modding by 1 or else we bvExtract -1:0 + if (bits == 0) { + return bvZero(*width_out); + } else { + assert(*width_out > bits && "invalid width_out"); + return mk_term(Kind::BV_CONCAT, {bvZero(*width_out - bits), + bvExtract(left, bits - 1, 0)}); + } + } + } + } + + Term right = castToBitVector(construct(de->right, width_out)); + Term result = mk_term(Kind::BV_UREM, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::SRem: { + SRemExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + Term right = castToBitVector(construct(de->right, width_out)); + assert(*width_out != 1 && "uncanonicalized srem"); + Term result = mk_term(Kind::BV_SREM, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + // Bitwise + case Expr::Not: { + NotExpr *ne = cast(e); + Term expr = construct(ne->expr, width_out); + if (*width_out == 1) { + return notExpr(expr); + } else { + return bvNotExpr(expr); + } + } + + case Expr::And: { + AndExpr *ae = cast(e); + Term left = construct(ae->left, width_out); + Term right = construct(ae->right, width_out); + if (*width_out == 1) { + return andExpr(left, right); + } else { + return bvAndExpr(left, right); + } + } + + case Expr::Or: { + OrExpr *oe = cast(e); + Term left = construct(oe->left, width_out); + Term right = construct(oe->right, width_out); + if (*width_out == 1) { + return orExpr(left, right); + } else { + return bvOrExpr(left, right); + } + } + + case Expr::Xor: { + XorExpr *xe = cast(e); + Term left = construct(xe->left, width_out); + Term right = construct(xe->right, width_out); + + if (*width_out == 1) { + // XXX check for most efficient? + return iteExpr(left, Term(notExpr(right)), right); + } else { + return bvXorExpr(left, right); + } + } + + case Expr::Shl: { + ShlExpr *se = cast(e); + Term left = construct(se->left, width_out); + assert(*width_out != 1 && "uncanonicalized shl"); + + if (ConstantExpr *CE = dyn_cast(se->right)) { + return bvLeftShift(left, (unsigned)CE->getLimitedValue()); + } else { + int shiftWidth; + Term amount = construct(se->right, &shiftWidth); + return bvVarLeftShift(left, amount); + } + } + + case Expr::LShr: { + LShrExpr *lse = cast(e); + Term left = construct(lse->left, width_out); + assert(*width_out != 1 && "uncanonicalized lshr"); + + if (ConstantExpr *CE = dyn_cast(lse->right)) { + return bvRightShift(left, (unsigned)CE->getLimitedValue()); + } else { + int shiftWidth; + Term amount = construct(lse->right, &shiftWidth); + return bvVarRightShift(left, amount); + } + } + + case Expr::AShr: { + AShrExpr *ase = cast(e); + Term left = castToBitVector(construct(ase->left, width_out)); + assert(*width_out != 1 && "uncanonicalized ashr"); + + if (ConstantExpr *CE = dyn_cast(ase->right)) { + unsigned shift = (unsigned)CE->getLimitedValue(); + Term signedBool = bvBoolExtract(left, *width_out - 1); + return constructAShrByConstant(left, shift, signedBool); + } else { + int shiftWidth; + Term amount = construct(ase->right, &shiftWidth); + return bvVarArithRightShift(left, amount); + } + } + + // Comparison + + case Expr::Eq: { + EqExpr *ee = cast(e); + Term left = construct(ee->left, width_out); + Term right = construct(ee->right, width_out); + if (*width_out == 1) { + if (ConstantExpr *CE = dyn_cast(ee->left)) { + if (CE->isTrue()) + return right; + return notExpr(right); + } else { + return iffExpr(left, right); + } + } else { + *width_out = 1; + return eqExpr(left, right); + } + } + + case Expr::Ult: { + UltExpr *ue = cast(e); + Term left = construct(ue->left, width_out); + Term right = construct(ue->right, width_out); + assert(*width_out != 1 && "uncanonicalized ult"); + *width_out = 1; + return bvLtExpr(left, right); + } + + case Expr::Ule: { + UleExpr *ue = cast(e); + Term left = construct(ue->left, width_out); + Term right = construct(ue->right, width_out); + assert(*width_out != 1 && "uncanonicalized ule"); + *width_out = 1; + return bvLeExpr(left, right); + } + + case Expr::Slt: { + SltExpr *se = cast(e); + Term left = construct(se->left, width_out); + Term right = construct(se->right, width_out); + assert(*width_out != 1 && "uncanonicalized slt"); + *width_out = 1; + return sbvLtExpr(left, right); + } + + case Expr::Sle: { + SleExpr *se = cast(e); + Term left = construct(se->left, width_out); + Term right = construct(se->right, width_out); + assert(*width_out != 1 && "uncanonicalized sle"); + *width_out = 1; + return sbvLeExpr(left, right); + } + + case Expr::FOEq: { + FOEqExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_EQUAL, {left, right}); + } + + case Expr::FOLt: { + FOLtExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_LT, {left, right}); + } + + case Expr::FOLe: { + FOLeExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_LEQ, {left, right}); + } + + case Expr::FOGt: { + FOGtExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_GT, {left, right}); + } + + case Expr::FOGe: { + FOGeExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_GEQ, {left, right}); + } + + case Expr::IsNaN: { + IsNaNExpr *ine = cast(e); + Term arg = castToFloat(construct(ine->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_NAN, {arg}); + } + + case Expr::IsInfinite: { + IsInfiniteExpr *iie = cast(e); + Term arg = castToFloat(construct(iie->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_INF, {arg}); + } + + case Expr::IsNormal: { + IsNormalExpr *ine = cast(e); + Term arg = castToFloat(construct(ine->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_NORMAL, {arg}); + } + + case Expr::IsSubnormal: { + IsSubnormalExpr *ise = cast(e); + Term arg = castToFloat(construct(ise->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_SUBNORMAL, {arg}); + } + + case Expr::FAdd: { + FAddExpr *fadd = cast(e); + Term left = castToFloat(construct(fadd->left, width_out)); + Term right = castToFloat(construct(fadd->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FAdd"); + return mk_term(Kind::FP_ADD, + {getRoundingModeSort(fadd->roundingMode), left, right}); + } + + case Expr::FSub: { + FSubExpr *fsub = cast(e); + Term left = castToFloat(construct(fsub->left, width_out)); + Term right = castToFloat(construct(fsub->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FSub"); + return mk_term(Kind::FP_SUB, + {getRoundingModeSort(fsub->roundingMode), left, right}); + } + + case Expr::FMul: { + FMulExpr *fmul = cast(e); + Term left = castToFloat(construct(fmul->left, width_out)); + Term right = castToFloat(construct(fmul->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FMul"); + return mk_term(Kind::FP_MUL, + {getRoundingModeSort(fmul->roundingMode), left, right}); + } + + case Expr::FDiv: { + FDivExpr *fdiv = cast(e); + Term left = castToFloat(construct(fdiv->left, width_out)); + Term right = castToFloat(construct(fdiv->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FDiv"); + return mk_term(Kind::FP_DIV, + {getRoundingModeSort(fdiv->roundingMode), left, right}); + } + case Expr::FRem: { + FRemExpr *frem = cast(e); + Term left = castToFloat(construct(frem->left, width_out)); + Term right = castToFloat(construct(frem->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FRem"); + return mk_term(Kind::FP_REM, {left, right}); + } + + case Expr::FMax: { + FMaxExpr *fmax = cast(e); + Term left = castToFloat(construct(fmax->left, width_out)); + Term right = castToFloat(construct(fmax->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FMax"); + return mk_term(Kind::FP_MAX, {left, right}); + } + + case Expr::FMin: { + FMinExpr *fmin = cast(e); + Term left = castToFloat(construct(fmin->left, width_out)); + Term right = castToFloat(construct(fmin->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FMin"); + return mk_term(Kind::FP_MIN, {left, right}); + } + + case Expr::FSqrt: { + FSqrtExpr *fsqrt = cast(e); + Term arg = castToFloat(construct(fsqrt->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FSqrt"); + return mk_term(Kind::FP_SQRT, + {getRoundingModeSort(fsqrt->roundingMode), arg}); + } + case Expr::FRint: { + FRintExpr *frint = cast(e); + Term arg = castToFloat(construct(frint->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FSqrt"); + return mk_term(Kind::FP_RTI, + {getRoundingModeSort(frint->roundingMode), arg}); + } + + case Expr::FAbs: { + FAbsExpr *fabsExpr = cast(e); + Term arg = castToFloat(construct(fabsExpr->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FAbs"); + return mk_term(Kind::FP_ABS, {arg}); + } + + case Expr::FNeg: { + FNegExpr *fnegExpr = cast(e); + Term arg = castToFloat(construct(fnegExpr->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FNeg"); + return mk_term(Kind::FP_NEG, {arg}); + } + +// unused due to canonicalization +#if 0 + case Expr::Ne: +case Expr::Ugt: +case Expr::Uge: +case Expr::Sgt: +case Expr::Sge: +#endif + + default: + assert(0 && "unhandled Expr type"); + return getTrue(); + } +} + +Term BitwuzlaBuilder::fpToIEEEBV(const Term &fp) { + if (!fp.sort().is_fp()) { + klee_error("BitwuzlaBuilder::fpToIEEEBV accepts only floats"); + } + + Term signBit = mk_const(getBvSort(1)); + Term exponentBits = mk_const(getBvSort(fp.sort().fp_exp_size())); + Term significandBits = mk_const(getBvSort(fp.sort().fp_sig_size() - 1)); + + Term floatTerm = + mk_term(Kind::FP_FP, {signBit, exponentBits, significandBits}); + sideConstraints.push_back(mk_term(Kind::EQUAL, {fp, floatTerm})); + + return mk_term(Kind::BV_CONCAT, {signBit, exponentBits, significandBits}); +} + +std::pair +BitwuzlaBuilder::getFloatSortFromBitWidth(unsigned bitWidth) { + switch (bitWidth) { + case Expr::Int16: { + return {5, 11}; + } + case Expr::Int32: { + return {8, 24}; + } + case Expr::Int64: { + return {11, 53}; + } + case Expr::Fl80: { + // Note this is an IEEE754 with a 15 bit exponent + // and 64 bit significand. This is not the same + // as x87 fp80 which has a different binary encoding. + // We can use this Bitwuzla type to get the appropriate + // amount of precision. We just have to be very + // careful which casting between floats and bitvectors. + // + // Note that the number of significand bits includes the "implicit" + // bit (which is not implicit for x87 fp80). + return {15, 64}; + } + case Expr::Int128: { + return {15, 113}; + } + default: + assert( + 0 && + "bitWidth cannot converted to a IEEE-754 binary-* number by Bitwuzla"); + std::abort(); + } +} + +Term BitwuzlaBuilder::castToFloat(const Term &e) { + Sort currentSort = e.sort(); + if (currentSort.is_fp()) { + // Already a float + return e; + } else if (currentSort.is_bv()) { + unsigned bitWidth = currentSort.bv_size(); + switch (bitWidth) { + case Expr::Int16: + case Expr::Int32: + case Expr::Int64: + case Expr::Int128: { + auto out_width = getFloatSortFromBitWidth(bitWidth); + return mk_term(Kind::FP_TO_FP_FROM_BV, {e}, + {out_width.first, out_width.second}); + } + case Expr::Fl80: { + // The bit pattern used by x87 fp80 and what we use in Bitwuzla are + // different + // + // x87 fp80 + // + // Sign Exponent Significand + // [1] [15] [1] [63] + // + // The exponent has bias 16383 and the significand has the integer portion + // as an explicit bit + // + // 79-bit IEEE-754 encoding used in Bitwuzla + // + // Sign Exponent [Significand] + // [1] [15] [63] + // + // Exponent has bias 16383 (2^(15-1) -1) and the significand has + // the integer portion as an implicit bit. + // + // We need to provide the mapping here and also emit a side constraint + // to make sure the explicit bit is appropriately constrained so when + // Bitwuzla generates a model we get the correct bit pattern back. + // + // This assumes Bitwuzla's IEEE semantics, x87 fp80 actually + // has additional semantics due to the explicit bit (See 8.2.2 + // "Unsupported Double Extended-Precision Floating-Point Encodings and + // Pseudo-Denormals" in the Intel 64 and IA-32 Architectures Software + // Developer's Manual) but this encoding means we can't model these + // unsupported values in Bitwuzla. + // + // Note this code must kept in sync with + // `BitwuzlaBuilder::castToBitVector()`. Which performs the inverse + // operation here. + // + // TODO: Experiment with creating a constraint that transforms these + // unsupported bit patterns into a Bitwuzla NaN to approximate the + // behaviour from those values. + + // Note we try very hard here to avoid calling into our functions + // here that do implicit casting so we can never recursively call + // into this function. + Term signBit = mk_term(Kind::BV_EXTRACT, {e}, {79, 79}); + Term exponentBits = mk_term(Kind::BV_EXTRACT, {e}, {78, 64}); + Term significandIntegerBit = mk_term(Kind::BV_EXTRACT, {e}, {63, 63}); + Term significandFractionBits = mk_term(Kind::BV_EXTRACT, {e}, {62, 0}); + + Term ieeeBitPatternAsFloat = mk_term( + Kind::FP_FP, {signBit, exponentBits, significandFractionBits}); + + // Generate side constraint on the significand integer bit. It is not + // used in `ieeeBitPatternAsFloat` so we need to constrain that bit to + // have the correct value so that when Bitwuzla gives a model the bit + // pattern has the right value for x87 fp80. + // + // If the number is a denormal or zero then the implicit integer bit + // is zero otherwise it is one. + Term significandIntegerBitConstrainedValue = + getx87FP80ExplicitSignificandIntegerBit(ieeeBitPatternAsFloat); + Term significandIntegerBitConstraint = + mk_term(Kind::EQUAL, {significandIntegerBit, + significandIntegerBitConstrainedValue}); + + sideConstraints.push_back(significandIntegerBitConstraint); + return ieeeBitPatternAsFloat; + } + default: + llvm_unreachable("Unhandled width when casting bitvector to float"); + } + } else { + llvm_unreachable("Sort cannot be cast to float"); + } +} + +Term BitwuzlaBuilder::castToBitVector(const Term &e) { + Sort currentSort = e.sort(); + if (currentSort.is_bool()) { + return mk_term(Kind::ITE, {e, bvOne(1), bvZero(1)}); + } else if (currentSort.is_bv()) { + // Already a bitvector + return e; + } else if (currentSort.is_fp()) { + // Note this picks a single representation for NaN which means + // `castToBitVector(castToFloat(e))` might not equal `e`. + unsigned exponentBits = currentSort.fp_exp_size(); + unsigned significandBits = + currentSort.fp_sig_size(); // Includes implicit bit + unsigned floatWidth = exponentBits + significandBits; + + switch (floatWidth) { + case Expr::Int16: + case Expr::Int32: + case Expr::Int64: + case Expr::Int128: + return fpToIEEEBV(e); + case 79: { + // This is Expr::Fl80 (64 bit exponent, 15 bit significand) but due to + // the "implicit" bit actually being implicit in x87 fp80 the sum of + // the exponent and significand bitwidth is 79 not 80. + + // Get Bitwuzla's IEEE representation + Term ieeeBits = fpToIEEEBV(e); + + // Construct the x87 fp80 bit representation + Term signBit = mk_term(Kind::BV_EXTRACT, {ieeeBits}, {78, 78}); + Term exponentBits = mk_term(Kind::BV_EXTRACT, {ieeeBits}, {77, 63}); + Term significandIntegerBit = getx87FP80ExplicitSignificandIntegerBit(e); + Term significandFractionBits = + mk_term(Kind::BV_EXTRACT, {ieeeBits}, {62, 0}); + Term x87FP80Bits = mk_term(Kind::BV_CONCAT, + {signBit, exponentBits, significandIntegerBit, + significandFractionBits}); + return x87FP80Bits; + } + default: + llvm_unreachable("Unhandled width when casting float to bitvector"); + } + } else { + llvm_unreachable("Sort cannot be cast to float"); + } +} + +Term BitwuzlaBuilder::getRoundingModeSort(llvm::APFloat::roundingMode rm) { + switch (rm) { + case llvm::APFloat::rmNearestTiesToEven: + return mk_rm_value(RoundingMode::RNE); + case llvm::APFloat::rmTowardPositive: + return mk_rm_value(RoundingMode::RTP); + case llvm::APFloat::rmTowardNegative: + return mk_rm_value(RoundingMode::RTN); + case llvm::APFloat::rmTowardZero: + return mk_rm_value(RoundingMode::RTZ); + case llvm::APFloat::rmNearestTiesToAway: + return mk_rm_value(RoundingMode::RNA); + default: + llvm_unreachable("Unhandled rounding mode"); + } +} + +Term BitwuzlaBuilder::getx87FP80ExplicitSignificandIntegerBit(const Term &e) { +#ifndef NDEBUG + // Check the passed in expression is the right type. + Sort currentSort = e.sort(); + assert(currentSort.is_fp()); + + unsigned exponentBits = currentSort.fp_exp_size(); + unsigned significandBits = currentSort.fp_sig_size(); + assert(exponentBits == 15); + assert(significandBits == 64); +#endif + // If the number is a denormal or zero then the implicit integer bit is zero + // otherwise it is one. Term isDenormal = + Term isDenormal = mk_term(Kind::FP_IS_SUBNORMAL, {e}); + Term isZero = mk_term(Kind::FP_IS_ZERO, {e}); + + // FIXME: Cache these constants somewhere + Sort oneBitBvSort = getBvSort(/*width=*/1); + + Term oneBvOne = mk_bv_value_uint64(oneBitBvSort, 1); + Term zeroBvOne = mk_bv_value_uint64(oneBitBvSort, 0); + + Term significandIntegerBitCondition = orExpr(isDenormal, isZero); + + Term significandIntegerBitConstrainedValue = + mk_term(Kind::ITE, {significandIntegerBitCondition, zeroBvOne, oneBvOne}); + + return significandIntegerBitConstrainedValue; +} +} // namespace klee + +#endif // ENABLE_BITWUZLA diff --git a/lib/Solver/BitwuzlaBuilder.h b/lib/Solver/BitwuzlaBuilder.h new file mode 100644 index 0000000000..35a7ae2512 --- /dev/null +++ b/lib/Solver/BitwuzlaBuilder.h @@ -0,0 +1,144 @@ +//===-- BitwuzlaBuilder.h --------------------------------------------*- C++ +//-*-====// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef BITWUZLABUILDER_H_ +#define BITWUZLABUILDER_H_ + +#include "klee/Config/config.h" +#include "klee/Expr/ArrayExprHash.h" +#include "klee/Expr/ExprHashMap.h" + +#include +#include + +using namespace bitwuzla; + +namespace klee { + +class BitwuzlaArrayExprHash : public ArrayExprHash { + friend class BitwuzlaBuilder; + +public: + BitwuzlaArrayExprHash(){}; + virtual ~BitwuzlaArrayExprHash(); + void clear(); + void clearUpdates(); +}; + +class BitwuzlaBuilder { +private: + void FPCastWidthAssert(int *width_out, char const *msg); + Term fpToIEEEBV(const Term &); + +protected: + Term bvOne(unsigned width); + Term bvZero(unsigned width); + Term bvMinusOne(unsigned width); + Term bvConst32(unsigned width, uint32_t value); + Term bvConst64(unsigned width, uint64_t value); + Term bvZExtConst(unsigned width, uint64_t value); + Term bvSExtConst(unsigned width, uint64_t value); + Term bvBoolExtract(Term expr, int bit); + Term bvExtract(Term expr, unsigned top, unsigned bottom); + Term eqExpr(Term a, Term b); + + // logical left and right shift (not arithmetic) + Term bvLeftShift(Term expr, unsigned shift); + Term bvRightShift(Term expr, unsigned shift); + Term bvVarLeftShift(Term expr, Term shift); + Term bvVarRightShift(Term expr, Term shift); + Term bvVarArithRightShift(Term expr, Term shift); + + Term notExpr(Term expr); + Term andExpr(Term lhs, Term rhs); + Term orExpr(Term lhs, Term rhs); + Term iffExpr(Term lhs, Term rhs); + + Term bvNotExpr(Term expr); + Term bvAndExpr(Term lhs, Term rhs); + Term bvOrExpr(Term lhs, Term rhs); + Term bvXorExpr(Term lhs, Term rhs); + Term bvSignExtend(Term src, unsigned width); + + // Array operations + Term writeExpr(Term array, Term index, Term value); + Term readExpr(Term array, Term index); + + // ITE-expression constructor + Term iteExpr(Term condition, Term whenTrue, Term whenFalse); + + // Bitvector length + unsigned getBVLength(Term expr); + + // Bitvector comparison + Term bvLtExpr(Term lhs, Term rhs); + Term bvLeExpr(Term lhs, Term rhs); + Term sbvLtExpr(Term lhs, Term rhs); + Term sbvLeExpr(Term lhs, Term rhs); + + Term constructAShrByConstant(Term expr, unsigned shift, Term isSigned); + + Term getInitialArray(const Array *os); + Term getArrayForUpdate(const Array *root, const UpdateNode *un); + + Term constructActual(ref e, int *width_out); + Term construct(ref e, int *width_out); + Term buildArray(const char *name, unsigned indexWidth, unsigned valueWidth); + Term buildConstantArray(const char *name, unsigned indexWidth, + unsigned valueWidth, unsigned value); + + Sort getBoolSort(); + Sort getBvSort(unsigned width); + Sort getArraySort(Sort domainSort, Sort rangeSort); + + std::pair getFloatSortFromBitWidth(unsigned bitWidth); + + // Float casts + Term castToFloat(const Term &e); + Term castToBitVector(const Term &e); + + Term getRoundingModeSort(llvm::APFloat::roundingMode rm); + Term getx87FP80ExplicitSignificandIntegerBit(const Term &e); + + ExprHashMap> constructed; + BitwuzlaArrayExprHash _arr_hash; + bool autoClearConstructCache; + +public: + std::unordered_map> + constant_array_assertions; + // These are additional constraints that are generated during the + // translation to Bitwuzla's constraint language. Clients should assert + // these. + std::vector sideConstraints; + + std::string symbolOf(const Array *array) { + return getInitialArray(array).symbol().value(); + } + + BitwuzlaBuilder(bool autoClearConstructCache); + ~BitwuzlaBuilder(); + + Term getTrue(); + Term getFalse(); + Term buildFreshBoolConst(); + Term getInitialRead(const Array *os, unsigned index); + + Term construct(ref e) { + Term res = construct(std::move(e), nullptr); + if (autoClearConstructCache) + clearConstructCache(); + return res; + } + void clearConstructCache() { constructed.clear(); } + void clearSideConstraints() { sideConstraints.clear(); } +}; +} // namespace klee + +#endif diff --git a/lib/Solver/BitwuzlaHashConfig.cpp b/lib/Solver/BitwuzlaHashConfig.cpp new file mode 100644 index 0000000000..4ee8cfe429 --- /dev/null +++ b/lib/Solver/BitwuzlaHashConfig.cpp @@ -0,0 +1,20 @@ +//===-- BitwuzlaHashConfig.cpp ---------------------------------------*- C++ +//-*-====// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "BitwuzlaHashConfig.h" +#include + +namespace BitwuzlaHashConfig { +llvm::cl::opt UseConstructHashBitwuzla( + "use-construct-hash-bitwuzla", + llvm::cl::desc( + "Use hash-consing during Bitwuzla query construction (default=true)"), + llvm::cl::init(true), llvm::cl::cat(klee::ExprCat)); +} // namespace BitwuzlaHashConfig diff --git a/lib/Solver/BitwuzlaHashConfig.h b/lib/Solver/BitwuzlaHashConfig.h new file mode 100644 index 0000000000..a4a2d97bb1 --- /dev/null +++ b/lib/Solver/BitwuzlaHashConfig.h @@ -0,0 +1,25 @@ +//===-- BitwuzlaHashConfig.h -----------------------------------------*- C++ +//-*-====// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_BITWUZLAHASHCONFIG_H +#define KLEE_BITWUZLAHASHCONFIG_H + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/CommandLine.h" +DISABLE_WARNING_POP + +#include + +namespace BitwuzlaHashConfig { +extern llvm::cl::opt UseConstructHashBitwuzla; +} // namespace BitwuzlaHashConfig +#endif // KLEE_BITWUZLAHASHCONFIG_H diff --git a/lib/Solver/BitwuzlaSolver.cpp b/lib/Solver/BitwuzlaSolver.cpp new file mode 100644 index 0000000000..10b9a48840 --- /dev/null +++ b/lib/Solver/BitwuzlaSolver.cpp @@ -0,0 +1,960 @@ + +//===-- BitwuzlaSolver.cpp ---------------------------------------*-C++-*-====// +// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Config/config.h" + +#ifdef ENABLE_BITWUZLA + +#include "BitwuzlaBuilder.h" +#include "BitwuzlaSolver.h" + +#include "klee/ADT/Incremental.h" +#include "klee/ADT/SparseStorage.h" +#include "klee/Expr/Assignment.h" +#include "klee/Expr/Constraints.h" +#include "klee/Expr/ExprUtil.h" +#include "klee/Solver/Solver.h" +#include "klee/Solver/SolverImpl.h" +#include "klee/Support/ErrorHandling.h" +#include "klee/Support/FileHandling.h" +#include "klee/Support/OptionCategories.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include + +#include "bitwuzla/cpp/bitwuzla.h" + +namespace { +// NOTE: Very useful for debugging Bitwuzla behaviour. These files can be given +// to the Bitwuzla binary to replay all Bitwuzla API calls using its `-log` +// option. + +llvm::cl::opt BitwuzlaValidateModels( + "debug-bitwuzla-validate-models", llvm::cl::init(false), + llvm::cl::desc( + "When generating Bitwuzla models validate these against the query"), + llvm::cl::cat(klee::SolvingCat)); + +llvm::cl::opt BitwuzlaVerbosityLevel( + "debug-bitwuzla-verbosity", llvm::cl::init(0), + llvm::cl::desc("Bitwuzla verbosity level (default=0)"), + llvm::cl::cat(klee::SolvingCat)); +} // namespace + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/ErrorHandling.h" +DISABLE_WARNING_POP + +namespace { +bool interrupted = false; + +void signal_handler(int signum) { interrupted = true; } +} // namespace + +namespace klee { + +class BitwuzlaTerminator : public bitwuzla::Terminator { +private: + uint64_t time_limit_micro; + time::Point start; + + bool _isTimeout = false; + +public: + BitwuzlaTerminator(uint64_t); + bool terminate() override; + + bool isTimeout() const { return _isTimeout; } +}; + +BitwuzlaTerminator::BitwuzlaTerminator(uint64_t time_limit_micro) + : Terminator(), time_limit_micro(time_limit_micro), + start(time::getWallTime()) {} + +bool BitwuzlaTerminator::terminate() { + time::Point end = time::getWallTime(); + if ((end - start).toMicroseconds() >= time_limit_micro) { + _isTimeout = true; + return true; + } + if (interrupted) { + return true; + } + return false; +} + +using ConstraintFrames = inc_vector>; +using ExprIncMap = inc_umap>; +using BitwuzlaASTIncMap = inc_umap; +using ExprIncSet = + inc_uset, klee::util::ExprHash, klee::util::ExprCmp>; +using BitwuzlaASTIncSet = inc_uset; + +extern void dump(const ConstraintFrames &); + +class ConstraintQuery { +private: + // this should be used when only query is needed, se comment below + ref expr; + +public: + // KLEE Queries are validity queries i.e. + // ∀ X Constraints(X) → query(X) + // but Bitwuzla works in terms of satisfiability so instead we ask the + // negation of the equivalent i.e. + // ∃ X Constraints(X) ∧ ¬ query(X) + // so this `constraints` field contains: Constraints(X) ∧ ¬ query(X) + ConstraintFrames constraints; + + explicit ConstraintQuery() {} + + explicit ConstraintQuery(const ConstraintFrames &frames, const ref &e) + : expr(e), constraints(frames) {} + explicit ConstraintQuery(ConstraintFrames &&frames, ref &&e) + : expr(std::move(e)), constraints(std::move(frames)) {} + + explicit ConstraintQuery(const Query &q, bool incremental) : expr(q.expr) { + if (incremental) { + for (auto &constraint : q.constraints.cs()) { + constraints.v.push_back(constraint); + constraints.push(); + } + } else { + const auto &other = q.constraints.cs(); + constraints.v.reserve(other.size()); + constraints.v.insert(constraints.v.end(), other.begin(), other.end()); + } + if (q.expr->getWidth() == Expr::Bool && !q.expr->isFalse()) + constraints.v.push_back(NotExpr::create(q.expr)); + } + + size_t size() const { return constraints.v.size(); } + + ref getOriginalQueryExpr() const { return expr; } + + ConstraintQuery withFalse() const { + return ConstraintQuery(ConstraintFrames(constraints), Expr::createFalse()); + } + + std::vector gatherArrays() const { + std::vector arrays; + findObjects(constraints.v.begin(), constraints.v.end(), arrays); + return arrays; + } +}; + +enum class ObjectAssignment { + NotNeeded, + NeededForObjectsFromEnv, + NeededForObjectsFromQuery +}; + +struct BitwuzlaSolverEnv { + using arr_vec = std::vector; + inc_vector objects; + arr_vec objectsForGetModel; + ExprIncMap bitwuzla_ast_expr_to_klee_expr; + BitwuzlaASTIncSet expr_to_track; + inc_umap usedArrayBytes; + ExprIncSet symbolicObjects; + + explicit BitwuzlaSolverEnv() = default; + explicit BitwuzlaSolverEnv(const arr_vec &objects); + + void pop(size_t popSize); + void push(); + void clear(); + + const arr_vec *getObjectsForGetModel(ObjectAssignment oa) const; +}; + +BitwuzlaSolverEnv::BitwuzlaSolverEnv(const arr_vec &objects) + : objectsForGetModel(objects) {} + +void BitwuzlaSolverEnv::pop(size_t popSize) { + if (popSize == 0) + return; + objects.pop(popSize); + objectsForGetModel.clear(); + bitwuzla_ast_expr_to_klee_expr.pop(popSize); + expr_to_track.pop(popSize); + usedArrayBytes.pop(popSize); + symbolicObjects.pop(popSize); +} + +void BitwuzlaSolverEnv::push() { + objects.push(); + bitwuzla_ast_expr_to_klee_expr.push(); + expr_to_track.push(); + usedArrayBytes.push(); + symbolicObjects.push(); +} + +void BitwuzlaSolverEnv::clear() { + objects.clear(); + objectsForGetModel.clear(); + bitwuzla_ast_expr_to_klee_expr.clear(); + expr_to_track.clear(); + usedArrayBytes.clear(); + symbolicObjects.clear(); +} + +const BitwuzlaSolverEnv::arr_vec * +BitwuzlaSolverEnv::getObjectsForGetModel(ObjectAssignment oa) const { + switch (oa) { + case ObjectAssignment::NotNeeded: + return nullptr; + case ObjectAssignment::NeededForObjectsFromEnv: + return &objectsForGetModel; + case ObjectAssignment::NeededForObjectsFromQuery: + return &objects.v; + default: + llvm_unreachable("unknown object assignment"); + } +} + +class BitwuzlaSolverImpl : public SolverImpl { +protected: + std::unique_ptr builder; + Options solverParameters; + +private: + time::Span timeout; + SolverImpl::SolverRunStatus runStatusCode; + + bool internalRunSolver(const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, + ValidityCore *validityCore, bool &hasSolution); + + SolverImpl::SolverRunStatus handleSolverResponse( + Bitwuzla &theSolver, Result satisfiable, const BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, bool &hasSolution); + +protected: + BitwuzlaSolverImpl(); + + virtual Bitwuzla &initNativeBitwuzla(const ConstraintQuery &query, + BitwuzlaASTIncSet &assertions) = 0; + virtual void deinitNativeBitwuzla(Bitwuzla &theSolver) = 0; + virtual void push(Bitwuzla &s) = 0; + + bool computeTruth(const ConstraintQuery &, BitwuzlaSolverEnv &env, + bool &isValid); + bool computeValue(const ConstraintQuery &, BitwuzlaSolverEnv &env, + ref &result); + bool computeInitialValues(const ConstraintQuery &, BitwuzlaSolverEnv &env, + std::vector> &values, + bool &hasSolution); + bool check(const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ref &result); + bool computeValidityCore(const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ValidityCore &validityCore, bool &isValid); + +public: + char *getConstraintLog(const Query &) final; + SolverImpl::SolverRunStatus getOperationStatusCode() final; + void setCoreSolverTimeout(time::Span _timeout) final { timeout = _timeout; } + void enableUnsatCore() { + solverParameters.set(Option::PRODUCE_UNSAT_CORES, true); + } + void disableUnsatCore() { + solverParameters.set(Option::PRODUCE_UNSAT_CORES, false); + } + + // pass virtual functions to children + using SolverImpl::check; + using SolverImpl::computeInitialValues; + using SolverImpl::computeTruth; + using SolverImpl::computeValidityCore; + using SolverImpl::computeValue; +}; + +void deleteNativeBitwuzla(std::optional &theSolver) { + theSolver.reset(); +} + +BitwuzlaSolverImpl::BitwuzlaSolverImpl() + : runStatusCode(SolverImpl::SOLVER_RUN_STATUS_FAILURE) { + builder = std::unique_ptr(new BitwuzlaBuilder( + /*autoClearConstructCache=*/false)); + assert(builder && "unable to create BitwuzlaBuilder"); + + solverParameters.set(Option::PRODUCE_MODELS, true); + + setCoreSolverTimeout(timeout); + + if (ProduceUnsatCore) { + enableUnsatCore(); + } else { + disableUnsatCore(); + } + + // Set verbosity + if (BitwuzlaVerbosityLevel > 0) { + solverParameters.set(Option::VERBOSITY, BitwuzlaVerbosityLevel); + } + + if (BitwuzlaValidateModels) { + solverParameters.set(Option::DBG_CHECK_MODEL, true); + } +} + +char *BitwuzlaSolverImpl::getConstraintLog(const Query &query) { + std::stringstream outputLog; + + // We use a different builder here because we don't want to interfere + // with the solver's builder because it may change the solver builder's + // cache. + // NOTE: The builder does not set `z3LogInteractionFile` to avoid conflicting + // with whatever the solver's builder is set to do. + std::unique_ptr tempBuilder(new BitwuzlaBuilder(false)); + ConstantArrayFinder constant_arrays_in_query; + + for (const auto array : + query.constraints.withExpr(query.expr).gatherArrays()) { + outputLog << "(declare-fun " << tempBuilder->symbolOf(array) + << " () (Array (_ BitVec " << array->getDomain() << ") (_ BitVec " + << array->getRange() << ")))\n"; + } + + for (auto const &constraint : query.constraints.cs()) { + outputLog << "(assert " << tempBuilder->construct(constraint).str(10) + << ")\n"; + constant_arrays_in_query.visit(constraint); + } + + // KLEE Queries are validity queries i.e. + // ∀ X Constraints(X) → query(X) + // but Z3 works in terms of satisfiability so instead we ask the + // the negation of the equivalent i.e. + // ∃ X Constraints(X) ∧ ¬ query(X) + Term formula = mk_term(Kind::NOT, {tempBuilder->construct(query.expr)}); + constant_arrays_in_query.visit(query.expr); + + for (auto const &constant_array : constant_arrays_in_query.results) { + for (auto const &arrayIndexValueExpr : + tempBuilder->constant_array_assertions[constant_array]) { + outputLog << "(assert " << arrayIndexValueExpr.str(10) << ")\n"; + } + } + + outputLog << "(assert " << formula.str(10) << ")\n"; + outputLog << "(check-sat)" + << "\n"; + + // Client is responsible for freeing the returned C-string + return strdup(outputLog.str().c_str()); +} + +bool BitwuzlaSolverImpl::computeTruth(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, bool &isValid) { + bool hasSolution = false; // to remove compiler warning + bool status = internalRunSolver(query, /*env=*/env, + ObjectAssignment::NotNeeded, /*values=*/NULL, + /*validityCore=*/NULL, hasSolution); + isValid = !hasSolution; + return status; +} + +bool BitwuzlaSolverImpl::computeValue(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, + ref &result) { + std::vector> values; + bool hasSolution; + + // Find the object used in the expression, and compute an assignment + // for them. + findSymbolicObjects(query.getOriginalQueryExpr(), env.objectsForGetModel); + if (!computeInitialValues(query.withFalse(), env, values, hasSolution)) + return false; + assert(hasSolution && "state has invalid constraint set"); + + // Evaluate the expression with the computed assignment. + Assignment a(env.objectsForGetModel, values); + result = a.evaluate(query.getOriginalQueryExpr()); + + return true; +} + +bool BitwuzlaSolverImpl::computeInitialValues( + const ConstraintQuery &query, BitwuzlaSolverEnv &env, + std::vector> &values, bool &hasSolution) { + return internalRunSolver(query, env, + ObjectAssignment::NeededForObjectsFromEnv, &values, + /*validityCore=*/NULL, hasSolution); +} + +bool BitwuzlaSolverImpl::check(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, + ref &result) { + std::vector> values; + ValidityCore validityCore; + bool hasSolution = false; + bool status = + internalRunSolver(query, env, ObjectAssignment::NeededForObjectsFromQuery, + &values, &validityCore, hasSolution); + if (status) { + result = hasSolution + ? (SolverResponse *)new InvalidResponse(env.objects.v, values) + : (SolverResponse *)new ValidResponse(validityCore); + } + return status; +} + +bool BitwuzlaSolverImpl::computeValidityCore(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, + ValidityCore &validityCore, + bool &isValid) { + bool hasSolution = false; // to remove compiler warning + bool status = + internalRunSolver(query, /*env=*/env, ObjectAssignment::NotNeeded, + /*values=*/NULL, &validityCore, hasSolution); + isValid = !hasSolution; + return status; +} + +bool BitwuzlaSolverImpl::internalRunSolver( + const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, + ValidityCore *validityCore, bool &hasSolution) { + TimerStatIncrementer t(stats::queryTime); + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_FAILURE; + + std::unordered_set all_constant_arrays_in_query; + BitwuzlaASTIncSet exprs; + + for (size_t i = 0; i < query.constraints.framesSize(); + i++, env.push(), exprs.push()) { + ConstantArrayFinder constant_arrays_in_query; + env.symbolicObjects.insert(query.constraints.begin(i), + query.constraints.end(i)); + // FIXME: findSymbolicObjects template does not support inc_uset::iterator + // findSymbolicObjects(env.symbolicObjects.begin(-1), + // env.symbolicObjects.end(-1), env.objects.v); + std::vector> tmp(env.symbolicObjects.begin(-1), + env.symbolicObjects.end(-1)); + findSymbolicObjects(tmp.begin(), tmp.end(), env.objects.v); + for (auto cs_it = query.constraints.begin(i), + cs_ite = query.constraints.end(i); + cs_it != cs_ite; cs_it++) { + const auto &constraint = *cs_it; + Term bitwuzlaConstraint = builder->construct(constraint); + if (ProduceUnsatCore && validityCore) { + env.bitwuzla_ast_expr_to_klee_expr.insert( + {bitwuzlaConstraint, constraint}); + env.expr_to_track.insert(bitwuzlaConstraint); + } + + exprs.insert(bitwuzlaConstraint); + + constant_arrays_in_query.visit(constraint); + + std::vector> reads; + findReads(constraint, true, reads); + for (const auto &readExpr : reads) { + auto readFromArray = readExpr->updates.root; + assert(readFromArray); + env.usedArrayBytes[readFromArray].insert(readExpr->index); + } + } + + for (auto constant_array : constant_arrays_in_query.results) { + if (all_constant_arrays_in_query.count(constant_array)) + continue; + all_constant_arrays_in_query.insert(constant_array); + const auto &cas = builder->constant_array_assertions[constant_array]; + exprs.insert(cas.begin(), cas.end()); + } + + // Assert an generated side constraints we have to this last so that all + // other constraints have been traversed so we have all the side constraints + // needed. + exprs.insert(builder->sideConstraints.begin(), + builder->sideConstraints.end()); + } + exprs.pop(1); // drop last empty frame + + ++stats::solverQueries; + if (!env.objects.v.empty()) + ++stats::queryCounterexamples; + + // Prepare signal handler and terminator fot bitwuzla + auto timeoutInMicroSeconds = static_cast(timeout.toMicroseconds()); + if (!timeoutInMicroSeconds) + timeoutInMicroSeconds = UINT_MAX; + BitwuzlaTerminator terminator(timeoutInMicroSeconds); + + struct sigaction action, old_action; + action.sa_handler = signal_handler; + action.sa_flags = 0; + sigaction(SIGINT, &action, &old_action); + + Bitwuzla &theSolver = initNativeBitwuzla(query, exprs); + theSolver.configure_terminator(&terminator); + + for (size_t i = 0; i < exprs.framesSize(); i++) { + push(theSolver); + for (auto it = exprs.begin(i), ie = exprs.end(i); it != ie; ++it) { + theSolver.assert_formula(*it); + } + } + + Result satisfiable = theSolver.check_sat(); + theSolver.configure_terminator(nullptr); + runStatusCode = handleSolverResponse(theSolver, satisfiable, env, needObjects, + values, hasSolution); + sigaction(SIGINT, &old_action, nullptr); + + if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_FAILURE) { + if (terminator.isTimeout()) { + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_TIMEOUT; + } + if (interrupted) { + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED; + } + } + + if (ProduceUnsatCore && validityCore && satisfiable == Result::UNSAT) { + const std::vector bitwuzla_unsat_core = theSolver.get_unsat_core(); + const std::unordered_set bitwuzla_term_unsat_core( + bitwuzla_unsat_core.begin(), bitwuzla_unsat_core.end()); + + constraints_ty unsatCore; + for (const auto &bitwuzla_constraint : env.expr_to_track) { + if (bitwuzla_term_unsat_core.count(bitwuzla_constraint)) { + ref constraint = + env.bitwuzla_ast_expr_to_klee_expr[bitwuzla_constraint]; + unsatCore.insert(constraint); + } + } + assert(validityCore && "validityCore cannot be nullptr"); + *validityCore = ValidityCore(unsatCore, query.getOriginalQueryExpr()); + + stats::validQueriesSize += theSolver.get_assertions().size(); + stats::validityCoresSize += bitwuzla_unsat_core.size(); + ++stats::queryValidityCores; + } + + deinitNativeBitwuzla(theSolver); + + // Clear the builder's cache to prevent memory usage exploding. + // By using ``autoClearConstructCache=false`` and clearning now + // we allow Term expressions to be shared from an entire + // ``Query`` rather than only sharing within a single call to + // ``builder->construct()``. + builder->clearConstructCache(); + builder->clearSideConstraints(); + if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE || + runStatusCode == SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE) { + if (hasSolution) { + ++stats::queriesInvalid; + } else { + ++stats::queriesValid; + } + return true; // success + } + if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED) { + raise(SIGINT); + } + return false; // failed +} + +SolverImpl::SolverRunStatus BitwuzlaSolverImpl::handleSolverResponse( + Bitwuzla &theSolver, Result satisfiable, const BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, bool &hasSolution) { + switch (satisfiable) { + case Result::SAT: { + hasSolution = true; + auto objects = env.getObjectsForGetModel(needObjects); + if (!objects) { + // No assignment is needed + assert(!values); + return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; + } + assert(values && "values cannot be nullptr"); + + values->reserve(objects->size()); + for (auto array : *objects) { + SparseStorage data; + + if (env.usedArrayBytes.count(array)) { + std::unordered_set offsetValues; + for (const ref &offsetExpr : env.usedArrayBytes.at(array)) { + Term arrayElementOffsetExpr = + theSolver.get_value(builder->construct(offsetExpr)); + + uint64_t concretizedOffsetValue = + std::stoull(arrayElementOffsetExpr.value(10)); + offsetValues.insert(concretizedOffsetValue); + } + + for (unsigned offset : offsetValues) { + // We can't use Term here so have to do ref counting manually + Term initial_read = builder->getInitialRead(array, offset); + Term initial_read_expr = theSolver.get_value(initial_read); + + uint64_t arrayElementValue = + std::stoull(initial_read_expr.value(10)); + data.store(offset, arrayElementValue); + } + } + + values->emplace_back(std::move(data)); + } + + assert(values->size() == objects->size()); + + return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; + } + case Result::UNSAT: + hasSolution = false; + return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE; + case Result::UNKNOWN: { + return SolverImpl::SOLVER_RUN_STATUS_FAILURE; + } + default: + llvm_unreachable("unhandled Bitwuzla result"); + } +} + +SolverImpl::SolverRunStatus BitwuzlaSolverImpl::getOperationStatusCode() { + return runStatusCode; +} + +class BitwuzlaNonIncSolverImpl final : public BitwuzlaSolverImpl { +private: + std::optional theSolver; + +public: + BitwuzlaNonIncSolverImpl() = default; + + /// implementation of BitwuzlaSolverImpl interface + Bitwuzla &initNativeBitwuzla(const ConstraintQuery &query, + BitwuzlaASTIncSet &assertions) override { + theSolver.emplace(solverParameters); + return theSolver.value(); + } + + void deinitNativeBitwuzla(Bitwuzla &) override { + deleteNativeBitwuzla(theSolver); + } + + void push(Bitwuzla &s) override {} + + /// implementation of the SolverImpl interface + bool computeTruth(const Query &query, bool &isValid) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::computeTruth(ConstraintQuery(query, false), env, + isValid); + } + bool computeValue(const Query &query, ref &result) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::computeValue(ConstraintQuery(query, false), env, + result); + } + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution) override { + BitwuzlaSolverEnv env(objects); + return BitwuzlaSolverImpl::computeInitialValues( + ConstraintQuery(query, false), env, values, hasSolution); + } + bool check(const Query &query, ref &result) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::check(ConstraintQuery(query, false), env, + result); + } + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::computeValidityCore( + ConstraintQuery(query, false), env, validityCore, isValid); + } + void notifyStateTermination(std::uint32_t id) override {} +}; + +BitwuzlaSolver::BitwuzlaSolver() + : Solver(std::make_unique()) {} + +struct ConstraintDistance { + size_t toPopSize = 0; + ConstraintQuery toPush; + + explicit ConstraintDistance() {} + ConstraintDistance(const ConstraintQuery &q) : toPush(q) {} + explicit ConstraintDistance(size_t toPopSize, const ConstraintQuery &q) + : toPopSize(toPopSize), toPush(q) {} + + size_t getDistance() const { return toPopSize + toPush.size(); } + + bool isOnlyPush() const { return toPopSize == 0; } + + void dump() const { + llvm::errs() << "ConstraintDistance: pop: " << toPopSize << "; push:\n"; + klee::dump(toPush.constraints); + } +}; + +class BitwuzlaIncNativeSolver { +private: + std::optional nativeSolver; + Options solverParameters; + /// underlying solver frames + /// saved only for calculating distances from next queries + ConstraintFrames frames; + + void pop(size_t popSize); + +public: + BitwuzlaSolverEnv env; + std::uint32_t stateID = 0; + bool isRecycled = false; + + BitwuzlaIncNativeSolver(Options solverParameters) + : solverParameters(solverParameters) {} + ~BitwuzlaIncNativeSolver(); + + void clear(); + + void distance(const ConstraintQuery &query, ConstraintDistance &delta) const; + + void popPush(ConstraintDistance &delta); + + Bitwuzla &getOrInit(); + + bool isConsistent() const { + klee_warning("Empty isConsistent() check"); + return true; + } + + void dump() const { ::klee::dump(frames); } +}; + +void BitwuzlaIncNativeSolver::pop(size_t popSize) { + if (!nativeSolver.has_value() || !popSize) + return; + nativeSolver.value().pop(popSize); +} + +void BitwuzlaIncNativeSolver::popPush(ConstraintDistance &delta) { + env.pop(delta.toPopSize); + pop(delta.toPopSize); + frames.pop(delta.toPopSize); + frames.extend(delta.toPush.constraints); +} + +Bitwuzla &BitwuzlaIncNativeSolver::getOrInit() { + if (!nativeSolver.has_value()) { + nativeSolver.emplace(solverParameters); + } + return nativeSolver.value(); +} + +BitwuzlaIncNativeSolver::~BitwuzlaIncNativeSolver() { + if (nativeSolver.has_value()) { + deleteNativeBitwuzla(nativeSolver); + } +} + +void BitwuzlaIncNativeSolver::clear() { + if (!nativeSolver.has_value()) + return; + env.clear(); + frames.clear(); + nativeSolver.emplace(solverParameters); + isRecycled = false; +} + +void BitwuzlaIncNativeSolver::distance(const ConstraintQuery &query, + ConstraintDistance &delta) const { + auto sit = frames.v.begin(); + auto site = frames.v.end(); + auto qit = query.constraints.v.begin(); + auto qite = query.constraints.v.end(); + auto it = frames.begin(); + auto ite = frames.end(); + size_t intersect = 0; + for (; it != ite && sit != site && qit != qite && *sit == *qit; it++) { + size_t frame_size = *it; + for (size_t i = 0; + i < frame_size && sit != site && qit != qite && *sit == *qit; + i++, sit++, qit++, intersect++) { + } + } + for (; sit != site && qit != qite && *sit == *qit; + sit++, qit++, intersect++) { + } + size_t toPop, extraTakeFromOther; + ConstraintFrames d; + if (sit == site) { // solver frames ended + toPop = 0; + extraTakeFromOther = 0; + } else { + frames.takeBefore(intersect, toPop, extraTakeFromOther); + } + query.constraints.takeAfter(intersect - extraTakeFromOther, d); + ConstraintQuery q(std::move(d), query.getOriginalQueryExpr()); + delta = ConstraintDistance(toPop, std::move(q)); +} + +class BitwuzlaTreeSolverImpl final : public BitwuzlaSolverImpl { +private: + using solvers_ty = std::vector>; + using solvers_it = solvers_ty::iterator; + + const size_t maxSolvers; + std::unique_ptr currentSolver = nullptr; + solvers_ty solvers; + + void findSuitableSolver(const ConstraintQuery &query, + ConstraintDistance &delta); + void setSolver(solvers_it &it, bool recycle = false); + ConstraintQuery prepare(const Query &q); + +public: + BitwuzlaTreeSolverImpl(size_t maxSolvers) : maxSolvers(maxSolvers){}; + + /// implementation of BitwuzlaSolverImpl interface + Bitwuzla &initNativeBitwuzla(const ConstraintQuery &query, + BitwuzlaASTIncSet &assertions) override { + return currentSolver->getOrInit(); + } + void deinitNativeBitwuzla(Bitwuzla &theSolver) override { + assert(currentSolver->isConsistent()); + solvers.push_back(std::move(currentSolver)); + } + void push(Bitwuzla &s) override { s.push(1); } + + /// implementation of the SolverImpl interface + bool computeTruth(const Query &query, bool &isValid) override; + bool computeValue(const Query &query, ref &result) override; + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution) override; + bool check(const Query &query, ref &result) override; + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid) override; + + void notifyStateTermination(std::uint32_t id) override; +}; + +void BitwuzlaTreeSolverImpl::setSolver(solvers_it &it, bool recycle) { + assert(it != solvers.end()); + currentSolver = std::move(*it); + solvers.erase(it); + currentSolver->isRecycled = false; + if (recycle) + currentSolver->clear(); +} + +void BitwuzlaTreeSolverImpl::findSuitableSolver(const ConstraintQuery &query, + ConstraintDistance &delta) { + ConstraintDistance min_delta; + auto min_distance = std::numeric_limits::max(); + auto min_it = solvers.end(); + auto free_it = solvers.end(); + for (auto it = solvers.begin(), ite = min_it; it != ite; it++) { + if ((*it)->isRecycled) + free_it = it; + (*it)->distance(query, delta); + if (delta.isOnlyPush()) { + setSolver(it); + return; + } + auto distance = delta.getDistance(); + if (distance < min_distance) { + min_delta = delta; + min_distance = distance; + min_it = it; + } + } + if (solvers.size() < maxSolvers) { + delta = ConstraintDistance(query); + if (delta.getDistance() < min_distance) { + // it is cheaper to create new solver + if (free_it == solvers.end()) + currentSolver = + std::make_unique(solverParameters); + else + setSolver(free_it, /*recycle=*/true); + return; + } + } + assert(min_it != solvers.end()); + delta = min_delta; + setSolver(min_it); +} + +ConstraintQuery BitwuzlaTreeSolverImpl::prepare(const Query &q) { + ConstraintDistance delta; + ConstraintQuery query(q, true); + findSuitableSolver(query, delta); + assert(currentSolver->isConsistent()); + currentSolver->stateID = q.id; + currentSolver->popPush(delta); + return delta.toPush; +} + +bool BitwuzlaTreeSolverImpl::computeTruth(const Query &query, bool &isValid) { + auto q = prepare(query); + return BitwuzlaSolverImpl::computeTruth(q, currentSolver->env, isValid); +} + +bool BitwuzlaTreeSolverImpl::computeValue(const Query &query, + ref &result) { + auto q = prepare(query); + return BitwuzlaSolverImpl::computeValue(q, currentSolver->env, result); +} + +bool BitwuzlaTreeSolverImpl::computeInitialValues( + const Query &query, const std::vector &objects, + std::vector> &values, bool &hasSolution) { + auto q = prepare(query); + currentSolver->env.objectsForGetModel = objects; + return BitwuzlaSolverImpl::computeInitialValues(q, currentSolver->env, values, + hasSolution); +} + +bool BitwuzlaTreeSolverImpl::check(const Query &query, + ref &result) { + auto q = prepare(query); + return BitwuzlaSolverImpl::check(q, currentSolver->env, result); +} + +bool BitwuzlaTreeSolverImpl::computeValidityCore(const Query &query, + ValidityCore &validityCore, + bool &isValid) { + auto q = prepare(query); + return BitwuzlaSolverImpl::computeValidityCore(q, currentSolver->env, + validityCore, isValid); +} + +void BitwuzlaTreeSolverImpl::notifyStateTermination(std::uint32_t id) { + for (auto &s : solvers) + if (s->stateID == id) + s->isRecycled = true; +} + +BitwuzlaTreeSolver::BitwuzlaTreeSolver(unsigned maxSolvers) + : Solver(std::make_unique(maxSolvers)) {} + +} // namespace klee +#endif // ENABLE_BITWUZLA diff --git a/lib/Solver/BitwuzlaSolver.h b/lib/Solver/BitwuzlaSolver.h new file mode 100644 index 0000000000..613b416c5a --- /dev/null +++ b/lib/Solver/BitwuzlaSolver.h @@ -0,0 +1,22 @@ +#ifndef BITWUZLASOLVER_H_ +#define BITWUZLASOLVER_H_ + +#include "klee/Solver/Solver.h" + +namespace klee { + +/// BitwuzlaSolver - A complete solver based on Bitwuzla +class BitwuzlaSolver : public Solver { +public: + /// BitwuzlaSolver - Construct a new BitwuzlaSolver. + BitwuzlaSolver(); +}; + +class BitwuzlaTreeSolver : public Solver { +public: + BitwuzlaTreeSolver(unsigned maxSolvers); +}; + +} // namespace klee + +#endif diff --git a/lib/Solver/CMakeLists.txt b/lib/Solver/CMakeLists.txt index a1b15052bc..b4523d1594 100644 --- a/lib/Solver/CMakeLists.txt +++ b/lib/Solver/CMakeLists.txt @@ -7,7 +7,11 @@ # #===------------------------------------------------------------------------===# add_library(kleaverSolver + AlphaEquivalenceSolver.cpp AssignmentValidatingSolver.cpp + BitwuzlaBuilder.cpp + BitwuzlaHashConfig.cpp + BitwuzlaSolver.cpp CachingSolver.cpp CexCachingSolver.cpp ConstantDivision.cpp @@ -48,7 +52,6 @@ target_include_directories(kleaverSolver PRIVATE ${KLEE_INCLUDE_DIRS} ${LLVM_INC target_compile_options(kleaverSolver PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) target_compile_definitions(kleaverSolver PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) - install(TARGETS kleaverSolver EXPORT run_klee DESTINATION "${RUN_KLEE_LIB_DEST}" diff --git a/lib/Solver/CachingSolver.cpp b/lib/Solver/CachingSolver.cpp index de43695d5e..f01d760d32 100644 --- a/lib/Solver/CachingSolver.cpp +++ b/lib/Solver/CachingSolver.cpp @@ -36,12 +36,12 @@ class CachingSolver : public SolverImpl { struct CacheEntry { CacheEntry(const ConstraintSet &c, ref q) - : constraints(c), query(q) {} + : constraints(c.cs()), query(q) {} CacheEntry(const CacheEntry &ce) : constraints(ce.constraints), query(ce.query) {} - ConstraintSet constraints; + constraints_ty constraints; ref query; bool operator==(const CacheEntry &b) const { @@ -53,8 +53,7 @@ class CachingSolver : public SolverImpl { unsigned operator()(const CacheEntry &ce) const { unsigned result = ce.query->hash(); - assert(ce.constraints.symcretes().empty()); - for (auto const &constraint : ce.constraints.cs()) { + for (auto const &constraint : ce.constraints) { result ^= constraint->hash(); } @@ -90,6 +89,7 @@ class CachingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; /** @returns the canonical version of the given query. The reference @@ -187,30 +187,36 @@ bool CachingSolver::computeValidity(const Query &query, return true; case PValidity::MayBeTrue: { ++stats::queryCacheMisses; - if (!solver->impl->computeTruth(query, tmp)) - return false; - if (tmp) { + bool success = solver->impl->computeTruth(query, tmp); + if (success && tmp) { cacheInsert(query, PValidity::MustBeTrue); result = PValidity::MustBeTrue; return true; - } else { + } else if (success && !tmp) { cacheInsert(query, PValidity::TrueOrFalse); result = PValidity::TrueOrFalse; return true; + } else { + cacheInsert(query, PValidity::MayBeTrue); + result = PValidity::MayBeTrue; + return true; } } case PValidity::MayBeFalse: { ++stats::queryCacheMisses; - if (!solver->impl->computeTruth(query.negateExpr(), tmp)) - return false; - if (tmp) { + bool success = solver->impl->computeTruth(query.negateExpr(), tmp); + if (success && tmp) { cacheInsert(query, PValidity::MustBeFalse); result = PValidity::MustBeFalse; return true; - } else { + } else if (success && !tmp) { cacheInsert(query, PValidity::TrueOrFalse); result = PValidity::TrueOrFalse; return true; + } else { + cacheInsert(query, PValidity::MayBeFalse); + result = PValidity::MayBeFalse; + return true; } } default: @@ -223,19 +229,11 @@ bool CachingSolver::computeValidity(const Query &query, if (!solver->impl->computeValidity(query, result)) return false; - switch (result) { - case PValidity::MustBeTrue: - cachedResult = PValidity::MustBeTrue; - break; - case PValidity::MustBeFalse: - cachedResult = PValidity::MustBeFalse; - break; - default: - cachedResult = PValidity::TrueOrFalse; - break; - } + cachedResult = result; + assert(cachedResult != PValidity::None); cacheInsert(query, cachedResult); + return true; } @@ -275,50 +273,8 @@ bool CachingSolver::computeTruth(const Query &query, bool &isValid) { bool CachingSolver::computeValidityCore(const Query &query, ValidityCore &validityCore, bool &isValid) { - PartialValidity cachedResult; - bool tmp, cacheHit = cacheLookup(query, cachedResult); - - // a cached result of MayBeTrue forces us to check whether - // a False assignment exists. - if (cacheHit && cachedResult != PValidity::MayBeTrue) { - ValidityCore cachedValidityCore; - cacheHit = validityCoreCacheLookup(query, cachedValidityCore); - if (cacheHit && cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheHits; - validityCore = cachedValidityCore; - } else if (cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheMisses; - if (!solver->impl->computeValidityCore(query, validityCore, tmp)) - return false; - assert(tmp && "Query must be true!"); - validityCoreCacheInsert(query, validityCore); - } else { - ++stats::queryCacheHits; - } - isValid = (cachedResult == PValidity::MustBeTrue); - return true; - } - ++stats::queryCacheMisses; - - // cache miss: query solver - if (!solver->impl->computeValidityCore(query, validityCore, isValid)) - return false; - - if (isValid) { - cachedResult = PValidity::MustBeTrue; - validityCoreCacheInsert(query, validityCore); - } else if (cacheHit) { - // We know a true assignment exists, and query isn't valid, so - // must be TrueOrFalse. - assert(cachedResult == PValidity::MayBeTrue); - cachedResult = PValidity::TrueOrFalse; - } else { - cachedResult = PValidity::MayBeFalse; - } - - cacheInsert(query, cachedResult); - return true; + return solver->impl->computeValidityCore(query, validityCore, isValid); } bool CachingSolver::computeInitialValues( @@ -330,50 +286,8 @@ bool CachingSolver::computeInitialValues( } bool CachingSolver::check(const Query &query, ref &result) { - PartialValidity cachedResult; - bool tmp, cacheHit = cacheLookup(query, cachedResult); - - // a cached result of MayBeTrue forces us to check whether - // a False assignment exists. - if (cacheHit && cachedResult != PValidity::MayBeTrue) { - ValidityCore cachedValidityCore; - cacheHit = validityCoreCacheLookup(query, cachedValidityCore); - if (cacheHit && cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheHits; - result = new ValidResponse(cachedValidityCore); - } else if (cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheMisses; - if (!solver->impl->computeValidityCore(query, cachedValidityCore, tmp)) - return false; - result = new ValidResponse(cachedValidityCore); - assert(tmp && "Query must be true!"); - } else { - ++stats::queryCacheMisses; - if (!solver->impl->check(query, result)) - return false; - } - return true; - } - ++stats::queryCacheMisses; - - // cache miss: query solver - if (!solver->impl->check(query, result)) - return false; - - if (isa(result)) { - cachedResult = PValidity::MustBeTrue; - } else if (cacheHit) { - // We know a true assignment exists, and query isn't valid, so - // must be TrueOrFalse. - assert(cachedResult == PValidity::MayBeTrue); - cachedResult = PValidity::TrueOrFalse; - } else { - cachedResult = PValidity::MayBeFalse; - } - - cacheInsert(query, cachedResult); - return true; + return solver->impl->check(query, result); } SolverImpl::SolverRunStatus CachingSolver::getOperationStatusCode() { @@ -388,6 +302,10 @@ void CachingSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } +void CachingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + /// std::unique_ptr diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index da3303359d..038af68e2e 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -93,6 +93,7 @@ class CexCachingSolver : public SolverImpl { } bool getResponse(const Query &query, ref &result); + void setResponse(const Query &query, ref &result); public: CexCachingSolver(std::unique_ptr solver) @@ -112,6 +113,7 @@ class CexCachingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &query); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; /// @@ -127,12 +129,13 @@ struct isInvalidResponse { }; struct isValidOrSatisfyingResponse { - KeyType &key; - + KeyType key; isValidOrSatisfyingResponse(KeyType &_key) : key(_key) {} bool operator()(ref a) const { - return isa(a) || cast(a)->satisfies(key); + return isa(a) || + (isa(a) && + cast(a)->satisfiesOrConstant(key)); } }; @@ -174,7 +177,8 @@ bool CexCachingSolver::searchForResponse(KeyType &key, ie = responseTable.end(); it != ie; ++it) { ref a = *it; - if (isa(a) && cast(a)->satisfies(key)) { + if (isa(a) && + cast(a)->satisfiesOrConstant(key)) { result = a; return true; } @@ -206,6 +210,17 @@ bool CexCachingSolver::searchForResponse(KeyType &key, return false; } +KeyType makeKey(const Query &query) { + KeyType key = + KeyType(query.constraints.cs().begin(), query.constraints.cs().end()); + for (ref s : query.constraints.symcretes()) { + key.insert(s->symcretized); + } + ref neg = Expr::createIsZero(query.expr); + key.insert(neg); + return key; +} + /// lookupResponse - Lookup a cached result for the given \arg query. /// /// \param query - The query to lookup. @@ -215,8 +230,7 @@ bool CexCachingSolver::searchForResponse(KeyType &key, /// an unsatisfiable query). \return True if a cached result was found. bool CexCachingSolver::lookupResponse(const Query &query, KeyType &key, ref &result) { - assert(!query.containsSymcretes()); - key = KeyType(query.constraints.cs().begin(), query.constraints.cs().end()); + key = makeKey(query); ref neg = Expr::createIsZero(query.expr); if (ConstantExpr *CE = dyn_cast(neg)) { if (CE->isFalse()) { @@ -224,8 +238,6 @@ bool CexCachingSolver::lookupResponse(const Query &query, KeyType &key, ++stats::queryCexCacheHits; return true; } - } else { - key.insert(neg); } bool found = searchForResponse(key, result); @@ -239,14 +251,22 @@ bool CexCachingSolver::lookupResponse(const Query &query, KeyType &key, bool CexCachingSolver::getResponse(const Query &query, ref &result) { - KeyType key; - if (lookupResponse(query, key, result)) + if (lookupResponse(query, result)) { return true; + } if (!solver->impl->check(query, result)) { return false; } + setResponse(query, result); + return true; +} + +void CexCachingSolver::setResponse(const Query &query, + ref &result) { + KeyType key = makeKey(query); + if (isa(result)) { // Memorize the result. std::pair res = @@ -255,27 +275,27 @@ bool CexCachingSolver::getResponse(const Query &query, result = *res.first; } - if (DebugCexCacheCheckBinding) - if (!cast(result)->satisfies(key)) { + if (DebugCexCacheCheckBinding) { + if (!cast(result)->satisfiesOrConstant(key, false)) { query.dump(); result->dump(); klee_error("Generated assignment doesn't match query"); } + } } ValidityCore resultCore; - if (CexCacheValidityCores && result->tryGetValidityCore(resultCore)) { + if (CexCacheValidityCores && isa(result)) { + result->tryGetValidityCore(resultCore); KeyType resultCoreConstarints(resultCore.constraints.begin(), resultCore.constraints.end()); - ref neg = Expr::createIsZero(query.expr); + ref neg = Expr::createIsZero(resultCore.expr); resultCoreConstarints.insert(neg); cache.insert(resultCoreConstarints, result); - cache.insert(key, result); - } else { + } + if (isa(result) || isa(result)) { cache.insert(key, result); } - - return true; } /// @@ -286,28 +306,28 @@ bool CexCachingSolver::computeValidity(const Query &query, PartialValidity &result) { TimerStatIncrementer t(stats::cexCacheTime); ref a; - if (!getResponse(query.withFalse(), a)) + ref q; + if (!computeValue(query, q)) return false; - assert(isa(a) && "computeValidity() must have assignment"); - - ref q = cast(a)->evaluate(query.expr); - - if (!isa(q) && solver->impl->computeValue(query, q)) - return false; - - assert(isa(q) && - "assignment evaluation did not result in constant"); if (cast(q)->isTrue()) { - if (!getResponse(query, a)) - return false; - result = - isa(a) ? PValidity::MustBeTrue : PValidity::TrueOrFalse; + bool success = getResponse(query, a); + if (success && isa(a)) { + result = PValidity::MustBeTrue; + } else if (success && isa(a)) { + result = PValidity::TrueOrFalse; + } else { + result = PValidity::MayBeTrue; + } } else { - if (!getResponse(query.negateExpr(), a)) - return false; - result = - isa(a) ? PValidity::MustBeFalse : PValidity::TrueOrFalse; + bool success = getResponse(query.negateExpr(), a); + if (success && isa(a)) { + result = PValidity::MustBeFalse; + } else if (success && isa(a)) { + result = PValidity::TrueOrFalse; + } else { + result = PValidity::MayBeFalse; + } } return true; @@ -334,7 +354,7 @@ bool CexCachingSolver::computeTruth(const Query &query, bool &isValid) { if (!getResponse(query, a)) return false; - isValid = isa(a); + isValid = !isa(a); return true; } @@ -343,16 +363,26 @@ bool CexCachingSolver::computeValue(const Query &query, ref &result) { TimerStatIncrementer t(stats::cexCacheTime); ref a; - if (!getResponse(query.withFalse(), a)) - return false; + if (!query.constraints.cs().empty()) { + if (!getResponse(query.withFalse(), a)) + return false; + } else { + a = new InvalidResponse(); + } assert(isa(a) && "computeValue() must have assignment"); - result = cast(a)->evaluate(query.expr); + result = cast(a)->evaluate(query.expr, false); if (!isa(result) && solver->impl->computeValue(query, result)) return false; assert(isa(result) && "assignment evaluation did not result in constant"); + + if (cast(result)->isTrue()) { + setResponse(query.negateExpr(), a); + } else if (cast(result)->isFalse()) { + setResponse(query, a); + } return true; } @@ -365,16 +395,17 @@ bool CexCachingSolver::computeInitialValues( return false; hasSolution = isa(a); - if (isa(a)) + if (!hasSolution) return true; // FIXME: We should use smarter assignment for result so we don't // need redundant copy. values = std::vector>(objects.size()); + Assignment::bindings_ty aBindings; + a->tryGetInitialValues(aBindings); + for (unsigned i = 0; i < objects.size(); ++i) { const Array *os = objects[i]; - Assignment::bindings_ty aBindings; - a->tryGetInitialValues(aBindings); Assignment::bindings_ty::iterator it = aBindings.find(os); if (it == aBindings.end()) { @@ -382,8 +413,7 @@ bool CexCachingSolver::computeInitialValues( cast(a)->evaluate(os->size); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); - values[i] = - SparseStorage(arrayConstantSize->getZExtValue(), 0); + values[i] = SparseStorage(0); } else { values[i] = it->second; } @@ -424,6 +454,10 @@ void CexCachingSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } +void CexCachingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + /// std::unique_ptr diff --git a/lib/Solver/ConcretizingSolver.cpp b/lib/Solver/ConcretizingSolver.cpp index 36f5a81191..6f0327a226 100644 --- a/lib/Solver/ConcretizingSolver.cpp +++ b/lib/Solver/ConcretizingSolver.cpp @@ -52,21 +52,63 @@ class ConcretizingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); private: bool assertConcretization(const Query &query, const Assignment &assign) const; + bool getBrokenArrays(const Query &query, const Assignment &diff, + ref &result, + std::vector &brokenArrays); bool relaxSymcreteConstraints(const Query &query, ref &result); Query constructConcretizedQuery(const Query &, const Assignment &); + Query getConcretizedVersion(const Query &); + +private: + void reverseConcretization(ValidityCore &validityCore, + const ExprHashMap> &reverse, + ref reverseExpr); + void reverseConcretization(ref &res, + const ExprHashMap> &reverse, + ref reverseExpr); }; Query ConcretizingSolver::constructConcretizedQuery(const Query &query, const Assignment &assign) { - ConstraintSet constraints = assign.createConstraintsFromAssignment(); - for (auto e : query.constraints.cs()) { - constraints.addConstraint(e, {}); + ConstraintSet cs = query.constraints; + ref concretizedExpr = assign.evaluate(query.expr); + return Query(cs.getConcretizedVersion(assign), concretizedExpr, query.id); +} + +Query ConcretizingSolver::getConcretizedVersion(const Query &query) { + ConstraintSet cs = query.constraints; + ref concretizedExpr = cs.concretization().evaluate(query.expr); + return Query(cs.getConcretizedVersion(), concretizedExpr, query.id); +} + +void ConcretizingSolver::reverseConcretization( + ValidityCore &validityCore, const ExprHashMap> &reverse, + ref reverseExpr) { + validityCore.expr = reverseExpr; + for (auto e : reverse) { + if (validityCore.constraints.find(e.second) != + validityCore.constraints.end()) { + validityCore.constraints.erase(e.second); + validityCore.constraints.insert(e.first); + } + } +} + +void ConcretizingSolver::reverseConcretization( + ref &res, const ExprHashMap> &reverse, + ref reverseExpr) { + if (!isa(res)) { + return; } - return Query(constraints, query.expr); + ValidityCore validityCore; + res->tryGetValidityCore(validityCore); + reverseConcretization(validityCore, reverse, reverseExpr); + res = new ValidResponse(validityCore); } bool ConcretizingSolver::assertConcretization(const Query &query, @@ -80,6 +122,41 @@ bool ConcretizingSolver::assertConcretization(const Query &query, return true; } +bool ConcretizingSolver::getBrokenArrays( + const Query &query, const Assignment &assign, ref &result, + std::vector &brokenArrays) { + Query concretizedQuery = constructConcretizedQuery(query, assign); + ref CE = dyn_cast(concretizedQuery.expr); + if (CE && CE->isTrue()) { + findObjects(query.expr, brokenArrays); + result = new UnknownResponse(); + return true; + } + const ExprHashMap> &reverse = + concretizedQuery.constraints.independentElements().concretizedExprs; + ref reverseExpr = query.expr; + if (!solver->impl->check(concretizedQuery, result)) { + return false; + } + reverseConcretization(result, reverse, reverseExpr); + + /* No unsat cores were found for the query, so we can try to find new + * solution. */ + if (isa(result)) { + return true; + } + + ValidityCore validityCore; + bool success = result->tryGetValidityCore(validityCore); + assert(success); + + constraints_ty allValidityCoreConstraints = validityCore.constraints; + allValidityCoreConstraints.insert(validityCore.expr); + findObjects(allValidityCoreConstraints.begin(), + allValidityCoreConstraints.end(), brokenArrays); + return true; +} + bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, ref &result) { if (!query.containsSizeSymcretes()) { @@ -111,28 +188,17 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, bool wereConcretizationsRemoved = true; while (wereConcretizationsRemoved) { wereConcretizationsRemoved = false; - if (!solver->impl->check(constructConcretizedQuery(query, assignment), - result)) { + + std::vector currentlyBrokenSymcretizedArrays; + if (!getBrokenArrays(query, assignment, result, + currentlyBrokenSymcretizedArrays)) { return false; } - /* No unsat cores were found for the query, so we can try to find new - * solution. */ if (isa(result)) { break; } - ValidityCore validityCore; - bool success = result->tryGetValidityCore(validityCore); - assert(success); - - constraints_ty allValidityCoreConstraints = validityCore.constraints; - allValidityCoreConstraints.insert(validityCore.expr); - std::vector currentlyBrokenSymcretizedArrays; - findObjects(allValidityCoreConstraints.begin(), - allValidityCoreConstraints.end(), - currentlyBrokenSymcretizedArrays); - std::queue arrayQueue; std::queue addressQueue; @@ -159,9 +225,10 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, if (arrayQueue.empty() && addressArrayPresent) { while (!addressQueue.empty()) { - assignment.bindings.erase(addressQueue.front()); + assignment.bindings.remove(addressQueue.front()); addressQueue.pop(); } + if (!solver->impl->check(constructConcretizedQuery(query, assignment), result)) { return false; @@ -175,7 +242,7 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, while (!arrayQueue.empty()) { const Array *brokenArray = arrayQueue.front(); - assignment.bindings.erase(brokenArray); + assignment.bindings.remove(brokenArray); wereConcretizationsRemoved = true; arrayQueue.pop(); @@ -198,14 +265,15 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, } for (const ref &symcrete : currentlyBrokenSymcretes) { - constraints_ty required; - IndependentElementSet eltsClosure = getIndependentConstraints( - Query(query.constraints, - AndExpr::create(query.expr, - Expr::createIsZero(symcrete->symcretized))), - required); - for (ref symcrete : eltsClosure.symcretes) { - currentlyBrokenSymcretes.insert(symcrete); + std::vector> factors; + query + .withExpr(AndExpr::create( + query.expr, Expr::createIsZero(symcrete->symcretized))) + .getAllDependentConstraintsSets(factors); + for (ref ics : factors) { + for (ref symcrete : ics->symcretes) { + currentlyBrokenSymcretes.insert(symcrete); + } } } @@ -255,7 +323,8 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, UgtExpr::create( symbolicSizesSum, ConstantExpr::create(SymbolicAllocationThreshold, - symbolicSizesSum->getWidth()))), + symbolicSizesSum->getWidth())), + query.id), response)) { return false; } @@ -264,14 +333,15 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, ref minimalValueOfSum; /* Receive model with a smallest sum as possible. */ if (!solver->impl->computeMinimalUnsignedValue( - Query(queryConstraints, symbolicSizesSum), minimalValueOfSum)) { + Query(queryConstraints, symbolicSizesSum, query.id), + minimalValueOfSum)) { return false; } bool hasSolution = false; if (!solver->impl->computeInitialValues( Query(queryConstraints, - EqExpr::create(symbolicSizesSum, minimalValueOfSum)) + EqExpr::create(symbolicSizesSum, minimalValueOfSum), query.id) .negateExpr(), objects, brokenSymcretizedValues, hasSolution)) { return false; @@ -281,7 +351,7 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, } for (unsigned idx = 0; idx < objects.size(); ++idx) { - assignment.bindings[objects[idx]] = brokenSymcretizedValues[idx]; + assignment.bindings.replace({objects[idx], brokenSymcretizedValues[idx]}); } ExprHashMap> concretizations; @@ -308,7 +378,7 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, sizeSymcrete->addressSymcrete.symcretized, newSize); unsigned char *charAddressIterator = reinterpret_cast(&address); - SparseStorage storage(sizeof(address)); + SparseStorage storage(0); storage.store(0, charAddressIterator, charAddressIterator + sizeof(address)); @@ -378,37 +448,10 @@ bool ConcretizingSolver::computeValidity( assert(assertConcretization(query, assign) && "Assignment does not contain concretization for all symcrete arrays!"); - auto concretizedQuery = constructConcretizedQuery(query, assign); - if (!solver->impl->computeValidity(concretizedQuery, queryResult, - negatedQueryResult)) { + if (!check(query, queryResult) || + !check(query.negateExpr(), negatedQueryResult)) { return false; } - - std::vector> queryResultValues, - negatedQueryResultValues; - - std::vector objects = assign.keys(); - - assert(isa(queryResult) || - isa(negatedQueryResult)); - - // *No more than one* of queryResult and negatedQueryResult is possible, - // i.e. `mustBeTrue` with values from `assign`. - // Take one which is `mustBeTrue` with symcretes from `assign` - // and try to relax them to `mayBeFalse`. This solution should be - // appropriate for the remain branch. - - if (isa(queryResult)) { - if (!relaxSymcreteConstraints(query, queryResult)) { - return false; - } - } else if (isa(negatedQueryResult)) { - if (!relaxSymcreteConstraints(query.negateExpr(), negatedQueryResult)) { - return false; - } - } else { - } - return true; } @@ -421,12 +464,15 @@ bool ConcretizingSolver::check(const Query &query, assert(assertConcretization(query, assign) && "Assignment does not contain concretization for all symcrete arrays!"); - auto concretizedQuery = constructConcretizedQuery(query, assign); - if (!solver->impl->check(concretizedQuery, result)) { - return false; - } + auto concretizedQuery = getConcretizedVersion(query); - if (isa(result)) { + ref CE = dyn_cast(concretizedQuery.expr); + if (!CE || !CE->isTrue()) { + if (!solver->impl->check(concretizedQuery, result)) { + return false; + } + } + if ((CE && CE->isTrue()) || isa(result)) { if (!relaxSymcreteConstraints(query, result)) { return false; } @@ -455,8 +501,7 @@ bool ConcretizingSolver::computeTruth(const Query &query, bool &isValid) { query.constraints.concretization().evaluate(query.expr))) { isValid = CE->isTrue(); } else { - auto concretizedQuery = constructConcretizedQuery(query, assign); - + auto concretizedQuery = getConcretizedVersion(query); if (!solver->impl->computeTruth(concretizedQuery, isValid)) { return false; } @@ -471,9 +516,7 @@ bool ConcretizingSolver::computeTruth(const Query &query, bool &isValid) { if (!relaxSymcreteConstraints(query, result)) { return false; } - if (ref resultInvalidResponse = - dyn_cast(result)) { - assign = resultInvalidResponse->initialValuesFor(assign.keys()); + if (isa(result)) { isValid = false; } } @@ -491,7 +534,7 @@ bool ConcretizingSolver::computeValidityCore(const Query &query, assert(assertConcretization(query, assign) && "Assignment does not contain concretization for all symcrete arrays!"); - Query concretizedQuery = constructConcretizedQuery(query, assign); + Query concretizedQuery = getConcretizedVersion(query); if (ref CE = dyn_cast( query.constraints.concretization().evaluate(query.expr))) { @@ -544,7 +587,7 @@ bool ConcretizingSolver::computeValue(const Query &query, ref &result) { result = expr; return true; } - auto concretizedQuery = constructConcretizedQuery(query, assign); + auto concretizedQuery = getConcretizedVersion(query); return solver->impl->computeValue(concretizedQuery, result); } @@ -560,7 +603,7 @@ bool ConcretizingSolver::computeInitialValues( assert(assertConcretization(query, assign) && "Assignment does not contain concretization for all symcrete arrays!"); - auto concretizedQuery = constructConcretizedQuery(query, assign); + auto concretizedQuery = getConcretizedVersion(query); if (!solver->impl->computeInitialValues(concretizedQuery, objects, values, hasSolution)) { return false; @@ -576,11 +619,7 @@ bool ConcretizingSolver::computeInitialValues( if (ref resultInvalidResponse = dyn_cast(result)) { hasSolution = true; - assign = resultInvalidResponse->initialValuesFor(assign.keys()); - values = std::vector>(); - return solver->impl->computeInitialValues( - constructConcretizedQuery(query, assign), objects, values, - hasSolution); + result->tryGetInitialValuesFor(objects, values); } } @@ -596,6 +635,10 @@ void ConcretizingSolver::setCoreSolverTimeout(time::Span timeout) { solver->setCoreSolverTimeout(timeout); } +void ConcretizingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + std::unique_ptr createConcretizingSolver(std::unique_ptr s, AddressGenerator *addressGenerator) { diff --git a/lib/Solver/ConstructSolverChain.cpp b/lib/Solver/ConstructSolverChain.cpp index a8eb1e2fe7..c734db9c64 100644 --- a/lib/Solver/ConstructSolverChain.cpp +++ b/lib/Solver/ConstructSolverChain.cpp @@ -34,7 +34,7 @@ std::unique_ptr constructSolverChain( std::unique_ptr coreSolver, std::string querySMT2LogPath, std::string baseSolverQuerySMT2LogPath, std::string queryKQueryLogPath, std::string baseSolverQueryKQueryLogPath, - AddressGenerator *addressGenerator) { + AddressGenerator *addressGenerator, ArrayCache &arrayCache) { Solver *rawCoreSolver = coreSolver.get(); std::unique_ptr solver = std::move(coreSolver); const time::Span minQueryTimeToLog(MinQueryTimeToLog); @@ -67,12 +67,24 @@ std::unique_ptr constructSolverChain( if (UseBranchCache) solver = createCachingSolver(std::move(solver)); + if (UseAlphaEquivalence) + solver = createAlphaEquivalenceSolver(std::move(solver), arrayCache); + if (UseIndependentSolver) solver = createIndependentSolver(std::move(solver)); if (UseConcretizingSolver) solver = createConcretizingSolver(std::move(solver), addressGenerator); + if (UseCexCache && UseConcretizingSolver) + solver = createCexCachingSolver(std::move(solver)); + + if (UseBranchCache && UseConcretizingSolver) + solver = createCachingSolver(std::move(solver)); + + if (UseIndependentSolver && UseConcretizingSolver) + solver = createIndependentSolver(std::move(solver)); + if (DebugValidateSolver) solver = createValidatingSolver(std::move(solver), rawCoreSolver, false); diff --git a/lib/Solver/CoreSolver.cpp b/lib/Solver/CoreSolver.cpp index b6de1024b8..a82dfc6a44 100644 --- a/lib/Solver/CoreSolver.cpp +++ b/lib/Solver/CoreSolver.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "BitwuzlaSolver.h" #include "MetaSMTSolver.h" #include "STPSolver.h" #include "Z3Solver.h" @@ -28,6 +29,11 @@ DISABLE_WARNING_POP namespace klee { std::unique_ptr createCoreSolver(CoreSolverType cst) { + bool isTreeSolver = (cst == Z3_TREE_SOLVER || cst == BITWUZLA_TREE_SOLVER); + if (!isTreeSolver && MaxSolversApproxTreeInc > 0) + klee_warning("--%s option is ignored because --%s is not z3-tree", + MaxSolversApproxTreeInc.ArgStr.str().c_str(), + CoreSolverToUse.ArgStr.str().c_str()); switch (cst) { case STP_SOLVER: #ifdef ENABLE_STP @@ -54,19 +60,43 @@ std::unique_ptr createCoreSolver(CoreSolverType cst) { #endif case DUMMY_SOLVER: return createDummySolver(); + case Z3_TREE_SOLVER: case Z3_SOLVER: #ifdef ENABLE_Z3 klee_message("Using Z3 solver backend"); + Z3BuilderType type; #ifdef ENABLE_FP klee_message("Using Z3 bitvector builder"); - return std::make_unique(KLEE_BITVECTOR); + type = KLEE_BITVECTOR; #else klee_message("Using Z3 core builder"); - return std::make_unique(KLEE_CORE); + type = KLEE_CORE; #endif + if (isTreeSolver) { + if (MaxSolversApproxTreeInc > 0) + return std::make_unique(type, MaxSolversApproxTreeInc); + klee_warning("--%s is 0, so falling back to non tree-incremental solver ", + MaxSolversApproxTreeInc.ArgStr.str().c_str()); + } + return std::make_unique(type); #else klee_message("Not compiled with Z3 support"); return NULL; +#endif + case BITWUZLA_TREE_SOLVER: + case BITWUZLA_SOLVER: +#ifdef ENABLE_BITWUZLA + klee_message("Using Bitwuzla solver backend"); + if (isTreeSolver) { + if (MaxSolversApproxTreeInc > 0) + return std::make_unique(MaxSolversApproxTreeInc); + klee_warning("--%s is 0, so falling back to non tree-incremental solver", + MaxSolversApproxTreeInc.ArgStr.str().c_str()); + } + return std::make_unique(); +#else + klee_message("Not compiled with Bitwuzla support"); + return NULL; #endif case NO_SOLVER: klee_message("Invalid solver"); diff --git a/lib/Solver/DummySolver.cpp b/lib/Solver/DummySolver.cpp index b039581ab1..89f4429896 100644 --- a/lib/Solver/DummySolver.cpp +++ b/lib/Solver/DummySolver.cpp @@ -30,6 +30,7 @@ class DummySolverImpl : public SolverImpl { bool computeValidityCore(const Query &query, ValidityCore &validityCore, bool &isValid); SolverRunStatus getOperationStatusCode(); + void notifyStateTermination(std::uint32_t id); }; DummySolverImpl::DummySolverImpl() {} @@ -79,6 +80,8 @@ SolverImpl::SolverRunStatus DummySolverImpl::getOperationStatusCode() { return SOLVER_RUN_STATUS_FAILURE; } +void DummySolverImpl::notifyStateTermination(std::uint32_t id) {} + std::unique_ptr createDummySolver() { return std::make_unique(std::make_unique()); } diff --git a/lib/Solver/FastCexSolver.cpp b/lib/Solver/FastCexSolver.cpp index 3ba7904ac4..f4c1b377aa 100644 --- a/lib/Solver/FastCexSolver.cpp +++ b/lib/Solver/FastCexSolver.cpp @@ -389,13 +389,9 @@ class CexRangeEvaluator : public ExprRangeEvaluator { if (array.isConstantArray() && index.isFixed()) { if (ref constantSource = dyn_cast(array.source)) { - if (index.min() < constantSource->constantValues.size()) { - return ValueRange( - constantSource->constantValues[index.min()]->getZExtValue(8)); + if (auto value = constantSource->constantValues.load(index.min())) { + return ValueRange(value->getZExtValue(8)); } - } else if (ref symbolicSizeConstantSource = - dyn_cast(array.source)) { - return ValueRange(symbolicSizeConstantSource->defaultValue); } } return ValueRange(0, 255); @@ -896,10 +892,11 @@ class CexData { if (ref constantSource = dyn_cast(array->source)) { // Verify the range. - propagateExactValues(constantSource->constantValues[index.min()], + if (!isa(array->size)) { + assert(0 && "Unimplemented"); + } + propagateExactValues(constantSource->constantValues.load(index.min()), range); - } else if (isa(array->source)) { - assert(0 && "not implemented"); } else { CexValueData cvd = cod.getExactValues(index.min()); if (range.min() > cvd.min()) { @@ -1088,7 +1085,6 @@ FastCexSolver::~FastCexSolver() {} /// \return - True if the propogation was able to prove validity or invalidity. static bool propagateValues(const Query &query, CexData &cd, bool checkExpr, bool &isValid) { - assert(!query.containsSymcretes()); for (const auto &constraint : query.constraints.cs()) { cd.propagatePossibleValue(constraint, 1); cd.propagateExactValue(constraint, 1); @@ -1196,7 +1192,6 @@ bool FastCexSolver::computeInitialValues( dyn_cast(cd.evaluatePossible(array->size)); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); - data.resize(arrayConstantSize->getZExtValue()); for (unsigned i = 0; i < arrayConstantSize->getZExtValue(); i++) { ref read = ReadExpr::create( diff --git a/lib/Solver/IncompleteSolver.cpp b/lib/Solver/IncompleteSolver.cpp index 5fd7c74b3b..85ad5a8d6d 100644 --- a/lib/Solver/IncompleteSolver.cpp +++ b/lib/Solver/IncompleteSolver.cpp @@ -119,13 +119,8 @@ bool StagedSolverImpl::computeInitialValues( } bool StagedSolverImpl::check(const Query &query, ref &result) { - ExprHashSet expressions; - expressions.insert(query.constraints.cs().begin(), - query.constraints.cs().end()); - expressions.insert(query.expr); - std::vector objects; - findSymbolicObjects(expressions.begin(), expressions.end(), objects); + findSymbolicObjects(query, objects); std::vector> values; bool hasSolution; @@ -157,3 +152,7 @@ char *StagedSolverImpl::getConstraintLog(const Query &query) { void StagedSolverImpl::setCoreSolverTimeout(time::Span timeout) { secondary->impl->setCoreSolverTimeout(timeout); } + +void StagedSolverImpl::notifyStateTermination(std::uint32_t id) { + secondary->impl->notifyStateTermination(id); +} diff --git a/lib/Solver/IndependentSolver.cpp b/lib/Solver/IndependentSolver.cpp index 9e0139200a..56cf4d043c 100644 --- a/lib/Solver/IndependentSolver.cpp +++ b/lib/Solver/IndependentSolver.cpp @@ -60,36 +60,28 @@ class IndependentSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; bool IndependentSolver::computeValidity(const Query &query, PartialValidity &result) { - constraints_ty required; - IndependentElementSet eltsClosure = - getIndependentConstraints(query, required); - ConstraintSet tmp( - required, eltsClosure.symcretes, - query.constraints.concretization().part(eltsClosure.symcretes)); + std::vector> factors; + query.getAllDependentConstraintsSets(factors); + ConstraintSet tmp(factors); return solver->impl->computeValidity(query.withConstraints(tmp), result); } bool IndependentSolver::computeTruth(const Query &query, bool &isValid) { - constraints_ty required; - IndependentElementSet eltsClosure = - getIndependentConstraints(query, required); - ConstraintSet tmp( - required, eltsClosure.symcretes, - query.constraints.concretization().part(eltsClosure.symcretes)); + std::vector> factors; + query.getAllDependentConstraintsSets(factors); + ConstraintSet tmp(factors); return solver->impl->computeTruth(query.withConstraints(tmp), isValid); } bool IndependentSolver::computeValue(const Query &query, ref &result) { - constraints_ty required; - IndependentElementSet eltsClosure = - getIndependentConstraints(query, required); - ConstraintSet tmp( - required, eltsClosure.symcretes, - query.constraints.concretization().part(eltsClosure.symcretes)); + std::vector> factors; + query.getAllDependentConstraintsSets(factors); + ConstraintSet tmp(factors); return solver->impl->computeValue(query.withConstraints(tmp), result); } @@ -99,22 +91,26 @@ bool IndependentSolver::computeValue(const Query &query, ref &result) { bool assertCreatedPointEvaluatesToTrue( const Query &query, const std::vector &objects, std::vector> &values, - std::map> &retMap) { + Assignment::bindings_ty &retMap) { // _allowFreeValues is set to true so that if there are missing bytes in the // assignment we will end up with a non ConstantExpr after evaluating the // assignment and fail - Assignment assign = Assignment(objects, values, /*_allowFreeValues=*/true); + Assignment assign = Assignment(objects, values); // Add any additional bindings. // The semantics of std::map should be to not insert a (key, value) // pair if it already exists so we should continue to use the assignment // from ``objects`` and ``values``. - if (retMap.size() > 0) - assign.bindings.insert(retMap.begin(), retMap.end()); - + if (retMap.size() > 0) { + for (auto it : retMap) { + assign.bindings.insert(it); + } + } for (auto const &constraint : query.constraints.cs()) { ref ret = assign.evaluate(constraint); - + if (!isa(ret)) { + ret = ret->rebuild(); + } assert(isa(ret) && "assignment evaluation did not result in constant"); ref evaluatedConstraint = dyn_cast(ret); @@ -124,15 +120,17 @@ bool assertCreatedPointEvaluatesToTrue( } ref neg = Expr::createIsZero(query.expr); ref q = assign.evaluate(neg); + if (!isa(q)) { + q = q->rebuild(); + } assert(isa(q) && "assignment evaluation did not result in constant"); return cast(q)->isTrue(); } -bool assertCreatedPointEvaluatesToTrue( - const Query &query, - std::map> &bindings, - std::map> &retMap) { +bool assertCreatedPointEvaluatesToTrue(const Query &query, + Assignment::bindings_ty &bindings, + Assignment::bindings_ty &retMap) { std::vector objects; std::vector> values; objects.reserve(bindings.size()); @@ -151,82 +149,93 @@ bool IndependentSolver::computeInitialValues( // This is important in case we don't have any constraints but // we need initial values for requested array objects. hasSolution = true; - // FIXME: When we switch to C++11 this should be a std::unique_ptr so we don't - // need to remember to manually call delete - std::list *factors = - getAllIndependentConstraintsSets(query); + Assignment retMap; + std::vector> dependentFactors; + query.getAllDependentConstraintsSets(dependentFactors); + std::vector> independentFactors; + query.getAllIndependentConstraintsSets(independentFactors); + + if (independentFactors.size() == 0 && dependentFactors.size() == 1) { + return solver->impl->computeInitialValues(query, objects, values, + hasSolution); + } + + ConstraintSet dependentConstriants(dependentFactors); + + std::vector dependentFactorsObjects; + calculateArraysInFactors(dependentFactors, query.expr, + dependentFactorsObjects); + + if (dependentFactorsObjects.size() != 0) { + std::vector> dependentFactorsValues; + + if (!solver->impl->computeInitialValues( + query.withConstraints(dependentConstriants), + dependentFactorsObjects, dependentFactorsValues, hasSolution)) { + values.clear(); + return false; + } else if (!hasSolution) { + values.clear(); + return true; + } else { + retMap = Assignment(dependentFactorsObjects, dependentFactorsValues); + } + } // Used to rearrange all of the answers into the correct order - std::map> retMap; - for (std::list::iterator it = factors->begin(); - it != factors->end(); ++it) { + for (ref it : independentFactors) { std::vector arraysInFactor; - calculateArrayReferences(*it, arraysInFactor); + it->calculateArrayReferences(arraysInFactor); // Going to use this as the "fresh" expression for the Query() invocation // below assert(it->exprs.size() >= 1 && "No null/empty factors"); if (arraysInFactor.size() == 0) { continue; } - ConstraintSet tmp(it->exprs, it->symcretes, - query.constraints.concretization().part(it->symcretes)); + ConstraintSet tmp(it); std::vector> tempValues; if (!solver->impl->computeInitialValues( - Query(tmp, ConstantExpr::alloc(0, Expr::Bool)), arraysInFactor, + Query(tmp, Expr::createFalse(), query.id), arraysInFactor, tempValues, hasSolution)) { values.clear(); - delete factors; + return false; } else if (!hasSolution) { values.clear(); - delete factors; + return true; } else { assert(tempValues.size() == arraysInFactor.size() && "Should be equal number arrays and answers"); - for (unsigned i = 0; i < tempValues.size(); i++) { - if (retMap.count(arraysInFactor[i])) { - // We already have an array with some partially correct answers, - // so we need to place the answers to the new query into the right - // spot while avoiding the undetermined values also in the array - SparseStorage *tempPtr = &retMap[arraysInFactor[i]]; - assert(tempPtr->size() == tempValues[i].size() && - "we're talking about the same array here"); - klee::DenseSet *ds = &(it->elements[arraysInFactor[i]]); - for (std::set::iterator it2 = ds->begin(); it2 != ds->end(); - it2++) { - unsigned index = *it2; - tempPtr->store(index, tempValues[i].load(index)); - } - } else { - // Dump all the new values into the array - retMap[arraysInFactor[i]] = tempValues[i]; - } - } + // We already have an array with some partially correct answers, + // so we need to place the answers to the new query into the right + // spot while avoiding the undetermined values also in the array + it->addValuesToAssignment(arraysInFactor, tempValues, retMap); } } - Assignment solutionAssignment(retMap, true); for (std::vector::const_iterator it = objects.begin(); it != objects.end(); it++) { const Array *arr = *it; - if (!retMap.count(arr)) { + if (!retMap.bindings.count(arr)) { // this means we have an array that is somehow related to the // constraint, but whose values aren't actually required to // satisfy the query. ref arrayConstantSize = - dyn_cast(solutionAssignment.evaluate(arr->size)); + dyn_cast(retMap.evaluate(arr->size)); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); - SparseStorage ret(arrayConstantSize->getZExtValue()); + SparseStorage ret(0); values.push_back(ret); } else { - values.push_back(retMap[arr]); + values.push_back(retMap.bindings.at(arr)); } } - assert(assertCreatedPointEvaluatesToTrue(query, objects, values, retMap) && + + assert(assertCreatedPointEvaluatesToTrue(query, objects, values, + retMap.bindings) && "should satisfy the equation"); - delete factors; + return true; } @@ -234,47 +243,58 @@ bool IndependentSolver::check(const Query &query, ref &result) { // We assume the query has a solution except proven differently // This is important in case we don't have any constraints but // we need initial values for requested array objects. + // result = new ValidResponse(ValidityCore()); + Assignment retMap; + std::vector> dependentFactors; + query.getAllDependentConstraintsSets(dependentFactors); + std::vector> independentFactors; + query.getAllIndependentConstraintsSets(independentFactors); + + if (independentFactors.size() == 0 && dependentFactors.size() == 1) { + return solver->impl->check(query, result); + } - // FIXME: When we switch to C++11 this should be a std::unique_ptr so we don't - // need to remember to manually call delete - std::list *factors = - getAllIndependentConstraintsSets(query); + ConstraintSet dependentConstriants(dependentFactors); + + std::vector dependentFactorsObjects; + std::vector> dependentFactorsValues; + ref dependentFactorsResult; + + calculateArraysInFactors(dependentFactors, query.expr, + dependentFactorsObjects); + + if (dependentFactorsObjects.size() != 0) { + if (!solver->impl->check(query.withConstraints(dependentConstriants), + dependentFactorsResult)) { + return false; + } else if (isa(dependentFactorsResult)) { + result = dependentFactorsResult; + return true; + } else { + bool success = dependentFactorsResult->tryGetInitialValuesFor( + dependentFactorsObjects, dependentFactorsValues); + assert(success && "Can not get initial values (Independent solver)!"); + retMap = Assignment(dependentFactorsObjects, dependentFactorsValues); + } + } // Used to rearrange all of the answers into the correct order - std::map> retMap; - for (std::list::iterator it = factors->begin(); - it != factors->end(); ++it) { + for (ref it : independentFactors) { std::vector arraysInFactor; - calculateArrayReferences(*it, arraysInFactor); + it->calculateArrayReferences(arraysInFactor); // Going to use this as the "fresh" expression for the Query() invocation // below assert(it->exprs.size() >= 1 && "No null/empty factors"); if (arraysInFactor.size() == 0) { continue; } - - constraints_ty factorConstraints = it->exprs; - ref factorExpr = ConstantExpr::alloc(0, Expr::Bool); - auto factorConstraintsExprIterator = - std::find(factorConstraints.begin(), factorConstraints.end(), - query.negateExpr().expr); - if (factorConstraintsExprIterator != factorConstraints.end()) { - factorConstraints.erase(factorConstraintsExprIterator); - factorExpr = query.expr; - } - ref tempResult; std::vector> tempValues; if (!solver->impl->check( - Query(ConstraintSet( - factorConstraints, it->symcretes, - query.constraints.concretization().part(it->symcretes)), - factorExpr), + Query(ConstraintSet(it), Expr::createFalse(), query.id), tempResult)) { - delete factors; return false; } else if (isa(tempResult)) { - delete factors; result = tempResult; return true; } else { @@ -283,46 +303,28 @@ bool IndependentSolver::check(const Query &query, ref &result) { assert(success && "Can not get initial values (Independent solver)!"); assert(tempValues.size() == arraysInFactor.size() && "Should be equal number arrays and answers"); - for (unsigned i = 0; i < tempValues.size(); i++) { - if (retMap.count(arraysInFactor[i])) { - // We already have an array with some partially correct answers, - // so we need to place the answers to the new query into the right - // spot while avoiding the undetermined values also in the array - SparseStorage *tempPtr = &retMap[arraysInFactor[i]]; - assert(tempPtr->size() == tempValues[i].size() && - "we're talking about the same array here"); - klee::DenseSet *ds = &(it->elements[arraysInFactor[i]]); - for (std::set::iterator it2 = ds->begin(); it2 != ds->end(); - it2++) { - unsigned index = *it2; - tempPtr->store(index, tempValues[i].load(index)); - } - } else { - // Dump all the new values into the array - retMap[arraysInFactor[i]] = tempValues[i]; - } - } + // We already have an array with some partially correct answers, + // so we need to place the answers to the new query into the right + // spot while avoiding the undetermined values also in the array + it->addValuesToAssignment(arraysInFactor, tempValues, retMap); } } - result = new InvalidResponse(retMap); - std::map> bindings; + result = new InvalidResponse(retMap.bindings); + Assignment::bindings_ty bindings; bool success = result->tryGetInitialValues(bindings); assert(success); - assert(assertCreatedPointEvaluatesToTrue(query, bindings, retMap) && + assert(assertCreatedPointEvaluatesToTrue(query, bindings, retMap.bindings) && "should satisfy the equation"); - delete factors; + return true; } bool IndependentSolver::computeValidityCore(const Query &query, ValidityCore &validityCore, bool &isValid) { - constraints_ty required; - IndependentElementSet eltsClosure = - getIndependentConstraints(query, required); - ConstraintSet tmp( - required, eltsClosure.symcretes, - query.constraints.concretization().part(eltsClosure.symcretes)); + std::vector> factors; + query.getAllDependentConstraintsSets(factors); + ConstraintSet tmp(factors); return solver->impl->computeValidityCore(query.withConstraints(tmp), validityCore, isValid); } @@ -339,6 +341,10 @@ void IndependentSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } +void IndependentSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + std::unique_ptr klee::createIndependentSolver(std::unique_ptr s) { return std::make_unique( diff --git a/lib/Solver/MetaSMTBuilder.h b/lib/Solver/MetaSMTBuilder.h index b2418b8f91..6944402788 100644 --- a/lib/Solver/MetaSMTBuilder.h +++ b/lib/Solver/MetaSMTBuilder.h @@ -216,10 +216,11 @@ MetaSMTBuilder::getInitialArray(const Array *root) { bool hashed = _arr_hash.lookupArrayExpr(root, array_expr); if (!hashed) { - if (isa(root->source)) { - llvm::report_fatal_error("MetaSMT does not support constant arrays or " - "quantifiers to instantiate " - "constant array of symbolic size!"); + if (ref constantSource = + dyn_cast(root->source)) { + if (!isa(root->size)) { + assert(0 && "MetaSMT does not support symsize constant arrays"); + } } array_expr = @@ -227,14 +228,14 @@ MetaSMTBuilder::getInitialArray(const Array *root) { if (ref constantSource = dyn_cast(root->source)) { - uint64_t constantSize = cast(root->size)->getZExtValue(); - for (unsigned i = 0, e = constantSize; i != e; ++i) { + auto constantSize = cast(root->size)->getZExtValue(); + for (unsigned i = 0; i < constantSize; ++i) { typename SolverContext::result_type tmp = evaluate( _solver, metaSMT::logic::Array::store( array_expr, construct(ConstantExpr::alloc(i, root->getDomain()), 0), - construct(constantSource->constantValues[i], 0))); + construct(constantSource->constantValues.load(i), 0))); array_expr = tmp; } } @@ -705,6 +706,33 @@ MetaSMTBuilder::constructActual(ref e, int *width_out) { ReadExpr *re = cast(e); assert(re && re->updates.root); *width_out = re->updates.root->getRange(); + + if (auto constantSource = + dyn_cast(re->updates.root->source)) { + if (!isa(re->updates.root->size)) { + ref selectExpr = constantSource->constantValues.defaultV(); + for (const auto &[index, value] : + constantSource->constantValues.storage()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } + std::vector update_nodes; + auto un = re->updates.head.get(); + for (; un; un = un->next.get()) { + update_nodes.push_back(un); + } + + for (auto it = update_nodes.rbegin(); it != update_nodes.rend(); ++it) { + selectExpr = + SelectExpr::create(EqExpr::create(re->index, (*it)->index), + (*it)->value, selectExpr); + } + return construct(selectExpr, width_out); + } + } + // FixMe call method of Array res = evaluate(_solver, metaSMT::logic::Array::select( getArrayForUpdate(re->updates.root, diff --git a/lib/Solver/MetaSMTSolver.cpp b/lib/Solver/MetaSMTSolver.cpp index 17e0972904..55ba6a4b4a 100644 --- a/lib/Solver/MetaSMTSolver.cpp +++ b/lib/Solver/MetaSMTSolver.cpp @@ -95,6 +95,7 @@ template class MetaSMTSolverImpl : public SolverImpl { char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout) { _timeout = timeout; } + void notifyStateTermination(std::uint32_t id) {} bool computeTruth(const Query &, bool &isValid); bool computeValue(const Query &, ref &result); @@ -260,14 +261,7 @@ SolverImpl::SolverRunStatus MetaSMTSolverImpl::runAndGetCex( typename SolverContext::result_type array_exp = _builder->getInitialArray(array); - size_t constantSize = 0; - if (ref sizeExpr = dyn_cast(array->size)) { - constantSize = sizeExpr->getZExtValue(); - } else { - constantSize = - read_value(_meta_solver, _builder->construct(array->size)); - } - SparseStorage data(constantSize, 0); + SparseStorage data(0); for (unsigned offset : readOffsets.at(array)) { typename SolverContext::result_type elem_exp = evaluate( @@ -414,7 +408,6 @@ MetaSMTSolverImpl::runAndGetCexForked( values = std::vector>(objects.size()); for (unsigned i = 0; i < objects.size(); ++i) { SparseStorage &data = values[i]; - data.resize(shared_memory_sizes_ptr[i]); data.store(0, pos, pos + shared_memory_sizes_ptr[i]); pos += shared_memory_sizes_ptr[i]; } diff --git a/lib/Solver/QueryLoggingSolver.cpp b/lib/Solver/QueryLoggingSolver.cpp index e35ca0daaa..45b6af359d 100644 --- a/lib/Solver/QueryLoggingSolver.cpp +++ b/lib/Solver/QueryLoggingSolver.cpp @@ -193,11 +193,11 @@ bool QueryLoggingSolver::computeInitialValues( new InvalidResponse(allObjects, allValues); success = invalidResponse->tryGetInitialValuesFor(objects, values); assert(success); - Assignment allSolutionAssignment(allObjects, allValues, true); + Assignment allSolutionAssignment(allObjects, allValues); std::vector>::iterator values_it = values.begin(); - Assignment solutionAssignment(objects, values, true); + Assignment solutionAssignment(objects, values); for (std::vector::const_iterator i = objects.begin(), e = objects.end(); i != e; ++i, ++values_it) { @@ -241,13 +241,12 @@ bool QueryLoggingSolver::check(const Query &query, logBuffer << queryCommentSign << " Solvable: " << (hasSolution ? "true" : "false") << "\n"; if (hasSolution) { - std::map> initialValues; + Assignment::bindings_ty initialValues; result->tryGetInitialValues(initialValues); - Assignment solutionAssignment(initialValues, true); + Assignment solutionAssignment(initialValues); - for (std::map>::const_iterator - i = initialValues.begin(), - e = initialValues.end(); + for (Assignment::bindings_ty::iterator i = initialValues.begin(), + e = initialValues.end(); i != e; ++i) { const Array *array = i->first; const SparseStorage &data = i->second; @@ -271,8 +270,7 @@ bool QueryLoggingSolver::check(const Query &query, result->tryGetValidityCore(validityCore); logBuffer << queryCommentSign << " ValidityCore:\n"; - printQuery(Query(ConstraintSet(validityCore.constraints, {}, {true}), - validityCore.expr)); + printQuery(validityCore.toQuery()); } } logBuffer << "\n"; @@ -300,8 +298,7 @@ bool QueryLoggingSolver::computeValidityCore(const Query &query, if (isValid) { logBuffer << queryCommentSign << " ValidityCore:\n"; - printQuery(Query(ConstraintSet(validityCore.constraints, {}, {true}), - validityCore.expr)); + printQuery(validityCore.toQuery()); } logBuffer << "\n"; @@ -322,3 +319,7 @@ char *QueryLoggingSolver::getConstraintLog(const Query &query) { void QueryLoggingSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } + +void QueryLoggingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} diff --git a/lib/Solver/QueryLoggingSolver.h b/lib/Solver/QueryLoggingSolver.h index 16e50f5546..3dd2f1a357 100644 --- a/lib/Solver/QueryLoggingSolver.h +++ b/lib/Solver/QueryLoggingSolver.h @@ -81,6 +81,7 @@ class QueryLoggingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; #endif /* KLEE_QUERYLOGGINGSOLVER_H */ diff --git a/lib/Solver/STPBuilder.cpp b/lib/Solver/STPBuilder.cpp index 3ee8fbe2b7..b766111ed7 100644 --- a/lib/Solver/STPBuilder.cpp +++ b/lib/Solver/STPBuilder.cpp @@ -426,6 +426,14 @@ ExprHandle STPBuilder::constructSDivByConstant(ExprHandle expr_n, ::VCExpr STPBuilder::getInitialArray(const Array *root) { assert(root); + + if (ref constantSource = + dyn_cast(root->source)) { + if (!isa(root->size)) { + assert(0 && "STP does not support symsize constant arrays"); + } + } + ::VCExpr array_expr; bool hashed = _arr_hash.lookupArrayExpr(root, array_expr); @@ -433,13 +441,7 @@ ::VCExpr STPBuilder::getInitialArray(const Array *root) { // STP uniques arrays by name, so we make sure the name is unique by // using the size of the array hash as a counter. std::string unique_id = llvm::utostr(_arr_hash._array_hash.size()); - std::string unique_name = root->getName() + unique_id; - - if (isa(root->source)) { - llvm::report_fatal_error( - "STP does not support constant arrays or quantifiers to instantiate " - "constant array of symbolic size!"); - } + std::string unique_name = root->getIdentifier() + unique_id; array_expr = buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); @@ -450,13 +452,13 @@ ::VCExpr STPBuilder::getInitialArray(const Array *root) { // using assertions, which is much faster, but we need to fix the caching // to work correctly in that case. + auto constSize = cast(root->size)->getZExtValue(); // TODO: usage of `constantValues.size()` seems unconvinient. - for (unsigned i = 0, e = constantSource->constantValues.size(); i != e; - ++i) { + for (unsigned i = 0; i < constSize; i++) { ::VCExpr prev = array_expr; array_expr = vc_writeExpr( vc, prev, construct(ConstantExpr::alloc(i, root->getDomain()), 0), - construct(constantSource->constantValues[i], 0)); + construct(constantSource->constantValues.load(i), 0)); vc_DeleteExpr(prev); } } @@ -568,6 +570,33 @@ ExprHandle STPBuilder::constructActual(ref e, int *width_out) { ReadExpr *re = cast(e); assert(re && re->updates.root); *width_out = re->updates.root->getRange(); + + if (auto constantSource = + dyn_cast(re->updates.root->source)) { + if (!isa(re->updates.root->size)) { + ref selectExpr = constantSource->constantValues.defaultV(); + for (const auto &[index, value] : + constantSource->constantValues.storage()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } + std::vector update_nodes; + auto un = re->updates.head.get(); + for (; un; un = un->next.get()) { + update_nodes.push_back(un); + } + + for (auto it = update_nodes.rbegin(); it != update_nodes.rend(); ++it) { + selectExpr = + SelectExpr::create(EqExpr::create(re->index, (*it)->index), + (*it)->value, selectExpr); + } + return construct(selectExpr, width_out); + } + } + return vc_readExpr( vc, getArrayForUpdate(re->updates.root, re->updates.head.get()), construct(re->index, 0)); diff --git a/lib/Solver/STPSolver.cpp b/lib/Solver/STPSolver.cpp index 4893115926..86679cc898 100644 --- a/lib/Solver/STPSolver.cpp +++ b/lib/Solver/STPSolver.cpp @@ -104,6 +104,7 @@ class STPSolverImpl : public SolverImpl { void setCoreSolverTimeout(time::Span timeout) override { this->timeout = timeout; } + void notifyStateTermination(std::uint32_t id) override {} bool computeTruth(const Query &, bool &isValid) override; bool computeValue(const Query &, ref &result) override; @@ -391,7 +392,7 @@ runAndGetCexForked(::VC vc, STPBuilder *builder, ::VCExpr q, values.reserve(objects.size()); for (unsigned idx = 0; idx < objects.size(); ++idx) { uint64_t objectSize = shared_memory_object_sizes[idx]; - values.emplace_back(objectSize, 0); + values.emplace_back(0); values.back().store(0, pos, pos + objectSize); pos += objectSize; } diff --git a/lib/Solver/Solver.cpp b/lib/Solver/Solver.cpp index ec30aa9b19..f6b0652235 100644 --- a/lib/Solver/Solver.cpp +++ b/lib/Solver/Solver.cpp @@ -162,6 +162,10 @@ bool Solver::check(const Query &query, ref &queryResult) { return impl->check(query, queryResult); } +void Solver::notifyStateTermination(std::uint32_t id) { + impl->notifyStateTermination(id); +} + static std::pair, ref> getDefaultRange() { return std::make_pair(ConstantExpr::create(0, 64), ConstantExpr::create(0, 64)); @@ -327,6 +331,15 @@ bool Query::containsSizeSymcretes() const { return false; } +void klee::findSymbolicObjects(const Query &query, + std::vector &results) { + ExprHashSet expressions; + expressions.insert(query.constraints.cs().begin(), + query.constraints.cs().end()); + expressions.insert(query.expr); + findSymbolicObjects(expressions.begin(), expressions.end(), results); +} + void Query::dump() const { constraints.dump(); llvm::errs() << "Query [\n"; @@ -334,6 +347,6 @@ void Query::dump() const { llvm::errs() << "]\n"; } -void ValidityCore::dump() const { - Query(ConstraintSet(constraints, {}, {true}), expr).dump(); -} +Query ValidityCore::toQuery() const { return Query(constraints, expr); } + +void ValidityCore::dump() const { toQuery().dump(); } diff --git a/lib/Solver/SolverCmdLine.cpp b/lib/Solver/SolverCmdLine.cpp index 0c96fb1263..41f8324e7c 100644 --- a/lib/Solver/SolverCmdLine.cpp +++ b/lib/Solver/SolverCmdLine.cpp @@ -56,6 +56,11 @@ cl::opt UseBranchCache("use-branch-cache", cl::init(true), cl::desc("Use the branch cache (default=true)"), cl::cat(SolvingCat)); +cl::opt + UseAlphaEquivalence("use-alpha-equivalence", cl::init(true), + cl::desc("Use the alpha version builder(default=true)"), + cl::cat(SolvingCat)); + cl::opt UseConcretizingSolver("use-concretizing-solver", cl::init(true), cl::desc("Use concretization manager(default=true)"), @@ -123,6 +128,13 @@ cl::opt UseAssignmentValidatingSolver( cl::desc("Debug the correctness of generated assignments (default=false)"), cl::cat(SolvingCat)); +cl::opt + MaxSolversApproxTreeInc("max-solvers-approx-tree-inc", + cl::desc("Maximum size of the Z3 solver pool for " + "approximating tree incrementality." + " Set to 0 to disable (default=0)"), + cl::init(0), cl::cat(SolvingCat)); + void KCommandLine::HideOptions(llvm::cl::OptionCategory &Category) { StringMap &map = cl::getRegisteredOptions(); @@ -174,15 +186,23 @@ cl::opt MetaSMTBackend( #endif /* ENABLE_METASMT */ // Pick the default core solver based on configuration -#ifdef ENABLE_Z3 +#ifdef ENABLE_BITWUZLA +#define STP_IS_DEFAULT_STR "" +#define METASMT_IS_DEFAULT_STR "" +#define Z3_IS_DEFAULT_STR "" +#define BITWUZLA_IS_DEFAULT_STR " (default)" +#define DEFAULT_CORE_SOLVER BITWUZLA_SOLVER +#elif ENABLE_Z3 #define STP_IS_DEFAULT_STR "" #define METASMT_IS_DEFAULT_STR "" #define Z3_IS_DEFAULT_STR " (default)" +#define BITWUZLA_IS_DEFAULT_STR "" #define DEFAULT_CORE_SOLVER Z3_SOLVER #elif ENABLE_STP #define STP_IS_DEFAULT_STR " (default)" #define METASMT_IS_DEFAULT_STR "" #define Z3_IS_DEFAULT_STR "" +#define BITWUZLA_IS_DEFAULT_STR "" #define DEFAULT_CORE_SOLVER STP_SOLVER #elif ENABLE_METASMT #define STP_IS_DEFAULT_STR "" @@ -190,17 +210,23 @@ cl::opt MetaSMTBackend( #define Z3_IS_DEFAULT_STR "" #define DEFAULT_CORE_SOLVER METASMT_SOLVER #define Z3_IS_DEFAULT_STR "" +#define BITWUZLA_IS_DEFAULT_STR "" #else #error "Unsupported solver configuration" #endif cl::opt CoreSolverToUse( "solver-backend", cl::desc("Specifiy the core solver backend to use"), - cl::values(clEnumValN(STP_SOLVER, "stp", "STP" STP_IS_DEFAULT_STR), - clEnumValN(METASMT_SOLVER, "metasmt", - "metaSMT" METASMT_IS_DEFAULT_STR), - clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), - clEnumValN(Z3_SOLVER, "z3", "Z3" Z3_IS_DEFAULT_STR)), + cl::values( + clEnumValN(BITWUZLA_SOLVER, "bitwuzla", + "Bitwuzla" BITWUZLA_IS_DEFAULT_STR), + clEnumValN(BITWUZLA_TREE_SOLVER, "bitwuzla-tree", + "Bitwuzla tree-incremental solver"), + clEnumValN(STP_SOLVER, "stp", "STP" STP_IS_DEFAULT_STR), + clEnumValN(METASMT_SOLVER, "metasmt", "metaSMT" METASMT_IS_DEFAULT_STR), + clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), + clEnumValN(Z3_SOLVER, "z3", "Z3" Z3_IS_DEFAULT_STR), + clEnumValN(Z3_TREE_SOLVER, "z3-tree", "Z3 tree-incremental solver")), cl::init(DEFAULT_CORE_SOLVER), cl::cat(SolvingCat)); cl::opt DebugCrossCheckCoreSolverWith( @@ -211,6 +237,7 @@ cl::opt DebugCrossCheckCoreSolverWith( clEnumValN(METASMT_SOLVER, "metasmt", "metaSMT"), clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), clEnumValN(Z3_SOLVER, "z3", "Z3"), + clEnumValN(BITWUZLA_SOLVER, "bitwuzla", "Bitwuzla"), clEnumValN(NO_SOLVER, "none", "Do not crosscheck (default)")), cl::init(NO_SOLVER), cl::cat(SolvingCat)); @@ -222,11 +249,12 @@ llvm::cl::opt llvm::cl::opt SymbolicAllocationThreshold( "symbolic-allocation-threshold", llvm::cl::desc("Maximum possible sum of sizes for all symbolic allocation " - "before minimazation (default 1Kb)"), + "before minimization (default 1Kb)"), llvm::cl::init(1024), llvm::cl::cat(klee::SolvingCat)); } // namespace klee #undef STP_IS_DEFAULT_STR #undef METASMT_IS_DEFAULT_STR #undef Z3_IS_DEFAULT_STR +#undef BITWUZLA_IS_DEFAULT_STR #undef DEFAULT_CORE_SOLVER diff --git a/lib/Solver/SolverImpl.cpp b/lib/Solver/SolverImpl.cpp index 033f1d6d19..e1d3ab3513 100644 --- a/lib/Solver/SolverImpl.cpp +++ b/lib/Solver/SolverImpl.cpp @@ -18,37 +18,46 @@ using namespace klee; SolverImpl::~SolverImpl() {} bool SolverImpl::computeValidity(const Query &query, PartialValidity &result) { + bool trueSuccess, falseSuccess; bool isTrue, isFalse; - if (!computeTruth(query, isTrue)) - return false; - if (isTrue) { + trueSuccess = computeTruth(query, isTrue); + if (trueSuccess && isTrue) { result = PValidity::MustBeTrue; } else { - if (!computeTruth(query.negateExpr(), isFalse)) - return false; - result = isFalse ? PValidity::MustBeFalse : PValidity::TrueOrFalse; + falseSuccess = computeTruth(query.negateExpr(), isFalse); + if (falseSuccess && isFalse) { + result = PValidity::MustBeFalse; + } else { + if (trueSuccess && falseSuccess) { + result = PValidity::TrueOrFalse; + } else if (!trueSuccess) { + result = PValidity::MayBeTrue; + } else if (!falseSuccess) { + result = PValidity::MayBeFalse; + } else { + result = PValidity::None; + } + } } - return true; + return result != PValidity::None; } bool SolverImpl::computeValidity(const Query &query, ref &queryResult, ref &negatedQueryResult) { - if (!check(query, queryResult)) - return false; - if (!check(query.negateExpr(), negatedQueryResult)) - return false; - return true; + if (!check(query, queryResult)) { + queryResult = new UnknownResponse(); + } + if (!check(query.negateExpr(), negatedQueryResult)) { + negatedQueryResult = new UnknownResponse(); + } + return !isa(queryResult) || + !isa(negatedQueryResult); } bool SolverImpl::check(const Query &query, ref &result) { - ExprHashSet expressions; - expressions.insert(query.constraints.cs().begin(), - query.constraints.cs().end()); - expressions.insert(query.expr); - std::vector objects; - findSymbolicObjects(expressions.begin(), expressions.end(), objects); + findSymbolicObjects(query, objects); std::vector> values; bool hasSolution; diff --git a/lib/Solver/ValidatingSolver.cpp b/lib/Solver/ValidatingSolver.cpp index ddae26f2e3..7e065f77bb 100644 --- a/lib/Solver/ValidatingSolver.cpp +++ b/lib/Solver/ValidatingSolver.cpp @@ -43,6 +43,7 @@ class ValidatingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; bool ValidatingSolver::computeTruth(const Query &query, bool &isValid) { @@ -95,7 +96,6 @@ bool ValidatingSolver::computeInitialValues( const Query &query, const std::vector &objects, std::vector> &values, bool &hasSolution) { bool answer; - assert(!query.containsSymcretes()); if (!solver->impl->computeInitialValues(query, objects, values, hasSolution)) return false; @@ -104,7 +104,7 @@ bool ValidatingSolver::computeInitialValues( // Assert the bindings as constraints, and verify that the // conjunction of the actual constraints is satisfiable. ConstraintSet bindings; - Assignment solutionAssignment(objects, values, true); + Assignment solutionAssignment(objects, values); for (unsigned i = 0; i != values.size(); ++i) { const Array *array = objects[i]; @@ -128,7 +128,8 @@ bool ValidatingSolver::computeInitialValues( for (auto const &constraint : query.constraints.cs()) constraints = AndExpr::create(constraints, constraint); - if (!oracle->impl->computeTruth(Query(bindings, constraints), answer)) + if (!oracle->impl->computeTruth(Query(bindings, constraints, query.id), + answer)) return false; if (!answer) assert(0 && "invalid solver result (computeInitialValues)"); @@ -159,7 +160,7 @@ bool ValidatingSolver::check(const Query &query, ref &result) { // conjunction of the actual constraints is satisfiable. ConstraintSet bindings; - std::map> initialValues; + Assignment::bindings_ty initialValues; cast(result)->tryGetInitialValues(initialValues); Assignment solutionAssignment(initialValues); for (auto &arrayValues : initialValues) { @@ -184,7 +185,8 @@ bool ValidatingSolver::check(const Query &query, ref &result) { for (auto const &constraint : query.constraints.cs()) constraints = AndExpr::create(constraints, constraint); - if (!oracle->impl->computeTruth(Query(bindings, constraints), banswer)) + if (!oracle->impl->computeTruth(Query(bindings, constraints, query.id), + banswer)) return false; if (!banswer) assert(0 && "invalid solver result (computeInitialValues)"); @@ -229,6 +231,11 @@ void ValidatingSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } +void ValidatingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); + oracle->impl->notifyStateTermination(id); +} + std::unique_ptr createValidatingSolver(std::unique_ptr s, Solver *oracle, bool ownsOracle) { diff --git a/lib/Solver/Z3Builder.cpp b/lib/Solver/Z3Builder.cpp index f74bf27a54..b26ec1e75c 100644 --- a/lib/Solver/Z3Builder.cpp +++ b/lib/Solver/Z3Builder.cpp @@ -30,14 +30,14 @@ using namespace klee; namespace klee { // Declared here rather than `Z3Builder.h` so they can be called in gdb. -template <> void Z3NodeHandle::dump() { +template <> void Z3NodeHandle::dump() const { llvm::errs() << "Z3SortHandle:\n" << ::Z3_sort_to_string(context, node) << "\n"; } template <> unsigned Z3NodeHandle::hash() { return Z3_get_ast_hash(context, as_ast()); } -template <> void Z3NodeHandle::dump() { +template <> void Z3NodeHandle::dump() const { llvm::errs() << "Z3ASTHandle:\n" << ::Z3_ast_to_string(context, as_ast()) << "\n"; } @@ -252,35 +252,47 @@ Z3ASTHandle Z3Builder::getInitialArray(const Array *root) { // using the size of the array hash as a counter. std::string unique_id = llvm::utostr(_arr_hash._array_hash.size()); std::string unique_name = root->getIdentifier() + unique_id; - if (ref symbolicSizeConstantSource = - dyn_cast(root->source)) { + + auto source = dyn_cast(root->source); + auto value = (source ? source->constantValues.defaultV() : nullptr); + if (source) { + assert(value); + } + + if (source && !isa(root->size)) { array_expr = buildConstantArray(unique_name.c_str(), root->getDomain(), - root->getRange(), - symbolicSizeConstantSource->defaultValue); + root->getRange(), value->getZExtValue(8)); } else { array_expr = buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); } - if (root->isConstantArray() && constant_array_assertions.count(root) == 0) { - std::vector array_assertions; - if (ref constantSource = - dyn_cast(root->source)) { - for (unsigned i = 0, e = constantSource->constantValues.size(); i != e; - ++i) { + if (source) { + if (auto constSize = dyn_cast(root->size)) { + std::vector array_assertions; + for (size_t i = 0; i < constSize->getZExtValue(); i++) { + auto value = source->constantValues.load(i); // construct(= (select i root) root->value[i]) to be asserted in // Z3Solver.cpp int width_out; - Z3ASTHandle array_value = - construct(constantSource->constantValues[i], &width_out); + Z3ASTHandle array_value = construct(value, &width_out); assert(width_out == (int)root->getRange() && "Value doesn't match root range"); array_assertions.push_back( eqExpr(readExpr(array_expr, bvConst32(root->getDomain(), i)), array_value)); } + constant_array_assertions[root] = std::move(array_assertions); + } else { + for (auto &[index, value] : source->constantValues.storage()) { + int width_out; + Z3ASTHandle array_value = construct(value, &width_out); + assert(width_out == (int)root->getRange() && + "Value doesn't match root range"); + array_expr = writeExpr( + array_expr, bvConst32(root->getDomain(), index), array_value); + } } - constant_array_assertions[root] = std::move(array_assertions); } _arr_hash.hashArrayExpr(root, array_expr); diff --git a/lib/Solver/Z3Builder.h b/lib/Solver/Z3Builder.h index 0ad50c151c..7b407c6e3d 100644 --- a/lib/Solver/Z3Builder.h +++ b/lib/Solver/Z3Builder.h @@ -31,7 +31,7 @@ template class Z3NodeHandle { private: // To be specialised - inline ::Z3_ast as_ast(); + inline ::Z3_ast as_ast() const; public: Z3NodeHandle() : node(NULL), context(NULL) {} @@ -73,7 +73,7 @@ template class Z3NodeHandle { return *this; } // To be specialised - void dump(); + void dump() const; operator T() const { return node; } @@ -82,19 +82,21 @@ template class Z3NodeHandle { }; // Specialise for Z3_sort -template <> inline ::Z3_ast Z3NodeHandle::as_ast() { +template <> inline ::Z3_ast Z3NodeHandle::as_ast() const { // In Z3 internally this call is just a cast. We could just do that // instead to simplify our implementation but this seems cleaner. return ::Z3_sort_to_ast(context, node); } typedef Z3NodeHandle Z3SortHandle; -template <> void Z3NodeHandle::dump() __attribute__((used)); +template <> void Z3NodeHandle::dump() const __attribute__((used)); template <> unsigned Z3NodeHandle::hash() __attribute__((used)); // Specialise for Z3_ast -template <> inline ::Z3_ast Z3NodeHandle::as_ast() { return node; } +template <> inline ::Z3_ast Z3NodeHandle::as_ast() const { + return node; +} typedef Z3NodeHandle Z3ASTHandle; -template <> void Z3NodeHandle::dump() __attribute__((used)); +template <> void Z3NodeHandle::dump() const __attribute__((used)); template <> unsigned Z3NodeHandle::hash() __attribute__((used)); struct Z3ASTHandleHash { diff --git a/lib/Solver/Z3Solver.cpp b/lib/Solver/Z3Solver.cpp index 3a92ae7fe1..a485ebe83e 100644 --- a/lib/Solver/Z3Solver.cpp +++ b/lib/Solver/Z3Solver.cpp @@ -8,11 +8,6 @@ //===----------------------------------------------------------------------===// #include "klee/Config/config.h" -#include "klee/Support/ErrorHandling.h" -#include "klee/Support/FileHandling.h" -#include "klee/Support/OptionCategories.h" - -#include #ifdef ENABLE_Z3 @@ -21,17 +16,20 @@ #include "Z3CoreBuilder.h" #include "Z3Solver.h" +#include "klee/ADT/Incremental.h" #include "klee/ADT/SparseStorage.h" #include "klee/Expr/Assignment.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/ExprUtil.h" #include "klee/Solver/Solver.h" #include "klee/Solver/SolverImpl.h" +#include "klee/Support/ErrorHandling.h" +#include "klee/Support/FileHandling.h" +#include "klee/Support/OptionCategories.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" -#include -#include +#include namespace { // NOTE: Very useful for debugging Z3 behaviour. These files can be given to @@ -67,30 +65,201 @@ DISABLE_WARNING_POP namespace klee { -class Z3SolverImpl : public SolverImpl { +using ConstraintFrames = inc_vector>; +using ExprIncMap = + inc_umap, Z3ASTHandleHash, Z3ASTHandleCmp>; +using Z3ASTIncMap = + inc_umap; +using ExprIncSet = + inc_uset, klee::util::ExprHash, klee::util::ExprCmp>; +using Z3ASTIncSet = inc_uset; + +void dump(const ConstraintFrames &frames) { + llvm::errs() << "frame sizes:"; + for (auto size : frames.frame_sizes) { + llvm::errs() << " " << size; + } + llvm::errs() << "\n"; + llvm::errs() << "frames:\n"; + for (auto &x : frames.v) { + llvm::errs() << x->toString() << "\n"; + } +} + +class ConstraintQuery { private: + // this should be used when only query is needed, se comment below + ref expr; + +public: + // KLEE Queries are validity queries i.e. + // ∀ X Constraints(X) → query(X) + // but Z3 works in terms of satisfiability so instead we ask the + // negation of the equivalent i.e. + // ∃ X Constraints(X) ∧ ¬ query(X) + // so this `constraints` field contains: Constraints(X) ∧ ¬ query(X) + ConstraintFrames constraints; + + explicit ConstraintQuery() {} + + explicit ConstraintQuery(const ConstraintFrames &frames, const ref &e) + : expr(e), constraints(frames) {} + explicit ConstraintQuery(ConstraintFrames &&frames, ref &&e) + : expr(std::move(e)), constraints(std::move(frames)) {} + + explicit ConstraintQuery(const Query &q, bool incremental) : expr(q.expr) { + if (incremental) { + for (auto &constraint : q.constraints.cs()) { + constraints.v.push_back(constraint); + constraints.push(); + } + } else { + const auto &other = q.constraints.cs(); + constraints.v.reserve(other.size()); + constraints.v.insert(constraints.v.end(), other.begin(), other.end()); + } + if (q.expr->getWidth() == Expr::Bool && !q.expr->isFalse()) + constraints.v.push_back(NotExpr::create(q.expr)); + } + + size_t size() const { return constraints.v.size(); } + + ref getOriginalQueryExpr() const { return expr; } + + ConstraintQuery withFalse() const { + return ConstraintQuery(ConstraintFrames(constraints), Expr::createFalse()); + } + + std::vector gatherArrays() const { + std::vector arrays; + findObjects(constraints.v.begin(), constraints.v.end(), arrays); + return arrays; + } +}; + +enum class ObjectAssignment { + NotNeeded, + NeededForObjectsFromEnv, + NeededForObjectsFromQuery +}; + +struct Z3SolverEnv { + using arr_vec = std::vector; + inc_vector objects; + arr_vec objectsForGetModel; + inc_vector z3_ast_expr_constraints; + ExprIncMap z3_ast_expr_to_klee_expr; + Z3ASTIncMap expr_to_track; + inc_umap usedArrayBytes; + ExprIncSet symbolicObjects; + + explicit Z3SolverEnv(){}; + explicit Z3SolverEnv(const arr_vec &objects); + + void pop(size_t popSize); + void push(); + void clear(); + + const arr_vec *getObjectsForGetModel(ObjectAssignment oa) const; +}; + +Z3SolverEnv::Z3SolverEnv(const std::vector &objects) + : objectsForGetModel(objects) {} + +void Z3SolverEnv::pop(size_t popSize) { + if (popSize == 0) + return; + objects.pop(popSize); + objectsForGetModel.clear(); + z3_ast_expr_constraints.pop(popSize); + z3_ast_expr_to_klee_expr.pop(popSize); + expr_to_track.pop(popSize); + usedArrayBytes.pop(popSize); + symbolicObjects.pop(popSize); +} + +void Z3SolverEnv::push() { + objects.push(); + z3_ast_expr_constraints.push(); + z3_ast_expr_to_klee_expr.push(); + expr_to_track.push(); + usedArrayBytes.push(); + symbolicObjects.push(); +} + +void Z3SolverEnv::clear() { + objects.clear(); + objectsForGetModel.clear(); + z3_ast_expr_constraints.clear(); + z3_ast_expr_to_klee_expr.clear(); + expr_to_track.clear(); + usedArrayBytes.clear(); + symbolicObjects.clear(); +} + +const Z3SolverEnv::arr_vec * +Z3SolverEnv::getObjectsForGetModel(ObjectAssignment oa) const { + switch (oa) { + case ObjectAssignment::NotNeeded: + return nullptr; + case ObjectAssignment::NeededForObjectsFromEnv: + return &objectsForGetModel; + case ObjectAssignment::NeededForObjectsFromQuery: + return &objects.v; + } +} + +class Z3SolverImpl : public SolverImpl { +protected: std::unique_ptr builder; + ::Z3_params solverParameters; + +private: Z3BuilderType builderType; time::Span timeout; - SolverRunStatus runStatusCode; + SolverImpl::SolverRunStatus runStatusCode; std::unique_ptr dumpedQueriesFile; - ::Z3_params solverParameters; // Parameter symbols ::Z3_symbol timeoutParamStrSymbol; ::Z3_symbol unsatCoreParamStrSymbol; - bool internalRunSolver(const Query &, - const std::vector *objects, + bool internalRunSolver(const ConstraintQuery &query, Z3SolverEnv &env, + ObjectAssignment needObjects, std::vector> *values, ValidityCore *validityCore, bool &hasSolution); + bool validateZ3Model(::Z3_solver &theSolver, ::Z3_model &theModel); -public: + SolverImpl::SolverRunStatus + handleSolverResponse(::Z3_solver theSolver, ::Z3_lbool satisfiable, + const Z3SolverEnv &env, ObjectAssignment needObjects, + std::vector> *values, + bool &hasSolution); + +protected: Z3SolverImpl(Z3BuilderType type); ~Z3SolverImpl(); - char *getConstraintLog(const Query &); - void setCoreSolverTimeout(time::Span _timeout) { + virtual Z3_solver initNativeZ3(const ConstraintQuery &query, + Z3ASTIncSet &assertions) = 0; + virtual void deinitNativeZ3(Z3_solver theSolver) = 0; + virtual void push(Z3_context c, Z3_solver s) = 0; + + bool computeTruth(const ConstraintQuery &, Z3SolverEnv &env, bool &isValid); + bool computeValue(const ConstraintQuery &, Z3SolverEnv &env, + ref &result); + bool computeInitialValues(const ConstraintQuery &, Z3SolverEnv &env, + std::vector> &values, + bool &hasSolution); + bool check(const ConstraintQuery &query, Z3SolverEnv &env, + ref &result); + bool computeValidityCore(const ConstraintQuery &query, Z3SolverEnv &env, + ValidityCore &validityCore, bool &isValid); + +public: + char *getConstraintLog(const Query &) final; + SolverImpl::SolverRunStatus getOperationStatusCode() final; + void setCoreSolverTimeout(time::Span _timeout) final { timeout = _timeout; auto timeoutInMilliSeconds = @@ -109,26 +278,20 @@ class Z3SolverImpl : public SolverImpl { Z3_FALSE); } - bool computeTruth(const Query &, bool &isValid); - bool computeValue(const Query &, ref &result); - bool computeInitialValues(const Query &, - const std::vector &objects, - std::vector> &values, - bool &hasSolution); - bool check(const Query &query, ref &result); - bool computeValidityCore(const Query &query, ValidityCore &validityCore, - bool &isValid); - SolverRunStatus handleSolverResponse( - ::Z3_solver theSolver, ::Z3_lbool satisfiable, - const std::vector *objects, - std::vector> *values, - const std::unordered_map &usedArrayBytes, - bool &hasSolution); - SolverRunStatus getOperationStatusCode(); + // pass virtual functions to children + using SolverImpl::check; + using SolverImpl::computeInitialValues; + using SolverImpl::computeTruth; + using SolverImpl::computeValidityCore; + using SolverImpl::computeValue; }; +void deleteNativeZ3(Z3_context ctx, Z3_solver theSolver) { + Z3_solver_dec_ref(ctx, theSolver); +} + Z3SolverImpl::Z3SolverImpl(Z3BuilderType type) - : builderType(type), runStatusCode(SOLVER_RUN_STATUS_FAILURE) { + : builderType(type), runStatusCode(SolverImpl::SOLVER_RUN_STATUS_FAILURE) { switch (type) { case KLEE_CORE: builder = std::unique_ptr(new Z3CoreBuilder( @@ -185,17 +348,6 @@ Z3SolverImpl::~Z3SolverImpl() { Z3_params_dec_ref(builder->ctx, solverParameters); } -Z3Solver::Z3Solver(Z3BuilderType type) - : Solver(std::make_unique(type)) {} - -char *Z3Solver::getConstraintLog(const Query &query) { - return impl->getConstraintLog(query); -} - -void Z3Solver::setCoreSolverTimeout(time::Span timeout) { - impl->setCoreSolverTimeout(timeout); -} - char *Z3SolverImpl::getConstraintLog(const Query &query) { std::vector assumptions; // We use a different builder here because we don't want to interfere @@ -217,7 +369,6 @@ char *Z3SolverImpl::getConstraintLog(const Query &query) { break; } ConstantArrayFinder constant_arrays_in_query; - assert(!query.containsSymcretes()); for (auto const &constraint : query.constraints.cs()) { assumptions.push_back(temp_builder->construct(constraint)); constant_arrays_in_query.visit(constraint); @@ -273,82 +424,77 @@ char *Z3SolverImpl::getConstraintLog(const Query &query) { return strdup(result); } -bool Z3SolverImpl::computeTruth(const Query &query, bool &isValid) { +bool Z3SolverImpl::computeTruth(const ConstraintQuery &query, Z3SolverEnv &env, + bool &isValid) { bool hasSolution = false; // to remove compiler warning - bool status = internalRunSolver(query, /*objects=*/NULL, /*values=*/NULL, + bool status = internalRunSolver(query, /*env=*/env, + ObjectAssignment::NotNeeded, /*values=*/NULL, /*validityCore=*/NULL, hasSolution); isValid = !hasSolution; return status; } -bool Z3SolverImpl::computeValue(const Query &query, ref &result) { - std::vector objects; +bool Z3SolverImpl::computeValue(const ConstraintQuery &query, Z3SolverEnv &env, + ref &result) { std::vector> values; bool hasSolution; // Find the object used in the expression, and compute an assignment // for them. - findSymbolicObjects(query.expr, objects); - if (!computeInitialValues(query.withFalse(), objects, values, hasSolution)) + findSymbolicObjects(query.getOriginalQueryExpr(), env.objectsForGetModel); + if (!computeInitialValues(query.withFalse(), env, values, hasSolution)) return false; assert(hasSolution && "state has invalid constraint set"); // Evaluate the expression with the computed assignment. - Assignment a(objects, values); - result = a.evaluate(query.expr); + Assignment a(env.objectsForGetModel, values); + result = a.evaluate(query.getOriginalQueryExpr()); return true; } bool Z3SolverImpl::computeInitialValues( - const Query &query, const std::vector &objects, + const ConstraintQuery &query, Z3SolverEnv &env, std::vector> &values, bool &hasSolution) { - return internalRunSolver(query, &objects, &values, /*validityCore=*/NULL, - hasSolution); + return internalRunSolver(query, env, + ObjectAssignment::NeededForObjectsFromEnv, &values, + /*validityCore=*/NULL, hasSolution); } -bool Z3SolverImpl::check(const Query &query, ref &result) { - ExprHashSet expressions; - assert(!query.containsSymcretes()); - expressions.insert(query.constraints.cs().begin(), - query.constraints.cs().end()); - expressions.insert(query.expr); - - std::vector objects; - findSymbolicObjects(expressions.begin(), expressions.end(), objects); +bool Z3SolverImpl::check(const ConstraintQuery &query, Z3SolverEnv &env, + ref &result) { std::vector> values; - ValidityCore validityCore; - bool hasSolution = false; - bool status = - internalRunSolver(query, &objects, &values, &validityCore, hasSolution); + internalRunSolver(query, env, ObjectAssignment::NeededForObjectsFromQuery, + &values, &validityCore, hasSolution); if (status) { result = hasSolution - ? (SolverResponse *)new InvalidResponse(objects, values) + ? (SolverResponse *)new InvalidResponse(env.objects.v, values) : (SolverResponse *)new ValidResponse(validityCore); } return status; } -bool Z3SolverImpl::computeValidityCore(const Query &query, +bool Z3SolverImpl::computeValidityCore(const ConstraintQuery &query, + Z3SolverEnv &env, ValidityCore &validityCore, bool &isValid) { bool hasSolution = false; // to remove compiler warning - bool status = internalRunSolver(query, /*objects=*/NULL, /*values=*/NULL, - &validityCore, hasSolution); + bool status = + internalRunSolver(query, /*env=*/env, ObjectAssignment::NotNeeded, + /*values=*/NULL, &validityCore, hasSolution); isValid = !hasSolution; return status; } bool Z3SolverImpl::internalRunSolver( - const Query &query, const std::vector *objects, + const ConstraintQuery &query, Z3SolverEnv &env, + ObjectAssignment needObjects, std::vector> *values, ValidityCore *validityCore, bool &hasSolution) { - assert(!query.containsSymcretes()); - if (ProduceUnsatCore && validityCore) { enableUnsatCore(); } else { @@ -363,107 +509,86 @@ bool Z3SolverImpl::internalRunSolver( // TODO: Investigate using a custom tactic as described in // https://github.com/klee/klee/issues/653 - Z3_goal goal = Z3_mk_goal(builder->ctx, false, false, false); - Z3_goal_inc_ref(builder->ctx, goal); - - // TODO: make a RAII - Z3_probe probe = Z3_mk_probe(builder->ctx, "is-qfaufbv"); - Z3_probe_inc_ref(builder->ctx, probe); - - runStatusCode = SOLVER_RUN_STATUS_FAILURE; + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_FAILURE; + + std::unordered_set all_constant_arrays_in_query; + Z3ASTIncSet exprs; + + for (size_t i = 0; i < query.constraints.framesSize(); + i++, env.push(), exprs.push()) { + ConstantArrayFinder constant_arrays_in_query; + env.symbolicObjects.insert(query.constraints.begin(i), + query.constraints.end(i)); + // FIXME: findSymbolicObjects template does not support inc_uset::iterator + // findSymbolicObjects(env.symbolicObjects.begin(-1), + // env.symbolicObjects.end(-1), env.objects.v); + std::vector> tmp(env.symbolicObjects.begin(-1), + env.symbolicObjects.end(-1)); + findSymbolicObjects(tmp.begin(), tmp.end(), env.objects.v); + for (auto cs_it = query.constraints.begin(i), + cs_ite = query.constraints.end(i); + cs_it != cs_ite; cs_it++) { + const auto &constraint = *cs_it; + Z3ASTHandle z3Constraint = builder->construct(constraint); + if (ProduceUnsatCore && validityCore) { + Z3ASTHandle p = builder->buildFreshBoolConst(); + env.z3_ast_expr_to_klee_expr.insert({p, constraint}); + env.z3_ast_expr_constraints.v.push_back(p); + env.expr_to_track[z3Constraint] = p; + } - ConstantArrayFinder constant_arrays_in_query; - std::vector z3_ast_expr_constraints; - std::unordered_map, Z3ASTHandleHash, Z3ASTHandleCmp> - z3_ast_expr_to_klee_expr; + exprs.insert(z3Constraint); - std::unordered_map - expr_to_track; - std::unordered_set exprs; + constant_arrays_in_query.visit(constraint); - for (auto const &constraint : query.constraints.cs()) { - Z3ASTHandle z3Constraint = builder->construct(constraint); - if (ProduceUnsatCore && validityCore) { - Z3ASTHandle p = builder->buildFreshBoolConst(); - z3_ast_expr_to_klee_expr.insert({p, constraint}); - z3_ast_expr_constraints.push_back(p); - expr_to_track[z3Constraint] = p; + std::vector> reads; + findReads(constraint, true, reads); + for (const auto &readExpr : reads) { + auto readFromArray = readExpr->updates.root; + assert(readFromArray); + env.usedArrayBytes[readFromArray].insert(readExpr->index); + } } - Z3_goal_assert(builder->ctx, goal, z3Constraint); - exprs.insert(z3Constraint); + for (auto constant_array : constant_arrays_in_query.results) { + // assert(builder->constant_array_assertions.count(constant_array) == 1 && + // "Constant array found in query, but not handled by Z3Builder"); + if (all_constant_arrays_in_query.count(constant_array)) + continue; + all_constant_arrays_in_query.insert(constant_array); + const auto &cas = builder->constant_array_assertions[constant_array]; + exprs.insert(cas.begin(), cas.end()); + } - constant_arrays_in_query.visit(constraint); + // Assert an generated side constraints we have to this last so that all + // other constraints have been traversed so we have all the side constraints + // needed. + exprs.insert(builder->sideConstraints.begin(), + builder->sideConstraints.end()); } + exprs.pop(1); // drop last empty frame + ++stats::solverQueries; - if (objects) + if (!env.objects.v.empty()) ++stats::queryCounterexamples; - Z3ASTHandle z3QueryExpr = - Z3ASTHandle(builder->construct(query.expr), builder->ctx); - constant_arrays_in_query.visit(query.expr); - - for (auto const &constant_array : constant_arrays_in_query.results) { - assert(builder->constant_array_assertions.count(constant_array) == 1 && - "Constant array found in query, but not handled by Z3Builder"); - for (auto const &arrayIndexValueExpr : - builder->constant_array_assertions[constant_array]) { - Z3_goal_assert(builder->ctx, goal, arrayIndexValueExpr); - exprs.insert(arrayIndexValueExpr); - } - } - - // KLEE Queries are validity queries i.e. - // ∀ X Constraints(X) → query(X) - // but Z3 works in terms of satisfiability so instead we ask the - // negation of the equivalent i.e. - // ∃ X Constraints(X) ∧ ¬ query(X) - Z3ASTHandle z3NotQueryExpr = - Z3ASTHandle(Z3_mk_not(builder->ctx, z3QueryExpr), builder->ctx); - Z3_goal_assert(builder->ctx, goal, z3NotQueryExpr); - - // Assert an generated side constraints we have to this last so that all other - // constraints have been traversed so we have all the side constraints needed. - for (std::vector::iterator it = builder->sideConstraints.begin(), - ie = builder->sideConstraints.end(); - it != ie; ++it) { - Z3ASTHandle sideConstraint = *it; - Z3_goal_assert(builder->ctx, goal, sideConstraint); - exprs.insert(sideConstraint); - } - - std::vector arrays = query.gatherArrays(); - bool forceTactic = true; - for (const Array *array : arrays) { - if (isa(array->source)) { - forceTactic = false; - break; - } - } - - Z3_solver theSolver; - if (forceTactic && Z3_probe_apply(builder->ctx, probe, goal)) { - theSolver = Z3_mk_solver_for_logic( - builder->ctx, Z3_mk_string_symbol(builder->ctx, "QF_AUFBV")); - } else { - theSolver = Z3_mk_solver(builder->ctx); - } - Z3_solver_inc_ref(builder->ctx, theSolver); - Z3_solver_set_params(builder->ctx, theSolver, solverParameters); - - for (std::unordered_set::iterator it = exprs.begin(), - ie = exprs.end(); - it != ie; ++it) { - Z3ASTHandle expr = *it; - if (expr_to_track.count(expr)) { - Z3_solver_assert_and_track(builder->ctx, theSolver, expr, - expr_to_track[expr]); - } else { - Z3_solver_assert(builder->ctx, theSolver, expr); + Z3_solver theSolver = initNativeZ3(query, exprs); + + for (size_t i = 0; i < exprs.framesSize(); i++) { + push(builder->ctx, theSolver); + for (auto it = exprs.begin(i), ie = exprs.end(i); it != ie; ++it) { + Z3ASTHandle expr = *it; + if (env.expr_to_track.count(expr)) { + Z3_solver_assert_and_track(builder->ctx, theSolver, expr, + env.expr_to_track[expr]); + } else { + Z3_solver_assert(builder->ctx, theSolver, expr); + } } } - Z3_solver_assert(builder->ctx, theSolver, z3NotQueryExpr); + assert(!Z3_solver_get_num_scopes(builder->ctx, theSolver) || + Z3_solver_get_num_scopes(builder->ctx, theSolver) + 1 == + env.objects.framesSize()); if (dumpedQueriesFile) { *dumpedQueriesFile << "; start Z3 query\n"; @@ -476,22 +601,9 @@ bool Z3SolverImpl::internalRunSolver( dumpedQueriesFile->flush(); } - constraints_ty allConstraints = query.constraints.cs(); - allConstraints.insert(query.expr); - std::unordered_map usedArrayBytes; - for (auto constraint : allConstraints) { - std::vector> reads; - findReads(constraint, true, reads); - for (auto readExpr : reads) { - const Array *readFromArray = readExpr->updates.root; - assert(readFromArray); - usedArrayBytes[readFromArray].insert(readExpr->index); - } - } - ::Z3_lbool satisfiable = Z3_solver_check(builder->ctx, theSolver); - runStatusCode = handleSolverResponse(theSolver, satisfiable, objects, values, - usedArrayBytes, hasSolution); + runStatusCode = handleSolverResponse(theSolver, satisfiable, env, needObjects, + values, hasSolution); if (ProduceUnsatCore && validityCore && satisfiable == Z3_L_FALSE) { constraints_ty unsatCore; Z3_ast_vector z3_unsat_core = @@ -508,15 +620,15 @@ bool Z3SolverImpl::internalRunSolver( z3_ast_expr_unsat_core.insert(constraint); } - for (auto &z3_constraint : z3_ast_expr_constraints) { + for (const auto &z3_constraint : env.z3_ast_expr_constraints.v) { if (z3_ast_expr_unsat_core.find(z3_constraint) != z3_ast_expr_unsat_core.end()) { - ref constraint = z3_ast_expr_to_klee_expr[z3_constraint]; + ref constraint = env.z3_ast_expr_to_klee_expr[z3_constraint]; unsatCore.insert(constraint); } } assert(validityCore && "validityCore cannot be nullptr"); - *validityCore = ValidityCore(unsatCore, query.expr); + *validityCore = ValidityCore(unsatCore, query.getOriginalQueryExpr()); Z3_ast_vector assertions = Z3_solver_get_assertions(builder->ctx, theSolver); @@ -531,9 +643,7 @@ bool Z3SolverImpl::internalRunSolver( Z3_ast_vector_dec_ref(builder->ctx, assertions); } - Z3_goal_dec_ref(builder->ctx, goal); - Z3_probe_dec_ref(builder->ctx, probe); - Z3_solver_dec_ref(builder->ctx, theSolver); + deinitNativeZ3(theSolver); // Clear the builder's cache to prevent memory usage exploding. // By using ``autoClearConstructCache=false`` and clearning now @@ -558,17 +668,16 @@ bool Z3SolverImpl::internalRunSolver( } SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( - ::Z3_solver theSolver, ::Z3_lbool satisfiable, - const std::vector *objects, - std::vector> *values, - const std::unordered_map &usedArrayBytes, - bool &hasSolution) { + ::Z3_solver theSolver, ::Z3_lbool satisfiable, const Z3SolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, bool &hasSolution) { switch (satisfiable) { case Z3_L_TRUE: { hasSolution = true; + auto objects = env.getObjectsForGetModel(needObjects); if (!objects) { // No assignment is needed - assert(values == NULL); + assert(!values); return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; } assert(values && "values cannot be nullptr"); @@ -576,10 +685,7 @@ SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( assert(theModel && "Failed to retrieve model"); Z3_model_inc_ref(builder->ctx, theModel); values->reserve(objects->size()); - for (std::vector::const_iterator it = objects->begin(), - ie = objects->end(); - it != ie; ++it) { - const Array *array = *it; + for (auto array : *objects) { SparseStorage data; ::Z3_ast arraySizeExpr; @@ -595,10 +701,9 @@ SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( Z3_get_numeral_uint64(builder->ctx, arraySizeExpr, &arraySize); assert(success && "Failed to get size"); - data.resize(arraySize); - if (usedArrayBytes.count(array)) { + if (env.usedArrayBytes.count(array)) { std::unordered_set offsetValues; - for (ref offsetExpr : usedArrayBytes.at(array)) { + for (const ref &offsetExpr : env.usedArrayBytes.at(array)) { ::Z3_ast arrayElementOffsetExpr; Z3_model_eval(builder->ctx, theModel, builder->construct(offsetExpr), Z3_TRUE, &arrayElementOffsetExpr); @@ -734,5 +839,356 @@ bool Z3SolverImpl::validateZ3Model(::Z3_solver &theSolver, SolverImpl::SolverRunStatus Z3SolverImpl::getOperationStatusCode() { return runStatusCode; } + +class Z3NonIncSolverImpl final : public Z3SolverImpl { +private: +public: + Z3NonIncSolverImpl(Z3BuilderType type) : Z3SolverImpl(type) {} + + /// implementation of Z3SolverImpl interface + Z3_solver initNativeZ3(const ConstraintQuery &query, + Z3ASTIncSet &assertions) override { + Z3_solver theSolver = nullptr; + auto arrays = query.gatherArrays(); + bool forceTactic = true; + for (auto array : arrays) { + if (isa(array->source) && + !isa(array->size)) { + forceTactic = false; + break; + } + } + + auto ctx = builder->ctx; + if (forceTactic) { + Z3_probe probe = Z3_mk_probe(ctx, "is-qfaufbv"); + Z3_probe_inc_ref(ctx, probe); + Z3_goal goal = Z3_mk_goal(ctx, false, false, false); + Z3_goal_inc_ref(ctx, goal); + + for (auto constraint : assertions) + Z3_goal_assert(ctx, goal, constraint); + if (Z3_probe_apply(ctx, probe, goal)) + theSolver = + Z3_mk_solver_for_logic(ctx, Z3_mk_string_symbol(ctx, "QF_AUFBV")); + Z3_goal_dec_ref(ctx, goal); + Z3_probe_dec_ref(ctx, probe); + } + if (!theSolver) + theSolver = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, theSolver); + Z3_solver_set_params(ctx, theSolver, solverParameters); + return theSolver; + } + void deinitNativeZ3(Z3_solver theSolver) override { + deleteNativeZ3(builder->ctx, theSolver); + } + void push(Z3_context c, Z3_solver s) override {} + + /// implementation of the SolverImpl interface + bool computeTruth(const Query &query, bool &isValid) override { + Z3SolverEnv env; + return Z3SolverImpl::computeTruth(ConstraintQuery(query, false), env, + isValid); + } + bool computeValue(const Query &query, ref &result) override { + Z3SolverEnv env; + return Z3SolverImpl::computeValue(ConstraintQuery(query, false), env, + result); + } + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution) override { + Z3SolverEnv env(objects); + return Z3SolverImpl::computeInitialValues(ConstraintQuery(query, false), + env, values, hasSolution); + } + bool check(const Query &query, ref &result) override { + Z3SolverEnv env; + return Z3SolverImpl::check(ConstraintQuery(query, false), env, result); + } + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid) override { + Z3SolverEnv env; + return Z3SolverImpl::computeValidityCore(ConstraintQuery(query, false), env, + validityCore, isValid); + } + void notifyStateTermination(std::uint32_t id) override {} +}; + +Z3Solver::Z3Solver(Z3BuilderType type) + : Solver(std::make_unique(type)) {} + +struct ConstraintDistance { + size_t toPopSize = 0; + ConstraintQuery toPush; + + explicit ConstraintDistance() {} + ConstraintDistance(const ConstraintQuery &q) : toPush(q) {} + explicit ConstraintDistance(size_t toPopSize, const ConstraintQuery &q) + : toPopSize(toPopSize), toPush(q) {} + + size_t getDistance() const { return toPopSize + toPush.size(); } + + bool isOnlyPush() const { return toPopSize == 0; } + + void dump() const { + llvm::errs() << "ConstraintDistance: pop: " << toPopSize << "; push:\n"; + klee::dump(toPush.constraints); + } +}; + +class Z3IncNativeSolver { +private: + Z3_solver nativeSolver = nullptr; + Z3_context ctx; + Z3_params solverParameters; + /// underlying solver frames + /// saved only for calculating distances from next queries + ConstraintFrames frames; + + void pop(size_t popSize); + void push(); + +public: + Z3SolverEnv env; + std::uint32_t stateID = 0; + bool isRecycled = false; + + Z3IncNativeSolver(Z3_context ctx, Z3_params solverParameters) + : ctx(ctx), solverParameters(solverParameters) {} + ~Z3IncNativeSolver(); + + void clear(); + + void distance(const ConstraintQuery &query, ConstraintDistance &delta) const; + + void popPush(ConstraintDistance &delta); + + Z3_solver getOrInit(); + + bool isConsistent() const { + auto num_scopes = + nativeSolver ? Z3_solver_get_num_scopes(ctx, nativeSolver) : 0; + bool consistentWithZ3 = num_scopes + 1 == frames.framesSize(); + assert(consistentWithZ3); + bool constistentItself = frames.framesSize() == env.objects.framesSize(); + assert(constistentItself); + return consistentWithZ3 && constistentItself; + } + + void dump() const { ::klee::dump(frames); } +}; + +void Z3IncNativeSolver::pop(size_t popSize) { + if (!nativeSolver || !popSize) + return; + Z3_solver_pop(ctx, nativeSolver, popSize); +} + +void Z3IncNativeSolver::popPush(ConstraintDistance &delta) { + env.pop(delta.toPopSize); + pop(delta.toPopSize); + frames.pop(delta.toPopSize); + frames.extend(delta.toPush.constraints); +} + +Z3_solver Z3IncNativeSolver::getOrInit() { + if (nativeSolver == nullptr) { + nativeSolver = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, nativeSolver); + Z3_solver_set_params(ctx, nativeSolver, solverParameters); + } + return nativeSolver; +} + +Z3IncNativeSolver::~Z3IncNativeSolver() { + if (nativeSolver != nullptr) + deleteNativeZ3(ctx, nativeSolver); +} + +void Z3IncNativeSolver::clear() { + if (!nativeSolver) + return; + env.clear(); + frames.clear(); + Z3_solver_reset(ctx, nativeSolver); + isRecycled = false; +} + +void Z3IncNativeSolver::distance(const ConstraintQuery &query, + ConstraintDistance &delta) const { + auto sit = frames.v.begin(); + auto site = frames.v.end(); + auto qit = query.constraints.v.begin(); + auto qite = query.constraints.v.end(); + auto it = frames.begin(); + auto ite = frames.end(); + size_t intersect = 0; + for (; it != ite && sit != site && qit != qite && *sit == *qit; it++) { + size_t frame_size = *it; + for (size_t i = 0; + i < frame_size && sit != site && qit != qite && *sit == *qit; + i++, sit++, qit++, intersect++) { + } + } + for (; sit != site && qit != qite && *sit == *qit; + sit++, qit++, intersect++) { + } + size_t toPop, extraTakeFromOther; + ConstraintFrames d; + if (sit == site) { // solver frames ended + toPop = 0; + extraTakeFromOther = 0; + } else { + frames.takeBefore(intersect, toPop, extraTakeFromOther); + } + query.constraints.takeAfter(intersect - extraTakeFromOther, d); + ConstraintQuery q(std::move(d), query.getOriginalQueryExpr()); + delta = ConstraintDistance(toPop, std::move(q)); +} + +class Z3TreeSolverImpl final : public Z3SolverImpl { +private: + using solvers_ty = std::vector>; + using solvers_it = solvers_ty::iterator; + + const size_t maxSolvers; + std::unique_ptr currentSolver = nullptr; + solvers_ty solvers; + + void findSuitableSolver(const ConstraintQuery &query, + ConstraintDistance &delta); + void setSolver(solvers_it &it, bool recycle = false); + ConstraintQuery prepare(const Query &q); + +public: + Z3TreeSolverImpl(Z3BuilderType type, size_t maxSolvers) + : Z3SolverImpl(type), maxSolvers(maxSolvers){}; + + /// implementation of Z3SolverImpl interface + Z3_solver initNativeZ3(const ConstraintQuery &query, + Z3ASTIncSet &assertions) override { + return currentSolver->getOrInit(); + } + void deinitNativeZ3(Z3_solver theSolver) override { + assert(currentSolver->isConsistent()); + solvers.push_back(std::move(currentSolver)); + } + void push(Z3_context c, Z3_solver s) override { Z3_solver_push(c, s); } + + /// implementation of the SolverImpl interface + bool computeTruth(const Query &query, bool &isValid) override; + bool computeValue(const Query &query, ref &result) override; + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution) override; + bool check(const Query &query, ref &result) override; + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid) override; + + void notifyStateTermination(std::uint32_t id) override; +}; + +void Z3TreeSolverImpl::setSolver(solvers_it &it, bool recycle) { + assert(it != solvers.end()); + currentSolver = std::move(*it); + solvers.erase(it); + currentSolver->isRecycled = false; + if (recycle) + currentSolver->clear(); +} + +void Z3TreeSolverImpl::findSuitableSolver(const ConstraintQuery &query, + ConstraintDistance &delta) { + ConstraintDistance min_delta; + auto min_distance = std::numeric_limits::max(); + auto min_it = solvers.end(); + auto free_it = solvers.end(); + for (auto it = solvers.begin(), ite = min_it; it != ite; it++) { + if ((*it)->isRecycled) + free_it = it; + (*it)->distance(query, delta); + if (delta.isOnlyPush()) { + setSolver(it); + return; + } + auto distance = delta.getDistance(); + if (distance < min_distance) { + min_delta = delta; + min_distance = distance; + min_it = it; + } + } + if (solvers.size() < maxSolvers) { + delta = ConstraintDistance(query); + if (delta.getDistance() < min_distance) { + // it is cheaper to create new solver + if (free_it == solvers.end()) + currentSolver = + std::make_unique(builder->ctx, solverParameters); + else + setSolver(free_it, /*recycle=*/true); + return; + } + } + assert(min_it != solvers.end()); + delta = min_delta; + setSolver(min_it); +} + +ConstraintQuery Z3TreeSolverImpl::prepare(const Query &q) { + ConstraintDistance delta; + ConstraintQuery query(q, true); + findSuitableSolver(query, delta); + assert(currentSolver->isConsistent()); + currentSolver->stateID = q.id; + currentSolver->popPush(delta); + return delta.toPush; +} + +bool Z3TreeSolverImpl::computeTruth(const Query &query, bool &isValid) { + auto q = prepare(query); + return Z3SolverImpl::computeTruth(q, currentSolver->env, isValid); +} + +bool Z3TreeSolverImpl::computeValue(const Query &query, ref &result) { + auto q = prepare(query); + return Z3SolverImpl::computeValue(q, currentSolver->env, result); +} + +bool Z3TreeSolverImpl::computeInitialValues( + const Query &query, const std::vector &objects, + std::vector> &values, bool &hasSolution) { + auto q = prepare(query); + currentSolver->env.objectsForGetModel = objects; + return Z3SolverImpl::computeInitialValues(q, currentSolver->env, values, + hasSolution); +} + +bool Z3TreeSolverImpl::check(const Query &query, ref &result) { + auto q = prepare(query); + return Z3SolverImpl::check(q, currentSolver->env, result); +} + +bool Z3TreeSolverImpl::computeValidityCore(const Query &query, + ValidityCore &validityCore, + bool &isValid) { + auto q = prepare(query); + return Z3SolverImpl::computeValidityCore(q, currentSolver->env, validityCore, + isValid); +} + +void Z3TreeSolverImpl::notifyStateTermination(std::uint32_t id) { + for (auto &s : solvers) + if (s->stateID == id) + s->isRecycled = true; +} + +Z3TreeSolver::Z3TreeSolver(Z3BuilderType type, unsigned maxSolvers) + : Solver(std::make_unique(type, maxSolvers)) {} + } // namespace klee #endif // ENABLE_Z3 diff --git a/lib/Solver/Z3Solver.h b/lib/Solver/Z3Solver.h index 0189dec08f..6b4aca126b 100644 --- a/lib/Solver/Z3Solver.h +++ b/lib/Solver/Z3Solver.h @@ -23,16 +23,13 @@ class Z3Solver : public Solver { public: /// Z3Solver - Construct a new Z3Solver. Z3Solver(Z3BuilderType type); +}; - /// Get the query in SMT-LIBv2 format. - /// \return A C-style string. The caller is responsible for freeing this. - virtual char *getConstraintLog(const Query &); - - /// setCoreSolverTimeout - Set constraint solver timeout delay to the given - /// value; 0 - /// is off. - virtual void setCoreSolverTimeout(time::Span timeout); +class Z3TreeSolver : public Solver { +public: + Z3TreeSolver(Z3BuilderType type, unsigned maxSolvers); }; + } // namespace klee #endif /* KLEE_Z3SOLVER_H */ diff --git a/runtime/Runtest/intrinsics.c b/runtime/Runtest/intrinsics.c index 34a9e9d2c8..7372549b93 100644 --- a/runtime/Runtest/intrinsics.c +++ b/runtime/Runtest/intrinsics.c @@ -43,7 +43,10 @@ static void report_internal_error(const char *msg, ...) { va_end(ap); fprintf(stderr, "\n"); char *testErrorsNonFatal = getenv("KLEE_RUN_TEST_ERRORS_NON_FATAL"); - if (testErrorsNonFatal) { + if (testErrorsNonFatal && !strcmp(testErrorsNonFatal, "STOP")) { + fprintf(stderr, "KLEE_RUN_TEST_ERROR: Stop execution without an error\n"); + exit(0); + } else if (testErrorsNonFatal && !strcmp(testErrorsNonFatal, "FORCE")) { fprintf(stderr, "KLEE_RUN_TEST_ERROR: Forcing execution to continue\n"); } else { exit(1); diff --git a/runtime/klee-fp/CMakeLists.txt b/runtime/klee-fp/CMakeLists.txt index 0314ca9c50..42b2829004 100644 --- a/runtime/klee-fp/CMakeLists.txt +++ b/runtime/klee-fp/CMakeLists.txt @@ -10,18 +10,18 @@ set(LIB_PREFIX "RuntimeFp") set(SRC_FILES ceil.c - klee_copysign.c + copysign.c exp.c fabs.c - klee_fenv.c - klee_floor.c + fenv.c + floor.c fpclassify.c - klee_internal_isinf.ll - klee_rint.c + isinf.ll klee_set_rounding_mode.c - klee_signbit.ll log.c + rint.c round.c + signbit.ll sqrt.c trigonometry.c ) diff --git a/runtime/klee-fp/ceil.c b/runtime/klee-fp/ceil.c index 9d112a16a3..d185cb7cb1 100644 --- a/runtime/klee-fp/ceil.c +++ b/runtime/klee-fp/ceil.c @@ -8,26 +8,26 @@ //===----------------------------------------------------------------------===*/ #include "float.h" -#include "klee_floor.h" -#include "klee_rint.h" +#include "floor.h" +#include "rint.h" float ceilf(float f) { - if (f == klee_internal_rintf(f)) { + if (f == rintf(f)) { return f; } - return ((f < 0.0f) ? -1 : 1) + klee_floorf(f); + return ((f < 0.0f) ? -1 : 1) + floorf(f); } double ceil(double f) { - if (f == klee_internal_rint(f)) { + if (f == rint(f)) { return f; } - return ((f < 0.0f) ? -1 : 1) + klee_floor(f); + return ((f < 0.0f) ? -1 : 1) + floor(f); } long double ceill(long double f) { - if (f == klee_internal_rintl(f)) { + if (f == rintl(f)) { return f; } - return ((f < 0.0f) ? -1 : 1) + klee_floorl(f); + return ((f < 0.0f) ? -1 : 1) + floorl(f); } diff --git a/runtime/klee-fp/klee_copysign.c b/runtime/klee-fp/copysign.c similarity index 97% rename from runtime/klee-fp/klee_copysign.c rename to runtime/klee-fp/copysign.c index ddd72fdc53..7505b51ffb 100644 --- a/runtime/klee-fp/klee_copysign.c +++ b/runtime/klee-fp/copysign.c @@ -1,4 +1,4 @@ -/*===-- klee_copysign.c ---------------------------------------------------===// +/*===-- copysign.c --------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===*/ -#include "klee_copysign.h" +#include "copysign.h" #include "ansidecl.h" #include "klee/klee.h" diff --git a/runtime/klee-fp/klee_copysign.h b/runtime/klee-fp/copysign.h similarity index 88% rename from runtime/klee-fp/klee_copysign.h rename to runtime/klee-fp/copysign.h index 444e0ab264..4384a216cb 100644 --- a/runtime/klee-fp/klee_copysign.h +++ b/runtime/klee-fp/copysign.h @@ -1,4 +1,4 @@ -/*===-- klee_copysign.h ---------------------------------------------------===// +/*===-- copysign.h --------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // diff --git a/runtime/klee-fp/fabs.c b/runtime/klee-fp/fabs.c index c3c4c88a6a..236cc38658 100644 --- a/runtime/klee-fp/fabs.c +++ b/runtime/klee-fp/fabs.c @@ -8,12 +8,10 @@ //===----------------------------------------------------------------------===*/ #include "klee/klee.h" -double klee_internal_fabs(double d) { return klee_abs_double(d); } +double fabs(double d) { return klee_abs_double(d); } -float klee_internal_fabsf(float f) { return klee_abs_float(f); } +float fabsf(float f) { return klee_abs_float(f); } #if defined(__x86_64__) || defined(__i386__) -long double klee_internal_fabsl(long double f) { - return klee_abs_long_double(f); -} +long double fabsl(long double f) { return klee_abs_long_double(f); } #endif diff --git a/runtime/klee-fp/klee_fenv.c b/runtime/klee-fp/fenv.c similarity index 92% rename from runtime/klee-fp/klee_fenv.c rename to runtime/klee-fp/fenv.c index d6b52e3820..0a70f90f34 100644 --- a/runtime/klee-fp/klee_fenv.c +++ b/runtime/klee-fp/fenv.c @@ -1,4 +1,4 @@ -/*===-- klee_fenv.c -------------------------------------------------------===// +/*===-- fenv.c ------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===*/ -#include "klee_fenv.h" +#include "fenv.h" #include "klee/klee.h" // Define the constants. Don't include `fenv.h` here to avoid @@ -28,7 +28,7 @@ enum { #error Architecture not supported #endif -int klee_internal_fegetround(void) { +int fegetround(void) { enum KleeRoundingMode rm = klee_get_rounding_mode(); switch (rm) { case KLEE_FP_RNE: @@ -52,7 +52,7 @@ int klee_internal_fegetround(void) { } } -int klee_internal_fesetround(int rm) { +int fesetround(int rm) { switch (rm) { case FE_TONEAREST: klee_set_rounding_mode(KLEE_FP_RNE); diff --git a/runtime/klee-fp/klee_fenv.h b/runtime/klee-fp/fenv.h similarity index 85% rename from runtime/klee-fp/klee_fenv.h rename to runtime/klee-fp/fenv.h index af75c5591b..3cb7728f20 100644 --- a/runtime/klee-fp/klee_fenv.h +++ b/runtime/klee-fp/fenv.h @@ -11,7 +11,7 @@ #define KLEE_FENV_H #include "klee/klee.h" -int klee_internal_fegetround(void); -int klee_internal_fesetround(int rm); +int fegetround(void); +int fesetround(int rm); #endif // KLEE_FENV_H diff --git a/runtime/klee-fp/klee_floor.c b/runtime/klee-fp/floor.c similarity index 79% rename from runtime/klee-fp/klee_floor.c rename to runtime/klee-fp/floor.c index 51a3785fe7..3b79738fe2 100644 --- a/runtime/klee-fp/klee_floor.c +++ b/runtime/klee-fp/floor.c @@ -1,4 +1,5 @@ -/*===-- klee_floor.c ------------------------------------------------------===// +/*===-- floor.c +------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -7,11 +8,11 @@ // //===----------------------------------------------------------------------===*/ -#include "klee_floor.h" +#include "floor.h" #include "klee/klee.h" #include "math.h" -float klee_floorf(float x) { +float floorf(float x) { int sign = signbit(x); x = klee_abs_float(x); if (klee_rintf(x) > x) { @@ -21,7 +22,7 @@ float klee_floorf(float x) { } } -double klee_floor(double x) { +double floor(double x) { int sign = signbit(x); x = klee_abs_double(x); if (klee_rint(x) > x) { @@ -31,7 +32,7 @@ double klee_floor(double x) { } } -long double klee_floorl(long double x) { +long double floorl(long double x) { int sign = signbit(x); x = klee_abs_long_double(x); if (klee_rintl(x) > x) { diff --git a/runtime/klee-fp/klee_floor.h b/runtime/klee-fp/floor.h similarity index 68% rename from runtime/klee-fp/klee_floor.h rename to runtime/klee-fp/floor.h index 03e1c1c8da..4cdbc93981 100644 --- a/runtime/klee-fp/klee_floor.h +++ b/runtime/klee-fp/floor.h @@ -1,4 +1,4 @@ -/*===-- klee_floor.h ------------------------------------------------------===// +/*===-- floor.h -----------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -10,8 +10,8 @@ #ifndef KLEE_FLOOR_H #define KLEE_FLOOR_H -float klee_floorf(float x); -double klee_floor(double x); -long double klee_floorl(long double x); +float floorf(float x); +double floor(double x); +long double floorl(long double x); #endif // KLEE_FLOOR_H diff --git a/runtime/klee-fp/fpclassify.c b/runtime/klee-fp/fpclassify.c index 06f9d001f9..0e0b1b179d 100644 --- a/runtime/klee-fp/fpclassify.c +++ b/runtime/klee-fp/fpclassify.c @@ -13,16 +13,19 @@ // during linking. // __isnanf -int klee_internal_isnanf(float f) { return klee_is_nan_float(f); } +int __isnanf(float f) { return klee_is_nan_float(f); } +int isnanf(float f) { return __isnanf(f); } // __isnan -int klee_internal_isnan(double d) { return klee_is_nan_double(d); } +int __isnan(double d) { return klee_is_nan_double(d); } +int isnan(double d) { return __isnan(d); } // __isnanl -int klee_internal_isnanl(long double d) { return klee_is_nan_long_double(d); } +int __isnanl(long double d) { return klee_is_nan_long_double(d); } +int isnanl(long double d) { return __isnanl(d); } // __fpclassifyf -int klee_internal_fpclassifyf(float f) { +int __fpclassifyf(float f) { /* * This version acts like a switch case which returns correct * float type from the enum, but itself does not fork @@ -33,38 +36,44 @@ int klee_internal_fpclassifyf(float f) { int x = klee_is_normal_float(f); return ((x << 2) | ((c | d) << 1) | (b | d)); } +int fpclassifyf(float f) { return __fpclassifyf(f); } // __fpclassify -int klee_internal_fpclassify(double f) { +int __fpclassify(double f) { int b = klee_is_infinite_double(f); int c = (f == 0.0f); int d = klee_is_subnormal_double(f); int x = klee_is_normal_double(f); return ((x << 2) | ((c | d) << 1) | (b | d)); } +int fpclassify(double f) { return __fpclassify(f); } // __fpclassifyl #if defined(__x86_64__) || defined(__i386__) -int klee_internal_fpclassifyl(long double f) { +int __fpclassifyl(long double f) { int b = klee_is_infinite_long_double(f); int c = (f == 0.0f); int d = klee_is_subnormal_long_double(f); int x = klee_is_normal_long_double(f); return ((x << 2) | ((c | d) << 1) | (b | d)); } +int fpclassifyl(long double f) { return __fpclassifyl(f); } #endif // __finitef -int klee_internal_finitef(float f) { +int __finitef(float f) { return (!klee_is_nan_float(f)) & (!klee_is_infinite_float(f)); } +int finitef(float f) { return __finitef(f); } // __finite -int klee_internal_finite(double f) { +int __finite(double f) { return (!klee_is_nan_double(f)) & (!klee_is_infinite_double(f)); } +int finite(double f) { return __finite(f); } // __finitel -int klee_internal_finitel(long double f) { +int __finitel(long double f) { return (!klee_is_nan_long_double(f)) & (!klee_is_infinite_long_double(f)); } +int finitel(long double f) { return finitel(f); } diff --git a/runtime/klee-fp/klee_internal_isinf.ll b/runtime/klee-fp/isinf.ll similarity index 78% rename from runtime/klee-fp/klee_internal_isinf.ll rename to runtime/klee-fp/isinf.ll index 8a50b15134..f22bee07ce 100644 --- a/runtime/klee-fp/klee_internal_isinf.ll +++ b/runtime/klee-fp/isinf.ll @@ -1,4 +1,4 @@ -;;===-- klee_internal_isinff.ll --------------------------------------------===;; +;;===-- isinff.ll ---------------------------------------------------------===;; ;; ;; The KLEE Symbolic Virtual Machine ;; @@ -6,8 +6,6 @@ ;; License. See LICENSE.TXT for details. ;; ;;===----------------------------------------------------------------------===;; -;target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -;target triple = "x86_64-unknown-linux-gnu" ;; These are implementations of internal functions found in libm for classifying ;; floating point numbers. They have different names to avoid name collisions @@ -19,7 +17,7 @@ declare zeroext i1 @klee_is_infinite_float(float) #2 declare zeroext i1 @klee_is_infinite_double(double) #2 declare zeroext i1 @klee_is_infinite_long_double(x86_fp80) #2 -define i32 @klee_internal_isinff(float %f) #1 #0 { +define i32 @__isinff(float %f) #1 #0 { entry: %isinf = tail call zeroext i1 @klee_is_infinite_float(float %f) #3 %cmp = fcmp ogt float %f, 0.000000e+00 @@ -28,7 +26,13 @@ entry: ret i32 %result } -define i32 @klee_internal_isinf(double %d) #1 #0 { +define i32 @isinff(float %f) #1 #0 { +entry: + %result = tail call zeroext i32 @__isinff(float %f) #3 + ret i32 %result +} + +define i32 @__isinf(double %d) #1 #0 { entry: %isinf = tail call zeroext i1 @klee_is_infinite_double(double %d) #3 %cmp = fcmp ogt double %d, 0.000000e+00 @@ -37,7 +41,13 @@ entry: ret i32 %result } -define i32 @klee_internal_isinfl(x86_fp80 %d) #0 { +define i32 @isinf(double %d) #1 #0 { +entry: + %result = tail call zeroext i32 @__isinf(double %d) #3 + ret i32 %result +} + +define i32 @__isinfl(x86_fp80 %d) #0 { entry: %isinf = tail call zeroext i1 @klee_is_infinite_long_double(x86_fp80 %d) #3 %cmp = fcmp ogt x86_fp80 %d, 0xK00000000000000000000 @@ -46,6 +56,12 @@ entry: ret i32 %result } +define i32 @isinfl(x86_fp80 %d) #0 { +entry: + %result = tail call zeroext i32 @__isinfl(x86_fp80 %d) #3 + ret i32 %result +} + ; NOTE: Use of optnone and noinline here are important so that the KLEE diff --git a/runtime/klee-fp/log.c b/runtime/klee-fp/log.c index 25b797ace4..77f3d3a12f 100644 --- a/runtime/klee-fp/log.c +++ b/runtime/klee-fp/log.c @@ -8,9 +8,10 @@ //===----------------------------------------------------------------------===*/ #include "fenv.h" -#include "klee_fenv.h" #include "math.h" +#include + #define LOG_CORNER_CASE(suffix, type, isnan_function) \ int log_corner_case_##suffix(type *x) { \ if (isinf(*x) || isnan_function(*x)) { \ diff --git a/runtime/klee-fp/klee_rint.c b/runtime/klee-fp/rint.c similarity index 62% rename from runtime/klee-fp/klee_rint.c rename to runtime/klee-fp/rint.c index 9dc7701991..a15096a01c 100644 --- a/runtime/klee-fp/klee_rint.c +++ b/runtime/klee-fp/rint.c @@ -1,4 +1,4 @@ -/*===-- klee_rint.c -------------------------------------------------------===// +/*===-- rint.c ------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===*/ -#include "klee_rint.h" +#include "rint.h" #include "klee/klee.h" -float klee_internal_rintf(float arg) { return klee_rintf(arg); } +float rintf(float arg) { return klee_rintf(arg); } -double klee_internal_rint(double arg) { return klee_rint(arg); } +double rint(double arg) { return klee_rint(arg); } -long double klee_internal_rintl(long double arg) { return klee_rintl(arg); } +long double rintl(long double arg) { return klee_rintl(arg); } float nearbyintf(float arg) { return klee_rintf(arg); } diff --git a/runtime/klee-fp/klee_rint.h b/runtime/klee-fp/rint.h similarity index 69% rename from runtime/klee-fp/klee_rint.h rename to runtime/klee-fp/rint.h index b1be763080..4fb35f4382 100644 --- a/runtime/klee-fp/klee_rint.h +++ b/runtime/klee-fp/rint.h @@ -1,4 +1,4 @@ -/*===-- klee_rint.h -------------------------------------------------------===// +/*===-- rint.h ------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -10,9 +10,9 @@ #ifndef KLEE_RINT_H #define KLEE_RINT_H -float klee_internal_rintf(float arg); -double klee_internal_rint(double arg); -long double klee_internal_rintl(long double arg); +float rintf(float arg); +double rint(double arg); +long double rintl(long double arg); float nearbyintf(float arg); double nearbyint(double arg); long double nearbyintl(long double arg); diff --git a/runtime/klee-fp/round.c b/runtime/klee-fp/round.c index 490cc4849e..d5a6ad9f51 100644 --- a/runtime/klee-fp/round.c +++ b/runtime/klee-fp/round.c @@ -9,6 +9,12 @@ #include "klee/klee.h" +float roundf(float x) { return klee_rintf(x); } + +double round(double x) { return klee_rint(x); } + +long double roundl(long double x) { return klee_rintl(x); } + long lroundf(float x) { return klee_rintf(x); } long lround(double x) { return klee_rint(x); } diff --git a/runtime/klee-fp/klee_signbit.ll b/runtime/klee-fp/signbit.ll similarity index 89% rename from runtime/klee-fp/klee_signbit.ll rename to runtime/klee-fp/signbit.ll index a7c504f856..8ee4768ed9 100644 --- a/runtime/klee-fp/klee_signbit.ll +++ b/runtime/klee-fp/signbit.ll @@ -9,7 +9,7 @@ ;target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" ;target triple = "x86_64-unknown-linux-gnu" -define i32 @klee_internal_signbitf(float %f) #1 #0 { +define i32 @__signbitf(float %f) #1 #0 { entry: %0 = bitcast float %f to i32 %1 = icmp slt i32 %0, 0 @@ -17,7 +17,7 @@ entry: ret i32 %2 } -define i32 @klee_internal_signbit(double %d) #1 #0 { +define i32 @__signbit(double %d) #1 #0 { entry: %0 = bitcast double %d to i64 %1 = icmp slt i64 %0, 0 @@ -25,7 +25,7 @@ entry: ret i32 %2 } -define i32 @klee_internal_signbitl(x86_fp80 %d) #0 { +define i32 @__signbitl(x86_fp80 %d) #0 { entry: %0 = bitcast x86_fp80 %d to i80 %1 = icmp slt i80 %0, 0 diff --git a/runtime/klee-fp/sqrt.c b/runtime/klee-fp/sqrt.c index ba1b928340..26fbe2cc9f 100644 --- a/runtime/klee-fp/sqrt.c +++ b/runtime/klee-fp/sqrt.c @@ -8,12 +8,10 @@ //===----------------------------------------------------------------------===*/ #include "klee/klee.h" -double klee_internal_sqrt(double d) { return klee_sqrt_double(d); } +double sqrt(double d) { return klee_sqrt_double(d); } -float klee_internal_sqrtf(float f) { return klee_sqrt_float(f); } +float sqrtf(float f) { return klee_sqrt_float(f); } #if defined(__x86_64__) || defined(__i386__) -long double klee_internal_sqrtl(long double f) { - return klee_sqrt_long_double(f); -} +long double sqrtl(long double f) { return klee_sqrt_long_double(f); } #endif diff --git a/scripts/build/common-functions b/scripts/build/common-functions index c964419f60..65027f0bd3 100644 --- a/scripts/build/common-functions +++ b/scripts/build/common-functions @@ -8,11 +8,18 @@ function git_clone_or_update() { if [[ ! -e "${destination}/.git" ]]; then git clone $([ "${branch}x" != "x" ] && echo "--depth 1 -b ${branch}" || echo "") "$url" "$destination" else - cd "$destination" + pushd "$destination" git pull if [[ ! -z "$branch" ]]; then git checkout "${branch}" fi + popd + fi + + if [[ $# -ge 4 ]]; then + pushd "$destination" + git checkout $4 + popd fi } @@ -20,12 +27,12 @@ function get_git_hash() { local url="$1" local branch="$2" local commit_id="" - + # List remote git branches and get the commit id of the branch - commit_id="$(git ls-remote -h "$url" |grep "$branch" | cut -d$'\t' -f 1)" - + commit_id="$(git ls-remote -h "$url" | grep "$branch" | cut -d$'\t' -f 1)" + # If that doesn't work use the branch instead of the commit id - if [[ -z "${commit_id}" ]]; then + if [[ -z "${commit_id}" ]]; then echo "${branch}" else echo "${commit_id:0:7}" @@ -33,10 +40,10 @@ function get_git_hash() { } function with_sudo() { - echo "Checking sudo $@" - if [[ $(whoami) != "root" ]]; then - sudo "$@" - else - "$@" - fi -} \ No newline at end of file + echo "Checking sudo $@" + if [[ $(whoami) != "root" ]]; then + sudo "$@" + else + "$@" + fi +} diff --git a/scripts/build/p-bitwuzla-linux-ubuntu.inc b/scripts/build/p-bitwuzla-linux-ubuntu.inc new file mode 100644 index 0000000000..f36ab25d5e --- /dev/null +++ b/scripts/build/p-bitwuzla-linux-ubuntu.inc @@ -0,0 +1,25 @@ +# Build dependencies Bitwuzla +install_build_dependencies_bitwuzla() { + source "${DIR}/common-functions" + with_sudo apt update -y + + dependencies=( + build-essential + + ninja-build + python3 + python3-pip + cmake + git + ) + + #Install essential dependencies + with_sudo apt -y --no-install-recommends install "${dependencies[@]}" + + with_sudo apt-get update -y + with_sudo apt-get -y --no-install-recommends install pkg-config cmake-data m4 + + pip3 install --user meson + base_path="$(python3 -m site --user-base)" + export PATH="$PATH:${base_path}/bin" +} diff --git a/scripts/build/p-bitwuzla-osx.inc b/scripts/build/p-bitwuzla-osx.inc new file mode 100644 index 0000000000..27df98058e --- /dev/null +++ b/scripts/build/p-bitwuzla-osx.inc @@ -0,0 +1,14 @@ +install_build_dependencies_bitwuzla() { + dependencies=( + ninja + python3 + python3-pip + cmake + git + pkg-config + ) + brew install "${dependencies[@]}" + pip3 install --user meson + base_path="$(python3 -m site --user-base)" + export PATH="$PATH:${base_path}/bin" +} diff --git a/scripts/build/p-bitwuzla.inc b/scripts/build/p-bitwuzla.inc new file mode 100644 index 0000000000..bce4406e33 --- /dev/null +++ b/scripts/build/p-bitwuzla.inc @@ -0,0 +1,57 @@ +# Build scripts for Bitwuzla +# Variables that any artifact of this package might depend on +setup_build_variables_bitwuzla() { + BITWUZLA_BUILD_PATH="${BASE}/bitwuzla-${BITWUZLA_VERSION}-build" + BITWUZLA_INSTALL_PATH="${BASE}/bitwuzla-${BITWUZLA_VERSION}-install" + bitwuzla_url="https://github.com/bitwuzla/bitwuzla.git" + + return 0 +} + +download_bitwuzla() { + source "${DIR}/common-functions" + # Download Bitwuzla + git_clone_or_update "${bitwuzla_url}" "${BASE}/bitwuzla-${BITWUZLA_VERSION}" "${BITWUZLA_VERSION}" "${BITWUZLA_COMMIT}" +} + +build_bitwuzla() { + pushd "${BASE}/bitwuzla-${BITWUZLA_VERSION}" + ./configure.py --build-dir "${BITWUZLA_BUILD_PATH}" --prefix "${BITWUZLA_INSTALL_PATH}" --no-assertions --static --no-unit-testing release + popd + cd "${BITWUZLA_BUILD_PATH}" || return 1 + yes n | ninja install + touch "${BITWUZLA_INSTALL_PATH}/.bitwuzla_installed" +} + +install_bitwuzla() { + return 0 +} + +# Check if the binary artifact is installed +is_installed_bitwuzla() { + ( + setup_build_variables_bitwuzla + [[ -f "${BITWUZLA_INSTALL_PATH}/.bitwuzla_installed" ]] + ) || return 1 +} + +setup_artifact_variables_bitwuzla() { + setup_build_variables_bitwuzla +} + +get_build_artifacts_bitwuzla() { + ( + setup_build_variables_bitwuzla + echo "${BITWUZLA_INSTALL_PATH}" + ) +} + +get_docker_config_id_bitwuzla() { + ( + source "${DIR}/common-functions" + setup_build_variables_bitwuzla + + biwuzla_remote_commit="$(get_git_hash "${bitwuzla_url}" "${BITWUZLA_VERSION}")" + echo "${biwuzla_remote_commit}" + ) +} diff --git a/scripts/build/p-klee-linux-ubuntu.inc b/scripts/build/p-klee-linux-ubuntu.inc index 8bf39a199b..a67a061615 100644 --- a/scripts/build/p-klee-linux-ubuntu.inc +++ b/scripts/build/p-klee-linux-ubuntu.inc @@ -10,6 +10,8 @@ install_build_dependencies_klee() { python3-setuptools python3-pip python3-wheel + pkg-config + cmake-data ) if [[ "${SOLVERS:-}" == "metaSMT" ]]; then diff --git a/scripts/build/p-klee-osx.inc b/scripts/build/p-klee-osx.inc index 0561e28f68..4f5b063599 100644 --- a/scripts/build/p-klee-osx.inc +++ b/scripts/build/p-klee-osx.inc @@ -9,6 +9,7 @@ install_build_dependencies_klee() { pip3 install --user --upgrade lit tabulate + brew install pkg-config # Get path of package location base_path=$(python3 -m site --user-base) export PATH="${base_path}/bin:$PATH" diff --git a/scripts/build/p-klee.inc b/scripts/build/p-klee.inc index 248d3a9bb7..b484cc9281 100644 --- a/scripts/build/p-klee.inc +++ b/scripts/build/p-klee.inc @@ -67,6 +67,7 @@ fi local KLEE_Z3_CONFIGURE_OPTION=("-DENABLE_SOLVER_Z3=OFF") local KLEE_STP_CONFIGURE_OPTION=("-DENABLE_SOLVER_STP=OFF") local KLEE_METASMT_CONFIGURE_OPTION=("-DENABLE_SOLVER_METASMT=OFF") + local KLEE_BITWUZLA_CONFIGURE_OPTION=("-DENABLE_SOLVER_BITWUZLA=OFF") KLEE_FLOATING_POINT=( "-DENABLE_FLOATING_POINT=FALSE" "-DENABLE_FP_RUNTIME=FALSE" @@ -106,6 +107,18 @@ fi "-DMETASMT_DEFAULT_BACKEND=${METASMT_DEFAULT}" ) ;; + bitwuzla) + KLEE_BITWUZLA_CONFIGURE_OPTION=( + "-DENABLE_SOLVER_BITWUZLA=TRUE" + ) + + CMAKE_PREFIX_PATH+=("${BITWUZLA_INSTALL_PATH}") + KLEE_FLOATING_POINT=( + "-DENABLE_FLOATING_POINT=TRUE" + "-DENABLE_FP_RUNTIME=TRUE" + ) + echo "bitwuzla" + ;; *) echo "Unknown solver ${solver}" exit 1 @@ -116,6 +129,7 @@ fi "${KLEE_Z3_CONFIGURE_OPTION[@]}" "${KLEE_STP_CONFIGURE_OPTION[@]}" "${KLEE_METASMT_CONFIGURE_OPTION[@]}" + "${KLEE_BITWUZLA_CONFIGURE_OPTION[@]}" "${KLEE_FLOATING_POINT[@]}" ) diff --git a/scripts/build/p-uclibc.inc b/scripts/build/p-uclibc.inc index 95af975137..f7cce95f2d 100644 --- a/scripts/build/p-uclibc.inc +++ b/scripts/build/p-uclibc.inc @@ -6,11 +6,18 @@ setup_build_variables_uclibc() { download_uclibc() { source "${DIR}/common-functions" - git_clone_or_update "${uclibc_url}" "${UCLIBC_PATH}" "${UCLIBC_VERSION}" + git_clone_or_update "${uclibc_url}" "${UCLIBC_PATH}-32" "${UCLIBC_VERSION}" + git_clone_or_update "${uclibc_url}" "${UCLIBC_PATH}-64" "${UCLIBC_VERSION}" } build_uclibc() { - cd "${UCLIBC_PATH}" || return 1 + pushd "${UCLIBC_PATH}-32" || return 1 + ./configure --make-llvm-lib --with-cc "${BITCODE_CC}" --with-llvm-config "${LLVM_CONFIG}" + make KLEE_CFLAGS="-m32" || return 1 + touch .is_installed + popd &>/dev/null + + pushd "${UCLIBC_PATH}-64" || return 1 ./configure --make-llvm-lib --with-cc "${BITCODE_CC}" --with-llvm-config "${LLVM_CONFIG}" make || return 1 touch .is_installed @@ -24,7 +31,11 @@ install_uclibc() { is_installed_uclibc() { ( setup_build_variables_uclibc - [[ -f "${UCLIBC_PATH}"/.is_installed ]] + [[ -f "${UCLIBC_PATH}-32"/.is_installed ]] + ) || return 1 + ( + setup_build_variables_uclibc + [[ -f "${UCLIBC_PATH}-64"/.is_installed ]] ) || return 1 } @@ -40,7 +51,8 @@ get_docker_config_id_uclibc() { get_build_artifacts_uclibc() { ( setup_build_variables_uclibc - echo "${UCLIBC_PATH}" + echo "${UCLIBC_PATH}-32" + echo "${UCLIBC_PATH}-64" ) } diff --git a/scripts/build/v-bitwuzla.inc b/scripts/build/v-bitwuzla.inc new file mode 100644 index 0000000000..7dd553d614 --- /dev/null +++ b/scripts/build/v-bitwuzla.inc @@ -0,0 +1,11 @@ +# Build information for Bitwuzla solver +required_variables_bitwuzla=( + "BITWUZLA_VERSION" + "BITWUZLA_COMMIT" +) + +artifact_dependency_bitwuzla=("") + +install_build_dependencies_bitwuzla() { + return 0 +} diff --git a/scripts/build/v-solvers.inc b/scripts/build/v-solvers.inc index 9d6bfdc857..74cdac1f5a 100644 --- a/scripts/build/v-solvers.inc +++ b/scripts/build/v-solvers.inc @@ -15,7 +15,8 @@ required_variables_check_solvers() { [[ "${solver}" == "z3" ]] && continue [[ "${solver}" == "stp" ]] && continue [[ "${solver}" == "metasmt" ]] && continue - + [[ "${solver}" == "bitwuzla" ]] && continue + echo "Unknown solver: \"$solver\"" exit 1 done @@ -51,7 +52,7 @@ setup_variables_solvers() { [[ "${solver}" == "z3" ]] && SELECTED_SOLVERS+=("z3") && continue [[ "${solver}" == "stp" ]] && SELECTED_SOLVERS+=("stp") && continue [[ "${solver}" == "metasmt" ]] && SELECTED_SOLVERS+=("metasmt") && continue - + [[ "${solver}" == "bitwuzla" ]] && SELECTED_SOLVERS+=("bitwuzla") && continue echo "Unknown solver: \"$solver\"" exit 1 done diff --git a/scripts/kleef b/scripts/kleef new file mode 100755 index 0000000000..1a41403e6d --- /dev/null +++ b/scripts/kleef @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +import argparse +import os +import subprocess +import shutil +import tempfile +import hashlib +from functools import partial +from pathlib import Path + + +def klee_options( + max_memory, + test_output_dir, + source, + hexhash, + max_time, + compiled_file, + is32, + f_err, + f_cov, + write_ktests, +): + if max_time and int(max_time) > 30: + MAX_SOLVER_TIME = 15 + else: + MAX_SOLVER_TIME = 10 + cmd = [ + "--strip-unwanted-calls", # removes llvm.dbg.* instructions, exponentially reduces time on some benchmarks + "--delete-dead-loops=false", # without this optimizer removes some code, which decreases coverage + "--emit-all-errors", # without this we generate only one test for assertion failures, which decreases coverage + "--mock-all-externals", # this helps for some linux benchmarks, which have unused extern globals. without this flag we will not even start on them. + "--external-calls=all", + "--optimize=true", + "--use-forked-solver=false", + # "--solver-backend=stp", + # "--solver-backend=z3-tree", + "--solver-backend=bitwuzla-tree", + "--max-solvers-approx-tree-inc=16", + f"--max-memory={int(max_memory * 0.9)}", # Just use half of the memory in case we have to fork + "--libc=klee", + "--skip-not-lazy-initialized", + f"--output-dir={test_output_dir}", # Output files into specific directory + "--output-source=false", # Do not output assembly.ll - it can be too large + "--output-stats=false", + "--output-istats=false", + # "--istats-write-interval=90s", # Istats file can be large as well + "--write-xml-tests", # Write tests in XML format + f"--write-ktests={write_ktests}", # Write tests in KTest format + f"--xml-metadata-programfile={source.name}", # Provide the name of the original source file + f"--xml-metadata-programhash={hexhash}", # Provide sha256 hash of source file + # "--use-guided-search=none", + "--use-sym-size-alloc=true", + "--cex-cache-validity-cores", + # "--libc=uclibc", + # "--posix-runtime", + "--fp-runtime", + # "--max-sym-array-size=4096", + "--symbolic-allocation-threshold=8192", + "--uninit-memory-test-multiplier=10", + # "--dump-all-states=false", + # "--search=nurs:covnew", + # "--search=nurs:md2u", "--search=random-path", + # "-const-array-opt", + ] + + if is32: + cmd += [ + "--allocate-determ", + f"--allocate-determ-size={min(int(max_memory * 0.6), 3 * 1024)}", + "--allocate-determ-start-address=0x00030000000", + "--x86FP-as-x87FP80", + ] + + if f_err: + cmd += [ + "--use-alpha-equivalence=true", + "--function-call-reproduce=reach_error", + # "--max-cycles=0", + # "--tc-type=bug", + "--dump-states-on-halt=unreached", # Explicitly do not dump states + "--exit-on-error-type=Assert", # Only generate test cases of type assert + # "--dump-test-case-type=Assert", # Only dump test cases of type assert + "--search=dfs", + "--search=bfs", + # "--search=nurs:covnew", "--search=random-path","--search=dfs", "--use-batching-search", + # "--search=distance","--search=random-path","--use-batching-search", + # "--target-assert", # Target + ] + if max_time: + max_time = float(max_time) + if max_time and int(max_time) > 30: + max_time = int(max_time * 0.99) + else: + max_time = int(max_time * 0.9) + cmd += [ + f"--max-time={max_time}", + ] + + if f_cov: + cmd += [ + "--mem-trigger-cof", # Start on the fly tests generation after approaching memory cup + "--use-alpha-equivalence=true", + "--optimize-aggressive=false", + "--track-coverage=all", # Only branches and only instructions are wrong in real life. E.g., ternary operators are sometimes counted as different branches, while we stick to look at them as a single instruction from a single branch + "--use-iterative-deepening-search=max-cycles", + f"--max-solver-time={MAX_SOLVER_TIME}s", + "--max-cycles-before-stuck=15", + # "--tc-type=cov", + "--only-output-states-covering-new", # Don't generate all test cases + "--dump-states-on-halt=all", # Check in case we missed some oncovered instructions + "--search=dfs", + "--search=random-state", + ] + if max_time: + max_time = float(max_time) + if max_time and int(max_time) > 30: + late_time = int(max_time * 0.9) + last_time = int(max_time * 0.97) + else: + late_time = int(max_time * 0.8) + last_time = int(max_time * 0.9) + cmd += [ + "--cover-on-the-fly=true", + f"--delay-cover-on-the-fly={late_time}", + f"--max-time={last_time}", + ] + + cmd += [compiled_file] # Finally add the file to be tested + return cmd + + +def normalize_command(cmd, shell=False): + if shell: + out = cmd + else: + cmd2 = [x.as_posix() if isinstance(x, Path) else x for x in cmd] + out = " ".join(cmd2) + print("Running:", out) + return out + + +def check_call(cmd, shell=False): + normalize_command(cmd, shell) + subprocess.check_call(cmd, shell=shell) + # p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + # p.communicate() + # print(p.returncode) + + +def locateBinaryOrFail(binary, err_mess=""): + output = shutil.which(binary) + if output is not None: + return Path(output) + print(f"Command '{binary}' not found{err_mess}") + exit(1) + + +def tryFind(folder, binary): + output = folder / binary + if output.exists(): + return output + return locateBinaryOrFail(binary) + + +def printNotNone(s): + if s is not None: + print(s.decode("utf-8")) + + +class KLEEF(object): + """ + Wrapper to run KLEEF within BenchExec + Compiles source and executes KLEEF + """ + + def __init__( + self, + source=None, + is32=False, + f_cov=False, + f_err=False, + max_memory=0, + max_time=0, + use_perf=False, + use_valgrind=False, + write_ktests=False, + ): + self.source = Path(source) if source else None + self.is32 = is32 + self.tempdir = None + self.compiled_file = None + self.f_cov = f_cov + self.f_err = f_err + self.max_memory = max_memory / 1024 / 1024 # Convert to MB + self.max_time = max_time + self.use_perf = use_perf + self.use_valgrind = use_valgrind + if write_ktests: + self.write_ktests = "true" + else: + self.write_ktests = "false" + + # This file is inside the bin directory - use the root as base + self.bin_directory = Path(__file__).parent + self.base_directory = self.bin_directory.parent + self.klee_path = self.bin_directory / "klee" + self.compiler_path = tryFind(self.bin_directory, "clang") + self.linker_path = tryFind(self.bin_directory, "llvm-link") + self.library_path = self.base_directory / "libraries" + self.runtime_library_path = self.base_directory / "runtime/lib" + self.test_results_path = Path.cwd() / "test-suite" + self.test_results_path.mkdir(exist_ok=True) + + self.callEnv = os.environ.copy() + self.callEnv["LD_LIBRARY_PATH"] = self.library_path + self.callEnv["KLEE_RUNTIME_LIBRARY_PATH"] = self.runtime_library_path + + def compile(self): + self.tempdir = Path(tempfile.mkdtemp()) + + # Compile file for testing + self.compiled_file = self.tempdir / (self.source.name + ".bc") + + compiler_options = [ + self.compiler_path, + "-O0", + "-Xclang", + "-disable-O0-optnone", + "-fbracket-depth=1024", + "-c", + "-g", + "-emit-llvm", + ] + if self.is32: + compiler_options += ["-m32"] + if self.use_perf: + compiler_options += ["-gdwarf-4"] + cmd = compiler_options + [ + "-Wno-everything", # do not print any error statements - we are not allowed to change the code + "-fno-default-inline", + "-o", + self.compiled_file, + self.source, + ] + check_call(cmd) + + # Compile library + compiled_library = self.tempdir / "library.bc" + include_path = self.base_directory / "include/klee-test-comp.c" + cmd = compiler_options + [ + "-o", + compiled_library, + include_path, + ] + check_call(cmd) + + # Link both together to final + cmd = [ + self.linker_path, + "-o", + self.compiled_file, + compiled_library, + self.compiled_file, + ] + check_call(cmd) + + def isModifyingUlimitPermitted(self): + out = subprocess.run( + "ulimit -s unlimited", + shell=True, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ).returncode + return not out + + def run(self): + test_output_dir = self.test_results_path / self.source.name + test_output_dir = self.test_results_path + # Clean-up from previous runs if needed + shutil.rmtree(test_output_dir, ignore_errors=True) + + # Calculate hashsum of original source file + with open(self.source, mode="rb") as f: + h = hashlib.sha256() + for buf in iter(partial(f.read, 128), b""): + h.update(buf) + + cmd = [self.klee_path] + if self.use_perf: + cmd = ["perf", "record", "-g", "--call-graph", "dwarf"] + cmd + elif self.use_valgrind: + cmd = ["valgrind", "--tool=massif"] + cmd + + # Add common arguments + cmd += klee_options( + self.max_memory, + test_output_dir, + self.source, + h.hexdigest(), + self.max_time, + self.compiled_file, + self.is32, + self.f_err, + self.f_cov, + self.write_ktests, + ) + if self.isModifyingUlimitPermitted(): + cmd = ["ulimit -s unlimited", "&&"] + cmd + cmd = normalize_command(cmd) + + p = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=True, + env=self.callEnv, + ) + s_out, s_err = p.communicate() + if not self.use_perf: + printNotNone(s_out) + printNotNone(s_err) + + if self.use_perf: + cmd = "perf script | c++filt | gprof2dot -f perf -s | dot -Tpdf -o output.pdf" + check_call(cmd, shell=True) + + return test_output_dir + + def version(self): + cmd = [self.klee_path, "--version"] + p = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=self.callEnv, + ) + s_out, s_err = p.communicate() + printNotNone(s_out) + + +def run(args): + if args.version: + wrapper = KLEEF() + wrapper.version() + exit(0) + + # Validation of arguments + if not args.source or not os.path.isfile(args.source): + print("File does not exist", args.source) + exit(1) + + if args.property_file: + with open(args.property_file, "r") as f: + for line in f: + if "@DECISIONEDGE" in line: + args.coverage_only = True + if "@CALL(reach_error)" in line: + args.error_only = True + # Generate wrapper + time = 0 + if args.max_cputime_soft: # Use soft timeout if available + time = args.max_cputime_soft + elif args.max_cputime_hard: + time = args.max_cputime_hard + elif args.max_walltime: + time = args.max_walltime + elif args.max_time: + time = args.max_time + + is32 = None + if vars(args).get("32"): + is32 = True + if vars(args).get("64"): + if is32: + print("Cannot set --64 and --32 simultanously") + exit(1) + is32 = False + + if is32 is None: + print("No architecture set. Assume 64bit") + is32 = False + optAndUsed = [ + (args.perf, "perf", ["perf", "c++filt", "gprof2dot", "dot"]), + (args.valgrind, "valgrind", ["valgrind"]), + ] + for opt, name, used_by_opt in optAndUsed: + if not opt: + continue + for tool in used_by_opt: + locateBinaryOrFail(tool, err_mess=f", so cannot run with option --{name}") + + if args.perf and args.valgrind: + print("Cannot use perf and valgrind at the same time") + exit(1) + wrapper = KLEEF( + source=args.source, + is32=is32, + f_cov=args.coverage_only, + f_err=args.error_only, + max_memory=args.max_memory, + max_time=time, + use_perf=args.perf, + use_valgrind=args.valgrind, + write_ktests=args.write_ktests, + ) + wrapper.compile() + return wrapper.run() + + +def main(): + # Initialize argparse + parser = argparse.ArgumentParser(description="KLEEF single-file runner") + parser.add_argument( + "source", help="klee-out directory to parse", nargs="?", default=None + ) + parser.add_argument("--version", help="print version of klee", action="store_true") + parser.add_argument("--32", help="Compile 32bit binaries", action="store_true") + parser.add_argument("--64", help="Compile 64bit binaries", action="store_true") + parser.add_argument( + "--error-only", help="Focus on searching errors", action="store_true" + ) + parser.add_argument( + "--perf", help="Measure speed with perf", action="store_true", default=False + ) + parser.add_argument( + "--valgrind", + help="Measure memory with valgrind", + action="store_true", + default=False, + ) + parser.add_argument( + "--coverage-only", help="Focus on coverage", action="store_true" + ) + parser.add_argument( + "--max-memory", help="Maximum memory in byte ", type=int, default=2000 + ) + parser.add_argument("--max-time", help="Maximum time in s", type=int, default=0) + parser.add_argument( + "--max-walltime", help="Maximum walltime in s", type=int, default=0 + ) + parser.add_argument( + "--max-cputime-soft", help="Maximum cputime in s (soft)", type=int, default=0 + ) + parser.add_argument( + "--max-cputime-hard", help="Maximum cputime in s (hard)", type=int, default=0 + ) + parser.add_argument( + "--property-file", + help="Property file for test goal description", + type=str, + default=None, + ) + parser.add_argument( + "--write-ktests", help="Write tests in KTest format", action="store_true" + ) + args = parser.parse_args() + run(args) + + +if __name__ == "__main__": + main() diff --git a/scripts/replay.sh b/scripts/replay.sh new file mode 100755 index 0000000000..2673c91e4a --- /dev/null +++ b/scripts/replay.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# ===-- replay.sh --------------------------------------------------------===## +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +# ===----------------------------------------------------------------------===## + +for f in `find $1 -name "*.ktest" -type f`; do + KLEE_RUN_TEST_ERRORS_NON_FATAL=STOP KTEST_FILE=$f timeout 1 $2 +done diff --git a/test/CXX/symex/libc++/can_catch_test.cpp b/test/CXX/symex/libc++/can_catch_test.cpp index c70d14a2aa..7515ef33d8 100644 --- a/test/CXX/symex/libc++/can_catch_test.cpp +++ b/test/CXX/symex/libc++/can_catch_test.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // REQUIRES: uclibc // REQUIRES: libcxx // REQUIRES: eh-cxx diff --git a/test/CXX/symex/libc++/exception_inheritance.cpp b/test/CXX/symex/libc++/exception_inheritance.cpp index ca207eb4be..e24be60da2 100644 --- a/test/CXX/symex/libc++/exception_inheritance.cpp +++ b/test/CXX/symex/libc++/exception_inheritance.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // REQUIRES: uclibc // REQUIRES: libcxx // REQUIRES: eh-cxx diff --git a/test/CXX/symex/libc++/landingpad.cpp b/test/CXX/symex/libc++/landingpad.cpp index 13dd6bc47a..6e8b13bcd6 100644 --- a/test/CXX/symex/libc++/landingpad.cpp +++ b/test/CXX/symex/libc++/landingpad.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // Testcase for proper handling of // c++ type, constructors and destructors. // Based on: https://gcc.gnu.org/wiki/Dwarf2EHNewbiesHowto diff --git a/test/CXX/symex/libc++/rethrow.cpp b/test/CXX/symex/libc++/rethrow.cpp index 149fe693d5..febdf0b3e9 100644 --- a/test/CXX/symex/libc++/rethrow.cpp +++ b/test/CXX/symex/libc++/rethrow.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // REQUIRES: uclibc // REQUIRES: libcxx // REQUIRES: eh-cxx diff --git a/test/CXX/symex/libc++/throw_specifiers.cpp b/test/CXX/symex/libc++/throw_specifiers.cpp index 96195cd498..6eae7f3abd 100644 --- a/test/CXX/symex/libc++/throw_specifiers.cpp +++ b/test/CXX/symex/libc++/throw_specifiers.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // Testcase for proper handling of // throw specifications on functions // REQUIRES: uclibc diff --git a/test/CXX/symex/libc++/throwing_exception_destructor.cpp b/test/CXX/symex/libc++/throwing_exception_destructor.cpp index 02d7cdb920..f1e0e5d447 100644 --- a/test/CXX/symex/libc++/throwing_exception_destructor.cpp +++ b/test/CXX/symex/libc++/throwing_exception_destructor.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // Testcase for proper handling of exception destructors that throw. // REQUIRES: uclibc // REQUIRES: libcxx diff --git a/test/Expr/Evaluate.kquery b/test/Expr/Evaluate.kquery index 6738c872eb..b2fc41d746 100644 --- a/test/Expr/Evaluate.kquery +++ b/test/Expr/Evaluate.kquery @@ -1,4 +1,4 @@ -# RUN: %kleaver -evaluate %s > %t.log +# RUN: %kleaver -evaluate --use-concretizing-solver=false %s > %t.log arr01 : (array (w64 4) (makeSymbolic arr0 0)) arr12 : (array (w64 8) (makeSymbolic arr1 0)) @@ -17,7 +17,7 @@ arr12 : (array (w64 8) (makeSymbolic arr1 0)) # RUN: grep "Query 2: VALID" %t.log # Query 2 -constant0 : (array (w64 4) (constant [ 1 2 3 5 ])) +constant0 : (array (w64 4) (constant [1, 2, 3, 5] default: 0)) (query [] (Eq (Add w8 (Read w8 0 constant0) (Read w8 3 constant0)) 6)) diff --git a/test/Expr/print-smt-let.kquery b/test/Expr/print-smt-let.kquery index 871e6e4f29..974112a37c 100644 --- a/test/Expr/print-smt-let.kquery +++ b/test/Expr/print-smt-let.kquery @@ -1069,7 +1069,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) [makeSymbolic0]) # Query 72 -- Type: InitialValues, Instructions: 30 -constant2 : (array (w64 4) (constant [121 101 115 0])) +constant2 : (array (w64 4) (constant [121, 101, 115, 0] default: 0)) makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) (query [(Eq false @@ -1105,7 +1105,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) # Query 74 -- Type: InitialValues, Instructions: 37 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1128,7 +1128,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 75 -- Type: InitialValues, Instructions: 40 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) 13)] @@ -1141,7 +1141,7 @@ constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) # Query 76 -- Type: InitialValues, Instructions: 50 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1160,7 +1160,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 77 -- Type: InitialValues, Instructions: 51 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) diff --git a/test/Expr/print-smt-let.smt2.good b/test/Expr/print-smt-let.smt2.good index d0ce68b168..05ea45d94e 100644 --- a/test/Expr/print-smt-let.smt2.good +++ b/test/Expr/print-smt-let.smt2.good @@ -859,19 +859,19 @@ ;SMTLIBv2 Query 72 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant1 (_ bv0 32) ) (_ bv121 8) ) ) -(assert (= (select constant1 (_ bv1 32) ) (_ bv101 8) ) ) -(assert (= (select constant1 (_ bv2 32) ) (_ bv115 8) ) ) -(assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31312 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant0 (_ bv0 32) ) (_ bv121 8) ) ) +(assert (= (select constant0 (_ bv1 32) ) (_ bv101 8) ) ) +(assert (= (select constant0 (_ bv2 32) ) (_ bv115 8) ) ) +(assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31312 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant0 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant0 (bvadd (_ bv1 32) ?B3 ) ) (select constant0 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -882,69 +882,69 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533360 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (not (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic2 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic2 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533360 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (not (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic1 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic1 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 74 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant3 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant3 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533328 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant3 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant3 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant3 (bvadd (_ bv1 32) ?B3 ) ) (select constant3 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533328 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 75 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant4 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant4 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant4 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant4 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant4 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant4 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 ((_ extract 31 0) ?B1 ) ) ) (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant4 (bvadd (_ bv3 32) ?B2 ) ) (concat (select constant4 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant4 (bvadd (_ bv1 32) ?B2 ) ) (select constant4 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 ((_ extract 31 0) ?B1 ) ) ) (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ?B2 ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B2 ) ) (select constant2 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -954,53 +954,53 @@ ;SMTLIBv2 Query 76 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant5 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant5 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv111120 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant5 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant5 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant5 (bvadd (_ bv1 32) ?B3 ) ) (select constant5 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv111120 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 77 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant6 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant6 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant6 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant6 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant6 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant6 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31760 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant6 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant6 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant6 (bvadd (_ bv1 32) ?B3 ) ) (select constant6 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31760 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B3 ) ) (select constant2 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -1011,15 +1011,15 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709532800 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709532800 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) diff --git a/test/Expr/print-smt-named.kquery b/test/Expr/print-smt-named.kquery index 5e0112b2b7..78bbbd4ef1 100644 --- a/test/Expr/print-smt-named.kquery +++ b/test/Expr/print-smt-named.kquery @@ -1068,7 +1068,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) [makeSymbolic0]) # Query 72 -- Type: InitialValues, Instructions: 30 -constant2 : (array (w64 4) (constant [121 101 115 0])) +constant2 : (array (w64 4) (constant [121, 101, 115, 0] default: 0)) makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) (query [(Eq false @@ -1104,7 +1104,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) # Query 74 -- Type: InitialValues, Instructions: 37 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1127,7 +1127,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 75 -- Type: InitialValues, Instructions: 40 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) 13)] @@ -1140,7 +1140,7 @@ constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) # Query 76 -- Type: InitialValues, Instructions: 50 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1159,7 +1159,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 77 -- Type: InitialValues, Instructions: 51 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) diff --git a/test/Expr/print-smt-named.smt2.good b/test/Expr/print-smt-named.smt2.good index 455fbc0dfd..fd7e2061ee 100644 --- a/test/Expr/print-smt-named.smt2.good +++ b/test/Expr/print-smt-named.smt2.good @@ -859,19 +859,19 @@ ;SMTLIBv2 Query 72 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant1 (_ bv0 32) ) (_ bv121 8) ) ) -(assert (= (select constant1 (_ bv1 32) ) (_ bv101 8) ) ) -(assert (= (select constant1 (_ bv2 32) ) (_ bv115 8) ) ) -(assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31312 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant0 (_ bv0 32) ) (_ bv121 8) ) ) +(assert (= (select constant0 (_ bv1 32) ) (_ bv101 8) ) ) +(assert (= (select constant0 (_ bv2 32) ) (_ bv115 8) ) ) +(assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant0 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31312 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant0 (bvadd (_ bv1 32) ?B3 ) ) (select constant0 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -882,69 +882,69 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (not (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533360 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic2 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic2 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (not (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533360 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic1 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic1 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 74 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant3 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant3 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant3 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533328 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant3 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant3 (bvadd (_ bv1 32) ?B3 ) ) (select constant3 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533328 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 75 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant4 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant4 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant4 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant4 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant4 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant4 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant4 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) ) (concat (select constant4 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant4 (bvadd (_ bv1 32) ?B2 ) ) (select constant4 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B2 ) ) (select constant2 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -954,53 +954,53 @@ ;SMTLIBv2 Query 76 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant5 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant5 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant5 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv111120 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant5 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant5 (bvadd (_ bv1 32) ?B3 ) ) (select constant5 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv111120 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 77 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant6 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant6 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant6 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant6 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant6 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant6 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant6 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31760 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant6 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant6 (bvadd (_ bv1 32) ?B3 ) ) (select constant6 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31760 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B3 ) ) (select constant2 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -1011,15 +1011,15 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709532800 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709532800 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) diff --git a/test/Expr/print-smt-none.kquery b/test/Expr/print-smt-none.kquery index 90c0bce0e7..9b002c3862 100644 --- a/test/Expr/print-smt-none.kquery +++ b/test/Expr/print-smt-none.kquery @@ -1068,7 +1068,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) [makeSymbolic0]) # Query 72 -- Type: InitialValues, Instructions: 30 -constant2 : (array (w64 4) (constant [121 101 115 0])) +constant2 : (array (w64 4) (constant [121, 101, 115, 0] default: 0)) makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) (query [(Eq false @@ -1104,7 +1104,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) # Query 74 -- Type: InitialValues, Instructions: 37 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1127,7 +1127,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 75 -- Type: InitialValues, Instructions: 40 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) 13)] @@ -1140,7 +1140,7 @@ constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) # Query 76 -- Type: InitialValues, Instructions: 50 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1159,7 +1159,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 77 -- Type: InitialValues, Instructions: 51 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) diff --git a/test/Expr/print-smt-none.smt2.good b/test/Expr/print-smt-none.smt2.good index 3a4d2e0ce6..1fe23264f3 100644 --- a/test/Expr/print-smt-none.smt2.good +++ b/test/Expr/print-smt-none.smt2.good @@ -859,19 +859,19 @@ ;SMTLIBv2 Query 72 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant1 (_ bv0 32) ) (_ bv121 8) ) ) -(assert (= (select constant1 (_ bv1 32) ) (_ bv101 8) ) ) -(assert (= (select constant1 (_ bv2 32) ) (_ bv115 8) ) ) -(assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant1 ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant0 (_ bv0 32) ) (_ bv121 8) ) ) +(assert (= (select constant0 (_ bv1 32) ) (_ bv101 8) ) ) +(assert (= (select constant0 (_ bv2 32) ) (_ bv115 8) ) ) +(assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant0 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant0 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant0 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant0 ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -882,69 +882,69 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (not (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic2 ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (not (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic1 ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 74 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant3 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant3 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant3 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant3 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant3 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant3 ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant1 ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 75 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant4 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant4 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant4 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant4 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant4 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant4 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant4 (bvadd (_ bv3 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant4 (bvadd (_ bv2 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant4 (bvadd (_ bv1 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (select constant4 ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv2 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv1 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (select constant2 ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -954,53 +954,53 @@ ;SMTLIBv2 Query 76 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant5 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant5 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant5 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant5 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant5 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant5 ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant1 ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 77 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant6 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant6 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant6 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant6 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant6 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant6 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant6 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant6 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant6 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant6 ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant2 ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -1011,15 +1011,15 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic0 ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic0 ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) diff --git a/test/Feature/CoverOnTheFly.c b/test/Feature/CoverOnTheFly.c new file mode 100644 index 0000000000..73bd550f2c --- /dev/null +++ b/test/Feature/CoverOnTheFly.c @@ -0,0 +1,33 @@ +// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=none +// REQUIRES: not-asan +// RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --only-output-states-covering-new --max-instructions=2000 --timer-interval=1ms --delay-cover-on-the-fly=1ms --dump-states-on-halt=none --cover-on-the-fly --search=bfs --use-guided-search=none --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s + +#include "klee/klee.h" + +int main() { + int res = 0; + for (;;) { + int n = klee_int("n"); + switch (n) { + case 1: + res += 1; + break; + case 2: + res += 2; + break; + case 3: + res += 3; + break; + case 4: + res += 4; + break; + + default: + break; + } + } +} + +// CHECK-NOT: KLEE: done: generated tests = 0 diff --git a/test/Feature/CoverageCheck.c b/test/Feature/CoverageCheck.c index 4800010350..a9c9eb2b63 100644 --- a/test/Feature/CoverageCheck.c +++ b/test/Feature/CoverageCheck.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --use-cov-check=instruction-based --output-dir=%t.klee-out %t.bc > %t.log +// RUN: %klee --use-guided-search=none --use-cov-check=instruction-based --output-dir=%t.klee-out %t.bc > %t.log #include "klee/klee.h" #define a (2) diff --git a/test/Feature/DanglingConcreteReadExpr.c b/test/Feature/DanglingConcreteReadExpr.c index 4f4dd6cc23..1f8a5a347a 100644 --- a/test/Feature/DanglingConcreteReadExpr.c +++ b/test/Feature/DanglingConcreteReadExpr.c @@ -1,7 +1,7 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --optimize=false --output-dir=%t.klee-out %t1.bc -// RUN: grep "total queries = 2" %t.klee-out/info +// RUN: grep "total queries = 1" %t.klee-out/info #include @@ -12,7 +12,7 @@ int main() { y = x; - // should be exactly two queries (prove x is/is not 10) + // should be exactly one query (prove x is 10) // eventually should be 0 when we have fast solver if (x == 10) { assert(y == 10); diff --git a/test/Feature/DumpStatesOnHalt.c b/test/Feature/DumpStatesOnHalt.c index aca8d7c810..9bda0cb83a 100644 --- a/test/Feature/DumpStatesOnHalt.c +++ b/test/Feature/DumpStatesOnHalt.c @@ -1,6 +1,6 @@ // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --max-instructions=1 --dump-states-on-halt=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --max-instructions=1 --dump-states-on-halt=all %t1.bc 2>&1 | FileCheck %s // RUN: test -f %t.klee-out/test000001.ktest int main(int argc, char **argv) { diff --git a/test/Feature/ExprLogging.c b/test/Feature/ExprLogging.c index 8109647a57..ca8d7a7913 100644 --- a/test/Feature/ExprLogging.c +++ b/test/Feature/ExprLogging.c @@ -1,7 +1,7 @@ // RUN: %clang %s -emit-llvm -g %O0opt -c -o %t1.bc // We disable the cex-cache to eliminate nondeterminism across different solvers, in particular when counting the number of queries in the last two commands // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-cex-cache=false --use-query-log=all:kquery,all:smt2,solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log +// RUN: %klee --output-dir=%t.klee-out --use-cex-cache=false --use-alpha-equivalence=false --use-query-log=all:kquery,all:smt2,solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log // RUN: %kleaver -print-ast %t.klee-out/all-queries.kquery > %t3.log // RUN: %kleaver -print-ast %t3.log > %t4.log // RUN: diff %t3.log %t4.log diff --git a/test/Feature/LazyInitialization/DerefSymbolicPointer.c b/test/Feature/LazyInitialization/DerefSymbolicPointer.c index 27fd4d1d42..b0919d56a3 100644 --- a/test/Feature/LazyInitialization/DerefSymbolicPointer.c +++ b/test/Feature/LazyInitialization/DerefSymbolicPointer.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --write-kqueries --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects %t.bc > %t.log +// RUN: %klee --write-kqueries --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc > %t.log // RUN: FileCheck %s -input-file=%t.log #include "klee/klee.h" diff --git a/test/Feature/LazyInitialization/ImpossibleAddressForLI.c b/test/Feature/LazyInitialization/ImpossibleAddressForLI.c index abc643eb05..f0d9f25bf6 100644 --- a/test/Feature/LazyInitialization/ImpossibleAddressForLI.c +++ b/test/Feature/LazyInitialization/ImpossibleAddressForLI.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -g -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects %t.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" diff --git a/test/Feature/LazyInitialization/LazyInitialization.c b/test/Feature/LazyInitialization/LazyInitialization.c index 74356f31b3..31e82a124e 100644 --- a/test/Feature/LazyInitialization/LazyInitialization.c +++ b/test/Feature/LazyInitialization/LazyInitialization.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects --use-timestamps=false --use-guided-search=none %t.bc > %t.log +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects --use-timestamps=false --use-guided-search=none %t.bc > %t.log // RUN: FileCheck %s -input-file=%t.log struct Node { diff --git a/test/Feature/LazyInitialization/LinkedList.c b/test/Feature/LazyInitialization/LinkedList.c index 9431e4ffc3..191ce3103b 100644 --- a/test/Feature/LazyInitialization/LinkedList.c +++ b/test/Feature/LazyInitialization/LinkedList.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --write-kqueries --solver-backend=z3 --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc > %t.log +// RUN: %klee --write-kqueries --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc > %t.log // RUN: FileCheck %s -input-file=%t.log #include "klee/klee.h" diff --git a/test/Feature/LazyInitialization/PointerOffset.c b/test/Feature/LazyInitialization/PointerOffset.c index aaf3694e1c..2d0b7a4321 100644 --- a/test/Feature/LazyInitialization/PointerOffset.c +++ b/test/Feature/LazyInitialization/PointerOffset.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects --use-timestamps=false --skip-local=false %t.bc +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects --use-timestamps=false --skip-local=false %t.bc // RUN: %ktest-tool %t.klee-out/test*.ktest > %t.log // RUN: FileCheck %s -input-file=%t.log // CHECK: pointers: [(0, 1, 4)] diff --git a/test/Feature/LazyInitialization/SingleInitializationAndAccess.c b/test/Feature/LazyInitialization/SingleInitializationAndAccess.c index 1def3a9876..4c2413aa9e 100644 --- a/test/Feature/LazyInitialization/SingleInitializationAndAccess.c +++ b/test/Feature/LazyInitialization/SingleInitializationAndAccess.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects --skip-local=false --use-sym-size-li --min-number-elements-li=1 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects --skip-local=false --use-sym-size-li --min-number-elements-li=1 %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/LazyInitialization/TwoObjectsInitialization.c b/test/Feature/LazyInitialization/TwoObjectsInitialization.c index ab67462f3d..957f4bd7da 100644 --- a/test/Feature/LazyInitialization/TwoObjectsInitialization.c +++ b/test/Feature/LazyInitialization/TwoObjectsInitialization.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/MemoryLimit.c b/test/Feature/MemoryLimit.c index 330b2547ea..a24a16993e 100644 --- a/test/Feature/MemoryLimit.c +++ b/test/Feature/MemoryLimit.c @@ -44,7 +44,7 @@ int main() { malloc_failed |= (p == 0); // Ensure we hit the periodic check // Use the pointer to be not optimized out by the compiler - for (j = 0; j < 10000; j++) + for (j = 0; j < 100; j++) x += (long)p; } #endif diff --git a/test/Feature/Searchers.c b/test/Feature/Searchers.c index 84abd378d1..aacb09de59 100644 --- a/test/Feature/Searchers.c +++ b/test/Feature/Searchers.c @@ -18,13 +18,13 @@ // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --search=random-path --search=nurs:qc %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search --search=random-state %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search --search=random-state %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search --search=nurs:depth %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search --search=nurs:depth %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search --search=nurs:qc %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search --search=nurs:qc %t2.bc /* this test is basically just for coverage and doesn't really do any correctness check (aside from testing that the various combinations diff --git a/test/Feature/SolverTimeout.c b/test/Feature/SolverTimeout.c index af449cebd0..41049f5b34 100644 --- a/test/Feature/SolverTimeout.c +++ b/test/Feature/SolverTimeout.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --max-solver-time=1 %t.bc +// RUN: %klee --output-dir=%t.klee-out --max-solver-time=1 %t.bc 2>&1 | FileCheck %s // // Note: This test occasionally fails when using Z3 4.4.1 @@ -11,6 +11,8 @@ int main() { klee_make_symbolic(&x, sizeof(x), "x"); + // CHECK-NOT: Yes + // CHECK: No if (x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x + (x * x % (x + 12)) == y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y % i) printf("Yes\n"); else diff --git a/test/Feature/SymbolicSizes/FirstAndLastElements.c b/test/Feature/SymbolicSizes/FirstAndLastElements.c index da74d0569b..10ba4c5784 100644 --- a/test/Feature/SymbolicSizes/FirstAndLastElements.c +++ b/test/Feature/SymbolicSizes/FirstAndLastElements.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/ImplicitArrayExtension.c b/test/Feature/SymbolicSizes/ImplicitArrayExtension.c index 604d137360..273334c84f 100644 --- a/test/Feature/SymbolicSizes/ImplicitArrayExtension.c +++ b/test/Feature/SymbolicSizes/ImplicitArrayExtension.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c b/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c index 0ca567204c..6b4e09d0ee 100644 --- a/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c +++ b/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c @@ -1,4 +1,3 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s diff --git a/test/Feature/SymbolicSizes/IntArray.c b/test/Feature/SymbolicSizes/IntArray.c index e820df0a04..48ea30e48e 100644 --- a/test/Feature/SymbolicSizes/IntArray.c +++ b/test/Feature/SymbolicSizes/IntArray.c @@ -1,7 +1,8 @@ -// REQUIRES: z3 +// REQUIRES: not-darwin, not-metasmt +// Disabling darwin and metasmt because test has flaky behaviour on CI // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c b/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c index 51ad20892e..be244f9ae0 100644 --- a/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c +++ b/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/LowerOutOfBound.c b/test/Feature/SymbolicSizes/LowerOutOfBound.c index 0a97e5c63a..41064df671 100644 --- a/test/Feature/SymbolicSizes/LowerOutOfBound.c +++ b/test/Feature/SymbolicSizes/LowerOutOfBound.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/MinimizeSize.c b/test/Feature/SymbolicSizes/MinimizeSize.c index 5da9f65c0f..c767ff6a97 100644 --- a/test/Feature/SymbolicSizes/MinimizeSize.c +++ b/test/Feature/SymbolicSizes/MinimizeSize.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --solver-backend=z3 --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/MultipleAllocations.c b/test/Feature/SymbolicSizes/MultipleAllocations.c index 4ef3193a47..d953192616 100644 --- a/test/Feature/SymbolicSizes/MultipleAllocations.c +++ b/test/Feature/SymbolicSizes/MultipleAllocations.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/NegativeIndexArray.c b/test/Feature/SymbolicSizes/NegativeIndexArray.c index 2d4e0a6368..6f5f7e904e 100644 --- a/test/Feature/SymbolicSizes/NegativeIndexArray.c +++ b/test/Feature/SymbolicSizes/NegativeIndexArray.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include "stdlib.h" diff --git a/test/Feature/SymbolicSizes/NegativeSize.c b/test/Feature/SymbolicSizes/NegativeSize.c index 72c0b9c4c7..c7f59e8b49 100644 --- a/test/Feature/SymbolicSizes/NegativeSize.c +++ b/test/Feature/SymbolicSizes/NegativeSize.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include @@ -22,7 +21,7 @@ int main() { s1[1] = 10; // n == -2 // CHECK: NegativeSize.c:[[@LINE+1]]: memory error: out of bound pointer s2[2] = 20; // m == 3 - // CHECK: NegativeSize.c:[[@LINE+1]]: ASSERTION FAIL: 0 + // CHECK: NegativeSize.c:[[@LINE+1]]: ASSERTION FAIL assert(0); } } diff --git a/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c b/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c index 7d3bab5940..885cc518dc 100644 --- a/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c +++ b/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/SegmentComparator.c b/test/Feature/SymbolicSizes/SegmentComparator.c index 3a7f16db76..614610b76a 100644 --- a/test/Feature/SymbolicSizes/SegmentComparator.c +++ b/test/Feature/SymbolicSizes/SegmentComparator.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c b/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c index acf086a65f..daa6bec34f 100644 --- a/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c +++ b/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --solver-backend=z3 --use-sym-size-alloc --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" diff --git a/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c b/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c index dbb2331aac..725dc56785 100644 --- a/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c +++ b/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" diff --git a/test/Feature/SymbolicSizes/UninitializedMemory.c b/test/Feature/SymbolicSizes/UninitializedMemory.c new file mode 100644 index 0000000000..f0501d3893 --- /dev/null +++ b/test/Feature/SymbolicSizes/UninitializedMemory.c @@ -0,0 +1,24 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +#include "klee/klee.h" + +#include +#include +#include + +int main() { + int n; + klee_make_symbolic(&n, sizeof(n), "n"); + + char *s = (char *)malloc(n); + s[2] = 10; + if (s[0] == 0) { + printf("1) 0\n"); + } else { + printf("1) not 0\n"); + } + + // CHECK-DAG: 1) 0 + // CHECK-DAG: 1) not 0 +} diff --git a/test/Feature/SymbolicSizes/VoidStar.c b/test/Feature/SymbolicSizes/VoidStar.c index 48924f7b69..8770065d7a 100644 --- a/test/Feature/SymbolicSizes/VoidStar.c +++ b/test/Feature/SymbolicSizes/VoidStar.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --skip-not-lazy-initialized --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --skip-not-lazy-initialized --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/TwoUninitializedRegions.c b/test/Feature/TwoUninitializedRegions.c new file mode 100644 index 0000000000..a772e4d549 --- /dev/null +++ b/test/Feature/TwoUninitializedRegions.c @@ -0,0 +1,23 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s + +#include "klee/klee.h" + +#include +#include +#include + +int main() { + char arr1[3]; + char arr2[3]; + + if (arr1[0] == arr2[0]) { + printf("1) equal\n"); + } else { + printf("1) not equal\n"); + } + + // CHECK-DAG: 1) equal + // CHECK-DAG: 1) not equal +} diff --git a/test/Feature/UninitializedConstantMemory.c b/test/Feature/UninitializedConstantMemory.c new file mode 100644 index 0000000000..ee8eb5cc92 --- /dev/null +++ b/test/Feature/UninitializedConstantMemory.c @@ -0,0 +1,29 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s +#include "klee/klee.h" + +#include +#include +#include + +int main() { + char arr[3]; + + if (arr[0] == 0) { + printf("1) 0\n"); + } else { + printf("1) not 0\n"); + } + + char *zero_arr = (char *)calloc(3, sizeof(char)); + if (zero_arr[1] == 0) { + return 0; + } else { + // CHECK-NOT: ASSERTION FAIL + assert(0); + } + + // CHECK-DAG: 1) 0 + // CHECK-DAG: 1) not 0 +} diff --git a/test/Feature/uint128.c b/test/Feature/uint128.c new file mode 100644 index 0000000000..efa5915beb --- /dev/null +++ b/test/Feature/uint128.c @@ -0,0 +1,11 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out %t1.bc 2>&1 | FileCheck %s +// CHECK-NOT: failed external call +#include "klee-test-comp.c" +extern unsigned __int128 __VERIFIER_nondet_uint128(); + +int main() { + __int128 x = __VERIFIER_nondet_uint128(); + return x > 0; +} diff --git a/test/Floats/copysign.c b/test/Floats/copysign.c index 03f3cb4851..80a5921322 100644 --- a/test/Floats/copysign.c +++ b/test/Floats/copysign.c @@ -16,4 +16,4 @@ int main() { return 2; } } -// CHECK: KLEE: done: completed paths = 4 +// CHECK: KLEE: done: completed paths = {{4|6}} diff --git a/test/Floats/float-benchs/cast_union_loose.c b/test/Floats/float-benchs/cast_union_loose.c new file mode 100644 index 0000000000..6dbf5c77a9 --- /dev/null +++ b/test/Floats/float-benchs/cast_union_loose.c @@ -0,0 +1,53 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --32 %s + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "cast_union_loose.c", 3, "reach_error"); } +/* Example from "Abstract Domains for Bit-Level Machine Integer and + Floating-point Operations" by Miné, published in WING 12. +*/ + +extern int __VERIFIER_nondet_int(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR : { + reach_error(); + abort(); + } + } + return; +} + +union u { + int i[2]; + double d; +}; + +double cast(int i) { + union u x, y; + x.i[0] = 0x43300000; + y.i[0] = x.i[0]; + x.i[1] = 0x80000000; + y.i[1] = i ^ x.i[1]; + return y.d - x.d; +} + +int main() { + int a; + double r; + + a = __VERIFIER_nondet_int(); + assume_abort_if_not(a >= -10000 && a <= 10000); + + r = cast(a); + __VERIFIER_assert(r >= -10000. && r <= 10000.); + return 0; +} diff --git a/test/Floats/float-benchs/cast_union_loose.yml b/test/Floats/float-benchs/cast_union_loose.yml new file mode 100644 index 0000000000..27094e3abe --- /dev/null +++ b/test/Floats/float-benchs/cast_union_loose.yml @@ -0,0 +1,18 @@ +format_version: '2.0' + +# old file name: cast_union_loose_false-unreach-call_true-termination.c +input_files: 'cast_union_loose.c' + +properties: + - property_file: ../properties/termination.prp + expected_verdict: true + - property_file: ../properties/unreach-call.prp + expected_verdict: false + - property_file: ../properties/coverage-error-call.prp + - property_file: ../properties/coverage-branches.prp + - property_file: ../properties/coverage-conditions.prp + - property_file: ../properties/coverage-statements.prp + +options: + language: C + data_model: ILP32 diff --git a/test/Floats/float-benchs/cast_union_tight.c b/test/Floats/float-benchs/cast_union_tight.c new file mode 100644 index 0000000000..a5f5e5fe44 --- /dev/null +++ b/test/Floats/float-benchs/cast_union_tight.c @@ -0,0 +1,46 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --32 %s + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "cast_union_tight.c", 3, "reach_error"); } +/* Example from "Abstract Domains for Bit-Level Machine Integer and + Floating-point Operations" by Miné, published in WING 12. +*/ + +extern int __VERIFIER_nondet_int(void); +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR : { + reach_error(); + abort(); + } + } + return; +} + +union u { + int i[2]; + double d; +}; + +double cast(int i) { + union u x, y; + x.i[0] = 0x43300000; + y.i[0] = x.i[0]; + x.i[1] = 0x80000000; + y.i[1] = i ^ x.i[1]; + return y.d - x.d; +} + +int main() { + int a; + double r; + + a = __VERIFIER_nondet_int(); + + r = cast(a); + __VERIFIER_assert(r == a); + return 0; +} diff --git a/test/Floats/float-benchs/cast_union_tight.yml b/test/Floats/float-benchs/cast_union_tight.yml new file mode 100644 index 0000000000..7bea04b7f8 --- /dev/null +++ b/test/Floats/float-benchs/cast_union_tight.yml @@ -0,0 +1,18 @@ +format_version: '2.0' + +# old file name: cast_union_tight_false-unreach-call_true-termination.c +input_files: 'cast_union_tight.c' + +properties: + - property_file: ../properties/termination.prp + expected_verdict: true + - property_file: ../properties/unreach-call.prp + expected_verdict: false + - property_file: ../properties/coverage-error-call.prp + - property_file: ../properties/coverage-branches.prp + - property_file: ../properties/coverage-conditions.prp + - property_file: ../properties/coverage-statements.prp + +options: + language: C + data_model: ILP32 diff --git a/test/Floats/float-benchs/coverage-error-call.prp b/test/Floats/float-benchs/coverage-error-call.prp new file mode 100644 index 0000000000..496ed998fa --- /dev/null +++ b/test/Floats/float-benchs/coverage-error-call.prp @@ -0,0 +1,2 @@ +COVER( init(main()), FQL(COVER EDGES(@CALL(reach_error))) ) + diff --git a/test/Floats/float-benchs/double_req_bl_0670.c b/test/Floats/float-benchs/double_req_bl_0670.c new file mode 100644 index 0000000000..0ecac476be --- /dev/null +++ b/test/Floats/float-benchs/double_req_bl_0670.c @@ -0,0 +1,279 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --32 %s + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "double_req_bl_0670.c", 3, "reach_error"); } +extern double __VERIFIER_nondet_double(); + +typedef int __int32_t; +typedef unsigned int __uint32_t; + +/* A union which permits us to convert between a double and two 32 bit + ints. */ +typedef union { + double value; + struct { + __uint32_t lsw; + __uint32_t msw; + } parts; +} ieee_double_shape_type; + +double fabs_double(double x) { + __uint32_t high; + do { + ieee_double_shape_type gh_u; + gh_u.value = (x); + (high) = gh_u.parts.msw; + } while (0); + do { + ieee_double_shape_type sh_u; + sh_u.value = (x); + sh_u.parts.msw = (high & 0x7fffffff); + (x) = sh_u.value; + } while (0); + return x; +} + +/* + * Preprocessed code for the function libs/newlib/math/s_atan.c + */ + +static const double atanhi_atan[] = { + 4.63647609000806093515e-01, + 7.85398163397448278999e-01, + 9.82793723247329054082e-01, + 1.57079632679489655800e+00, +}; + +static const double atanlo_atan[] = { + 2.26987774529616870924e-17, + 3.06161699786838301793e-17, + 1.39033110312309984516e-17, + 6.12323399573676603587e-17, +}; + +static const double aT_atan[] = { + 3.33333333333329318027e-01, + -1.99999999998764832476e-01, + 1.42857142725034663711e-01, + -1.11111104054623557880e-01, + 9.09088713343650656196e-02, + -7.69187620504482999495e-02, + 6.66107313738753120669e-02, + -5.83357013379057348645e-02, + 4.97687799461593236017e-02, + -3.65315727442169155270e-02, + 1.62858201153657823623e-02, +}; + +static const double one_atan = 1.0, pi_o_4 = 7.8539816339744827900E-01, + pi_o_2 = 1.5707963267948965580E+00, + pi = 3.1415926535897931160E+00, huge_atan = 1.0e300; + +double atan_double(double x) { + double w, s1, s2, z; + __int32_t ix, hx, id; + + do { + ieee_double_shape_type gh_u; + gh_u.value = (x); + (hx) = gh_u.parts.msw; + } while (0); + ix = hx & 0x7fffffff; + if (ix >= 0x44100000) { + __uint32_t low; + do { + ieee_double_shape_type gl_u; + gl_u.value = (x); + (low) = gl_u.parts.lsw; + } while (0); + if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (low != 0))) + return x + x; + if (hx > 0) + return atanhi_atan[3] + atanlo_atan[3]; + else + return -atanhi_atan[3] - atanlo_atan[3]; + } + if (ix < 0x3fdc0000) { + if (ix < 0x3e200000) { + if (huge_atan + x > one_atan) + return x; + } + id = -1; + } else { + x = fabs_double(x); + if (ix < 0x3ff30000) { + if (ix < 0x3fe60000) { + id = 0; + x = (2.0 * x - one_atan) / (2.0 + x); + } else { + id = 1; + x = (x - one_atan) / (x + one_atan); + } + } else { + if (ix < 0x40038000) { + id = 2; + x = (x - 1.5) / (one_atan + 1.5 * x); + } else { + id = 3; + x = -1.0 / x; + } + } + } + + z = x * x; + w = z * z; + + s1 = z * (aT_atan[0] + + w * (aT_atan[2] + + w * (aT_atan[4] + + w * (aT_atan[6] + w * (aT_atan[8] + w * aT_atan[10]))))); + s2 = + w * + (aT_atan[1] + + w * (aT_atan[3] + w * (aT_atan[5] + w * (aT_atan[7] + w * aT_atan[9])))); + if (id < 0) + return x - x * (s1 + s2); + else { + z = atanhi_atan[id] - ((x * (s1 + s2) - atanlo_atan[id]) - x); + return (hx < 0) ? -z : z; + } +} + +/* + * Preprocessed code for the function libs/newlib/math/e_atan2.c (Constants are + * defined in requrements/includes/math_constants_double.h) + */ + +static const double tiny_atan2 = 1.0e-300, zero_atan2 = 0.0, + pi_lo_atan2 = 1.2246467991473531772E-16; + +double __ieee754_atan2(double y, double x) { + double z; + __int32_t k, m, hx, hy, ix, iy; + __uint32_t lx, ly; + + do { + ieee_double_shape_type ew_u; + ew_u.value = (x); + (hx) = ew_u.parts.msw; + (lx) = ew_u.parts.lsw; + } while (0); + ix = hx & 0x7fffffff; + do { + ieee_double_shape_type ew_u; + ew_u.value = (y); + (hy) = ew_u.parts.msw; + (ly) = ew_u.parts.lsw; + } while (0); + iy = hy & 0x7fffffff; + if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000) || + ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) + return x + y; + if (((hx - 0x3ff00000) | lx) == 0) + return atan_double(y); + m = ((hy >> 31) & 1) | ((hx >> 30) & 2); + + if ((iy | ly) == 0) { + switch (m) { + case 0: + case 1: + return y; + case 2: + return pi + tiny_atan2; + case 3: + return -pi - tiny_atan2; + } + } + + if ((ix | lx) == 0) + return (hy < 0) ? -pi_o_2 - tiny_atan2 : pi_o_2 + tiny_atan2; + + if (ix == 0x7ff00000) { + if (iy == 0x7ff00000) { + switch (m) { + case 0: + return pi_o_4 + tiny_atan2; + case 1: + return -pi_o_4 - tiny_atan2; + case 2: + return 3.0 * pi_o_4 + tiny_atan2; + case 3: + return -3.0 * pi_o_4 - tiny_atan2; + } + } else { + switch (m) { + case 0: + return zero_atan2; + case 1: + return -zero_atan2; + case 2: + return pi + tiny_atan2; + case 3: + return -pi - tiny_atan2; + } + } + } + + if (iy == 0x7ff00000) + return (hy < 0) ? -pi_o_2 - tiny_atan2 : pi_o_2 + tiny_atan2; + + k = (iy - ix) >> 20; + if (k > 60) + z = pi_o_2 + 0.5 * pi_lo_atan2; + else if (hx < 0 && k < -60) + z = 0.0; + else + z = atan_double(fabs_double(y / x)); + switch (m) { + case 0: + return z; + case 1: { + __uint32_t zh; + do { + ieee_double_shape_type gh_u; + gh_u.value = (z); + (zh) = gh_u.parts.msw; + } while (0); + do { + ieee_double_shape_type sh_u; + sh_u.value = (z); + sh_u.parts.msw = (zh ^ 0x80000000); + (z) = sh_u.value; + } while (0); + } + return z; + case 2: + return pi - (z - pi_lo_atan2); + default: + return (z - pi_lo_atan2) - pi; + } +} + +// nan check for doubles +int isnan_double(double x) { return x != x; } + +int main() { + + /* REQ-BL-0670: + * The atan2 and atan2f procedures shall return NaN if any argument is NaN. + */ + + double x = __VERIFIER_nondet_double(); + double y = __VERIFIER_nondet_double(); + + if (isnan_double(x) || isnan_double(y)) { + + double res = __ieee754_atan2(y, x); + + // x is NAN, y is any or vice versa, the result shall be NAN + if (!isnan_double(res)) { + { reach_error(); } + return 1; + } + } + + return 0; +} diff --git a/test/Floats/float-benchs/double_req_bl_0670.yml b/test/Floats/float-benchs/double_req_bl_0670.yml new file mode 100644 index 0000000000..dfe3bebd6a --- /dev/null +++ b/test/Floats/float-benchs/double_req_bl_0670.yml @@ -0,0 +1,15 @@ +format_version: '2.0' + +# old file name: double_req_bl_0670_true-unreach-call.c +input_files: 'double_req_bl_0670.c' + +properties: + - property_file: ../properties/unreach-call.prp + expected_verdict: true + - property_file: ../properties/coverage-branches.prp + - property_file: ../properties/coverage-conditions.prp + - property_file: ../properties/coverage-statements.prp + +options: + language: C + data_model: ILP32 diff --git a/test/Industry/AssignNull_Scene_BadCase02.c b/test/Industry/AssignNull_Scene_BadCase02.c index ecb898b0b2..55fb4b7989 100644 --- a/test/Industry/AssignNull_Scene_BadCase02.c +++ b/test/Industry/AssignNull_Scene_BadCase02.c @@ -49,7 +49,6 @@ void TestBad5(struct STU *pdev, const char *buf, unsigned int count) printf("teacher id is %ud", teacherID); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/AssignNull_Scene_BadCase04.c b/test/Industry/AssignNull_Scene_BadCase04.c index 757479e40d..6a0979278f 100644 --- a/test/Industry/AssignNull_Scene_BadCase04.c +++ b/test/Industry/AssignNull_Scene_BadCase04.c @@ -50,7 +50,6 @@ int TestBad7(char *arg, unsigned int count) return 1; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --smart-resolve-entry-function --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/BadCase01_SecB_ForwardNull.c b/test/Industry/BadCase01_SecB_ForwardNull.c index 38431719b3..f72959d73c 100644 --- a/test/Industry/BadCase01_SecB_ForwardNull.c +++ b/test/Industry/BadCase01_SecB_ForwardNull.c @@ -140,7 +140,6 @@ void badbad(char *ptr) } #endif -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/CheckNull_Scene_BadCase02.c b/test/Industry/CheckNull_Scene_BadCase02.c index fc27954a53..3effb46f57 100644 --- a/test/Industry/CheckNull_Scene_BadCase02.c +++ b/test/Industry/CheckNull_Scene_BadCase02.c @@ -41,7 +41,6 @@ void TestBad2() free(errMsg); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/CheckNull_Scene_BadCase04.c b/test/Industry/CheckNull_Scene_BadCase04.c index dba74dd82a..0e9038201d 100644 --- a/test/Industry/CheckNull_Scene_BadCase04.c +++ b/test/Industry/CheckNull_Scene_BadCase04.c @@ -56,7 +56,6 @@ void TestBad12(int cond1, int cond2) } } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c new file mode 100644 index 0000000000..fff21e4d2b --- /dev/null +++ b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c @@ -0,0 +1,36 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=all %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s + +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK-COV %s + +// Branch coverage 100%, the number of branches is 2: +// CHECK-COV: Lines executed:100.00% of 11 +// CHECK-COV-NEXT: Branches executed:100.00% of 2 +// CHECK-COV-NEXT: Taken at least once:100.00% of 2 + +#include "klee-test-comp.c" + +extern int __VERIFIER_nondet_int(void); + +int main() { + int *x = alloca(sizeof(int)); + int *y = alloca(sizeof(int)); + int *z = alloca(sizeof(int)); + *x = __VERIFIER_nondet_int(); + *y = __VERIFIER_nondet_int(); + *z = __VERIFIER_nondet_int(); + + while (*x > 0) { + *x = *x + *y; + *y = *z; + *z = -(*z) - 1; + } +} + +// CHECK: generated tests = 3 diff --git a/test/Industry/CoverageBranches/CostasArray-17.c b/test/Industry/CoverageBranches/CostasArray-17.c new file mode 100644 index 0000000000..6f2bcea325 --- /dev/null +++ b/test/Industry/CoverageBranches/CostasArray-17.c @@ -0,0 +1,1771 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs %t1.bc + +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs %t1.bc + +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// Branch coverage 100%, the number of branches is 2: +// CHECK: Lines executed:{{(0\.7[0-9])}}% of 1545 +// CHECK-NEXT: Branches executed:100.00% of 2 +// CHECK-NEXT: Taken at least once:100.00% of 2 + +#include "klee-test-comp.c" + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://github.com/sosy-lab/sv-benchmarks +// +// SPDX-FileCopyrightText: 2016 Gilles Audemard +// SPDX-FileCopyrightText: 2020 Dirk Beyer +// SPDX-FileCopyrightText: 2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: MIT + +extern void abort(void) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +extern void __assert_fail(const char *, const char *, unsigned int, + const char *) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +int __VERIFIER_nondet_int(); + +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} + +void reach_error() { __assert_fail("0", "CostasArray-17.c", 5, "reach_error"); } +void assume(int cond) { + if (!cond) + abort_prog(); +} +int main() { + int cond0; + int dummy = 0; + int N; + int var0; + var0 = __VERIFIER_nondet_int(); + assume(var0 >= 1); + assume(var0 <= 17); + int var1; + var1 = __VERIFIER_nondet_int(); + assume(var1 >= 1); + assume(var1 <= 17); + int var2; + var2 = __VERIFIER_nondet_int(); + assume(var2 >= 1); + assume(var2 <= 17); + int var3; + var3 = __VERIFIER_nondet_int(); + assume(var3 >= 1); + assume(var3 <= 17); + int var4; + var4 = __VERIFIER_nondet_int(); + assume(var4 >= 1); + assume(var4 <= 17); + int var5; + var5 = __VERIFIER_nondet_int(); + assume(var5 >= 1); + assume(var5 <= 17); + int var6; + var6 = __VERIFIER_nondet_int(); + assume(var6 >= 1); + assume(var6 <= 17); + int var7; + var7 = __VERIFIER_nondet_int(); + assume(var7 >= 1); + assume(var7 <= 17); + int var8; + var8 = __VERIFIER_nondet_int(); + assume(var8 >= 1); + assume(var8 <= 17); + int var9; + var9 = __VERIFIER_nondet_int(); + assume(var9 >= 1); + assume(var9 <= 17); + int var10; + var10 = __VERIFIER_nondet_int(); + assume(var10 >= 1); + assume(var10 <= 17); + int var11; + var11 = __VERIFIER_nondet_int(); + assume(var11 >= 1); + assume(var11 <= 17); + int var12; + var12 = __VERIFIER_nondet_int(); + assume(var12 >= 1); + assume(var12 <= 17); + int var13; + var13 = __VERIFIER_nondet_int(); + assume(var13 >= 1); + assume(var13 <= 17); + int var14; + var14 = __VERIFIER_nondet_int(); + assume(var14 >= 1); + assume(var14 <= 17); + int var15; + var15 = __VERIFIER_nondet_int(); + assume(var15 >= 1); + assume(var15 <= 17); + int var16; + var16 = __VERIFIER_nondet_int(); + assume(var16 >= 1); + assume(var16 <= 17); + int var17; + var17 = __VERIFIER_nondet_int(); + assume(var17 >= -16); + assume(var17 <= 16); + assume(var17 != 0); + int var18; + var18 = __VERIFIER_nondet_int(); + assume(var18 >= -16); + assume(var18 <= 16); + assume(var18 != 0); + int var19; + var19 = __VERIFIER_nondet_int(); + assume(var19 >= -16); + assume(var19 <= 16); + assume(var19 != 0); + int var20; + var20 = __VERIFIER_nondet_int(); + assume(var20 >= -16); + assume(var20 <= 16); + assume(var20 != 0); + int var21; + var21 = __VERIFIER_nondet_int(); + assume(var21 >= -16); + assume(var21 <= 16); + assume(var21 != 0); + int var22; + var22 = __VERIFIER_nondet_int(); + assume(var22 >= -16); + assume(var22 <= 16); + assume(var22 != 0); + int var23; + var23 = __VERIFIER_nondet_int(); + assume(var23 >= -16); + assume(var23 <= 16); + assume(var23 != 0); + int var24; + var24 = __VERIFIER_nondet_int(); + assume(var24 >= -16); + assume(var24 <= 16); + assume(var24 != 0); + int var25; + var25 = __VERIFIER_nondet_int(); + assume(var25 >= -16); + assume(var25 <= 16); + assume(var25 != 0); + int var26; + var26 = __VERIFIER_nondet_int(); + assume(var26 >= -16); + assume(var26 <= 16); + assume(var26 != 0); + int var27; + var27 = __VERIFIER_nondet_int(); + assume(var27 >= -16); + assume(var27 <= 16); + assume(var27 != 0); + int var28; + var28 = __VERIFIER_nondet_int(); + assume(var28 >= -16); + assume(var28 <= 16); + assume(var28 != 0); + int var29; + var29 = __VERIFIER_nondet_int(); + assume(var29 >= -16); + assume(var29 <= 16); + assume(var29 != 0); + int var30; + var30 = __VERIFIER_nondet_int(); + assume(var30 >= -16); + assume(var30 <= 16); + assume(var30 != 0); + int var31; + var31 = __VERIFIER_nondet_int(); + assume(var31 >= -16); + assume(var31 <= 16); + assume(var31 != 0); + int var32; + var32 = __VERIFIER_nondet_int(); + assume(var32 >= -16); + assume(var32 <= 16); + assume(var32 != 0); + int var33; + var33 = __VERIFIER_nondet_int(); + assume(var33 >= -16); + assume(var33 <= 16); + assume(var33 != 0); + int var34; + var34 = __VERIFIER_nondet_int(); + assume(var34 >= -16); + assume(var34 <= 16); + assume(var34 != 0); + int var35; + var35 = __VERIFIER_nondet_int(); + assume(var35 >= -16); + assume(var35 <= 16); + assume(var35 != 0); + int var36; + var36 = __VERIFIER_nondet_int(); + assume(var36 >= -16); + assume(var36 <= 16); + assume(var36 != 0); + int var37; + var37 = __VERIFIER_nondet_int(); + assume(var37 >= -16); + assume(var37 <= 16); + assume(var37 != 0); + int var38; + var38 = __VERIFIER_nondet_int(); + assume(var38 >= -16); + assume(var38 <= 16); + assume(var38 != 0); + int var39; + var39 = __VERIFIER_nondet_int(); + assume(var39 >= -16); + assume(var39 <= 16); + assume(var39 != 0); + int var40; + var40 = __VERIFIER_nondet_int(); + assume(var40 >= -16); + assume(var40 <= 16); + assume(var40 != 0); + int var41; + var41 = __VERIFIER_nondet_int(); + assume(var41 >= -16); + assume(var41 <= 16); + assume(var41 != 0); + int var42; + var42 = __VERIFIER_nondet_int(); + assume(var42 >= -16); + assume(var42 <= 16); + assume(var42 != 0); + int var43; + var43 = __VERIFIER_nondet_int(); + assume(var43 >= -16); + assume(var43 <= 16); + assume(var43 != 0); + int var44; + var44 = __VERIFIER_nondet_int(); + assume(var44 >= -16); + assume(var44 <= 16); + assume(var44 != 0); + int var45; + var45 = __VERIFIER_nondet_int(); + assume(var45 >= -16); + assume(var45 <= 16); + assume(var45 != 0); + int var46; + var46 = __VERIFIER_nondet_int(); + assume(var46 >= -16); + assume(var46 <= 16); + assume(var46 != 0); + int var47; + var47 = __VERIFIER_nondet_int(); + assume(var47 >= -16); + assume(var47 <= 16); + assume(var47 != 0); + int var48; + var48 = __VERIFIER_nondet_int(); + assume(var48 >= -16); + assume(var48 <= 16); + assume(var48 != 0); + int var49; + var49 = __VERIFIER_nondet_int(); + assume(var49 >= -16); + assume(var49 <= 16); + assume(var49 != 0); + int var50; + var50 = __VERIFIER_nondet_int(); + assume(var50 >= -16); + assume(var50 <= 16); + assume(var50 != 0); + int var51; + var51 = __VERIFIER_nondet_int(); + assume(var51 >= -16); + assume(var51 <= 16); + assume(var51 != 0); + int var52; + var52 = __VERIFIER_nondet_int(); + assume(var52 >= -16); + assume(var52 <= 16); + assume(var52 != 0); + int var53; + var53 = __VERIFIER_nondet_int(); + assume(var53 >= -16); + assume(var53 <= 16); + assume(var53 != 0); + int var54; + var54 = __VERIFIER_nondet_int(); + assume(var54 >= -16); + assume(var54 <= 16); + assume(var54 != 0); + int var55; + var55 = __VERIFIER_nondet_int(); + assume(var55 >= -16); + assume(var55 <= 16); + assume(var55 != 0); + int var56; + var56 = __VERIFIER_nondet_int(); + assume(var56 >= -16); + assume(var56 <= 16); + assume(var56 != 0); + int var57; + var57 = __VERIFIER_nondet_int(); + assume(var57 >= -16); + assume(var57 <= 16); + assume(var57 != 0); + int var58; + var58 = __VERIFIER_nondet_int(); + assume(var58 >= -16); + assume(var58 <= 16); + assume(var58 != 0); + int var59; + var59 = __VERIFIER_nondet_int(); + assume(var59 >= -16); + assume(var59 <= 16); + assume(var59 != 0); + int var60; + var60 = __VERIFIER_nondet_int(); + assume(var60 >= -16); + assume(var60 <= 16); + assume(var60 != 0); + int var61; + var61 = __VERIFIER_nondet_int(); + assume(var61 >= -16); + assume(var61 <= 16); + assume(var61 != 0); + int var62; + var62 = __VERIFIER_nondet_int(); + assume(var62 >= -16); + assume(var62 <= 16); + assume(var62 != 0); + int var63; + var63 = __VERIFIER_nondet_int(); + assume(var63 >= -16); + assume(var63 <= 16); + assume(var63 != 0); + int var64; + var64 = __VERIFIER_nondet_int(); + assume(var64 >= -16); + assume(var64 <= 16); + assume(var64 != 0); + int var65; + var65 = __VERIFIER_nondet_int(); + assume(var65 >= -16); + assume(var65 <= 16); + assume(var65 != 0); + int var66; + var66 = __VERIFIER_nondet_int(); + assume(var66 >= -16); + assume(var66 <= 16); + assume(var66 != 0); + int var67; + var67 = __VERIFIER_nondet_int(); + assume(var67 >= -16); + assume(var67 <= 16); + assume(var67 != 0); + int var68; + var68 = __VERIFIER_nondet_int(); + assume(var68 >= -16); + assume(var68 <= 16); + assume(var68 != 0); + int var69; + var69 = __VERIFIER_nondet_int(); + assume(var69 >= -16); + assume(var69 <= 16); + assume(var69 != 0); + int var70; + var70 = __VERIFIER_nondet_int(); + assume(var70 >= -16); + assume(var70 <= 16); + assume(var70 != 0); + int var71; + var71 = __VERIFIER_nondet_int(); + assume(var71 >= -16); + assume(var71 <= 16); + assume(var71 != 0); + int var72; + var72 = __VERIFIER_nondet_int(); + assume(var72 >= -16); + assume(var72 <= 16); + assume(var72 != 0); + int var73; + var73 = __VERIFIER_nondet_int(); + assume(var73 >= -16); + assume(var73 <= 16); + assume(var73 != 0); + int var74; + var74 = __VERIFIER_nondet_int(); + assume(var74 >= -16); + assume(var74 <= 16); + assume(var74 != 0); + int var75; + var75 = __VERIFIER_nondet_int(); + assume(var75 >= -16); + assume(var75 <= 16); + assume(var75 != 0); + int var76; + var76 = __VERIFIER_nondet_int(); + assume(var76 >= -16); + assume(var76 <= 16); + assume(var76 != 0); + int var77; + var77 = __VERIFIER_nondet_int(); + assume(var77 >= -16); + assume(var77 <= 16); + assume(var77 != 0); + int var78; + var78 = __VERIFIER_nondet_int(); + assume(var78 >= -16); + assume(var78 <= 16); + assume(var78 != 0); + int var79; + var79 = __VERIFIER_nondet_int(); + assume(var79 >= -16); + assume(var79 <= 16); + assume(var79 != 0); + int var80; + var80 = __VERIFIER_nondet_int(); + assume(var80 >= -16); + assume(var80 <= 16); + assume(var80 != 0); + int var81; + var81 = __VERIFIER_nondet_int(); + assume(var81 >= -16); + assume(var81 <= 16); + assume(var81 != 0); + int var82; + var82 = __VERIFIER_nondet_int(); + assume(var82 >= -16); + assume(var82 <= 16); + assume(var82 != 0); + int var83; + var83 = __VERIFIER_nondet_int(); + assume(var83 >= -16); + assume(var83 <= 16); + assume(var83 != 0); + int var84; + var84 = __VERIFIER_nondet_int(); + assume(var84 >= -16); + assume(var84 <= 16); + assume(var84 != 0); + int var85; + var85 = __VERIFIER_nondet_int(); + assume(var85 >= -16); + assume(var85 <= 16); + assume(var85 != 0); + int var86; + var86 = __VERIFIER_nondet_int(); + assume(var86 >= -16); + assume(var86 <= 16); + assume(var86 != 0); + int var87; + var87 = __VERIFIER_nondet_int(); + assume(var87 >= -16); + assume(var87 <= 16); + assume(var87 != 0); + int var88; + var88 = __VERIFIER_nondet_int(); + assume(var88 >= -16); + assume(var88 <= 16); + assume(var88 != 0); + int var89; + var89 = __VERIFIER_nondet_int(); + assume(var89 >= -16); + assume(var89 <= 16); + assume(var89 != 0); + int var90; + var90 = __VERIFIER_nondet_int(); + assume(var90 >= -16); + assume(var90 <= 16); + assume(var90 != 0); + int var91; + var91 = __VERIFIER_nondet_int(); + assume(var91 >= -16); + assume(var91 <= 16); + assume(var91 != 0); + int var92; + var92 = __VERIFIER_nondet_int(); + assume(var92 >= -16); + assume(var92 <= 16); + assume(var92 != 0); + int var93; + var93 = __VERIFIER_nondet_int(); + assume(var93 >= -16); + assume(var93 <= 16); + assume(var93 != 0); + int var94; + var94 = __VERIFIER_nondet_int(); + assume(var94 >= -16); + assume(var94 <= 16); + assume(var94 != 0); + int var95; + var95 = __VERIFIER_nondet_int(); + assume(var95 >= -16); + assume(var95 <= 16); + assume(var95 != 0); + int var96; + var96 = __VERIFIER_nondet_int(); + assume(var96 >= -16); + assume(var96 <= 16); + assume(var96 != 0); + int var97; + var97 = __VERIFIER_nondet_int(); + assume(var97 >= -16); + assume(var97 <= 16); + assume(var97 != 0); + int var98; + var98 = __VERIFIER_nondet_int(); + assume(var98 >= -16); + assume(var98 <= 16); + assume(var98 != 0); + int var99; + var99 = __VERIFIER_nondet_int(); + assume(var99 >= -16); + assume(var99 <= 16); + assume(var99 != 0); + int var100; + var100 = __VERIFIER_nondet_int(); + assume(var100 >= -16); + assume(var100 <= 16); + assume(var100 != 0); + int var101; + var101 = __VERIFIER_nondet_int(); + assume(var101 >= -16); + assume(var101 <= 16); + assume(var101 != 0); + int var102; + var102 = __VERIFIER_nondet_int(); + assume(var102 >= -16); + assume(var102 <= 16); + assume(var102 != 0); + int var103; + var103 = __VERIFIER_nondet_int(); + assume(var103 >= -16); + assume(var103 <= 16); + assume(var103 != 0); + int var104; + var104 = __VERIFIER_nondet_int(); + assume(var104 >= -16); + assume(var104 <= 16); + assume(var104 != 0); + int var105; + var105 = __VERIFIER_nondet_int(); + assume(var105 >= -16); + assume(var105 <= 16); + assume(var105 != 0); + int var106; + var106 = __VERIFIER_nondet_int(); + assume(var106 >= -16); + assume(var106 <= 16); + assume(var106 != 0); + int var107; + var107 = __VERIFIER_nondet_int(); + assume(var107 >= -16); + assume(var107 <= 16); + assume(var107 != 0); + int var108; + var108 = __VERIFIER_nondet_int(); + assume(var108 >= -16); + assume(var108 <= 16); + assume(var108 != 0); + int var109; + var109 = __VERIFIER_nondet_int(); + assume(var109 >= -16); + assume(var109 <= 16); + assume(var109 != 0); + int var110; + var110 = __VERIFIER_nondet_int(); + assume(var110 >= -16); + assume(var110 <= 16); + assume(var110 != 0); + int var111; + var111 = __VERIFIER_nondet_int(); + assume(var111 >= -16); + assume(var111 <= 16); + assume(var111 != 0); + int var112; + var112 = __VERIFIER_nondet_int(); + assume(var112 >= -16); + assume(var112 <= 16); + assume(var112 != 0); + int var113; + var113 = __VERIFIER_nondet_int(); + assume(var113 >= -16); + assume(var113 <= 16); + assume(var113 != 0); + int var114; + var114 = __VERIFIER_nondet_int(); + assume(var114 >= -16); + assume(var114 <= 16); + assume(var114 != 0); + int var115; + var115 = __VERIFIER_nondet_int(); + assume(var115 >= -16); + assume(var115 <= 16); + assume(var115 != 0); + int var116; + var116 = __VERIFIER_nondet_int(); + assume(var116 >= -16); + assume(var116 <= 16); + assume(var116 != 0); + int var117; + var117 = __VERIFIER_nondet_int(); + assume(var117 >= -16); + assume(var117 <= 16); + assume(var117 != 0); + int var118; + var118 = __VERIFIER_nondet_int(); + assume(var118 >= -16); + assume(var118 <= 16); + assume(var118 != 0); + int var119; + var119 = __VERIFIER_nondet_int(); + assume(var119 >= -16); + assume(var119 <= 16); + assume(var119 != 0); + int var120; + var120 = __VERIFIER_nondet_int(); + assume(var120 >= -16); + assume(var120 <= 16); + assume(var120 != 0); + int var121; + var121 = __VERIFIER_nondet_int(); + assume(var121 >= -16); + assume(var121 <= 16); + assume(var121 != 0); + int var122; + var122 = __VERIFIER_nondet_int(); + assume(var122 >= -16); + assume(var122 <= 16); + assume(var122 != 0); + int var123; + var123 = __VERIFIER_nondet_int(); + assume(var123 >= -16); + assume(var123 <= 16); + assume(var123 != 0); + int var124; + var124 = __VERIFIER_nondet_int(); + assume(var124 >= -16); + assume(var124 <= 16); + assume(var124 != 0); + int var125; + var125 = __VERIFIER_nondet_int(); + assume(var125 >= -16); + assume(var125 <= 16); + assume(var125 != 0); + int var126; + var126 = __VERIFIER_nondet_int(); + assume(var126 >= -16); + assume(var126 <= 16); + assume(var126 != 0); + int var127; + var127 = __VERIFIER_nondet_int(); + assume(var127 >= -16); + assume(var127 <= 16); + assume(var127 != 0); + int var128; + var128 = __VERIFIER_nondet_int(); + assume(var128 >= -16); + assume(var128 <= 16); + assume(var128 != 0); + int var129; + var129 = __VERIFIER_nondet_int(); + assume(var129 >= -16); + assume(var129 <= 16); + assume(var129 != 0); + int var130; + var130 = __VERIFIER_nondet_int(); + assume(var130 >= -16); + assume(var130 <= 16); + assume(var130 != 0); + int var131; + var131 = __VERIFIER_nondet_int(); + assume(var131 >= -16); + assume(var131 <= 16); + assume(var131 != 0); + int var132; + var132 = __VERIFIER_nondet_int(); + assume(var132 >= -16); + assume(var132 <= 16); + assume(var132 != 0); + int var133; + var133 = __VERIFIER_nondet_int(); + assume(var133 >= -16); + assume(var133 <= 16); + assume(var133 != 0); + int var134; + var134 = __VERIFIER_nondet_int(); + assume(var134 >= -16); + assume(var134 <= 16); + assume(var134 != 0); + int var135; + var135 = __VERIFIER_nondet_int(); + assume(var135 >= -16); + assume(var135 <= 16); + assume(var135 != 0); + int var136; + var136 = __VERIFIER_nondet_int(); + assume(var136 >= -16); + assume(var136 <= 16); + assume(var136 != 0); + int var137; + var137 = __VERIFIER_nondet_int(); + assume(var137 >= -16); + assume(var137 <= 16); + assume(var137 != 0); + int var138; + var138 = __VERIFIER_nondet_int(); + assume(var138 >= -16); + assume(var138 <= 16); + assume(var138 != 0); + int var139; + var139 = __VERIFIER_nondet_int(); + assume(var139 >= -16); + assume(var139 <= 16); + assume(var139 != 0); + int var140; + var140 = __VERIFIER_nondet_int(); + assume(var140 >= -16); + assume(var140 <= 16); + assume(var140 != 0); + int var141; + var141 = __VERIFIER_nondet_int(); + assume(var141 >= -16); + assume(var141 <= 16); + assume(var141 != 0); + int var142; + var142 = __VERIFIER_nondet_int(); + assume(var142 >= -16); + assume(var142 <= 16); + assume(var142 != 0); + int var143; + var143 = __VERIFIER_nondet_int(); + assume(var143 >= -16); + assume(var143 <= 16); + assume(var143 != 0); + int var144; + var144 = __VERIFIER_nondet_int(); + assume(var144 >= -16); + assume(var144 <= 16); + assume(var144 != 0); + int var145; + var145 = __VERIFIER_nondet_int(); + assume(var145 >= -16); + assume(var145 <= 16); + assume(var145 != 0); + int var146; + var146 = __VERIFIER_nondet_int(); + assume(var146 >= -16); + assume(var146 <= 16); + assume(var146 != 0); + int var147; + var147 = __VERIFIER_nondet_int(); + assume(var147 >= -16); + assume(var147 <= 16); + assume(var147 != 0); + int var148; + var148 = __VERIFIER_nondet_int(); + assume(var148 >= -16); + assume(var148 <= 16); + assume(var148 != 0); + int var149; + var149 = __VERIFIER_nondet_int(); + assume(var149 >= -16); + assume(var149 <= 16); + assume(var149 != 0); + int myvar0 = 1; + assume(var0 != var1); + assume(var0 != var2); + assume(var0 != var3); + assume(var0 != var4); + assume(var0 != var5); + assume(var0 != var6); + assume(var0 != var7); + assume(var0 != var8); + assume(var0 != var9); + assume(var0 != var10); + assume(var0 != var11); + assume(var0 != var12); + assume(var0 != var13); + assume(var0 != var14); + assume(var0 != var15); + assume(var0 != var16); + assume(var1 != var2); + assume(var1 != var3); + assume(var1 != var4); + assume(var1 != var5); + assume(var1 != var6); + assume(var1 != var7); + assume(var1 != var8); + assume(var1 != var9); + assume(var1 != var10); + assume(var1 != var11); + assume(var1 != var12); + assume(var1 != var13); + assume(var1 != var14); + assume(var1 != var15); + assume(var1 != var16); + assume(var2 != var3); + assume(var2 != var4); + assume(var2 != var5); + assume(var2 != var6); + assume(var2 != var7); + assume(var2 != var8); + assume(var2 != var9); + assume(var2 != var10); + assume(var2 != var11); + assume(var2 != var12); + assume(var2 != var13); + assume(var2 != var14); + assume(var2 != var15); + assume(var2 != var16); + assume(var3 != var4); + assume(var3 != var5); + assume(var3 != var6); + assume(var3 != var7); + assume(var3 != var8); + assume(var3 != var9); + assume(var3 != var10); + assume(var3 != var11); + assume(var3 != var12); + assume(var3 != var13); + assume(var3 != var14); + assume(var3 != var15); + assume(var3 != var16); + assume(var4 != var5); + assume(var4 != var6); + assume(var4 != var7); + assume(var4 != var8); + assume(var4 != var9); + assume(var4 != var10); + assume(var4 != var11); + assume(var4 != var12); + assume(var4 != var13); + assume(var4 != var14); + assume(var4 != var15); + assume(var4 != var16); + assume(var5 != var6); + assume(var5 != var7); + assume(var5 != var8); + assume(var5 != var9); + assume(var5 != var10); + assume(var5 != var11); + assume(var5 != var12); + assume(var5 != var13); + assume(var5 != var14); + assume(var5 != var15); + assume(var5 != var16); + assume(var6 != var7); + assume(var6 != var8); + assume(var6 != var9); + assume(var6 != var10); + assume(var6 != var11); + assume(var6 != var12); + assume(var6 != var13); + assume(var6 != var14); + assume(var6 != var15); + assume(var6 != var16); + assume(var7 != var8); + assume(var7 != var9); + assume(var7 != var10); + assume(var7 != var11); + assume(var7 != var12); + assume(var7 != var13); + assume(var7 != var14); + assume(var7 != var15); + assume(var7 != var16); + assume(var8 != var9); + assume(var8 != var10); + assume(var8 != var11); + assume(var8 != var12); + assume(var8 != var13); + assume(var8 != var14); + assume(var8 != var15); + assume(var8 != var16); + assume(var9 != var10); + assume(var9 != var11); + assume(var9 != var12); + assume(var9 != var13); + assume(var9 != var14); + assume(var9 != var15); + assume(var9 != var16); + assume(var10 != var11); + assume(var10 != var12); + assume(var10 != var13); + assume(var10 != var14); + assume(var10 != var15); + assume(var10 != var16); + assume(var11 != var12); + assume(var11 != var13); + assume(var11 != var14); + assume(var11 != var15); + assume(var11 != var16); + assume(var12 != var13); + assume(var12 != var14); + assume(var12 != var15); + assume(var12 != var16); + assume(var13 != var14); + assume(var13 != var15); + assume(var13 != var16); + assume(var14 != var15); + assume(var14 != var16); + assume(var15 != var16); + assume(var17 != var18); + assume(var17 != var19); + assume(var17 != var20); + assume(var17 != var21); + assume(var17 != var22); + assume(var17 != var23); + assume(var17 != var24); + assume(var17 != var25); + assume(var17 != var26); + assume(var17 != var27); + assume(var17 != var28); + assume(var17 != var29); + assume(var17 != var30); + assume(var17 != var31); + assume(var17 != var32); + assume(var18 != var19); + assume(var18 != var20); + assume(var18 != var21); + assume(var18 != var22); + assume(var18 != var23); + assume(var18 != var24); + assume(var18 != var25); + assume(var18 != var26); + assume(var18 != var27); + assume(var18 != var28); + assume(var18 != var29); + assume(var18 != var30); + assume(var18 != var31); + assume(var18 != var32); + assume(var19 != var20); + assume(var19 != var21); + assume(var19 != var22); + assume(var19 != var23); + assume(var19 != var24); + assume(var19 != var25); + assume(var19 != var26); + assume(var19 != var27); + assume(var19 != var28); + assume(var19 != var29); + assume(var19 != var30); + assume(var19 != var31); + assume(var19 != var32); + assume(var20 != var21); + assume(var20 != var22); + assume(var20 != var23); + assume(var20 != var24); + assume(var20 != var25); + assume(var20 != var26); + assume(var20 != var27); + assume(var20 != var28); + assume(var20 != var29); + assume(var20 != var30); + assume(var20 != var31); + assume(var20 != var32); + assume(var21 != var22); + assume(var21 != var23); + assume(var21 != var24); + assume(var21 != var25); + assume(var21 != var26); + assume(var21 != var27); + assume(var21 != var28); + assume(var21 != var29); + assume(var21 != var30); + assume(var21 != var31); + assume(var21 != var32); + assume(var22 != var23); + assume(var22 != var24); + assume(var22 != var25); + assume(var22 != var26); + assume(var22 != var27); + assume(var22 != var28); + assume(var22 != var29); + assume(var22 != var30); + assume(var22 != var31); + assume(var22 != var32); + assume(var23 != var24); + assume(var23 != var25); + assume(var23 != var26); + assume(var23 != var27); + assume(var23 != var28); + assume(var23 != var29); + assume(var23 != var30); + assume(var23 != var31); + assume(var23 != var32); + assume(var24 != var25); + assume(var24 != var26); + assume(var24 != var27); + assume(var24 != var28); + assume(var24 != var29); + assume(var24 != var30); + assume(var24 != var31); + assume(var24 != var32); + assume(var25 != var26); + assume(var25 != var27); + assume(var25 != var28); + assume(var25 != var29); + assume(var25 != var30); + assume(var25 != var31); + assume(var25 != var32); + assume(var26 != var27); + assume(var26 != var28); + assume(var26 != var29); + assume(var26 != var30); + assume(var26 != var31); + assume(var26 != var32); + assume(var27 != var28); + assume(var27 != var29); + assume(var27 != var30); + assume(var27 != var31); + assume(var27 != var32); + assume(var28 != var29); + assume(var28 != var30); + assume(var28 != var31); + assume(var28 != var32); + assume(var29 != var30); + assume(var29 != var31); + assume(var29 != var32); + assume(var30 != var31); + assume(var30 != var32); + assume(var31 != var32); + assume(var33 != var34); + assume(var33 != var35); + assume(var33 != var36); + assume(var33 != var37); + assume(var33 != var38); + assume(var33 != var39); + assume(var33 != var40); + assume(var33 != var41); + assume(var33 != var42); + assume(var33 != var43); + assume(var33 != var44); + assume(var33 != var45); + assume(var33 != var46); + assume(var33 != var47); + assume(var34 != var35); + assume(var34 != var36); + assume(var34 != var37); + assume(var34 != var38); + assume(var34 != var39); + assume(var34 != var40); + assume(var34 != var41); + assume(var34 != var42); + assume(var34 != var43); + assume(var34 != var44); + assume(var34 != var45); + assume(var34 != var46); + assume(var34 != var47); + assume(var35 != var36); + assume(var35 != var37); + assume(var35 != var38); + assume(var35 != var39); + assume(var35 != var40); + assume(var35 != var41); + assume(var35 != var42); + assume(var35 != var43); + assume(var35 != var44); + assume(var35 != var45); + assume(var35 != var46); + assume(var35 != var47); + assume(var36 != var37); + assume(var36 != var38); + assume(var36 != var39); + assume(var36 != var40); + assume(var36 != var41); + assume(var36 != var42); + assume(var36 != var43); + assume(var36 != var44); + assume(var36 != var45); + assume(var36 != var46); + assume(var36 != var47); + assume(var37 != var38); + assume(var37 != var39); + assume(var37 != var40); + assume(var37 != var41); + assume(var37 != var42); + assume(var37 != var43); + assume(var37 != var44); + assume(var37 != var45); + assume(var37 != var46); + assume(var37 != var47); + assume(var38 != var39); + assume(var38 != var40); + assume(var38 != var41); + assume(var38 != var42); + assume(var38 != var43); + assume(var38 != var44); + assume(var38 != var45); + assume(var38 != var46); + assume(var38 != var47); + assume(var39 != var40); + assume(var39 != var41); + assume(var39 != var42); + assume(var39 != var43); + assume(var39 != var44); + assume(var39 != var45); + assume(var39 != var46); + assume(var39 != var47); + assume(var40 != var41); + assume(var40 != var42); + assume(var40 != var43); + assume(var40 != var44); + assume(var40 != var45); + assume(var40 != var46); + assume(var40 != var47); + assume(var41 != var42); + assume(var41 != var43); + assume(var41 != var44); + assume(var41 != var45); + assume(var41 != var46); + assume(var41 != var47); + assume(var42 != var43); + assume(var42 != var44); + assume(var42 != var45); + assume(var42 != var46); + assume(var42 != var47); + assume(var43 != var44); + assume(var43 != var45); + assume(var43 != var46); + assume(var43 != var47); + assume(var44 != var45); + assume(var44 != var46); + assume(var44 != var47); + assume(var45 != var46); + assume(var45 != var47); + assume(var46 != var47); + assume(var48 != var49); + assume(var48 != var50); + assume(var48 != var51); + assume(var48 != var52); + assume(var48 != var53); + assume(var48 != var54); + assume(var48 != var55); + assume(var48 != var56); + assume(var48 != var57); + assume(var48 != var58); + assume(var48 != var59); + assume(var48 != var60); + assume(var48 != var61); + assume(var49 != var50); + assume(var49 != var51); + assume(var49 != var52); + assume(var49 != var53); + assume(var49 != var54); + assume(var49 != var55); + assume(var49 != var56); + assume(var49 != var57); + assume(var49 != var58); + assume(var49 != var59); + assume(var49 != var60); + assume(var49 != var61); + assume(var50 != var51); + assume(var50 != var52); + assume(var50 != var53); + assume(var50 != var54); + assume(var50 != var55); + assume(var50 != var56); + assume(var50 != var57); + assume(var50 != var58); + assume(var50 != var59); + assume(var50 != var60); + assume(var50 != var61); + assume(var51 != var52); + assume(var51 != var53); + assume(var51 != var54); + assume(var51 != var55); + assume(var51 != var56); + assume(var51 != var57); + assume(var51 != var58); + assume(var51 != var59); + assume(var51 != var60); + assume(var51 != var61); + assume(var52 != var53); + assume(var52 != var54); + assume(var52 != var55); + assume(var52 != var56); + assume(var52 != var57); + assume(var52 != var58); + assume(var52 != var59); + assume(var52 != var60); + assume(var52 != var61); + assume(var53 != var54); + assume(var53 != var55); + assume(var53 != var56); + assume(var53 != var57); + assume(var53 != var58); + assume(var53 != var59); + assume(var53 != var60); + assume(var53 != var61); + assume(var54 != var55); + assume(var54 != var56); + assume(var54 != var57); + assume(var54 != var58); + assume(var54 != var59); + assume(var54 != var60); + assume(var54 != var61); + assume(var55 != var56); + assume(var55 != var57); + assume(var55 != var58); + assume(var55 != var59); + assume(var55 != var60); + assume(var55 != var61); + assume(var56 != var57); + assume(var56 != var58); + assume(var56 != var59); + assume(var56 != var60); + assume(var56 != var61); + assume(var57 != var58); + assume(var57 != var59); + assume(var57 != var60); + assume(var57 != var61); + assume(var58 != var59); + assume(var58 != var60); + assume(var58 != var61); + assume(var59 != var60); + assume(var59 != var61); + assume(var60 != var61); + assume(var62 != var63); + assume(var62 != var64); + assume(var62 != var65); + assume(var62 != var66); + assume(var62 != var67); + assume(var62 != var68); + assume(var62 != var69); + assume(var62 != var70); + assume(var62 != var71); + assume(var62 != var72); + assume(var62 != var73); + assume(var62 != var74); + assume(var63 != var64); + assume(var63 != var65); + assume(var63 != var66); + assume(var63 != var67); + assume(var63 != var68); + assume(var63 != var69); + assume(var63 != var70); + assume(var63 != var71); + assume(var63 != var72); + assume(var63 != var73); + assume(var63 != var74); + assume(var64 != var65); + assume(var64 != var66); + assume(var64 != var67); + assume(var64 != var68); + assume(var64 != var69); + assume(var64 != var70); + assume(var64 != var71); + assume(var64 != var72); + assume(var64 != var73); + assume(var64 != var74); + assume(var65 != var66); + assume(var65 != var67); + assume(var65 != var68); + assume(var65 != var69); + assume(var65 != var70); + assume(var65 != var71); + assume(var65 != var72); + assume(var65 != var73); + assume(var65 != var74); + assume(var66 != var67); + assume(var66 != var68); + assume(var66 != var69); + assume(var66 != var70); + assume(var66 != var71); + assume(var66 != var72); + assume(var66 != var73); + assume(var66 != var74); + assume(var67 != var68); + assume(var67 != var69); + assume(var67 != var70); + assume(var67 != var71); + assume(var67 != var72); + assume(var67 != var73); + assume(var67 != var74); + assume(var68 != var69); + assume(var68 != var70); + assume(var68 != var71); + assume(var68 != var72); + assume(var68 != var73); + assume(var68 != var74); + assume(var69 != var70); + assume(var69 != var71); + assume(var69 != var72); + assume(var69 != var73); + assume(var69 != var74); + assume(var70 != var71); + assume(var70 != var72); + assume(var70 != var73); + assume(var70 != var74); + assume(var71 != var72); + assume(var71 != var73); + assume(var71 != var74); + assume(var72 != var73); + assume(var72 != var74); + assume(var73 != var74); + assume(var75 != var76); + assume(var75 != var77); + assume(var75 != var78); + assume(var75 != var79); + assume(var75 != var80); + assume(var75 != var81); + assume(var75 != var82); + assume(var75 != var83); + assume(var75 != var84); + assume(var75 != var85); + assume(var75 != var86); + assume(var76 != var77); + assume(var76 != var78); + assume(var76 != var79); + assume(var76 != var80); + assume(var76 != var81); + assume(var76 != var82); + assume(var76 != var83); + assume(var76 != var84); + assume(var76 != var85); + assume(var76 != var86); + assume(var77 != var78); + assume(var77 != var79); + assume(var77 != var80); + assume(var77 != var81); + assume(var77 != var82); + assume(var77 != var83); + assume(var77 != var84); + assume(var77 != var85); + assume(var77 != var86); + assume(var78 != var79); + assume(var78 != var80); + assume(var78 != var81); + assume(var78 != var82); + assume(var78 != var83); + assume(var78 != var84); + assume(var78 != var85); + assume(var78 != var86); + assume(var79 != var80); + assume(var79 != var81); + assume(var79 != var82); + assume(var79 != var83); + assume(var79 != var84); + assume(var79 != var85); + assume(var79 != var86); + assume(var80 != var81); + assume(var80 != var82); + assume(var80 != var83); + assume(var80 != var84); + assume(var80 != var85); + assume(var80 != var86); + assume(var81 != var82); + assume(var81 != var83); + assume(var81 != var84); + assume(var81 != var85); + assume(var81 != var86); + assume(var82 != var83); + assume(var82 != var84); + assume(var82 != var85); + assume(var82 != var86); + assume(var83 != var84); + assume(var83 != var85); + assume(var83 != var86); + assume(var84 != var85); + assume(var84 != var86); + assume(var85 != var86); + assume(var87 != var88); + assume(var87 != var89); + assume(var87 != var90); + assume(var87 != var91); + assume(var87 != var92); + assume(var87 != var93); + assume(var87 != var94); + assume(var87 != var95); + assume(var87 != var96); + assume(var87 != var97); + assume(var88 != var89); + assume(var88 != var90); + assume(var88 != var91); + assume(var88 != var92); + assume(var88 != var93); + assume(var88 != var94); + assume(var88 != var95); + assume(var88 != var96); + assume(var88 != var97); + assume(var89 != var90); + assume(var89 != var91); + assume(var89 != var92); + assume(var89 != var93); + assume(var89 != var94); + assume(var89 != var95); + assume(var89 != var96); + assume(var89 != var97); + assume(var90 != var91); + assume(var90 != var92); + assume(var90 != var93); + assume(var90 != var94); + assume(var90 != var95); + assume(var90 != var96); + assume(var90 != var97); + assume(var91 != var92); + assume(var91 != var93); + assume(var91 != var94); + assume(var91 != var95); + assume(var91 != var96); + assume(var91 != var97); + assume(var92 != var93); + assume(var92 != var94); + assume(var92 != var95); + assume(var92 != var96); + assume(var92 != var97); + assume(var93 != var94); + assume(var93 != var95); + assume(var93 != var96); + assume(var93 != var97); + assume(var94 != var95); + assume(var94 != var96); + assume(var94 != var97); + assume(var95 != var96); + assume(var95 != var97); + assume(var96 != var97); + assume(var98 != var99); + assume(var98 != var100); + assume(var98 != var101); + assume(var98 != var102); + assume(var98 != var103); + assume(var98 != var104); + assume(var98 != var105); + assume(var98 != var106); + assume(var98 != var107); + assume(var99 != var100); + assume(var99 != var101); + assume(var99 != var102); + assume(var99 != var103); + assume(var99 != var104); + assume(var99 != var105); + assume(var99 != var106); + assume(var99 != var107); + assume(var100 != var101); + assume(var100 != var102); + assume(var100 != var103); + assume(var100 != var104); + assume(var100 != var105); + assume(var100 != var106); + assume(var100 != var107); + assume(var101 != var102); + assume(var101 != var103); + assume(var101 != var104); + assume(var101 != var105); + assume(var101 != var106); + assume(var101 != var107); + assume(var102 != var103); + assume(var102 != var104); + assume(var102 != var105); + assume(var102 != var106); + assume(var102 != var107); + assume(var103 != var104); + assume(var103 != var105); + assume(var103 != var106); + assume(var103 != var107); + assume(var104 != var105); + assume(var104 != var106); + assume(var104 != var107); + assume(var105 != var106); + assume(var105 != var107); + assume(var106 != var107); + assume(var108 != var109); + assume(var108 != var110); + assume(var108 != var111); + assume(var108 != var112); + assume(var108 != var113); + assume(var108 != var114); + assume(var108 != var115); + assume(var108 != var116); + assume(var109 != var110); + assume(var109 != var111); + assume(var109 != var112); + assume(var109 != var113); + assume(var109 != var114); + assume(var109 != var115); + assume(var109 != var116); + assume(var110 != var111); + assume(var110 != var112); + assume(var110 != var113); + assume(var110 != var114); + assume(var110 != var115); + assume(var110 != var116); + assume(var111 != var112); + assume(var111 != var113); + assume(var111 != var114); + assume(var111 != var115); + assume(var111 != var116); + assume(var112 != var113); + assume(var112 != var114); + assume(var112 != var115); + assume(var112 != var116); + assume(var113 != var114); + assume(var113 != var115); + assume(var113 != var116); + assume(var114 != var115); + assume(var114 != var116); + assume(var115 != var116); + assume(var117 != var118); + assume(var117 != var119); + assume(var117 != var120); + assume(var117 != var121); + assume(var117 != var122); + assume(var117 != var123); + assume(var117 != var124); + assume(var118 != var119); + assume(var118 != var120); + assume(var118 != var121); + assume(var118 != var122); + assume(var118 != var123); + assume(var118 != var124); + assume(var119 != var120); + assume(var119 != var121); + assume(var119 != var122); + assume(var119 != var123); + assume(var119 != var124); + assume(var120 != var121); + assume(var120 != var122); + assume(var120 != var123); + assume(var120 != var124); + assume(var121 != var122); + assume(var121 != var123); + assume(var121 != var124); + assume(var122 != var123); + assume(var122 != var124); + assume(var123 != var124); + assume(var125 != var126); + assume(var125 != var127); + assume(var125 != var128); + assume(var125 != var129); + assume(var125 != var130); + assume(var125 != var131); + assume(var126 != var127); + assume(var126 != var128); + assume(var126 != var129); + assume(var126 != var130); + assume(var126 != var131); + assume(var127 != var128); + assume(var127 != var129); + assume(var127 != var130); + assume(var127 != var131); + assume(var128 != var129); + assume(var128 != var130); + assume(var128 != var131); + assume(var129 != var130); + assume(var129 != var131); + assume(var130 != var131); + assume(var132 != var133); + assume(var132 != var134); + assume(var132 != var135); + assume(var132 != var136); + assume(var132 != var137); + assume(var133 != var134); + assume(var133 != var135); + assume(var133 != var136); + assume(var133 != var137); + assume(var134 != var135); + assume(var134 != var136); + assume(var134 != var137); + assume(var135 != var136); + assume(var135 != var137); + assume(var136 != var137); + assume(var138 != var139); + assume(var138 != var140); + assume(var138 != var141); + assume(var138 != var142); + assume(var139 != var140); + assume(var139 != var141); + assume(var139 != var142); + assume(var140 != var141); + assume(var140 != var142); + assume(var141 != var142); + assume(var143 != var144); + assume(var143 != var145); + assume(var143 != var146); + assume(var144 != var145); + assume(var144 != var146); + assume(var145 != var146); + assume(var147 != var148); + assume(var147 != var149); + assume(var148 != var149); + assume(var0 - var1 == var17); + assume(var1 - var2 == var18); + assume(var2 - var3 == var19); + assume(var3 - var4 == var20); + assume(var4 - var5 == var21); + assume(var5 - var6 == var22); + assume(var6 - var7 == var23); + assume(var7 - var8 == var24); + assume(var8 - var9 == var25); + assume(var9 - var10 == var26); + assume(var10 - var11 == var27); + assume(var11 - var12 == var28); + assume(var12 - var13 == var29); + assume(var13 - var14 == var30); + assume(var14 - var15 == var31); + assume(var15 - var16 == var32); + assume(var0 - var2 == var33); + assume(var1 - var3 == var34); + assume(var2 - var4 == var35); + assume(var3 - var5 == var36); + assume(var4 - var6 == var37); + assume(var5 - var7 == var38); + assume(var6 - var8 == var39); + assume(var7 - var9 == var40); + assume(var8 - var10 == var41); + assume(var9 - var11 == var42); + assume(var10 - var12 == var43); + assume(var11 - var13 == var44); + assume(var12 - var14 == var45); + assume(var13 - var15 == var46); + assume(var14 - var16 == var47); + assume(var0 - var3 == var48); + assume(var1 - var4 == var49); + assume(var2 - var5 == var50); + assume(var3 - var6 == var51); + assume(var4 - var7 == var52); + assume(var5 - var8 == var53); + assume(var6 - var9 == var54); + assume(var7 - var10 == var55); + assume(var8 - var11 == var56); + assume(var9 - var12 == var57); + assume(var10 - var13 == var58); + assume(var11 - var14 == var59); + assume(var12 - var15 == var60); + assume(var13 - var16 == var61); + assume(var0 - var4 == var62); + assume(var1 - var5 == var63); + assume(var2 - var6 == var64); + assume(var3 - var7 == var65); + assume(var4 - var8 == var66); + assume(var5 - var9 == var67); + assume(var6 - var10 == var68); + assume(var7 - var11 == var69); + assume(var8 - var12 == var70); + assume(var9 - var13 == var71); + assume(var10 - var14 == var72); + assume(var11 - var15 == var73); + assume(var12 - var16 == var74); + assume(var0 - var5 == var75); + assume(var1 - var6 == var76); + assume(var2 - var7 == var77); + assume(var3 - var8 == var78); + assume(var4 - var9 == var79); + assume(var5 - var10 == var80); + assume(var6 - var11 == var81); + assume(var7 - var12 == var82); + assume(var8 - var13 == var83); + assume(var9 - var14 == var84); + assume(var10 - var15 == var85); + assume(var11 - var16 == var86); + assume(var0 - var6 == var87); + assume(var1 - var7 == var88); + assume(var2 - var8 == var89); + assume(var3 - var9 == var90); + assume(var4 - var10 == var91); + assume(var5 - var11 == var92); + assume(var6 - var12 == var93); + assume(var7 - var13 == var94); + assume(var8 - var14 == var95); + assume(var9 - var15 == var96); + assume(var10 - var16 == var97); + assume(var0 - var7 == var98); + assume(var1 - var8 == var99); + assume(var2 - var9 == var100); + assume(var3 - var10 == var101); + assume(var4 - var11 == var102); + assume(var5 - var12 == var103); + assume(var6 - var13 == var104); + assume(var7 - var14 == var105); + assume(var8 - var15 == var106); + assume(var9 - var16 == var107); + assume(var0 - var8 == var108); + assume(var1 - var9 == var109); + assume(var2 - var10 == var110); + assume(var3 - var11 == var111); + assume(var4 - var12 == var112); + assume(var5 - var13 == var113); + assume(var6 - var14 == var114); + assume(var7 - var15 == var115); + assume(var8 - var16 == var116); + assume(var0 - var9 == var117); + assume(var1 - var10 == var118); + assume(var2 - var11 == var119); + assume(var3 - var12 == var120); + assume(var4 - var13 == var121); + assume(var5 - var14 == var122); + assume(var6 - var15 == var123); + assume(var7 - var16 == var124); + assume(var0 - var10 == var125); + assume(var1 - var11 == var126); + assume(var2 - var12 == var127); + assume(var3 - var13 == var128); + assume(var4 - var14 == var129); + assume(var5 - var15 == var130); + assume(var6 - var16 == var131); + assume(var0 - var11 == var132); + assume(var1 - var12 == var133); + assume(var2 - var13 == var134); + assume(var3 - var14 == var135); + assume(var4 - var15 == var136); + assume(var5 - var16 == var137); + assume(var0 - var12 == var138); + assume(var1 - var13 == var139); + assume(var2 - var14 == var140); + assume(var3 - var15 == var141); + assume(var4 - var16 == var142); + assume(var0 - var13 == var143); + assume(var1 - var14 == var144); + assume(var2 - var15 == var145); + assume(var3 - var16 == var146); + assume(var0 - var14 == var147); + assume(var1 - var15 == var148); + assume(var2 - var16 == var149); + assume((var0 - var15) != (var1 - var16)); + reach_error(); + return 0; /* 0 x[0]1 x[1]2 x[2]3 x[3]4 x[4]5 x[5]6 x[6]7 x[7]8 x[8]9 x[9]10 + x[10]11 x[11]12 x[12]13 x[13]14 x[14]15 x[15]16 x[16]17 y[0]18 + y[1]19 y[2]20 y[3]21 y[4]22 y[5]23 y[6]24 y[7]25 y[8]26 y[9]27 + y[10]28 y[11]29 y[12]30 y[13]31 y[14]32 y[15]33 y[16]34 y[17]35 + y[18]36 y[19]37 y[20]38 y[21]39 y[22]40 y[23]41 y[24]42 y[25]43 + y[26]44 y[27]45 y[28]46 y[29]47 y[30]48 y[31]49 y[32]50 y[33]51 + y[34]52 y[35]53 y[36]54 y[37]55 y[38]56 y[39]57 y[40]58 y[41]59 + y[42]60 y[43]61 y[44]62 y[45]63 y[46]64 y[47]65 y[48]66 y[49]67 + y[50]68 y[51]69 y[52]70 y[53]71 y[54]72 y[55]73 y[56]74 y[57]75 + y[58]76 y[59]77 y[60]78 y[61]79 y[62]80 y[63]81 y[64]82 y[65]83 + y[66]84 y[67]85 y[68]86 y[69]87 y[70]88 y[71]89 y[72]90 y[73]91 + y[74]92 y[75]93 y[76]94 y[77]95 y[78]96 y[79]97 y[80]98 y[81]99 + y[82]100 y[83]101 y[84]102 y[85]103 y[86]104 y[87]105 y[88]106 + y[89]107 y[90]108 y[91]109 y[92]110 y[93]111 y[94]112 y[95]113 + y[96]114 y[97]115 y[98]116 y[99]117 y[100]118 y[101]119 y[102]120 + y[103]121 y[104]122 y[105]123 y[106]124 y[107]125 y[108]126 + y[109]127 y[110]128 y[111]129 y[112]130 y[113]131 y[114]132 + y[115]133 y[116]134 y[117]135 y[118]136 y[119]137 y[120]138 + y[121]139 y[122]140 y[123]141 y[124]142 y[125]143 y[126]144 + y[127]145 y[128]146 y[129]147 y[130]148 y[131]149 y[132] */ +} \ No newline at end of file diff --git a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c new file mode 100644 index 0000000000..9d433194b3 --- /dev/null +++ b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c @@ -0,0 +1,110 @@ +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --max-solver-time=5s --track-coverage=branches --use-iterative-deepening-search=max-cycles --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=all --search=dfs --search=random-state %t1.bc + +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// CHECK: Lines executed:87.93% of 58 +// CHECK-NEXT: Branches executed:100.00% of 18 +// CHECK-NEXT: Taken at least once:83.33% of 18 + +#include "klee-test-comp.c" +/* extended Euclid's algorithm */ +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); +#endif +} + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "egcd3-ll.c", 4, "reach_error"); } +extern int __VERIFIER_nondet_int(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort_prog();} +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: + {reach_error();} + } + return; +} + +int main() { + int x, y; + long long a, b, p, q, r, s; + x = __VERIFIER_nondet_int(); + assume_abort_if_not(x>=0 && x<=10); + y = __VERIFIER_nondet_int(); + assume_abort_if_not(y>=0 && y<=10); + assume_abort_if_not(x >= 1); + assume_abort_if_not(y >= 1); + + a = x; + b = y; + p = 1; + q = 0; + r = 0; + s = 1; + + while (1) { + if (!(b != 0)) + break; + long long c, k; + c = a; + k = 0; + + while (1) { + if (!(c >= b)) + break; + long long d, v; + d = 1; + v = b; + + while (1) { + __VERIFIER_assert(a == y * r + x * p); + __VERIFIER_assert(b == x * q + y * s); + __VERIFIER_assert(a == k * b + c); + __VERIFIER_assert(v == b * d); + + if (!(c >= 2 * v)) + break; + d = 2 * d; + v = 2 * v; + } + c = c - v; + k = k + d; + } + + a = b; + b = c; + long long temp; + temp = p; + p = q; + q = temp - q * k; + temp = r; + r = s; + s = temp - s * k; + } + __VERIFIER_assert(p*x - q*x + r*y - s*y == a); + return 0; +} diff --git a/test/Industry/CoverageBranches/lit.local.cfg b/test/Industry/CoverageBranches/lit.local.cfg new file mode 100644 index 0000000000..ad131f8f64 --- /dev/null +++ b/test/Industry/CoverageBranches/lit.local.cfg @@ -0,0 +1,8 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +rootConfig = getRoot(config) +if config.have_asan or config.have_ubsan or config.have_msan or config.target_triple.find("darwin") != -1: + config.unsupported = True diff --git a/test/Industry/CoverageBranches/matrix-2-2.c b/test/Industry/CoverageBranches/matrix-2-2.c new file mode 100644 index 0000000000..6170da72fe --- /dev/null +++ b/test/Industry/CoverageBranches/matrix-2-2.c @@ -0,0 +1,68 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=all --max-cycles=2 --optimize=true --emit-all-errors --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=all --use-sym-size-alloc=true --symbolic-allocation-threshold=8192 %t1.bc 2>&1 + +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK-COV %s + +// Branch coverage is greater 80%: +// CHECK-COV: Lines executed:9{{([0-9]\.[0-9][0-9])}}% of 24 +// CHECK-COV-NEXT: Branches executed:100.00% of 16 +// CHECK-COV-NEXT: Taken at least once:{{([8-9][0-9]\.[0-9][0-9])}}% of 16 + +#include "klee-test-comp.c" + +extern void exit(int); +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#endif +} + +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "matrix-2-2.c", 3, "reach_error"); } + +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: {reach_error();abort();} + } + return; +} +extern unsigned int __VERIFIER_nondet_uint(); +extern int __VERIFIER_nondet_int(); + +int main() +{ + unsigned int N_LIN=__VERIFIER_nondet_uint(); + unsigned int N_COL=__VERIFIER_nondet_uint(); + if (N_LIN >= 4000000000 / sizeof(int) || N_COL >= 4000000000 / sizeof(int)) { + return 0; + } + unsigned int j,k; + int matriz[N_COL][N_LIN], maior; + + maior = __VERIFIER_nondet_int(); + for(j=0;jmaior) + maior = matriz[j][k]; + } + + for(j=0;j %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// CHECK: Lines executed:{{(9[0-9]\.[0-9][0-9])}}% of 4114 +// CHECK-NEXT: Branches executed:{{(9[0-9]\.[0-9][0-9])}}% of 13404 +// CHECK-NEXT: Taken at least once:{{(8[0-9]\.[0-9][0-9])}}% of 13404 + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2012 The RERS Challenge +// SPDX-FileCopyrightText: 2013 Carnegie Mellon University +// SPDX-FileCopyrightText: 2014-2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: LicenseRef-BSD-3-Clause-Attribution-CMU +#include "klee-test-comp.c" + +extern unsigned int __VERIFIER_nondet_uint(); +extern char __VERIFIER_nondet_char(); +extern int __VERIFIER_nondet_int(); +extern long __VERIFIER_nondet_long(); +extern unsigned long __VERIFIER_nondet_ulong(); +extern float __VERIFIER_nondet_float(); +extern void exit(int); +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#endif +} + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "pals_lcr.3.ufo.UNBOUNDED.pals.c", 3, "reach_error"); } + + +/* Generated by CIL v. 1.6.0 */ +/* print_CIL_Input is true */ + +_Bool __VERIFIER_nondet_bool(void) ; +char __VERIFIER_nondet_char(void) ; +unsigned char __VERIFIER_nondet_uchar(void) ; +void assert(_Bool arg ) ; +void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort_prog();} +} +typedef char msg_t; +typedef int port_t; +extern void read(port_t p , msg_t m ) ; +extern void write(port_t p , msg_t m ) ; +msg_t nomsg = (msg_t )-1; +unsigned char r1 ; +port_t p1 ; +char p1_old ; +char p1_new ; +char id1 ; +char st1 ; +msg_t send1 ; +_Bool mode1 ; +port_t p2 ; +char p2_old ; +char p2_new ; +char id2 ; +char st2 ; +msg_t send2 ; +_Bool mode2 ; +port_t p3 ; +char p3_old ; +char p3_new ; +char id3 ; +char st3 ; +msg_t send3 ; +_Bool mode3 ; +void node1(void) +{ + msg_t m1 ; + + { + m1 = nomsg; + if (mode1) { + if (r1 == 255) { + r1 = 2; + } + r1 = r1 + 1; + m1 = p3_old; + p3_old = nomsg; + if ((int )m1 != (int )nomsg) { + if ((int )m1 > (int )id1) { + send1 = m1; + } else + if ((int )m1 == (int )id1) { + st1 = (char)1; + } + } + mode1 = (_Bool)0; + } else { + p1_new = send1 != nomsg && p1_new == nomsg ? send1 : p1_new; + mode1 = (_Bool)1; + } + return; +} +} +void node2(void) +{ + msg_t m2 ; + + { + m2 = nomsg; + if (mode2) { + m2 = p1_old; + p1_old = nomsg; + if ((int )m2 != (int )nomsg) { + if ((int )m2 > (int )id2) { + send2 = m2; + } else + if ((int )m2 == (int )id2) { + st2 = (char)1; + } + } + mode2 = (_Bool)0; + } else { + p2_new = send2 != nomsg && p2_new == nomsg ? send2 : p2_new; + mode2 = (_Bool)1; + } + return; +} +} +void node3(void) +{ + msg_t m3 ; + + { + m3 = nomsg; + if (mode3) { + m3 = p2_old; + p2_old = nomsg; + if ((int )m3 != (int )nomsg) { + if ((int )m3 > (int )id3) { + send3 = m3; + } else + if ((int )m3 == (int )id3) { + st3 = (char)1; + } + } + mode3 = (_Bool)0; + } else { + p3_new = send3 != nomsg && p3_new == nomsg ? send3 : p3_new; + mode3 = (_Bool)1; + } + return; +} +} +int init(void) +{ + int tmp ; + + { + if ((int )r1 == 0) { + if ((int )id1 >= 0) { + if ((int )st1 == 0) { + if ((int )send1 == (int )id1) { + if ((int )mode1 == 0) { + if ((int )id2 >= 0) { + if ((int )st2 == 0) { + if ((int )send2 == (int )id2) { + if ((int )mode2 == 0) { + if ((int )id3 >= 0) { + if ((int )st3 == 0) { + if ((int )send3 == (int )id3) { + if ((int )mode3 == 0) { + if ((int )id1 != (int )id2) { + if ((int )id1 != (int )id3) { + if ((int )id2 != (int )id3) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + return (tmp); +} +} +int check(void) +{ + int tmp ; + + { + if (((int )st1 + (int )st2) + (int )st3 <= 1) { + if ((int )r1 >= 3) { + goto _L; + } else + if (((int )st1 + (int )st2) + (int )st3 == 0) { + _L: /* CIL Label */ + if ((int )r1 < 3) { + tmp = 1; + } else + if (((int )st1 + (int )st2) + (int )st3 == 1) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + return (tmp); +} +} +int main1(void) +{ + int c1 ; + int i2 ; + + { + c1 = 0; + r1 = __VERIFIER_nondet_uchar(); + id1 = __VERIFIER_nondet_char(); + st1 = __VERIFIER_nondet_char(); + send1 = __VERIFIER_nondet_char(); + mode1 = __VERIFIER_nondet_bool(); + id2 = __VERIFIER_nondet_char(); + st2 = __VERIFIER_nondet_char(); + send2 = __VERIFIER_nondet_char(); + mode2 = __VERIFIER_nondet_bool(); + id3 = __VERIFIER_nondet_char(); + st3 = __VERIFIER_nondet_char(); + send3 = __VERIFIER_nondet_char(); + mode3 = __VERIFIER_nondet_bool(); + i2 = init(); + assume_abort_if_not(i2); + p1_old = nomsg; + p1_new = nomsg; + p2_old = nomsg; + p2_new = nomsg; + p3_old = nomsg; + p3_new = nomsg; + i2 = 0; + while (1) { + { + node1(); + node2(); + node3(); + p1_old = p1_new; + p1_new = nomsg; + p2_old = p2_new; + p2_new = nomsg; + p3_old = p3_new; + p3_new = nomsg; + c1 = check(); + assert(c1); + } + } +} +return 0; +} +void assert(_Bool arg ) +{ + + + { + if (! arg) { + { + ERROR: {reach_error();abort();} + } + } +} +} + +int calculate_output(int); +int calculate_output2(int); +int calculate_output3(int); +int calculate_output4(int); +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +extern int __VERIFIER_nondet_int(void); +extern void exit(int); + + // inputs + int inputC = 3; + int inputF = 6; + int inputA = 1; + int inputB = 2; + int inputD = 4; + int inputE = 5; + + + int a17 = -124; + int a5 = 4; + int a24 = 15; + int a2 = 170; + int a7 = 13; + + int calculate_output2(int input); + int calculate_output3(int input); + int calculate_output4(int input); + + int calculate_output(int input) { + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==3))){ + error_7: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==4))){ + error_35: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==4))){ + error_55: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==4))){ + error_40: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==4))){ + error_48: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==4))){ + error_51: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==3))){ + error_20: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==4))){ + error_37: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==3))){ + error_19: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==3))){ + error_0: {reach_error();abort();} + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==15)) && (a5==3))){ + error_34: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==3))){ + error_25: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==4))){ + error_50: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==3))){ + error_3: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==3))){ + error_28: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==4))){ + error_39: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==3))){ + error_21: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==3))){ + error_6: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==4))){ + error_38: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==3))){ + error_30: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==4))){ + error_42: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==3))){ + error_10: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==3))){ + error_13: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==3))){ + error_8: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==4))){ + error_52: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==3))){ + error_27: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==4))){ + error_53: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==4))){ + error_54: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==4))){ + error_58: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==3))){ + error_23: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==3))){ + globalError: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==4))){ + error_57: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==4))){ + error_47: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==3))){ + error_11: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==3))){ + error_17: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==4))){ + error_43: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==4))){ + error_49: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==15)) && (a5==3))){ + error_32: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==4))){ + error_59: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==3))){ + error_26: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==3))){ + error_24: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==3))){ + error_1: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==3))){ + error_14: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==15)) && (a5==3))){ + error_33: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==4))){ + error_44: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==4))){ + error_45: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==4))){ + error_41: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==3))){ + error_18: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==3))){ + error_15: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==3))){ + error_29: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==4))){ + error_56: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==4))){ + error_36: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==3))){ + error_12: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==3))){ + error_5: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==3))){ + error_4: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==4))){ + error_46: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==3))){ + error_2: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==3))){ + error_31: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==3))){ + error_22: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==3))){ + error_16: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==3))){ + error_9: exit(0); + } + + if(((( ((189 < a2) && (281 >= a2)) && ((input == 4) && (((a7==12) && 255 < a17 ) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))))) && (a5==4)) && (a24==14))){ + a17 = (((((a17 % 109)+ -11) - 547674) + -15873) - -563482); + a7 = 12; + + return -1; + } else if(((((a24==13) && (((input == 2) && ((a7==13) || (a7==14))) && (a5==3))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) - -478038) / -5); + a7 = 12; + + return -1; + } else if((((((((a7==12) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14)))) && (input == 1)) && (a24==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a2 = (((a2 - 384978) + -172247) * 1); + a17 = (((a17 * 5) + 542386) * 1); + a7 = 12; + a5 = 7; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && (((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 4))) && (a5==3)) && (a24==14))){ + a2 = ((((a2 + -131864) * 10)/ 9) - 73578); + a17 = ((((a17 - 0) % 299946)+ -300053) * 1); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==6) && (((a24==13) && ((input == 6) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ( 255 < a17 && (a7==12))))) && a2 <= 189 ))){ + a2 = (((((a2 * 9)/ 10) % 45)+ 236) * 1); + a17 = ((((a17 + -100855) - 172157) / 5) + 357533); + a7 = 13; + a24 = 14; + a5 = 3; + + return 23; + } else if((((a24==13) && ( ((189 < a2) && (281 >= a2)) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12))) && (input == 3)))) && (a5==6))){ + a17 = ((((a17 / 5) % 109)- -2) - 41); + a7 = 12; + + return -1; + } else if(((a5==4) && ( a2 <= 189 && ((((input == 1) && ((a7==13) || (a7==14))) && a17 <= -108 ) && (a24==15))))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ((( ((189 < a2) && (281 >= a2)) && ((input == 1) && (a5==4))) && (a7==13)) && 255 < a17 ))){ + a17 = ((((a17 % 71)+ 119) * 1) + -2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 4)))))){ + a2 = (((a2 + 448263) + -951842) * 1); + a17 = (((a17 * 5) / 5) + -274764); + a7 = 14; + a24 = 15; + a5 = 5; + + return -1; + } else if(((((a5==5) && ( a2 <= 189 && ((input == 1) && (a24==15)))) && 255 < a17 ) && (a7==14))){ + a2 = (((((a2 % 45)+ 236) * 5) % 45)- -199); + a7 = 13; + a24 = 14; + + return 26; + } else if((( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && ((((a7==14) || ((a7==12) || (a7==13))) && (input == 1)) && (a24==15)))) && (a5==5))){ + a17 = (((((a17 % 109)+ 16) * 5) % 109)- -2); + a7 = 14; + a24 = 13; + + return -1; + } else if((( a17 <= -108 && (( ((189 < a2) && (281 >= a2)) && (((a7==12) || (a7==13)) && (input == 5))) && (a24==13))) && (a5==6))){ + a17 = (((((a17 + 0) - -350799) - -197891) % 71)- -182); + a7 = 14; + a24 = 14; + a5 = 4; + + return -1; + } else if((((a24==13) && ( a17 <= -108 && (((a5==4) && (input == 2)) && ((189 < a2) && (281 >= a2)) ))) && (a7==12))){ + a17 = ((((((a17 - 0) * 9)/ 10) / 5) % 109)- -93); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a5==3) && ( ((-108 < a17) && (111 >= a17)) && ((a24==13) && (((a7==12) || (a7==13)) && (input == 4))))) && ((189 < a2) && (281 >= a2)) )){ + + a7 = 12; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && ((a5==4) && ( a2 <= 189 && ((a24==15) && (((a7==13) || (a7==14)) && (input == 5))))))){ + a17 = ((((a17 - 135275) * 10)/ 9) * 3); + a7 = 13; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && ((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 6)) && (a5==7)) && (a24==13)))){ + a17 = ((((a17 % 109)+ 2) - 1) - -2); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(((((((a24==13) && ( a17 <= -108 && (a7==13))) && (a5==5)) || (((a5==4) && ((a24==15) && ((a7==14) && 255 < a17 ))) || ((a5==5) && ((a24==13) && ((a7==12) && a17 <= -108 ))))) && (input == 1)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 - 0) % 109)- -2) + -577173) + 577173); + a7 = 14; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a24==13) && ((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) )) && (a5==3)) && a17 <= -108 )){ + a2 = (((a2 + -532580) * 1) + -62227); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if((((a5==4) && ((((input == 5) && ((a7==12) || (a7==13))) && (a24==14)) && ((189 < a2) && (281 >= a2)) )) && a17 <= -108 )){ + a2 = (((a2 * 5) / -5) / 5); + a17 = (((((a17 % 109)+ 4) * 5) % 109)+ 1); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a24==14) && ((a5==3) && (((( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 ))) && (input == 2)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 - 260500) / 5) + -428690); + a17 = ((((a17 % 71)- -184) * 1) - -1); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if(((((a5==4) && (((input == 1) && (a24==15)) && ((-108 < a17) && (111 >= a17)) )) && a2 <= 189 ) && (a7==12))){ + + a24 = 13; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && (((a5==4) && (((input == 2) && (a24==15)) && (a7==12))) && ((-108 < a17) && (111 >= a17)) ))){ + + a7 = 14; + a24 = 13; + a5 = 5; + + return 26; + } else if(((a24==13) && ( ((-108 < a17) && (111 >= a17)) && ((a5==5) && (((input == 2) && a2 <= 189 ) && (a7==14)))))){ + + a7 = 13; + a24 = 15; + a5 = 6; + + return 26; + } else if(( a2 <= 189 && ((((a5==5) && ((input == 3) && (a24==13))) && (a7==14)) && ((111 < a17) && (255 >= a17)) ))){ + a17 = (((a17 * 5) + -131690) - 406420); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((((a5==5) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a7==13)) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 / 5) - 248849) * 2); + a17 = ((((a17 / 5) * 5) / 5) - 458249); + a7 = 12; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((input == 6) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))) && (a24==15))) && (a5==3))){ + a17 = ((((a17 - -260026) + 97662) * 10)/ 9); + a7 = 12; + a24 = 14; + + return -1; + } else if((((a5==7) && ((( ((-108 < a17) && (111 >= a17)) && (input == 1)) && (a7==13)) && a2 <= 189 )) && (a24==14))){ + a17 = ((((a17 % 71)+ 184) - -1) - 1); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && ((a5==5) && ( ((111 < a17) && (255 >= a17)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 6))))))){ + a17 = (((a17 - 33426) - 518487) - 34791); + a7 = 13; + a5 = 4; + + return -1; + } else if((( a2 <= 189 && (( 255 < a17 && ((input == 3) && ((a7==13) || (a7==14)))) && (a5==7))) && (a24==15))){ + a17 = ((((a17 - 593212) - -274925) - -137841) + -419796); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==13) && ( ((-108 < a17) && (111 >= a17)) && ((input == 4) && ((a7==12) || (a7==13)))))) && (a5==6))){ + a2 = (((a2 - 356828) + -57766) * 1); + a7 = 14; + + return 26; + } else if(( a17 <= -108 && (((((input == 5) && ((a7==12) || (a7==13))) && (a5==5)) && ((189 < a2) && (281 >= a2)) ) && (a24==14)))){ + a2 = (((a2 - 367280) / 5) + -340709); + a17 = (((((a17 % 299872)+ 300127) * 1) + -276171) + 347263); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((a5==5) && ((input == 6) && (((a24==14) && ((a7==13) && a17 <= -108 )) || (((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ((a7==12) && a17 <= -108 )))))))){ + a17 = (((((a17 - 0) % 299946)+ -300053) - -266634) + -266635); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==6) && ((a24==13) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )) && (input == 1)))) && a2 <= 189 )){ + a17 = ((((a17 + -600109) - 2) / 5) - 329060); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==7) && ((((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ( ((-108 < a17) && (111 >= a17)) && (a7==13))) && (input == 4)) && a2 <= 189 )) && (a24==13))){ + a2 = ((((a2 / 5) - 178027) % 45)- -249); + a17 = ((((a17 / 5) - 189029) * 10)/ 9); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && ((a24==15) && ((((input == 6) && ((a7==13) || (a7==14))) && (a5==4)) && ((-108 < a17) && (111 >= a17)) )))){ + a17 = ((((a17 - -591336) + -371053) * -1)/ 10); + a7 = 14; + a24 = 14; + a5 = 5; + + return 21; + } else if((( ((189 < a2) && (281 >= a2)) && ((((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 3)) && (a5==3))) && (a24==14))){ + a2 = (((a2 * -5) * 5) - 39358); + a17 = ((((a17 % 109)- -1) + -513301) + 513302); + a7 = 13; + a5 = 5; + + return 26; + } else if((((a24==13) && (((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12))) && (input == 2)) && (a5==4))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 * -5) + -139298) * 10)/ 9); + a17 = (((a17 - 600110) - 0) * 1); + a7 = 12; + a5 = 3; + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (((a5==5) && (input == 4)) && a2 <= 189 )) && (a7==14)) && (a24==15))){ + a2 = ((((a2 / 5) + -370165) % 45)- -261); + a17 = (((a17 + 573666) * 1) + -329578); + a7 = 12; + a5 = 4; + + return 21; + } else if(((((((a7==12) && (input == 6)) && ((189 < a2) && (281 >= a2)) ) && (a5==4)) && (a24==13)) && a17 <= -108 )){ + + return 21; + } else if(((a24==15) && ((a5==6) && ((((a7==12) && (input == 6)) && a17 <= -108 ) && a2 <= 189 )))){ + a2 = ((((((a2 * 9)/ 10) + -20706) + -31885) % 45)- -245); + a17 = ((((a17 % 109)- -26) / 5) * 5); + a5 = 3; + + return 23; + } else if((( ((111 < a17) && (255 >= a17)) && ((a24==15) && ((a5==6) && ((a7==12) && (input == 6))))) && a2 <= 189 )){ + a2 = ((((a2 - 0) + 15546) % 45)+ 235); + a17 = (((a17 * 5) - -401693) - -144036); + a5 = 3; + + return 23; + } else if((((((a24==14) && ((input == 4) && ((a7==12) || (a7==13)))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a17 = ((((((a17 % 71)- -223) * 10)/ 9) * 9)/ 10); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if(((a24==13) && (( ((111 < a17) && (255 >= a17)) && (((input == 6) && ((a7==12) || (a7==13))) && (a5==4))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 - 188462) * 3) + -6); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a24==15) && ( a2 <= 189 && ((((a7==12) || (a7==13)) && (input == 6)) && (a5==5)))) && 255 < a17 )){ + a17 = (((a17 + -66404) - -20679) + -554407); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a7==12) && ((a24==15) && ((a5==6) && ((input == 2) && a2 <= 189 )))) && a17 <= -108 )){ + a2 = (((((a2 % 45)+ 235) * 1) - -275959) + -275957); + a17 = (((((a17 % 71)+ 208) / 5) * 10)/ 2); + a7 = 13; + a24 = 13; + a5 = 3; + + return 23; + } else if(((a5==6) && ((((a7==12) && ((input == 3) && (a24==13))) && a2 <= 189 ) && a17 <= -108 ))){ + a2 = ((((a2 / 5) + 158559) % 45)+ 204); + a17 = (((((a17 % 109)+ 75) - 24) + 175099) - 175127); + a24 = 15; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && ((((a24==15) && (input == 6)) && (a5==4)) && (a7==12))))){ + a17 = (((a17 + -497569) + 497379) - -33); + a7 = 14; + a24 = 14; + a5 = 5; + + return 26; + } else if((((a5==6) && (((input == 2) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && (a24==13))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / -5) * 10)/ 9) + -424739); + a17 = (((a17 + -600109) * 1) + -3); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && ((a5==4) && ((((a7==12) || (a7==13)) && (input == 6)) && a2 <= 189 ))) && 255 < a17 )){ + + a7 = 14; + a5 = 5; + + return 26; + } else if((((( ((189 < a2) && (281 >= a2)) && ((input == 6) && (a5==4))) && (a24==15)) && ((-108 < a17) && (111 >= a17)) ) && (a7==13))){ + a17 = (((a17 - 534822) - -388608) * 4); + a7 = 14; + a24 = 14; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && (((a24==13) && ((a5==4) && (((a7==13) || (a7==14)) && (input == 5)))) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if(( a17 <= -108 && ((a24==14) && (( a2 <= 189 && ((input == 3) && ((a7==13) || (a7==14)))) && (a5==6))))){ + a2 = ((((a2 / 5) * 4) % 45)+ 236); + a17 = ((((a17 - -556050) % 109)- -1) - 0); + a7 = 12; + a5 = 3; + + return 21; + } else if(( a2 <= 189 && (((a5==4) && ( 255 < a17 && (((a7==12) || (a7==13)) && (input == 1)))) && (a24==15)))){ + a17 = ((((a17 + -600240) / 5) * 10)/ 4); + a7 = 14; + a24 = 13; + a5 = 6; + + return 23; + } else if(((a5==7) && (((a24==14) && ((input == 2) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14)))))) && a2 <= 189 ))){ + a17 = ((((a17 % 299946)+ -300053) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==14) && (((a7==13) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && ((-108 < a17) && (111 >= a17)) ))) && (a5==4)))){ + a2 = (((a2 / 5) / -5) * 5); + a7 = 14; + a24 = 13; + + return -1; + } else if(((((a5==5) && (((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ((a7==13) && ((-108 < a17) && (111 >= a17)) )) && (input == 6))) && (a24==13)) && a2 <= 189 )){ + a17 = (((((a17 / 5) + 383422) + -411251) % 71)- -233); + a7 = 14; + a24 = 14; + a5 = 6; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a7==14) && ((a5==5) && (((a24==13) && (input == 6)) && a2 <= 189 ))))){ + a17 = (((a17 * 5) - 61428) + -534582); + a7 = 13; + a24 = 15; + a5 = 6; + + return 21; + } else if((( ((-108 < a17) && (111 >= a17)) && ((((input == 3) && ((a7==13) || (a7==14))) && (a5==6)) && (a24==15))) && a2 <= 189 )){ + a2 = (((((a2 + 39352) / 5) / 5) % 45)+ 234); + a7 = 12; + a24 = 14; + a5 = 3; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==14) && ((a7==13) && ((a5==3) && (input == 5)))) && ((111 < a17) && (255 >= a17)) ))){ + a2 = (((a2 - 43077) / 5) / 5); + a17 = (((a17 / 5) / 5) - -99709); + a7 = 12; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((a24==14) && ( ((-108 < a17) && (111 >= a17)) && (((input == 2) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==6)))))){ + a2 = (((((a2 % 45)- -235) - -2) - 444254) - -444251); + a7 = 13; + a5 = 3; + + return 26; + } else if(((a5==5) && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 2)) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ) && (a24==15)))){ + a2 = (((a2 + -159174) - 203606) + -130058); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && (( ((-108 < a17) && (111 >= a17)) && ((a24==14) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a5==5)))){ + a17 = (((a17 + -547450) / 5) + -82633); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 5) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))) && (a24==14)) && (a5==5)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -395244) - -867612) + -1020920); + a17 = (((((a17 % 299872)- -256) * 1) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==13) && ((((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 5)) && (a5==4)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = ((((a2 - 325121) * 10)/ 9) * 1); + a17 = (((((a17 % 71)+ 160) / 5) + -586476) - -586646); + a7 = 14; + a24 = 15; + + return 21; + } else if((((((a24==14) && (((a7==13) || (a7==14)) && (input == 4))) && ((189 < a2) && (281 >= a2)) ) && (a5==4)) && 255 < a17 )){ + a2 = (((a2 - -513398) * 1) * -1); + a17 = (((a17 + -11058) * 1) + -589131); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==6) && (((a24==13) && ((input == 2) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14)))))) && a2 <= 189 ))){ + a17 = (((a17 / 5) - -11377) - 448490); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==5) && ( ((-108 < a17) && (111 >= a17)) && (((a7==14) && (input == 5)) && (a24==13)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / -5) * 10)/ 9) - 571457); + a17 = ((((a17 - -227661) + 18143) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==4) && ((((((a7==12) && 255 < a17 ) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 3)) && (a24==14)) && ((189 < a2) && (281 >= a2)) ))){ + a17 = (((((a17 % 109)+ 3) + -187035) + 26490) + 160528); + a7 = 13; + + return -1; + } else if(((a7==14) && ((a5==5) && ((( ((-108 < a17) && (111 >= a17)) && (input == 2)) && (a24==13)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * -5) + -437978) + 281140); + a17 = ((((a17 * 5) / 5) / 5) - 83944); + a7 = 12; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((input == 1) && (a5==6)) && (a24==13)) && (a7==13))) && 255 < a17 )){ + a17 = (((a17 + -491213) - 108914) + -47); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if(((a5==6) && ( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((((a7==12) || (a7==13)) && (input == 2)) && (a24==13)))))){ + a2 = (((a2 + 391304) * -1) / 5); + a17 = (((a17 - 532893) - 26035) + -34319); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a5==4) && ((((a7==13) || (a7==14)) && (input == 5)) && a2 <= 189 )) && ((-108 < a17) && (111 >= a17)) ) && (a24==15))){ + a17 = (((((a17 * 5) % 71)- -183) + -26829) + 26828); + a7 = 13; + a24 = 13; + a5 = 5; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && (((((a24==13) && (input == 4)) && (a5==5)) && (a7==14)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * -5) * 5) - 149618); + a17 = (((a17 / 5) * 5) - 544978); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if((( a2 <= 189 && ((input == 4) && (((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ( a17 <= -108 && (a7==12)))))) && (a5==7))){ + a17 = ((((a17 / 5) - -3819) - 117000) - 285915); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ((a24==13) && ( a2 <= 189 && ((a7==14) && ( ((-108 < a17) && (111 >= a17)) && (input == 5))))))){ + a17 = ((((a17 - 51813) - -610607) * -1)/ 10); + a24 = 15; + a5 = 6; + + return 23; + } else if(((((a24==14) && ((input == 2) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )))) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) + -132328) + -282019); + a17 = (((a17 + -600110) * 1) - 2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a17 <= -108 && ((a5==4) && ( a2 <= 189 && ((input == 6) && ((a7==13) || (a7==14)))))) && (a24==15))){ + a17 = ((((((a17 % 109)- -74) * 5) * 5) % 109)- -2); + a7 = 14; + + return 21; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 2)))) && (a24==13))){ + a2 = ((((a2 / -5) + 8939) * 5) - 171471); + a17 = ((((a17 + -514608) + 103914) % 109)+ 2); + a7 = 14; + a5 = 7; + + return -1; + } else if(( 255 < a17 && ((a5==3) && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && ((189 < a2) && (281 >= a2)) ) && (a24==15))))){ + + a7 = 13; + a24 = 13; + + return -1; + } else if(((((((a24==13) && ((a7==13) && a17 <= -108 )) && (a5==5)) || (((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==4)) || ((( a17 <= -108 && (a7==12)) && (a24==13)) && (a5==5)))) && (input == 2)) && a2 <= 189 )){ + a17 = (((((a17 + 0) - 0) / 5) % 71)- -184); + a7 = 13; + a24 = 13; + a5 = 6; + + return 26; + } else if(( a17 <= -108 && ((a24==15) && ( a2 <= 189 && ((((a7==13) || (a7==14)) && (input == 3)) && (a5==4)))))){ + a17 = ((((a17 % 299872)+ 300127) + 133154) / 5); + a7 = 12; + + return 21; + } else if(( a2 <= 189 && ((a24==14) && ((a5==6) && ( ((111 < a17) && (255 >= a17)) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 4))))))){ + a2 = (((((a2 % 45)- -234) * 1) + 447091) + -447090); + a7 = 13; + a5 = 3; + + return 23; + } else if((( 255 < a17 && (((a24==13) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 3))) && (a5==5))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -391458) - 38043) * 1); + a17 = ((((((a17 * 9)/ 10) - 302989) / 5) % 71)+ 184); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a24==15) && ((((input == 4) && (a5==5)) && a17 <= -108 ) && (a7==14))) && a2 <= 189 )){ + a2 = (((((a2 % 45)- -234) * 5) % 45)+ 227); + a17 = ((((((a17 * 9)/ 10) * 1) + -14728) % 109)- -22); + a24 = 14; + a5 = 4; + + return 23; + } else if((((a5==3) && (((( 255 < a17 && (a7==14)) && (a24==14)) || ((a24==15) && ( a17 <= -108 && (a7==12)))) && (input == 6))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - 0) % 109)- -1) - 0); + a7 = 12; + a24 = 14; + + return -1; + } else if((((a5==7) && ((a24==15) && (((input == 6) && 255 < a17 ) && (a7==12)))) && a2 <= 189 )){ + a17 = ((((a17 + -312975) + -287141) / 5) + -19782); + a24 = 14; + a5 = 5; + + return -1; + } else if(((a5==4) && ((a24==15) && ((((input == 5) && (((a7==12) || (a7==13)) || (a7==14))) && ((189 < a2) && (281 >= a2)) ) && a17 <= -108 )))){ + + a7 = 14; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) || ((a7==13) && 255 < a17 )) && (input == 3)) && (a5==3))) && (a24==14))){ + a2 = (((a2 * 5) * 5) / -5); + a17 = (((a17 + 0) - 600109) - 1); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((input == 5) && ((( a17 <= -108 && (a7==12)) && (a24==14)) || ((((a7==13) && 255 < a17 ) && (a24==13)) || ((a24==13) && ( 255 < a17 && (a7==14)))))) && (a5==3)))){ + a2 = ((((a2 - 68838) - -367491) + 74473) * -1); + a17 = (((((a17 + 0) / 5) / 5) % 71)- -184); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if(((( a2 <= 189 && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 5))) && (a24==14)) && (a5==7))){ + a17 = ((((a17 % 299946)- 300053) * 1) - 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && (((a7==13) && ((input == 2) && (a5==3))) && (a24==14))) && ((189 < a2) && (281 >= a2)) )){ + + a7 = 14; + a24 = 13; + + return -1; + } else if((((a24==13) && (((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))) && 255 < a17 )){ + a2 = (((a2 - 410733) / 5) / 5); + a17 = ((((a17 % 71)+ 113) * 1) + 14); + a7 = 13; + a24 = 15; + + return -1; + } else if(((a5==3) && (((((input == 2) && (a7==12)) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && a17 <= -108 ))){ + a2 = ((((a2 - 291109) - 296476) + 724390) + -687165); + return -1; + } else if(( a17 <= -108 && ((((a24==15) && ((a7==12) && (input == 1))) && a2 <= 189 ) && (a5==6)))){ + a2 = (((((a2 * 9)/ 10) - -368757) % 45)- -235); + a17 = ((((((a17 % 299872)- -300127) * 10)/ 9) * 10)/ 9); + a7 = 13; + a24 = 14; + a5 = 3; + + return 23; + } else if(((a24==13) && ((a5==6) && ((((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)) && a2 <= 189 )))){ + a2 = ((((((a2 - 0) % 45)+ 235) / 5) * 51)/ 10); + a17 = ((((a17 / 5) / 5) / 5) - 297755); + a7 = 12; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==14) && (((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) || ( 255 < a17 && (a7==13))) && (input == 5))) && (a5==3)))){ + a17 = (((((a17 - 157643) / 5) * 5) % 71)- -182); + a7 = 14; + + return 21; + } else if(((a5==3) && ((((input == 3) && ((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * -5) * 5) * 5); + a17 = ((((a17 % 299946)+ -300053) * 1) - 1); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==15) && (( a2 <= 189 && (((a5==6) && (input == 4)) && a17 <= -108 )) && (a7==12)))){ + a2 = ((((a2 % 45)+ 235) - 1) - 0); + a17 = ((((((a17 * 9)/ 10) % 109)- -104) + 237666) - 237686); + a5 = 3; + + return 21; + } else if((((((( a17 <= -108 && (a7==13)) && (a24==14)) || ((((a7==14) && 255 < a17 ) && (a24==13)) || (( a17 <= -108 && (a7==12)) && (a24==14)))) && (input == 3)) && (a5==5)) && a2 <= 189 )){ + a17 = ((((a17 % 299872)- -300127) - 0) + 1); + a7 = 12; + a24 = 15; + a5 = 7; + + return 23; + } else if(((( a2 <= 189 && (((a24==13) && (input == 2)) && (a5==5))) && (a7==14)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 + -462656) * 10)/ 9) + 160772); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((((input == 4) && ((a7==12) || (a7==13))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a5==6))){ + + a7 = 12; + a24 = 15; + a5 = 5; + + return -1; + } else if(( a2 <= 189 && (((a24==15) && ((a5==7) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 6)))) && ((111 < a17) && (255 >= a17)) ))){ + a17 = ((((a17 * 5) - 15195) % 109)+ 56); + a7 = 14; + a24 = 14; + + return -1; + } else if((((((input == 4) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))) && (a24==13)) && (a5==6)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 * 9)/ 10) + -528924) % 109)+ 1); + a7 = 14; + a5 = 3; + + return -1; + } else if((((a5==7) && ((input == 2) && ((((a7==14) && 255 < a17 ) && (a24==13)) || (((a7==12) && a17 <= -108 ) && (a24==14))))) && a2 <= 189 )){ + a17 = (((((a17 % 299946)+ -300053) + 96027) - 5279) - 90748); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((input == 1) && ((a7==12) || (a7==13))) && (a5==5)) && (a24==14))) && a17 <= -108 )){ + a2 = ((((a2 - 167702) / 5) - -475488) * -1); + a17 = (((((a17 % 109)+ 25) - -194163) + 403579) - 597709); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a7==12) && (((a5==6) && (( a2 <= 189 && (input == 4)) && a17 <= -108 )) && (a24==13)))){ + a2 = (((((a2 - 0) * 9)/ 10) % 45)- -234); + a24 = 15; + a5 = 5; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 1)) && (a24==14)) && (a5==5)))){ + a2 = (((a2 * 5) * 5) - 477470); + a17 = ((((a17 % 299946)+ -300053) + 309977) - 309978); + a7 = 12; + a5 = 7; + + return -1; + } else if(((a5==6) && ((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 5)))))){ + a2 = (((a2 / -5) - 543395) - 31512); + a17 = (((a17 - 374709) - 89040) - 22731); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (((( a17 <= -108 && (a7==12)) && (a24==14)) || (((a24==13) && ( 255 < a17 && (a7==13))) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 6))) && (a5==6))){ + a2 = ((((a2 % 45)- -236) - 2) * 1); + a17 = ((((((a17 * 9)/ 10) % 299872)+ 300127) - 202607) - -202608); + a7 = 13; + a24 = 15; + a5 = 3; + + return 23; + } else if(( 255 < a17 && ((((a24==13) && (((a7==13) || (a7==14)) && (input == 4))) && (a5==4)) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 13; + + return -1; + } else if(((a24==13) && ((( ((189 < a2) && (281 >= a2)) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13))))) && ((111 < a17) && (255 >= a17)) ) && (a5==5)))){ + a2 = (((a2 * -5) + -99498) * 5); + a17 = (((a17 + 560485) + 34614) * 1); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a24==14) && (((((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) || ((a7==13) && 255 < a17 )) && (input == 4)) && (a5==3)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 / -5) + -562394) - 36545); + a17 = ((((a17 - 600109) - 2) + 90959) + -90958); + a7 = 12; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 4)) && (a24==15)) && ((111 < a17) && (255 >= a17)) ) && (a5==7)))){ + + a7 = 14; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((((a5==5) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 5))) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)))){ + a2 = ((((a2 - -285304) + -146058) % 45)- -236); + a17 = ((((a17 / 5) - 378389) - 189972) + 981500); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if((((((input == 3) && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && a2 <= 189 ) && (a5==6)) && (a24==13))){ + a2 = ((((a2 + 0) % 45)+ 235) + 1); + a17 = (((a17 * 5) - -515114) - 13294); + a7 = 13; + + return 26; + } else if(( a2 <= 189 && (( a17 <= -108 && ((a24==15) && ((input == 2) && ((a7==12) || (a7==13))))) && (a5==5)))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a7==12) && ((a24==15) && ((a5==4) && ( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && (input == 5))))))){ + a17 = ((((a17 * 10)/ -9) + -170917) * 3); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a24==15) && ( 255 < a17 && ((input == 4) && a2 <= 189 ))) && (a7==12)) && (a5==7))){ + a17 = ((((a17 % 71)+ 179) - 53) - -56); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ((a5==5) && (((input == 1) && ((a7==13) || (a7==14))) && ((189 < a2) && (281 >= a2)) ))))){ + a2 = ((((a2 + -164688) * 10)/ 9) + -309761); + a17 = (((a17 * 5) + -186431) * 3); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ( ((189 < a2) && (281 >= a2)) && (((( ((111 < a17) && (255 >= a17)) && (a7==12)) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))) && (input == 6)) && (a24==14))))){ + a17 = ((((a17 - -337472) * 10)/ 9) + 150308); + a7 = 12; + a5 = 4; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && (((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 5))) && (a24==14)) && (a5==3))){ + a17 = (((((a17 / 5) + 139884) - -176184) * -1)/ 10); + a7 = 13; + + return 23; + } else if((((a5==6) && (( 255 < a17 && ((input == 2) && ((a7==12) || (a7==13)))) && (a24==15))) && a2 <= 189 )){ + a17 = (((((a17 % 109)+ 1) + 493840) - 420141) + -73780); + a7 = 12; + a24 = 14; + a5 = 4; + + return -1; + } else if(((((((input == 6) && ((189 < a2) && (281 >= a2)) ) && 255 < a17 ) && (a24==15)) && (a5==4)) && (a7==13))){ + a2 = (((a2 * -5) + 126647) * -4); + a24 = 13; + a5 = 7; + + return -1; + } else if(((((((input == 1) && ((a7==12) || (a7==13))) && (a24==15)) && (a5==5)) && a2 <= 189 ) && 255 < a17 )){ + a2 = (((((a2 % 45)- -235) - 1) / 5) - -212); + a17 = ((((((a17 % 71)+ 132) - 10) * 5) % 71)+ 135); + a7 = 14; + a24 = 13; + + return 23; + } else if(((a7==13) && ( ((-108 < a17) && (111 >= a17)) && ((((a24==14) && (input == 2)) && a2 <= 189 ) && (a5==7))))){ + a17 = ((((a17 - 453039) * 10)/ 9) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==3) && ( ((-108 < a17) && (111 >= a17)) && ((((a24==15) && (input == 5)) && (a7==13)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * 5) / 5) / -5); + a17 = (((a17 - 279125) - 101385) * 1); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a5==6) && (((input == 5) && (((a7==12) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))))) && (a24==13))) && a2 <= 189 )){ + a2 = (((((a2 - 0) + 194300) * 1) % 45)+ 235); + a17 = ((((a17 - 508865) * 10)/ 9) + -4999); + a7 = 14; + + return 23; + } else if(((( a2 <= 189 && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) && (input == 6))) && (a24==14)) && (a5==7))){ + a17 = ((((a17 * 9)/ 10) + 13957) - -35746); + a7 = 12; + + return -1; + } else if((((( ((189 < a2) && (281 >= a2)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && (a24==13)) && (a5==5)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 - 216) - 479578) - 45364) + 524988); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(((( a2 <= 189 && (((input == 6) && ((a7==12) || (a7==13))) && (a5==5))) && (a24==15)) && a17 <= -108 )){ + a2 = (((((a2 % 45)- -235) + -1) - 553229) - -553229); + a17 = (((a17 / 5) - -167109) / 5); + a7 = 12; + a24 = 13; + a5 = 4; + + return 26; + } else if(( a2 <= 189 && ((input == 1) && ((((a5==4) && (( 255 < a17 && (a7==14)) && (a24==15))) || ((a5==5) && (((a7==12) && a17 <= -108 ) && (a24==13)))) || ((a5==5) && (( a17 <= -108 && (a7==13)) && (a24==13))))))){ + a17 = ((((a17 - 0) % 299946)- 300053) + -1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a24==15) && ((input == 5) && (a5==4))) && ((189 < a2) && (281 >= a2)) ) && 255 < a17 ) && (a7==13))){ + a2 = (((a2 / 5) / 5) - 136738); + a24 = 14; + a5 = 7; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((input == 6) && ((a7==13) || (a7==14))) && (a24==15)))) && (a5==5))){ + a17 = (((a17 / 5) + 572999) + 22824); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==5) && ((a24==14) && ((input == 4) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 ))))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 % 109)+ 2) / 5) + -88); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && (((((input == 6) && ((a7==13) || (a7==14))) && (a5==7)) && 255 < a17 ) && (a24==15)))){ + a17 = ((((a17 % 109)- 61) / 5) / 5); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a24==13) && ((a5==7) && (((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (input == 5)) && a2 <= 189 )))){ + a2 = ((((((a2 % 45)+ 234) * 1) / 5) * 51)/ 10); + a17 = ((((a17 / 5) * 4) % 109)- -2); + a7 = 12; + a24 = 14; + a5 = 3; + + return 23; + } else if(((( a2 <= 189 && ((input == 3) && ((( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ((a7==13) && ((-108 < a17) && (111 >= a17)) )))) && (a5==7)) && (a24==13))){ + a17 = ((((a17 % 299946)+ -300053) * 1) - 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==6) && ( a2 <= 189 && ((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))))))) && (a24==13))){ + a2 = (((((a2 + 0) % 45)+ 234) - 472412) + 472412); + a17 = ((((a17 + 0) % 71)- -182) + 3); + a7 = 12; + a24 = 15; + a5 = 5; + + return 23; + } else if(((((a24==15) && (((input == 2) && ((a7==12) || (a7==13))) && (a5==5))) && ((-108 < a17) && (111 >= a17)) ) && a2 <= 189 )){ + a17 = (((((a17 / 5) + -238456) - -765474) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a24==15) && ((((input == 4) && (((a7==12) || (a7==13)) || (a7==14))) && ((189 < a2) && (281 >= a2)) ) && (a5==5))) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((a2 * 5) * 5) + -325620); + a17 = (((a17 + 366270) + 10197) + 134633); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a24==13) && ((a5==4) && (((((a7==13) || (a7==14)) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && ((-108 < a17) && (111 >= a17)) )))){ + + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a5==6) && ((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((a7==14) && (input == 1))))) && a17 <= -108 )){ + a17 = ((((((a17 % 71)- -247) + 5) / 5) * 32)/ 10); + a7 = 13; + a24 = 15; + a5 = 5; + + return -1; + } else if(((((a5==5) && ((input == 4) && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))) && ((189 < a2) && (281 >= a2)) ) && (a24==14))){ + a2 = (((a2 * 5) - 562071) * 1); + a17 = (((((a17 - -128476) + 315707) + -905468) * -1)/ 10); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((((((a7==13) || (a7==14)) && (input == 5)) && a2 <= 189 ) && (a5==7)) && (a24==15)))){ + a17 = (((((a17 - 271153) + 418092) / 5) * -1)/ 10); + a7 = 14; + + return -1; + } else if(((a24==13) && ((((((a7==12) || (a7==13)) && (input == 4)) && 255 < a17 ) && a2 <= 189 ) && (a5==5)))){ + a17 = (((((a17 % 109)+ 3) * 5) % 109)- -2); + a7 = 14; + a24 = 15; + a5 = 7; + + return 23; + } else if((((a5==4) && ((a24==14) && ((input == 3) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * 5) - 516770) - 71238); + a17 = ((((a17 - 0) % 299872)+ 300127) + 1); + a7 = 12; + a5 = 7; + + return -1; + } else if((( 255 < a17 && (((a24==15) && ((input == 2) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==3))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 507108) + -40186) * 1); + a17 = ((((a17 % 71)- -168) + 373224) + -373250); + a7 = 14; + a24 = 14; + + return -1; + } else if(((((a7==14) && (((input == 3) && (a24==15)) && a2 <= 189 )) && 255 < a17 ) && (a5==5))){ + a2 = (((((a2 % 45)- -236) / 5) / 5) + 268); + a7 = 12; + a24 = 14; + + return 21; + } else if(((a5==5) && ( a2 <= 189 && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 1)) && (a24==15))))){ + a17 = ((((a17 - 99808) / 5) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==3) && (((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) )) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a24==15)))){ + a2 = (((a2 - -222045) / 5) + -435548); + a17 = (((((a17 * 5) % 71)- -183) + 531003) + -531001); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if(((a24==14) && ( ((189 < a2) && (281 >= a2)) && (((input == 3) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==5))))){ + a2 = (((a2 - 537051) + -19713) - 17151); + a17 = (((((a17 % 299872)+ 300127) + -161234) - 361454) + 522690); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && ((((a7==13) || (a7==14)) && (input == 4)) && (a5==6)))) && (a24==15))){ + a17 = (((a17 - 438310) / 5) + -185271); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a24==13) && ((a5==4) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 6)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 252975) * 2) - -454453); + a17 = (((((((a17 * 9)/ 10) % 71)+ 176) / 5) * 39)/ 10); + a7 = 13; + a24 = 15; + + return 21; + } else if(( 255 < a17 && ((( ((189 < a2) && (281 >= a2)) && ((a7==13) && (input == 5))) && (a24==13)) && (a5==6)))){ + + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && (((input == 3) && ((a7==12) || (a7==13))) && a17 <= -108 ))) && (a5==5))){ + a17 = ((((((a17 * 9)/ 10) * 1) * 1) % 109)- -107); + a7 = 14; + a5 = 4; + + return -1; + } else if(((a5==5) && ( a2 <= 189 && ((a24==13) && ((input == 4) && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ((a7==13) && ((-108 < a17) && (111 >= a17)) ))))))){ + a17 = ((((a17 + 0) % 299946)- 300053) + -1); + a7 = 12; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ((a24==14) && ( ((111 < a17) && (255 >= a17)) && ((a5==6) && ((input == 6) && ((a7==14) || ((a7==12) || (a7==13))))))))){ + a17 = ((((a17 - -144076) * 10)/ -9) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (( a17 <= -108 && ((((a7==13) || (a7==14)) && (input == 6)) && (a24==13))) && (a5==3)))){ + a2 = (((a2 - 324660) + 36683) * 2); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && (((a7==14) && ((a24==13) && (input == 2))) && (a5==6))))){ + a2 = (((a2 - -379518) + 60031) + -652869); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==4) && (((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) && (input == 3)) && ((189 < a2) && (281 >= a2)) )) && (a24==15))){ + a17 = (((a17 - 0) + -600109) - 1); + a7 = 14; + a24 = 14; + + return -1; + } else if((((((a24==15) && (((a7==12) || (a7==13)) && (input == 4))) && 255 < a17 ) && a2 <= 189 ) && (a5==5))){ + a2 = (((((a2 % 45)- -235) - -264986) / 5) - 52838); + a17 = (((((a17 % 109)+ 3) + -92) - -39346) - 39285); + a7 = 14; + a24 = 13; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && (((a5==4) && ((input == 2) && ((a7==13) || (a7==14)))) && (a24==13))))){ + a17 = ((((a17 - 8964) * 10)/ 9) / 5); + a7 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==5) && ((a24==15) && (((input == 1) && ((a7==14) || ((a7==12) || (a7==13)))) && 255 < a17 ))))){ + a17 = (((((a17 + -204208) + -294222) / 5) % 109)- -2); + a7 = 14; + a5 = 4; + + return -1; + } else if(((a24==15) && (( a2 <= 189 && ((input == 1) && ((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))))) && (a5==7)))){ + a17 = ((((a17 + 445460) + -108723) % 109)+ 2); + a7 = 14; + a5 = 4; + + return -1; + } else if(((a5==6) && ( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && ((a24==13) && ((a7==14) && (input == 6))))))){ + a17 = ((((((a17 * 9)/ 10) + -8929) / 5) % 109)- -99); + a5 = 5; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && (a24==13)))){ + + a7 = 12; + + return -1; + } else if(((a24==13) && ((a5==3) && (((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 6)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = ((((a2 * 5) - -456899) * 1) * -1); + a17 = ((((a17 % 109)+ 2) - -1) + -2); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==5) && ( a2 <= 189 && ( ((-108 < a17) && (111 >= a17)) && ((((a7==12) || (a7==13)) && (input == 6)) && (a24==15)))))){ + a17 = (((((a17 - 533399) + 268098) + 539288) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ((( ((189 < a2) && (281 >= a2)) && ((a24==13) && (input == 3))) && ((-108 < a17) && (111 >= a17)) ) && (a7==13)))){ + a2 = ((((a2 + 15012) - -575888) * 1) * -1); + a17 = ((((a17 - -31776) - -471905) / 5) - 154264); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a5==4) && ((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12))) && (input == 6))) && (a24==15)))){ + a17 = ((((a17 - 600111) + 328854) * 1) + -328853); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==7) && (((input == 4) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12)))) && a2 <= 189 )) && (a24==14))){ + a17 = ((((a17 % 71)- -117) + 189902) - 189835); + a7 = 13; + + return -1; + } else if(((a24==13) && ( ((189 < a2) && (281 >= a2)) && (((a5==5) && ((input == 6) && ((a7==14) || ((a7==12) || (a7==13))))) && 255 < a17 )))){ + a2 = ((((a2 - 330313) * 10)/ 9) - 15295); + a17 = (((((a17 / 5) - 422861) + 205502) % 109)- -66); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==13) && (( ((-108 < a17) && (111 >= a17)) && ((input == 4) && ((a7==13) || (a7==14)))) && (a5==4))))){ + a17 = (((a17 + -505795) * 1) * 1); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (( 255 < a17 && (((a7==14) || ((a7==12) || (a7==13))) && (input == 2))) && (a5==6))) && (a24==14))){ + a17 = (((a17 - 600255) + -1) - 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a24==14) && (((input == 4) && (a7==13)) && ((-108 < a17) && (111 >= a17)) )) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 574876) / 5) - 126841); + a17 = ((((a17 % 71)- -182) - 0) - 0); + a24 = 13; + a5 = 7; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 1)) && (a24==14))))){ + a2 = (((a2 / -5) - -106688) - 700155); + a17 = ((((a17 - -444995) * 1) % 71)- -142); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if((( a2 <= 189 && ( 255 < a17 && ((a24==15) && ((input == 3) && (a7==12))))) && (a5==7))){ + a17 = ((((a17 + -443894) / 5) / 5) + -460355); + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==5) && ( ((111 < a17) && (255 >= a17)) && (((input == 5) && (a24==13)) && (a7==12)))) && a2 <= 189 )){ + a17 = ((((a17 + -406871) - 29414) + 509500) - 209883); + a7 = 13; + a5 = 7; + + return 23; + } else if(((a5==5) && ( ((111 < a17) && (255 >= a17)) && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 1)) && (a24==13)) && ((189 < a2) && (281 >= a2)) )))){ + a17 = ((((a17 + -386404) - -386194) - -24721) - 24655); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((((a5==4) && (((a7==13) || (a7==14)) && (input == 4))) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)))){ + a17 = ((((a17 % 71)+ 184) - -1) - 1); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((((a5==5) && ((a24==13) && ( a17 <= -108 && (a7==13)))) || (((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==4)) || ((a5==5) && (((a7==12) && a17 <= -108 ) && (a24==13))))) && (input == 3)))){ + a2 = (((a2 * 5) + -496396) - -43586); + a17 = ((((a17 + 0) % 71)- -183) - -1); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a5==6)) && (a24==13))){ + a17 = (((((a17 % 71)- -184) - 1) + -591569) + 591570); + a7 = 14; + a5 = 4; + + return -1; + } else if((((((input == 1) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))) && (a24==14)) && (a5==7)) && a2 <= 189 )){ + a17 = ((((a17 / 5) - -456210) - 346519) + -109681); + a7 = 13; + + return -1; + } else if(((a7==13) && ((a24==15) && (((a5==6) && ((input == 2) && a17 <= -108 )) && a2 <= 189 )))){ + a17 = (((((a17 % 71)- -191) + 37) + 557078) + -557055); + a7 = 12; + a24 = 13; + a5 = 7; + + return 26; + } else if(((a5==7) && (((a24==14) && ((input == 5) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))))) && a2 <= 189 ))){ + a17 = (((((a17 + -437926) * 1) / 5) % 71)+ 182); + a7 = 14; + + return 26; + } else if(((a7==13) && ((a24==13) && ((((input == 3) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 ) && (a5==5))))){ + a17 = ((((a17 * 23)/ 10) - -95194) + 367978); + a5 = 7; + + return 23; + } else if(((a24==13) && ((a7==13) && ( ((-108 < a17) && (111 >= a17)) && (((input == 2) && (a5==5)) && ((189 < a2) && (281 >= a2)) ))))){ + a2 = (((a2 * 5) + -75316) * 5); + a17 = ((((a17 / 5) * 5) * 5) - 551159); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==14) && ((a5==7) && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ((a7==13) && ((111 < a17) && (255 >= a17)) )) && (input == 6)) && a2 <= 189 )))){ + a17 = (((a17 + 497335) - 362468) / 5); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a7==14) && ((a5==3) && ( ((111 < a17) && (255 >= a17)) && (((input == 4) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))))){ + + a7 = 12; + a24 = 14; + + return -1; + } else if(( a2 <= 189 && ((a5==7) && ((a24==13) && (((( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) || ((a7==13) && ((-108 < a17) && (111 >= a17)) )) && (input == 2)))))){ + a2 = ((((a2 % 45)+ 235) - -164895) - 164893); + a17 = (((((a17 * 9)/ 10) % 109)- -2) / 5); + a7 = 12; + a24 = 14; + a5 = 3; + + return 23; + } else if(( ((-108 < a17) && (111 >= a17)) && ( a2 <= 189 && ((a24==14) && (((input == 2) && (((a7==12) || (a7==13)) || (a7==14))) && (a5==5)))))){ + a2 = ((((a2 / 5) / 5) % 45)- -235); + a17 = (((a17 * 5) - -230268) / 5); + a7 = 14; + a24 = 13; + a5 = 3; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && (((a5==4) && ((input == 5) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )))) && (a24==15)))){ + a17 = (((((a17 % 71)+ 146) - -107220) - 259531) + 152347); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ((a24==14) && (( a2 <= 189 && ((input == 4) && (a5==5))) && (a7==14))))){ + a17 = ((((a17 * 10)/ -9) * 5) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (((a5==6) && (input == 5)) && (a24==15))) && (a7==12)) && a2 <= 189 )){ + a2 = ((((a2 % 45)+ 234) * 1) + 1); + a7 = 13; + a24 = 13; + a5 = 3; + + return 23; + } else if(((a5==5) && ((( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && (input == 3))) && (a7==12)) && (a24==13)))){ + a17 = ((((a17 * 10)/ -9) * 5) + -240506); + a5 = 3; + + return -1; + } else if(((((((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 2)) && (a24==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a2 = ((((a2 / -5) + -417573) * 10)/ 9); + a17 = ((((a17 - 128270) + -400314) + 6367) + -77894); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && ( ((189 < a2) && (281 >= a2)) && ((((a5==4) && (input == 4)) && (a7==13)) && (a24==15))))){ + a2 = ((((a2 + -199858) * 10)/ 9) + -50269); + a17 = (((((a17 + -143986) * 1) / 5) % 71)- -183); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 6) && ((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) || ((a7==13) && 255 < a17 ))))))){ + a2 = (((a2 * 5) / 5) - 103911); + a17 = (((a17 - 600110) * 1) - 2); + a7 = 12; + a24 = 13; + + return -1; + } else if(((( a2 <= 189 && ((input == 6) && ((( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) || ( ((-108 < a17) && (111 >= a17)) && (a7==13))))) && (a5==7)) && (a24==13))){ + a17 = ((((a17 % 299946)+ -300053) - 2) - 0); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((input == 2) && (((((a24==15) && ((a7==14) && 255 < a17 )) && (a5==4)) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==5))) || (((a24==13) && ( a17 <= -108 && (a7==13))) && (a5==5)))))){ + a2 = (((a2 / -5) / 5) - 528849); + a17 = ((((a17 - 0) / 5) - 300593) + 687900); + a7 = 14; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((input == 4) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )))))) && (a24==15))){ + a2 = (((a2 + -76921) + -80615) - 172398); + a17 = (((((a17 - 0) % 299946)+ -300053) - -542550) - 542551); + a7 = 12; + a24 = 13; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((a24==13) && (input == 5)) && (a7==13)))) && (a5==5))){ + a2 = (((a2 / 5) - 555637) + -17770); + a17 = (((((a17 - -266183) * 10)/ 9) * 10)/ 9); + a7 = 14; + a5 = 7; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a5==3) && ((a24==15) && (((input == 1) && (a7==13)) && ((189 < a2) && (281 >= a2)) ))))){ + a17 = ((((a17 / 5) + 156) + 305089) + -305059); + a7 = 14; + a24 = 13; + + return -1; + } else if(( 255 < a17 && ((a24==14) && (( a2 <= 189 && ((input == 1) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==5))))){ + a2 = ((((((a2 % 45)- -235) * 1) * 5) % 45)+ 226); + a17 = (((a17 - 600142) + 457437) + -457541); + a7 = 12; + a24 = 13; + a5 = 4; + + return 21; + } else if((((a7==12) && (((a5==4) && ((input == 3) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 )) && (a24==15))){ + + a24 = 14; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && ((input == 4) && (((((a24==15) && ((a7==14) && 255 < a17 )) && (a5==6)) || ((a5==7) && ((a24==13) && ( a17 <= -108 && (a7==12))))) || ((( a17 <= -108 && (a7==13)) && (a24==13)) && (a5==7)))))){ + a2 = ((((a2 % 45)+ 234) * 1) * 1); + a17 = ((((a17 % 109)- -2) - -1) / 5); + a7 = 14; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a5==4) && ((a24==14) && ( ((189 < a2) && (281 >= a2)) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 5))))))){ + a2 = (((a2 * -5) + 490210) + -622035); + a17 = (((((a17 / 5) + -253338) - -303884) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && ((a24==15) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )))){ + a17 = (((((a17 / 5) * 5) - 517057) % 71)- -222); + a7 = 13; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && ( a17 <= -108 && ((a5==5) && ((input == 5) && ((a7==14) || ((a7==12) || (a7==13))))))) && (a24==15))){ + a2 = (((a2 - 51957) - 201016) + -229661); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((input == 4) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==5)) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14))){ + a17 = ((((a17 + -583681) / 5) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((( ((189 < a2) && (281 >= a2)) && ((input == 2) && ((a7==12) || (a7==13)))) && a17 <= -108 ) && (a5==4)) && (a24==14))){ + a2 = ((((a2 * -5) / 5) - -461012) * -1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((((((a7==13) && 255 < a17 ) && (a24==14)) || (((a7==14) && 255 < a17 ) && (a24==14))) || ((a24==15) && ((a7==12) && a17 <= -108 ))) && (input == 2))) && (a5==7))){ + a17 = ((((a17 % 299946)- 300053) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12))) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a24==14)) && (a5==4))){ + a2 = (((a2 + -56097) + -204457) / 5); + a17 = ((((a17 - 0) - 600111) / 5) + -466402); + a7 = 14; + a5 = 7; + + return -1; + } else if(((a24==15) && (((((input == 1) && (a5==3)) && ((189 < a2) && (281 >= a2)) ) && ((111 < a17) && (255 >= a17)) ) && (a7==14)))){ + a2 = (((a2 + -198382) * 3) - 2631); + a17 = ((((a17 / 5) * 10)/ -2) + -174727); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==14) && ((a5==7) && (((input == 5) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))) && a2 <= 189 )))){ + a17 = ((((a17 - 587947) / 5) / 5) + 23535); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if((((a24==15) && ( ((189 < a2) && (281 >= a2)) && ((a7==13) && ((a5==4) && (input == 4))))) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 * 5) / 5) + -257179); + a17 = (((((a17 % 71)- -184) + 43333) / 5) + -8544); + a7 = 12; + a5 = 5; + + return -1; + } else if((((((a24==14) && (((a7==12) || (a7==13)) && (input == 2))) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a5==5))){ + a2 = (((((a2 % 45)+ 234) * 5) % 45)+ 193); + a17 = ((((a17 - -121418) * 10)/ -9) + -75458); + a7 = 12; + a24 = 15; + a5 = 3; + + return 23; + } else if(( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((a24==13) && (((a7==13) || (a7==14)) && (input == 1))))))){ + a2 = (((a2 + -566056) + -17565) - 7708); + a17 = ((((((a17 - -545152) % 109)- -2) * 5) % 109)- -2); + a7 = 13; + a24 = 15; + a5 = 4; + + return 21; + } else if(((a7==12) && (((( a2 <= 189 && (input == 2)) && ((111 < a17) && (255 >= a17)) ) && (a5==4)) && (a24==15)))){ + a17 = ((((((a17 - -393608) * 10)/ 9) - 738081) * -1)/ 10); + a7 = 13; + a24 = 14; + a5 = 5; + + return 23; + } else if((( ((-108 < a17) && (111 >= a17)) && ((((input == 1) && ((a7==13) || (a7==14))) && a2 <= 189 ) && (a5==4))) && (a24==15))){ + a17 = (((a17 - -93652) / 5) * 5); + a7 = 14; + a24 = 13; + a5 = 5; + + return 23; + } + return calculate_output2(input); + } + + int calculate_output2(int input) { + + + if(((a5==7) && (((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )) && (input == 4)) && a2 <= 189 ) && (a24==13)))){ + a17 = (((a17 + -223220) - 376890) - 0); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==13) && (((a5==3) && (((a7==13) || (a7==14)) && (input == 3))) && ((189 < a2) && (281 >= a2)) )) && a17 <= -108 )){ + a2 = (((a2 * 5) - 572766) - 10840); + a17 = (((((a17 + 0) % 299872)+ 300127) * 10)/ 9); + a7 = 12; + a5 = 7; + + return -1; + } else if((((a5==5) && ( a17 <= -108 && (((input == 5) && ((a7==12) || (a7==13))) && a2 <= 189 ))) && (a24==15))){ + a2 = ((((a2 % 45)- -234) * 1) + 0); + a17 = (((((a17 % 299872)- -300127) - -85883) - 234462) - -340820); + a7 = 13; + a24 = 13; + a5 = 4; + + return 23; + } else if(((a5==7) && ((( ((111 < a17) && (255 >= a17)) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13))))) && (a24==15)) && a2 <= 189 ))){ + a17 = (((a17 - 554057) - 32150) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((input == 4) && (((a24==14) && ((a7==12) && a17 <= -108 )) || ((( 255 < a17 && (a7==13)) && (a24==13)) || (((a7==14) && 255 < a17 ) && (a24==13)))))) && (a5==6))){ + a17 = (((a17 / 5) - 146392) - 201110); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 2))) && (a5==4)) && (a24==14))){ + a2 = ((((a2 + -438465) * 10)/ 9) + -61750); + a17 = (((a17 - -547585) - -40543) + -650123); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && (((a24==14) && ((( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 2))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * 5) - 588386) - 700); + a17 = ((((a17 % 299946)- 300053) / 5) - 223475); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((input == 1) && (a5==5)) && (a7==12)))))){ + a17 = (((a17 - -556781) - -32123) - -2336); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((((a7==12) && (input == 1)) && (a24==13)) && a17 <= -108 )))){ + + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==3) && (((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 5)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + -105771) / 5) * 5); + a17 = ((((a17 / 5) + 192183) * -1)/ 10); + a7 = 12; + + return -1; + } else if(((((((a24==13) && (input == 6)) && (a7==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 - 160975) / 5) * 5); + a17 = (((a17 + -217141) + 302270) - 56859); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a24==13) && ((((input == 3) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (a5==7)) && a2 <= 189 ))){ + a17 = (((((a17 * 5) - 221071) / 5) % 71)- -220); + a7 = 12; + a5 = 5; + + return 21; + } else if((((( a2 <= 189 && ((input == 4) && (a24==13))) && ((111 < a17) && (255 >= a17)) ) && (a7==12)) && (a5==5))){ + a17 = (((a17 + -543666) - 48044) - 4253); + a5 = 3; + + return -1; + } else if(((a5==6) && ( ((189 < a2) && (281 >= a2)) && (((((a7==12) || (a7==13)) && (input == 3)) && (a24==13)) && ((-108 < a17) && (111 >= a17)) )))){ + a17 = (((a17 + -479754) * 1) - 60677); + a7 = 12; + a24 = 14; + a5 = 5; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a5==4) && ( ((189 < a2) && (281 >= a2)) && (((a24==15) && (input == 5)) && (a7==13)))))){ + a17 = ((((a17 - 89845) % 71)- -187) * 1); + a24 = 13; + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 2)) && (a24==13))) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a2 = (((a2 / 5) * 5) + -133618); + a17 = ((((a17 - 64840) - 296199) * 10)/ 9); + a7 = 12; + a5 = 3; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && (((a7==12) && (input == 6)) && ((-108 < a17) && (111 >= a17)) )) && (a24==15)) && (a5==5))){ + a2 = (((a2 + -519111) - -90859) / 5); + a17 = (((a17 / 5) + -553032) + 553176); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if(((a5==4) && ((a24==15) && ( ((-108 < a17) && (111 >= a17)) && (((input == 3) && a2 <= 189 ) && (a7==12)))))){ + a17 = (((((a17 / 5) + 521700) - 934556) * -1)/ 10); + a7 = 14; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((a24==14) && ((input == 6) && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))))))){ + a2 = (((a2 / 5) * -5) * 5); + a17 = ((((a17 * 5) % 71)+ 182) + 1); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if((((((((a7==13) || (a7==14)) && (input == 4)) && a17 <= -108 ) && (a24==15)) && (a5==4)) && a2 <= 189 )){ + a17 = ((((((a17 + 343527) % 71)+ 183) * 5) % 71)- -165); + a7 = 13; + + return 21; + } else if((( a17 <= -108 && ((a5==6) && ( a2 <= 189 && ((a24==15) && (input == 3))))) && (a7==13))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 3) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && (a5==5)) && (a24==14)))){ + a2 = (((a2 + -81628) * 5) - 151837); + a17 = (((a17 + -600110) - 0) + -2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && (((a5==5) && ( ((189 < a2) && (281 >= a2)) && ((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a24==15)))){ + a17 = (((((a17 - 0) + -206889) + 16806) % 109)- -2); + a7 = 13; + a5 = 4; + + return -1; + } else if((((((a24==14) && (((a7==12) || (a7==13)) && (input == 3))) && (a5==4)) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 217302) + -351806) / 5); + a17 = ((((((a17 % 71)- -205) * 9)/ 10) * 10)/ 9); + a7 = 14; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && ((input == 6) && (((( a17 <= -108 && (a7==13)) && (a24==13)) && (a5==5)) || ((((a24==15) && ( 255 < a17 && (a7==14))) && (a5==4)) || (((a24==13) && ( a17 <= -108 && (a7==12))) && (a5==5))))))){ + a17 = ((((a17 + 0) % 299946)+ -300053) - 2); + a7 = 14; + a24 = 14; + a5 = 6; + + return 26; + } else if(((((input == 6) && ((( 255 < a17 && (a7==14)) && (a24==13)) || (((a7==12) && a17 <= -108 ) && (a24==14)))) && (a5==7)) && a2 <= 189 )){ + a17 = (((((a17 + 0) - 0) + 0) % 299946)+ -300053); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && ((((input == 2) && ((a7==13) || (a7==14))) && (a5==4)) && ((111 < a17) && (255 >= a17)) )))){ + a17 = (((a17 - 112842) + -369240) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((a24==15) && (input == 3)) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )) && (a7==12))){ + a17 = (((a17 + 316175) * 1) + 233255); + a24 = 14; + a5 = 4; + + return -1; + } else if((((a5==7) && ((a24==13) && (((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 6)))) && a2 <= 189 )){ + a17 = (((a17 + -600109) + -1) + -2); + a7 = 12; + a5 = 3; + + return -1; + } else if((((( a17 <= -108 && ((input == 6) && (a5==5))) && (a7==14)) && (a24==15)) && a2 <= 189 )){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((a5==4) && ((input == 1) && ((a7==12) || (a7==13)))) && (a24==13))))){ + + a7 = 12; + + return 23; + } else if((((((input == 4) && (( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12)))) && (a24==13)) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 + -427791) / 5) / 5) % 71)+ 182); + a7 = 13; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 3)) && (a5==3))) && (a24==14))){ + a2 = (((a2 + -120881) * 4) * 1); + a17 = (((((a17 % 109)- -2) + -127431) - 362706) + 490136); + a7 = 12; + a5 = 5; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && (((input == 2) && ((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==3))) && (a24==15))){ + a2 = (((a2 * 5) * -5) - 245970); + a17 = (((((a17 % 299946)+ -300053) + -1) + 161315) - 161314); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==14) && ((input == 6) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )))) && (a5==4)))){ + a17 = ((((a17 % 299946)- 300053) * 1) * 1); + a7 = 13; + a24 = 13; + a5 = 3; + + return -1; + } else if((((( ((189 < a2) && (281 >= a2)) && ((input == 3) && (a7==12))) && (a24==13)) && a17 <= -108 ) && (a5==3))){ + a2 = (((a2 + 430380) * 1) / -5); + a17 = (((((a17 * 9)/ 10) % 109)+ 42) - 25); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((((((a7==13) && 255 < a17 ) && (a24==13)) || (((a7==14) && 255 < a17 ) && (a24==13))) || ((a24==14) && ((a7==12) && a17 <= -108 ))) && (input == 3))))){ + a2 = (((a2 - -54478) + -529752) + -118732); + a17 = (((a17 / 5) / 5) + -531417); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==13) && ((a5==7) && ((a7==13) && ( a2 <= 189 && ( 255 < a17 && (input == 2))))))){ + a17 = (((a17 - 0) + -600254) - 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((((((a7==12) || (a7==13)) && (input == 5)) && (a24==15)) && 255 < a17 ) && a2 <= 189 ) && (a5==5))){ + a2 = (((((a2 - -169038) + -8583) + -45242) % 45)+ 234); + a7 = 13; + a24 = 13; + + return 23; + } else if(((a24==15) && ((a5==6) && ( a2 <= 189 && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 3)))))){ + a17 = ((((a17 % 299946)+ -300053) * 1) - 2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a7==12) && (((input == 2) && ((111 < a17) && (255 >= a17)) ) && (a5==6))) && a2 <= 189 ) && (a24==15))){ + a2 = (((((a2 % 45)- -236) / 5) - -550201) + -549992); + a7 = 14; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && (((a5==4) && (((input == 3) && ((a7==13) || (a7==14))) && ((111 < a17) && (255 >= a17)) )) && (a24==15)))){ + + a7 = 14; + a5 = 5; + + return 23; + } else if(((a7==14) && (((( a2 <= 189 && (input == 2)) && (a24==14)) && (a5==5)) && ((111 < a17) && (255 >= a17)) ))){ + a2 = (((((a2 % 45)- -235) - -1) + 81498) - 81497); + a17 = (((((a17 * 10)/ 4) / 5) * 10)/ 2); + a7 = 12; + a24 = 15; + a5 = 3; + + return 21; + } else if(((a24==13) && ( 255 < a17 && (((a5==5) && (((a7==12) || (a7==13)) && (input == 5))) && a2 <= 189 )))){ + a17 = ((((a17 % 109)+ -14) + -65) - 16); + a7 = 12; + a24 = 15; + a5 = 7; + + return 26; + } else if(( a2 <= 189 && (( ((-108 < a17) && (111 >= a17)) && (((a5==5) && (input == 4)) && (a24==13))) && (a7==14)))){ + a17 = (((((a17 - 567803) % 71)+ 187) - 424769) - -424798); + a24 = 15; + a5 = 6; + + return 23; + } else if(( a2 <= 189 && (((((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==6)))){ + a2 = (((((a2 - -148382) + 15537) - 69273) % 45)+ 235); + a17 = (((a17 - 250975) * 2) - -374533); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && (((a24==14) && (((input == 1) && (((a7==12) || (a7==13)) || (a7==14))) && a2 <= 189 )) && (a5==6)))){ + a2 = (((((((a2 * 9)/ 10) % 45)- -234) / 5) * 51)/ 10); + a7 = 13; + a5 = 3; + + return 23; + } else if(( 255 < a17 && (((a5==5) && (((input == 1) && ((a7==12) || (a7==13))) && a2 <= 189 )) && (a24==13)))){ + a17 = ((((a17 / 5) * 10)/ -4) - 18616); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a5==6) && (((((a24==14) && ((a7==12) && a17 <= -108 )) || ((((a7==13) && 255 < a17 ) && (a24==13)) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 3)) && a2 <= 189 ))){ + a2 = (((((a2 * 9)/ 10) % 45)+ 234) + 0); + a17 = (((((a17 * 9)/ 10) % 299946)+ -300053) - 0); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if(( ((189 < a2) && (281 >= a2)) && (((a5==4) && ( a17 <= -108 && ((input == 1) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a24==15)))){ + a17 = (((((a17 * 9)/ 10) - -39396) % 109)- -1); + a7 = 12; + a24 = 14; + + return -1; + } else if(((((((a7==12) && (input == 4)) && ((-108 < a17) && (111 >= a17)) ) && (a5==4)) && a2 <= 189 ) && (a24==15))){ + a17 = (((a17 * 5) / 5) - 8323); + a24 = 13; + a5 = 3; + + return -1; + } else if(((( a2 <= 189 && ((a5==6) && ((input == 5) && a17 <= -108 ))) && (a24==13)) && (a7==12))){ + + a5 = 3; + + return -1; + } else if(((((a5==5) && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 5))) && (a24==13)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((((a17 % 71)+ 183) * 5) * 5) % 71)- -147); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((((a7==12) && a17 <= -108 ) && (a24==14)) || ((( 255 < a17 && (a7==13)) && (a24==13)) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 1))))){ + a2 = ((((a2 * -5) + 512688) / 5) + -671267); + a17 = (((((a17 % 299946)+ -300053) + -2) - -209672) - 209671); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14)))) && (input == 1)))) && (a24==15))){ + a17 = ((((((a17 * 9)/ 10) % 71)- -182) - -14398) + -14397); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==3) && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) )) && (input == 4)) && (a24==15))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 - 440571) * 10)/ 9) * 1); + a17 = (((a17 / 5) + 199) + -13); + a7 = 12; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a24==14) && (((a5==6) && ( a2 <= 189 && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5)))) && 255 < a17 ))){ + + a7 = 12; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a5==5) && ((a24==15) && ((((a7==12) || (a7==13)) && (input == 1)) && a2 <= 189 ))))){ + a17 = ((((a17 - 548709) + 66483) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 4) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (a5==6)) && ((189 < a2) && (281 >= a2)) ) && (a24==13))){ + a17 = ((((a17 * 5) - 44693) % 109)+ 15); + a7 = 14; + a5 = 5; + + return -1; + } else if((((a24==13) && (( ((189 < a2) && (281 >= a2)) && ( a17 <= -108 && (input == 5))) && (a7==12))) && (a5==3))){ + a2 = (((a2 + -572725) + 175794) * 1); + a17 = ((((a17 / 5) % 109)- -105) / 5); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((((( a17 <= -108 && (input == 1)) && (a7==14)) && a2 <= 189 ) && (a24==14)) && (a5==5))){ + a2 = ((((a2 / 5) % 45)+ 235) - 1); + a17 = (((((a17 % 109)- -95) - 397967) + 16520) + 381429); + a24 = 13; + a5 = 3; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && ((a7==12) && ((a5==6) && (( a2 <= 189 && (input == 4)) && (a24==15)))))){ + a17 = ((((a17 - -175358) * 10)/ -9) * 3); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((input == 5) && a2 <= 189 ) && (a5==5)) && (a24==15)) && (a7==14)) && a17 <= -108 )){ + a2 = (((((a2 + 0) - -533443) / 5) % 45)- -235); + a17 = ((((a17 % 109)+ 56) + 32) - 64); + a7 = 13; + a24 = 14; + a5 = 4; + + return 23; + } else if(((a5==6) && ((a24==14) && ((((input == 4) && (((a7==12) || (a7==13)) || (a7==14))) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) )))){ + a2 = ((((a2 % 45)+ 236) * 1) - 2); + a17 = ((((a17 - -285478) - -176297) % 71)+ 120); + a7 = 14; + a5 = 3; + + return 23; + } else if((((a5==3) && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 3)) && (a24==15))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / -5) * 5) * 5); + a17 = (((a17 / 5) + 443474) - -14231); + a7 = 13; + a24 = 14; + + return -1; + } else if(((a5==4) && ((a7==12) && ( ((-108 < a17) && (111 >= a17)) && ((a24==15) && ((input == 2) && ((189 < a2) && (281 >= a2)) )))))){ + a2 = ((((a2 - -382813) + -765612) - -535577) * -3); + a17 = ((((a17 - 191016) * 10)/ 9) * 2); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==6)) || ((a5==7) && (( a17 <= -108 && (a7==12)) && (a24==13)))) || ((a5==7) && (((a7==13) && a17 <= -108 ) && (a24==13)))) && (input == 2)) && a2 <= 189 )){ + a17 = ((((a17 % 299946)- 300053) * 1) + -1); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if((((a5==3) && ((( ((111 < a17) && (255 >= a17)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ) && (a7==14))) && (a24==15))){ + a2 = ((((a2 - 503628) * 10)/ 9) * 1); + a17 = (((a17 - 141047) * 4) - 9786); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a24==14) && ( a2 <= 189 && ((input == 6) && ((((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && (a5==7))){ + a17 = (((((a17 % 109)+ 1) * 5) % 109)- -1); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==7) && (((a24==15) && (((input == 5) && ((a7==13) || (a7==14))) && a2 <= 189 )) && 255 < a17 ))){ + a17 = (((((a17 % 71)+ 138) + 39) - 439359) + 439313); + a7 = 13; + a24 = 14; + + return -1; + } else if(((a5==4) && ((a24==13) && ((((input == 2) && ((a7==12) || (a7==13))) && ((189 < a2) && (281 >= a2)) ) && ((111 < a17) && (255 >= a17)) )))){ + a2 = (((a2 * 5) - -555151) * -1); + a17 = (((((a17 / 5) - 449993) + 603017) * -1)/ 10); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==6) && ( ((-108 < a17) && (111 >= a17)) && ( a2 <= 189 && (((a7==13) || (a7==14)) && (input == 2))))) && (a24==15))){ + a2 = ((((((a2 % 45)+ 235) + 1) * 5) % 45)+ 219); + a17 = ((((a17 % 71)+ 184) + 1) + -1); + a7 = 14; + a24 = 13; + a5 = 3; + + return 21; + } else if((( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && ((a7==12) && ((input == 2) && (a5==5))))) && (a24==13))){ + a17 = (((a17 - 199) + -6) + -5); + a7 = 14; + a5 = 7; + + return 21; + } else if(((a7==13) && (((((input == 4) && (a5==7)) && (a24==14)) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ))){ + a17 = (((a17 - 357382) + -119715) * 1); + a7 = 14; + + return -1; + } else if(((a24==14) && ((a5==5) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )))))))){ + a2 = (((a2 - -271816) / 5) * -5); + a17 = ((((a17 - -250279) + 97462) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 3) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )))) && a2 <= 189 ) && (a5==6)) && (a24==13))){ + a17 = (((((a17 % 299946)- 300053) / 5) / 5) + -264660); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a7==12) && ((a5==5) && ((((input == 1) && (a24==13)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) )))){ + a17 = (((((a17 * -1)/ 10) + 161751) + -250598) + 88873); + a5 = 7; + + return 23; + } else if((((a24==13) && ((((input == 1) && (a5==5)) && ((-108 < a17) && (111 >= a17)) ) && (a7==14))) && a2 <= 189 )){ + a17 = ((((((a17 % 71)- -182) - 0) * 5) % 71)- -178); + a7 = 12; + a24 = 15; + a5 = 6; + + return 26; + } else if((((a5==3) && ( a17 <= -108 && (((a24==13) && (input == 4)) && ((189 < a2) && (281 >= a2)) ))) && (a7==12))){ + a2 = (((a2 * -5) * 5) / 5); + a24 = 14; + a5 = 5; + + return 23; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((( ((111 < a17) && (255 >= a17)) && (a7==12)) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))) && (input == 4)))) && (a24==14))){ + a17 = (((((a17 % 109)+ 2) - 348657) + -227996) - -576653); + a7 = 14; + + return -1; + } else if(((a24==14) && ((a5==4) && (( ((-108 < a17) && (111 >= a17)) && ((input == 3) && (a7==13))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 / -5) - -389340) * -1); + a17 = (((((a17 + 69965) + -188133) + -248443) * -1)/ 10); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a7==13) && ((a24==15) && ( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && ((a5==4) && (input == 3))))))){ + a2 = (((a2 * -5) - 523034) * 1); + a17 = ((((((a17 % 71)+ 184) + 138561) * 4) % 71)+ 151); + a24 = 13; + a5 = 7; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && (((((a7==13) || (a7==14)) && (input == 2)) && (a5==6)) && (a24==15))))){ + a2 = ((((((a2 - 0) % 45)+ 236) * 5) % 45)+ 213); + a17 = (((a17 - -31328) * 5) * 3); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if(((a5==7) && ( a2 <= 189 && ((a24==13) && ((input == 3) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))))))){ + a17 = ((((((a17 % 109)- 13) * 5) + -231249) % 109)- -55); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==6) && ( a2 <= 189 && ((a24==14) && ( ((-108 < a17) && (111 >= a17)) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 5))))))){ + a17 = (((((a17 % 71)+ 184) * 1) / 5) + 111); + a7 = 12; + a24 = 13; + a5 = 7; + + return 23; + } else if(((a5==5) && ( ((-108 < a17) && (111 >= a17)) && ((((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))) && (a24==14)) && a2 <= 189 )))){ + a2 = (((((a2 % 45)- -234) * 1) + -304708) - -304710); + a7 = 13; + a5 = 3; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a24==14) && ((((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==6)) && a2 <= 189 )))){ + a2 = (((((a2 % 45)- -236) - -1) / 5) + 208); + a17 = (((((a17 + -583311) / 5) * 5) % 71)- -225); + a7 = 14; + a24 = 15; + a5 = 3; + + return 23; + } else if(((a24==14) && ((a5==4) && (((((a7==12) && 255 < a17 ) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * 5) * 5) - 372070); + a17 = ((((a17 % 71)+ 123) - -13742) + -13696); + a7 = 14; + a24 = 15; + + return 21; + } else if((((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((input == 1) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))))) && (a24==15))){ + a2 = ((((a2 - 67499) * 5) * 10)/ 9); + a17 = ((((((a17 % 71)+ 183) * 5) * 5) % 71)- -126); + a7 = 12; + a5 = 5; + + return 21; + } else if(((((a24==13) && ((input == 1) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )))) && (a5==5)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - 0) % 109)+ 2) + 1); + a7 = 13; + a5 = 3; + + return -1; + } else if(((a5==6) && (((a24==13) && ((input == 6) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))))) && a2 <= 189 ))){ + a2 = ((((a2 / 5) - -545601) % 45)+ 203); + a17 = ((((a17 % 109)- -2) + 1) + -2); + a7 = 13; + + return 23; + } else if(((a5==4) && ((((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))))) && ((189 < a2) && (281 >= a2)) ) && (a24==13)))){ + a17 = (((((a17 % 71)- -182) - -29808) + -229764) + 199957); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a5==5) && ((( ((189 < a2) && (281 >= a2)) && (input == 6)) && (a24==13)) && ((-108 < a17) && (111 >= a17)) )) && (a7==13))){ + a2 = ((((a2 - -93069) / 5) * 5) - 656223); + a17 = (((a17 + -400644) - 189700) - 2801); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a7==14) && (((input == 1) && a2 <= 189 ) && (a5==5))) && (a24==15)) && a17 <= -108 )){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((input == 4) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)))) && (a7==13))){ + + return 26; + } else if(((((((input == 5) && (((a7==12) || (a7==13)) || (a7==14))) && ((189 < a2) && (281 >= a2)) ) && (a24==15)) && (a5==5)) && 255 < a17 )){ + a2 = (((a2 + -1933) * 5) + -538505); + a7 = 13; + a5 = 7; + + return -1; + } else if(( 255 < a17 && ((((a5==3) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))){ + a17 = ((((a17 % 71)+ 182) + -10) + 11); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a5==6) && (((((input == 5) && (a7==12)) && (a24==15)) && a2 <= 189 ) && a17 <= -108 ))){ + a2 = ((((a2 % 45)- -235) + 1) + -2); + a7 = 13; + a24 = 14; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && (((input == 5) && (((a24==13) && ( 255 < a17 && (a7==14))) || (( a17 <= -108 && (a7==12)) && (a24==14)))) && (a5==7)))){ + a17 = (((((a17 % 109)- -2) + 1) - -372693) - 372693); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((((a24==14) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 3))) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = (((a2 * 5) + -72167) * 5); + a17 = ((((a17 + -186071) + -206980) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if((((((a24==13) && ((input == 6) && ((a7==12) || (a7==13)))) && 255 < a17 ) && (a5==5)) && a2 <= 189 )){ + a17 = (((a17 + -600164) * 1) + -53); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==13) && ( 255 < a17 && (((a7==13) && ((input == 4) && (a5==7))) && a2 <= 189 )))){ + a17 = (((((a17 - 0) - 0) + 0) % 71)- -150); + a5 = 5; + + return -1; + } else if(( a2 <= 189 && ((((a24==15) && (((a7==13) || (a7==14)) && (input == 2))) && ((-108 < a17) && (111 >= a17)) ) && (a5==4)))){ + a17 = (((a17 - 164414) - 174884) + -159208); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((a24==14) && (((a7==12) || (a7==13)) && (input == 1))) && a17 <= -108 )) && (a5==4))){ + a2 = (((a2 / 5) * 5) / -5); + a7 = 12; + a24 = 15; + a5 = 5; + + return -1; + } else if((((a24==15) && ( 255 < a17 && ((a5==7) && (((a7==13) || (a7==14)) && (input == 2))))) && a2 <= 189 )){ + a17 = (((a17 - 600173) / 5) * 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && (( 255 < a17 && ( a2 <= 189 && ((input == 3) && ((a7==12) || (a7==13))))) && (a24==15)))){ + + a7 = 13; + a5 = 5; + + return 23; + } else if((( a17 <= -108 && ((a24==15) && ( a2 <= 189 && ((a5==6) && (input == 3))))) && (a7==12))){ + a17 = ((((a17 % 109)- -35) - 26) / 5); + a5 = 4; + + return 21; + } else if(((a24==15) && ((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 4)))))){ + a17 = ((((a17 - 384201) % 109)+ 1) + 2); + a7 = 13; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a17 <= -108 && ((a5==6) && ((a24==13) && ((input == 6) && (a7==12))))) && a2 <= 189 )){ + a2 = ((((((a2 * 9)/ 10) * 1) - -556567) % 45)+ 231); + a17 = ((((a17 % 109)+ 37) + 6) - 19); + a7 = 13; + a24 = 15; + a5 = 5; + + return 23; + } else if(((a5==3) && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 3)) && 255 < a17 ) && ((189 < a2) && (281 >= a2)) ) && (a24==15)))){ + a17 = (((((a17 % 109)+ 3) + -50) - -516936) + -516973); + a7 = 12; + a24 = 14; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (( ((-108 < a17) && (111 >= a17)) && (((a7==12) || (a7==13)) && (input == 6))) && (a5==3))) && (a24==13))){ + a2 = (((a2 + -109630) - 123244) - 219626); + a17 = ((((a17 + -100817) * 5) * 10)/ 9); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==13) && ((a5==5) && ( ((-108 < a17) && (111 >= a17)) && (((input == 1) && (a7==14)) && ((189 < a2) && (281 >= a2)) ))))){ + a17 = (((a17 + 526530) + 65040) + 5305); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==5) && ( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 6) && (( 255 < a17 && (a7==12)) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))))))){ + a2 = (((a2 * 5) / 5) / -5); + a17 = (((a17 - 0) - 600110) + -2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (( a17 <= -108 && ((input == 2) && (a7==12))) && (a5==6))) && (a24==13))){ + + a5 = 3; + + return -1; + } else if(((((a24==15) && ( a2 <= 189 && ((input == 2) && ((a7==12) || (a7==13))))) && 255 < a17 ) && (a5==5))){ + a17 = ((((a17 + 0) / 5) * 4) + -576078); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==7) && ((((input == 2) && (((a7==12) && 255 < a17 ) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))))) && a2 <= 189 ) && (a24==13)))){ + a17 = (((((a17 + -600111) + -1) * 9)/ 10) + -11291); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a5==7) && ( a2 <= 189 && ((input == 4) && (((((a7==13) && 255 < a17 ) && (a24==14)) || (( 255 < a17 && (a7==14)) && (a24==14))) || ((a24==15) && ((a7==12) && a17 <= -108 ))))))){ + a17 = (((((a17 * 9)/ 10) % 71)- -184) - 2); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if((((a24==14) && ( a2 <= 189 && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 3)))) && (a5==7))){ + a17 = ((((a17 % 109)+ 1) - -2) - 1); + a7 = 12; + + return -1; + } else if((((((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) && (input == 2)) && a2 <= 189 ) && (a24==14)) && (a5==7))){ + a17 = (((a17 - 600111) - 1) - 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==14) && ((a5==5) && (( a2 <= 189 && ((input == 3) && (a7==14))) && a17 <= -108 )))){ + a2 = ((((a2 % 45)+ 236) - -1) * 1); + a24 = 13; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && ((a5==7) && ((a24==13) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 5)))))){ + a17 = ((((((a17 % 71)+ 166) * 9)/ 10) * 9)/ 10); + a7 = 13; + + return -1; + } else if((( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && (((input == 1) && (a7==13)) && (a24==13)))) && (a5==5))){ + + a5 = 7; + + return 26; + } else if((((a24==13) && ((a5==5) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ))) && 255 < a17 )){ + + a7 = 13; + + return 23; + } else if(( a2 <= 189 && ((a24==13) && ((a5==5) && ((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || (((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (input == 5)))))){ + a17 = ((((a17 * 9)/ 10) - 5211) + 549653); + a7 = 13; + a24 = 14; + a5 = 6; + + return 26; + } else if((( ((111 < a17) && (255 >= a17)) && ((a5==5) && ((a7==14) && ((input == 6) && (a24==13))))) && a2 <= 189 )){ + a17 = ((((a17 + 372015) + -372184) + 315921) + -315903); + a24 = 14; + a5 = 7; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==13) && ((a5==4) && ((input == 3) && ((((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))))))){ + a2 = (((a2 * 5) - 399704) * 1); + a17 = (((((a17 % 299946)- 300053) + -1) - -345280) - 345280); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ))) && (a5==5))){ + a2 = ((((a2 * -5) * 5) - -579500) * -1); + a17 = (((a17 / 5) - 391832) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( ((189 < a2) && (281 >= a2)) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (input == 2)) && (a5==3))))){ + a2 = (((a2 + -106788) * 5) * 1); + a17 = ((((a17 + 74148) + 98517) % 109)- 1); + a7 = 13; + a24 = 13; + a5 = 4; + + return -1; + } else if((((a5==5) && ((((input == 3) && ((-108 < a17) && (111 >= a17)) ) && (a7==14)) && (a24==13))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / -5) - 597366) + -852); + a17 = (((a17 - 484669) + -100380) - 5769); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a5==7) && (((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && (a24==13))) && a2 <= 189 )){ + a17 = ((((a17 % 109)- -2) / 5) / 5); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if(((a5==6) && ((a24==14) && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && 255 < a17 ) && a2 <= 189 )))){ + a2 = ((((a2 - -292946) + -155034) % 45)+ 234); + a17 = (((((a17 % 109)+ -95) - -473885) * 1) - 473817); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if(((a24==14) && (((a5==5) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 3)))) && ((189 < a2) && (281 >= a2)) ))){ + a17 = (((((a17 + -251055) % 71)+ 183) + 492006) + -492005); + a7 = 12; + + return -1; + } else if((( 255 < a17 && ((((input == 2) && (a7==14)) && a2 <= 189 ) && (a5==5))) && (a24==15))){ + a17 = ((((a17 / 5) * 4) * -6)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && (((a7==13) && ( 255 < a17 && ((a24==15) && (input == 3)))) && ((189 < a2) && (281 >= a2)) ))){ + a17 = ((((a17 % 109)- 46) - 573448) + 573425); + a24 = 14; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((a5==3) && ((input == 3) && (a24==15))) && (a7==14))) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((a2 - 230215) / 5) + -123947); + a17 = ((((a17 / 5) * 10)/ -2) * 5); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((( ((111 < a17) && (255 >= a17)) && ((input == 4) && ((a7==12) || (a7==13)))) && (a5==4)) && (a24==13)))){ + a2 = ((((a2 * -5) * 10)/ 9) * 5); + a17 = (((a17 * 5) * 5) / 5); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(((( 255 < a17 && ( a2 <= 189 && ((input == 4) && ((a7==12) || (a7==13))))) && (a5==4)) && (a24==15))){ + a17 = ((((((a17 % 71)+ 177) * 9)/ 10) + -198267) + 198271); + a7 = 12; + a24 = 13; + a5 = 6; + + return 26; + } else if(( a2 <= 189 && ((input == 3) && (((a5==7) && ((a24==13) && ((a7==13) && a17 <= -108 ))) || (((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==6)) || ((a5==7) && ((a24==13) && ( a17 <= -108 && (a7==12))))))))){ + a2 = (((((a2 % 45)+ 235) - -2) - 281898) - -281896); + a17 = (((((a17 * 9)/ 10) % 299946)- 300053) - 2); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((((a5==6) && ((((a7==13) || (a7==14)) && (input == 1)) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 ) && (a24==15))){ + a2 = ((((a2 + 0) % 45)- -235) + -1); + a7 = 13; + a24 = 13; + a5 = 3; + + return 23; + } else if((((a5==6) && (((a24==14) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 4))) && 255 < a17 )) && a2 <= 189 )){ + a2 = (((((a2 - 0) % 45)+ 236) + 67568) - 67569); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if((((((a24==15) && ((input == 3) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 ) && (a5==6)) && (a7==12))){ + + return 23; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 2))))) && (a5==4))){ + a2 = (((a2 - 517350) / 5) + -227328); + a17 = ((((a17 * 9)/ 10) + -544188) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a5==5) && (((a7==12) || (a7==13)) && (input == 1))) && (a24==14)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((((a2 % 45)- -236) * 5) % 45)- -234); + a7 = 13; + a5 = 3; + + return 26; + } else if(((a24==14) && (( ((189 < a2) && (281 >= a2)) && ((((a7==13) || (a7==14)) && (input == 1)) && (a5==4))) && 255 < a17 ))){ + a17 = ((((((a17 % 71)+ 148) * 9)/ 10) * 9)/ 10); + a7 = 14; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 2) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )))) && (a5==4)) && (a24==13)))){ + a2 = (((a2 - 478599) * 1) * 1); + a17 = ((((a17 / 5) / 5) / 5) + -495670); + a7 = 12; + a5 = 3; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ((((input == 3) && ((a7==12) || (a7==13))) && (a24==13)) && (a5==3))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) + -578339) + -2272); + a17 = ((((a17 % 71)+ 183) + 2) - 1); + a7 = 14; + a5 = 7; + + return -1; + } else if(((a5==7) && (((input == 5) && ((((a24==14) && ( 255 < a17 && (a7==13))) || ((a24==14) && ((a7==14) && 255 < a17 ))) || (( a17 <= -108 && (a7==12)) && (a24==15)))) && a2 <= 189 ))){ + a17 = (((((a17 * 9)/ 10) % 109)- -2) + -1); + a7 = 14; + a24 = 14; + + return -1; + } else if(((a5==4) && ( a17 <= -108 && ((((input == 3) && (a24==13)) && (a7==12)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = ((((a2 + -508787) / 5) * 10)/ 9); + a17 = (((((a17 + 0) % 71)+ 254) * 9)/ 10); + a24 = 15; + + return -1; + } else if((( a17 <= -108 && (((a5==6) && ((input == 5) && ((a7==13) || (a7==14)))) && (a24==14))) && a2 <= 189 )){ + a2 = ((((((a2 % 45)+ 236) - 1) / 5) * 51)/ 10); + a17 = ((((a17 % 109)- -32) + -26) - -40); + a7 = 14; + a5 = 3; + + return 23; + } else if((((a24==13) && (((input == 3) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && ((189 < a2) && (281 >= a2)) )) && (a5==3))){ + a17 = (((((a17 % 109)+ 1) + 536699) + 4168) - 540865); + a7 = 13; + + return -1; + } else if((((a24==13) && ((((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ( 255 < a17 && (a7==12))) && (input == 1)) && ((189 < a2) && (281 >= a2)) )) && (a5==3))){ + a2 = (((a2 * 5) / -5) - 131726); + a17 = (((((a17 / 5) / 5) - 197914) % 109)+ 43); + a7 = 13; + a24 = 14; + a5 = 5; + + return -1; + } else if(((a24==13) && ( a17 <= -108 && (((a5==6) && (((a7==12) || (a7==13)) && (input == 2))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + 123909) - 483346) - 41719); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==3) && ((a24==14) && ((input == 5) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 - -143250) / -5) * 10)/ 9); + a17 = ((((a17 % 71)+ 183) / 5) + 104); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && (((a7==12) && ( ((189 < a2) && (281 >= a2)) && ((a24==15) && (input == 2)))) && (a5==5)))){ + a2 = (((a2 + -139817) - 311967) / 5); + a17 = (((a17 - 584030) / 5) / 5); + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==6) && (((( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))) && (input == 4)) && a2 <= 189 )))){ + a2 = (((((a2 * 9)/ 10) % 45)- -236) + -2); + a17 = ((((a17 % 71)+ 183) + 2) + -3); + a7 = 14; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a24==15) && ((a5==4) && ((((a7==13) || (a7==14)) && (input == 3)) && a2 <= 189 ))))){ + a17 = ((((a17 + -240122) * 10)/ -9) / 5); + a7 = 12; + a24 = 13; + a5 = 5; + + return 26; + } else if(( a2 <= 189 && ((a5==6) && ( a17 <= -108 && ((a24==14) && (((a7==13) || (a7==14)) && (input == 6))))))){ + a2 = (((((a2 % 45)- -236) - -1) - -152243) - 152245); + a7 = 12; + a5 = 3; + + return 26; + } else if(((a5==6) && (((a24==13) && (((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 4))) && a2 <= 189 ))){ + a2 = (((((a2 % 45)+ 236) - -249333) - 625277) - -375944); + a17 = ((((((a17 % 109)- -1) - 100) * 5) % 109)+ 2); + a7 = 13; + a5 = 4; + + return 26; + } else if((((((( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 2)) && (a5==6)) && a2 <= 189 ) && (a24==13))){ + a2 = (((((a2 % 45)- -234) + -442292) - -617405) - 175110); + a17 = ((((((a17 * 9)/ 10) % 71)- -115) / 5) - -197); + a7 = 13; + a24 = 14; + a5 = 3; + + return 21; + } else if((( a2 <= 189 && ((((a7==14) && (input == 4)) && (a5==5)) && (a24==14))) && a17 <= -108 )){ + a2 = ((((a2 % 45)+ 235) - 1) + 2); + a17 = ((((a17 % 109)+ 8) - 7) - -91); + a7 = 13; + a24 = 13; + a5 = 3; + + return 26; + } else if((( a2 <= 189 && ((a24==14) && ((input == 4) && (((a7==13) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))))) && (a5==7))){ + a17 = ((((a17 - 363253) / 5) + -406812) + 479520); + a7 = 13; + + return -1; + } else if((( a2 <= 189 && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && (a24==14)) && (a5==5))) && 255 < a17 )){ + a17 = (((((a17 * 9)/ 10) / 5) * 10)/ -4); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a5==7) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && a2 <= 189 ) && (a24==15)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 / 5) + -515705) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( a17 <= -108 && ((a5==5) && ((input == 2) && (a24==14)))) && (a7==14)) && a2 <= 189 )){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ( ((-108 < a17) && (111 >= a17)) && ((a5==6) && ((((a7==14) || ((a7==12) || (a7==13))) && (input == 3)) && (a24==14)))))){ + a2 = (((((a2 + 0) / 5) * 4) % 45)+ 234); + a7 = 12; + a5 = 3; + + return 26; + } else if((((a24==15) && ((((input == 2) && a2 <= 189 ) && (a7==12)) && (a5==7))) && 255 < a17 )){ + a17 = ((((a17 - 570713) - 29535) / 5) - 458064); + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==5) && (((input == 3) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))) && a2 <= 189 )) && (a24==15))){ + a2 = ((((((a2 * 9)/ 10) * 1) - 13827) % 45)+ 249); + a17 = ((((a17 % 109)+ 1) - -2) + -2); + a7 = 14; + a5 = 4; + + return 26; + } else if((((a24==15) && ( a2 <= 189 && ((input == 4) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))))) && (a5==5))){ + a2 = (((((a2 % 45)- -235) - 195114) - 258356) - -453470); + a17 = (((((a17 + 155793) % 109)- 63) + 567392) - 567346); + a7 = 13; + a5 = 4; + + return 23; + } else if((((a24==14) && ((a5==4) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 6)))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - -528091) - 699874) + 649609) + -972756); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( 255 < a17 && ((a24==15) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 1)) && ((189 < a2) && (281 >= a2)) ))) && (a5==3))){ + a2 = (((a2 / -5) - 163348) + 56585); + a7 = 14; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((a24==15) && ((input == 5) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))))))))){ + a2 = (((a2 / -5) + -568912) + -5609); + a17 = (((((a17 % 71)+ 184) + -1) / 5) - -182); + a7 = 12; + a5 = 4; + + return 23; + } else if(((a24==13) && ((((input == 1) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12)))) && (a5==4)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = ((((a2 - 161488) * 3) + 590787) + -671028); + a17 = ((((a17 - 600109) + 22162) + -18521) - 3641); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(((a5==6) && (((a24==14) && (((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && a2 <= 189 )) && 255 < a17 ))){ + + a7 = 14; + + return 26; + } else if((((((input == 6) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))))) && (a24==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = (((a2 - 579407) - 8118) * 1); + a17 = (((((a17 % 109)+ 3) + -458073) + 848155) + -390111); + a7 = 13; + a24 = 15; + a5 = 5; + + return -1; + } else if(((((((((a7==14) && 255 < a17 ) && (a24==15)) && (a5==4)) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==5))) || ((( a17 <= -108 && (a7==13)) && (a24==13)) && (a5==5))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 % 299872)- -300127) - -1) + 0); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if(((a5==5) && ((( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && (input == 5))) && (a24==13)) && (a7==13)))){ + a17 = (((a17 + -452489) * 1) * 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((a5==7) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 4)))) && (a24==13))){ + a17 = ((((a17 % 109)- -1) / 5) / 5); + a7 = 12; + a24 = 15; + a5 = 4; + + return 21; + } else if((((a24==13) && (((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)) && (a5==5))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / 5) + -341809) * 10)/ 9); + a17 = (((((a17 % 299872)- -300127) - 515739) + 17318) - -498422); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((((a24==15) && ((((a7==13) || (a7==14)) && (input == 3)) && a2 <= 189 )) && (a5==7)) && ((-108 < a17) && (111 >= a17)) )){ + + a7 = 14; + a24 = 14; + + return -1; + } else if(((a7==12) && (( a2 <= 189 && (((input == 5) && (a5==4)) && (a24==15))) && ((-108 < a17) && (111 >= a17)) ))){ + a17 = (((a17 - 277016) * 2) + -6397); + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==7) && (((((a24==15) && ( a17 <= -108 && (a7==12))) || (((a24==14) && ((a7==13) && 255 < a17 )) || ((a24==14) && ( 255 < a17 && (a7==14))))) && (input == 1)) && a2 <= 189 ))){ + a17 = ((((a17 % 299872)- -300127) + 1) + 0); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && (((a5==5) && ((a24==15) && ((input == 5) && ((a7==14) || ((a7==12) || (a7==13)))))) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 13; + a24 = 13; + a5 = 4; + + return -1; + } else if(((a5==5) && (((((a24==14) && ( a17 <= -108 && (a7==13))) || (((a24==13) && ((a7==14) && 255 < a17 )) || ((a24==14) && ((a7==12) && a17 <= -108 )))) && (input == 4)) && a2 <= 189 ))){ + a17 = ((((a17 + 0) - 0) / 5) + -383300); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (input == 5)) && (a24==15)) && (a5==3)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 219315) + -185024) / 5); + a17 = ((((a17 + -245709) % 71)- -191) * 1); + a7 = 13; + a24 = 13; + + return -1; + } else if((((a5==6) && ((a24==13) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 2)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) / 5) + -556465); + a17 = (((a17 / 5) + -548457) + -1247); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==15) && (((((input == 5) && (a5==7)) && a2 <= 189 ) && 255 < a17 ) && (a7==12)))){ + a17 = ((((((a17 * 9)/ 10) * 1) - 509339) % 71)+ 183); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==7) && (((input == 2) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && a2 <= 189 )) && (a24==13))){ + a2 = ((((((a2 % 45)+ 236) * 5) - -150446) % 45)- -205); + a17 = ((((a17 + -490890) / 5) + -314798) + 884206); + a7 = 14; + a24 = 14; + a5 = 3; + + return 23; + } else if((( 255 < a17 && (( a2 <= 189 && ((a24==15) && (input == 6))) && (a5==5))) && (a7==14))){ + a2 = (((((a2 * 9)/ 10) % 45)- -234) + 2); + a17 = (((((a17 / 5) + 157023) - 304246) % 109)+ 90); + a7 = 13; + a24 = 14; + + return 23; + } else if(((((a5==6) && (((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 2))) && a2 <= 189 ) && (a24==13))){ + a17 = ((((a17 % 299946)- 300053) * 1) - 1); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ((a5==6) && ((((input == 2) && ((a7==14) || ((a7==12) || (a7==13)))) && a2 <= 189 ) && (a24==14))))){ + a2 = (((((a2 + 0) * 9)/ 10) % 45)- -236); + a17 = ((((a17 + -217095) - -761433) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 4; + + return 21; + } else if(( a2 <= 189 && (((a7==14) && (((input == 1) && ((111 < a17) && (255 >= a17)) ) && (a5==5))) && (a24==14)))){ + a2 = ((((a2 % 45)- -234) - 10732) - -10732); + a24 = 15; + a5 = 3; + + return 26; + } else if(( a17 <= -108 && ((( ((189 < a2) && (281 >= a2)) && ((a5==3) && (input == 1))) && (a7==12)) && (a24==13)))){ + a2 = (((a2 + -187375) * 3) - -239890); + a17 = ((((((a17 % 71)- -216) * 9)/ 10) * 10)/ 9); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if(((((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )) && (input == 1)) && (a5==5)) && (a24==14)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - 309533) % 299872)- -300127) * 1); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 4)) && (a24==13))) && (a5==3))){ + a2 = (((a2 / 5) / 5) + -113113); + a17 = ((((a17 + -152498) - 120570) * 10)/ 9); + a7 = 14; + a24 = 14; + a5 = 5; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((((( 255 < a17 && (a7==13)) && (a24==13)) || (( 255 < a17 && (a7==14)) && (a24==13))) || (((a7==12) && a17 <= -108 ) && (a24==14))) && (input == 4))))){ + a2 = (((a2 + -277502) * 2) - 40398); + a17 = ((((a17 + 0) / 5) + 23146) - 484422); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==13) && ((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((input == 4) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 ))))))){ + a2 = (((a2 / 5) / -5) - 183721); + a17 = ((((a17 % 109)+ -83) + -12) + 78); + a7 = 13; + a24 = 14; + a5 = 5; + + return 26; + } else if((((((input == 3) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && (a24==13)) && (a5==6)) && a2 <= 189 )){ + a2 = ((((a2 + 0) % 45)- -234) * 1); + a17 = (((((a17 * 9)/ 10) * 1) % 71)- -138); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((a5==4) && (((input == 5) && ((a7==12) || (a7==13))) && ((111 < a17) && (255 >= a17)) ))))){ + + a7 = 13; + + return -1; + } else if(((a5==4) && (( ((189 < a2) && (281 >= a2)) && ((input == 4) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 ))))) && (a24==13)))){ + a2 = (((a2 * 5) * 5) + -590870); + a17 = ((((a17 + 439473) + -202777) % 299946)+ -300053); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==15) && (( 255 < a17 && ((a5==5) && ((input == 3) && (((a7==12) || (a7==13)) || (a7==14))))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 - -345840) * 1) * -1); + a17 = ((((a17 % 109)- 50) - 15) / 5); + a7 = 13; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && (( ((111 < a17) && (255 >= a17)) && (((input == 2) && (((a7==12) || (a7==13)) || (a7==14))) && (a5==7))) && (a24==15)))){ + a17 = ((((a17 / 5) + -289356) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && ((a24==13) && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14)))) && (input == 6)) && ((189 < a2) && (281 >= a2)) )))){ + a17 = (((((a17 % 299872)- -300127) / 5) / 5) - -212547); + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ( a2 <= 189 && ((a24==15) && ((((a7==13) || (a7==14)) && (input == 6)) && (a5==6)))))){ + a2 = ((((a2 % 45)+ 234) / 5) - -178); + a7 = 14; + a5 = 3; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && (((((a24==15) && (input == 2)) && ((189 < a2) && (281 >= a2)) ) && (a5==4)) && (a7==13)))){ + a2 = (((a2 + -185317) * 3) * 1); + a17 = (((a17 - -209383) / 5) + -402688); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==4) && ((a24==13) && ((input == 4) && a17 <= -108 ))) && (a7==12)) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 + -340540) + -216382) - -1035898) * -1); + a17 = ((((a17 % 299872)- -300127) - 43079) + 207436); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && (((input == 1) && ((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (a24==14))))){ + a2 = (((a2 * 5) * 5) - 195095); + a17 = ((((((a17 * 9)/ 10) * 1) * 1) % 109)+ 2); + a7 = 13; + a5 = 5; + + return 26; + } else if(((a5==4) && (( ((189 < a2) && (281 >= a2)) && ((((a7==12) || (a7==13)) && (input == 4)) && a17 <= -108 )) && (a24==14)))){ + + a7 = 12; + + return -1; + } else if(( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && ((a7==12) && ((a5==4) && ((a24==15) && (input == 4))))))){ + a17 = ((((a17 * 5) * 5) * 10)/ -9); + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (( ((-108 < a17) && (111 >= a17)) && ((a7==13) && ((input == 6) && (a5==3)))) && (a24==15)))){ + a2 = (((a2 + 505188) / 5) - 263894); + a17 = (((((a17 % 71)- -182) + 569253) * 1) + -569250); + a7 = 12; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((input == 6) && ((((((a7==14) && 255 < a17 ) && (a24==15)) && (a5==6)) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==7))) || (((a24==13) && ( a17 <= -108 && (a7==13))) && (a5==7)))))){ + a2 = (((((a2 % 45)- -236) + -2) / 5) - -177); + a17 = ((((a17 % 299872)- -300127) / 5) - -33046); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if(((( ((189 < a2) && (281 >= a2)) && (((input == 6) && ((a7==13) || (a7==14))) && (a24==14))) && 255 < a17 ) && (a5==4))){ + + a7 = 12; + a24 = 13; + + return -1; + } else if(((a5==6) && ((a24==15) && (((a7==13) && ((input == 6) && a17 <= -108 )) && a2 <= 189 )))){ + a2 = (((((a2 % 45)- -235) + 573332) * 1) + -573331); + a17 = ((((a17 % 109)- -40) - 575414) + 575451); + a7 = 14; + a24 = 13; + a5 = 4; + + return 23; + } else if(((a24==15) && ((a5==4) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 4)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * 5) + -205527) + -261072); + a17 = ((((a17 * 5) + 376065) % 71)+ 172); + a7 = 12; + a5 = 5; + + return 21; + } else if((( a2 <= 189 && ((((( 255 < a17 && (a7==13)) && (a24==13)) || (((a7==14) && 255 < a17 ) && (a24==13))) || ((a24==14) && ( a17 <= -108 && (a7==12)))) && (input == 1))) && (a5==6))){ + a2 = ((((a2 % 45)- -235) / 5) * 5); + a17 = (((((a17 * 9)/ 10) % 299946)- 300053) - 1); + a7 = 12; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a7==14) && ((a24==15) && ((((input == 6) && ((111 < a17) && (255 >= a17)) ) && ((189 < a2) && (281 >= a2)) ) && (a5==3))))){ + a17 = (((a17 + -508114) * 1) - 7160); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==5) && (( a2 <= 189 && ((input == 5) && (a7==14))) && 255 < a17 )) && (a24==15))){ + a2 = ((((a2 - 0) / 5) % 45)- -236); + a17 = (((a17 - 600247) * 1) * 1); + a7 = 12; + a24 = 14; + + return 21; + } else if(((((a24==13) && ((input == 6) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))) && ((189 < a2) && (281 >= a2)) ) && (a5==6))){ + a17 = (((((a17 / 5) - -11) * 5) % 109)+ 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && ((a5==4) && ((input == 3) && (( ((111 < a17) && (255 >= a17)) && (a7==13)) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 - 251250) * 10)/ 9) + -123956); + a17 = ((((a17 + -55926) + -49743) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a7==13) && ((a5==6) && ((((input == 2) && 255 < a17 ) && ((189 < a2) && (281 >= a2)) ) && (a24==13))))){ + a2 = ((((a2 + -73789) * 10)/ 9) - 475570); + a17 = (((a17 + -600188) - 1) + -26); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ((((((a7==13) || (a7==14)) && (input == 4)) && a2 <= 189 ) && (a24==15)) && (a5==4)))){ + + a7 = 13; + a5 = 5; + + return 21; + } + return calculate_output3(input); + } + + int calculate_output3(int input) { + + + if(( a2 <= 189 && ((a24==15) && ((a7==14) && ((a5==5) && ( a17 <= -108 && (input == 2))))))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((input == 3) && ((a7==13) || (a7==14)))))) && (a5==5))){ + a2 = (((a2 / 5) * -5) / 5); + a17 = ((((a17 + 77227) + 218385) - 579561) - -466982); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a5==5) && ( a2 <= 189 && ((a7==14) && ((a24==13) && (input == 4))))) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 + -361852) * 1) / 5) - -72429); + a7 = 13; + a24 = 14; + a5 = 7; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((((a7==13) && ((a5==3) && (input == 3))) && (a24==15)) && ((-108 < a17) && (111 >= a17)) ))){ + + a7 = 14; + a24 = 14; + + return -1; + } else if(((((((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) || ( ((-108 < a17) && (111 >= a17)) && (a7==13))) && (input == 1)) && a2 <= 189 ) && (a5==7)) && (a24==13))){ + a2 = ((((a2 - -278577) * 1) % 45)- -234); + a17 = ((((a17 / 5) % 109)- -2) - 1); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a24==13) && (((a5==3) && ((input == 2) && ((a7==12) || (a7==13)))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + 542429) / -5) + -452431); + a17 = (((((a17 + -62715) % 71)- -200) * 9)/ 10); + a7 = 14; + + return -1; + } else if(((((a5==5) && ((((a7==12) || (a7==13)) && (input == 5)) && (a24==14))) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 )){ + a17 = ((((a17 * 5) / 5) * 10)/ -9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==13) && ( 255 < a17 && ( ((189 < a2) && (281 >= a2)) && ((((a7==13) || (a7==14)) && (input == 1)) && (a5==4)))))){ + a2 = ((((a2 + -345206) - -753451) / 5) * -5); + a17 = ((((a17 % 109)- 98) - 8) + 96); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(( 255 < a17 && (((a24==14) && ((a5==5) && ((input == 1) && ((a7==13) || (a7==14))))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * 5) + 150678) + -312416); + a17 = (((((a17 + 0) + 0) / 5) % 71)+ 147); + a7 = 13; + a5 = 7; + + return -1; + } else if(((((((input == 2) && (((a7==12) || (a7==13)) || (a7==14))) && 255 < a17 ) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a5==5))){ + a2 = (((a2 + -439935) * 1) * 1); + a17 = (((a17 - 581561) + -18563) - 36); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (((input == 2) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))) && (a5==7))) && (a24==14))){ + a17 = (((a17 - 547158) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==3) && ((a24==14) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) || ( 255 < a17 && (a7==13)))))))){ + a2 = (((a2 * -5) * 5) - 267645); + a17 = ((((((a17 * 9)/ 10) % 71)+ 146) - 7467) - -7498); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if((((a5==5) && (( a2 <= 189 && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && (a24==14))) && 255 < a17 )){ + a17 = (((a17 + -600255) + -1) + 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==6) && (( ((189 < a2) && (281 >= a2)) && ((input == 5) && (a7==14))) && a17 <= -108 )) && (a24==13))){ + a17 = ((((((a17 % 109)- -39) * 5) - 208544) % 109)+ 56); + a5 = 3; + + return -1; + } else if(((a7==14) && ( ((189 < a2) && (281 >= a2)) && ((( a17 <= -108 && (input == 3)) && (a24==13)) && (a5==6))))){ + a2 = (((a2 + -369894) + -119659) - 59892); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a7==14) && (((a5==5) && ((input == 1) && (a24==13))) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 )){ + a17 = (((((a17 * 10)/ -9) - -538584) * 1) - 852442); + a7 = 12; + a24 = 15; + a5 = 7; + + return 23; + } else if((( a2 <= 189 && ((((input == 3) && ((a7==12) || (a7==13))) && (a5==6)) && 255 < a17 )) && (a24==15))){ + a2 = ((((a2 - 0) % 45)+ 235) + 1); + a17 = ((((a17 - 0) % 109)- 13) - -1); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if((((a24==15) && ( ((189 < a2) && (281 >= a2)) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) && (input == 2)))) && (a5==4))){ + a2 = (((a2 * 5) / -5) * 5); + a17 = (((a17 + -600110) * 1) + -1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((((a24==14) && ( 255 < a17 && (a7==14))) || ((a24==15) && ( a17 <= -108 && (a7==12)))) && (input == 5)) && (a5==3)))){ + a2 = (((a2 * -5) - 176348) - 175983); + a17 = ((((a17 % 71)- -182) + 3) - 3); + a7 = 12; + a24 = 13; + a5 = 7; + + return -1; + } else if(((((((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && 255 < a17 ) && a2 <= 189 ) && (a24==14)) && (a5==5))){ + a2 = (((((a2 + 252809) % 45)+ 234) - -188524) + -188523); + a17 = ((((((a17 / 5) % 109)+ 1) * 5) % 109)+ 3); + a7 = 14; + a24 = 13; + a5 = 4; + + return 21; + } else if(( a2 <= 189 && ((a24==14) && ( ((-108 < a17) && (111 >= a17)) && ((a7==13) && ((input == 3) && (a5==7))))))){ + a17 = (((a17 - 479950) * 1) / 5); + a7 = 12; + + return -1; + } else if((((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (input == 1)) && a2 <= 189 ) && (a5==5)) && (a24==13))){ + a17 = ((((a17 - -331363) % 109)- -1) + 0); + a7 = 12; + a24 = 14; + a5 = 6; + + return 21; + } else if((( 255 < a17 && (( ((189 < a2) && (281 >= a2)) && ((input == 4) && (((a7==12) || (a7==13)) || (a7==14)))) && (a24==15))) && (a5==3))){ + a2 = ((((a2 * 5) / 5) - -456557) * -1); + a17 = (((a17 / 5) * 4) + -534343); + a7 = 13; + a24 = 13; + + return -1; + } else if((((a24==15) && (((input == 2) && (( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && a2 <= 189 )) && (a5==6))){ + a17 = ((((a17 % 299946)- 300053) / 5) + -177770); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && (((a24==15) && (((input == 4) && ((a7==13) || (a7==14))) && (a5==7))) && 255 < a17 ))){ + + a7 = 13; + a24 = 13; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((input == 4) && ((( 255 < a17 && (a7==14)) && (a24==14)) || ((a24==15) && ( a17 <= -108 && (a7==12)))))))){ + a17 = (((((a17 % 299872)+ 300127) + 0) + -528429) + 528430); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a24==14) && ((a5==4) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 1)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -412962) - 162289) + -93); + a17 = ((((a17 + 200708) / 5) - -224575) + -264525); + a7 = 13; + a24 = 15; + + return 21; + } else if(( 255 < a17 && ((a5==4) && ((((a7==13) && (input == 2)) && ((189 < a2) && (281 >= a2)) ) && (a24==15))))){ + a2 = ((((a2 + 17174) - -390384) * 1) * -1); + a17 = (((a17 + -200385) - 399757) + -108); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a5==5) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13))))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((a2 / 5) / 5) * 5); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && ((a5==6) && (((input == 1) && ((a7==13) || (a7==14))) && ((-108 < a17) && (111 >= a17)) ))))){ + a2 = ((((a2 % 45)- -236) + 1) - 2); + a17 = ((((a17 * 5) % 71)- -183) + -1); + a7 = 14; + a24 = 14; + a5 = 3; + + return 21; + } else if((((a24==13) && (((input == 5) && ((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && a2 <= 189 )) && (a5==6))){ + a2 = ((((a2 % 45)+ 235) - 1) + 1); + a17 = ((((a17 - 0) % 299872)- -300127) * 1); + a7 = 13; + a24 = 15; + a5 = 5; + + return 26; + } else if((((((a24==14) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 1))) && a2 <= 189 ) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )){ + a2 = ((((a2 % 45)+ 234) + 293810) + -293808); + a7 = 12; + a5 = 3; + + return 23; + } else if(((((((a24==15) && (input == 1)) && (a5==4)) && (a7==12)) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 )){ + + a7 = 14; + a24 = 14; + a5 = 5; + + return 23; + } else if(((a5==5) && ( ((-108 < a17) && (111 >= a17)) && ((((input == 5) && ((a7==12) || (a7==13))) && a2 <= 189 ) && (a24==15))))){ + a2 = (((((a2 % 45)+ 236) - 49315) / 5) + 10068); + a17 = (((a17 + -103117) / 5) - 439137); + a7 = 13; + a5 = 4; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==13) && ((a5==4) && ( ((111 < a17) && (255 >= a17)) && ((input == 3) && ((a7==12) || (a7==13)))))))){ + a2 = ((((a2 * -5) - 314138) - -565933) + -292419); + a17 = (((a17 + -173172) + -177178) * 1); + a7 = 13; + a24 = 15; + a5 = 5; + + return -1; + } else if((((a5==3) && (((( a17 <= -108 && (a7==12)) && (a24==14)) || (((a24==13) && ( 255 < a17 && (a7==13))) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 2))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -532738) + -47238) * 1); + a17 = (((((a17 + 0) * 9)/ 10) % 71)- -182); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if(((a5==6) && ((a24==13) && (((input == 4) && ((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && a2 <= 189 )))){ + a17 = ((((a17 - -565469) + -60299) / 5) - 520148); + a7 = 12; + a5 = 3; + + return -1; + } else if((((( 255 < a17 && ((input == 3) && (a7==13))) && (a24==13)) && (a5==6)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / -5) - 310362) - 118239); + a17 = ((((a17 + -527475) + -43049) / 5) + -159294); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==14) && ((a5==4) && ((input == 1) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((((a2 * -5) * 10)/ 9) - -320944) * -1); + a17 = (((((a17 * 9)/ 10) + 31872) % 71)+ 182); + a7 = 13; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((a24==15) && ( a17 <= -108 && (((a7==13) && (input == 4)) && (a5==6)))))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 5) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a24==14)) && (a5==5)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * 5) - 436847) + -130272); + a17 = (((a17 / 5) - 469094) - -33679); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==4) && ( 255 < a17 && ( ((189 < a2) && (281 >= a2)) && ((input == 3) && ((a7==13) || (a7==14)))))) && (a24==14))){ + a17 = (((((a17 / 5) * 4) - -51204) % 71)+ 129); + a7 = 14; + + return -1; + } else if((((( a2 <= 189 && ((a7==12) && (input == 1))) && (a5==7)) && 255 < a17 ) && (a24==15))){ + a17 = ((((a17 - 204408) - -50146) % 109)- -2); + a7 = 14; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((a24==15) && ((a5==5) && ( a17 <= -108 && ((a7==14) && (input == 3))))))){ + a2 = (((((a2 % 45)+ 236) * 5) % 45)+ 204); + a17 = (((((a17 + 0) * 9)/ 10) % 109)+ 90); + a7 = 12; + a24 = 14; + a5 = 4; + + return 26; + } else if(((((a5==6) && ((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 5))) && (a24==15)) && a2 <= 189 )){ + a17 = ((((a17 % 71)+ 184) - 1) - 1); + a7 = 12; + a24 = 13; + a5 = 7; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((( 255 < a17 && (a7==13)) || (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12)))) && (input == 1)))) && (a5==3))){ + a17 = (((((a17 * 9)/ 10) % 109)- -2) + 1); + a7 = 12; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && ((a7==14) && (((input == 2) && ((111 < a17) && (255 >= a17)) ) && (a5==5)))))){ + a17 = ((((a17 - 501351) * 10)/ 9) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a7==13) && (((((input == 5) && (a5==7)) && (a24==14)) && ((-108 < a17) && (111 >= a17)) ) && a2 <= 189 ))){ + a17 = (((a17 + -506871) + -84379) / 5); + a7 = 12; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 2) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && (a5==3)) && (a24==13)))){ + a2 = (((a2 / 5) * 5) - 539865); + a17 = (((a17 + -583438) - 9976) - 606); + a7 = 12; + + return -1; + } else if((((( ((111 < a17) && (255 >= a17)) && ((input == 5) && a2 <= 189 )) && (a7==14)) && (a5==5)) && (a24==14))){ + a17 = ((((a17 / 5) + 148886) * 10)/ -9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==7) && (((( 255 < a17 && (input == 1)) && (a24==13)) && a2 <= 189 ) && (a7==13)))){ + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (( ((189 < a2) && (281 >= a2)) && (input == 4)) && (a7==13))) && (a24==14)) && (a5==3))){ + a17 = ((((a17 / 5) - 84) * 10)/ 9); + a7 = 12; + + return -1; + } else if((((((a24==15) && ((input == 6) && ((111 < a17) && (255 >= a17)) )) && (a5==5)) && (a7==14)) && a2 <= 189 )){ + a2 = (((((a2 % 45)- -234) + 3) - 467950) - -467949); + a17 = ((((a17 * 23)/ 10) - -254710) + 246366); + a5 = 4; + + return 21; + } else if(((((((a5==4) && ((a24==15) && ((a7==14) && 255 < a17 ))) || ((( a17 <= -108 && (a7==12)) && (a24==13)) && (a5==5))) || ((a5==5) && (((a7==13) && a17 <= -108 ) && (a24==13)))) && (input == 4)) && a2 <= 189 )){ + a17 = ((((a17 + 0) + 0) % 299946)+ -300053); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((( ((111 < a17) && (255 >= a17)) && (input == 6)) && (a7==13)) && a2 <= 189 ) && (a24==13)) && (a5==5))){ + a17 = (((a17 * 5) + 157598) / 5); + a7 = 14; + a5 = 7; + + return 21; + } else if(( a2 <= 189 && ((a5==7) && (((( 255 < a17 && (a7==14)) && (a24==13)) || ((a24==14) && ( a17 <= -108 && (a7==12)))) && (input == 3))))){ + a17 = ((((a17 + 0) + 0) % 299872)+ 300127); + a7 = 13; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((a5==6) && (((((a7==12) && a17 <= -108 ) && (a24==14)) || (((a24==13) && ( 255 < a17 && (a7==13))) || (( 255 < a17 && (a7==14)) && (a24==13)))) && (input == 2))))){ + a2 = (((((a2 + 453687) % 45)- -236) - -350177) + -350178); + a17 = (((((a17 % 71)+ 182) + 0) - -438904) - 438902); + a7 = 12; + a24 = 14; + a5 = 3; + + return 23; + } else if(( ((111 < a17) && (255 >= a17)) && ((a7==13) && ((( ((189 < a2) && (281 >= a2)) && (input == 3)) && (a24==14)) && (a5==3))))){ + a2 = (((a2 / 5) / -5) * 5); + a17 = (((a17 * 5) - -273749) - 586768); + a7 = 14; + + return -1; + } else if(((a5==7) && (( a2 <= 189 && ((input == 3) && (( ((111 < a17) && (255 >= a17)) && (a7==13)) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))))) && (a24==14)))){ + a17 = (((((a17 - 515132) / 5) + 523785) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==5) && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 2))) && ((189 < a2) && (281 >= a2)) ) && (a24==13))){ + a2 = (((a2 * 5) + 144469) + -189230); + a17 = (((((a17 + 0) % 299946)- 300053) / 5) + -445482); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a5==5) && (( ((189 < a2) && (281 >= a2)) && (input == 4)) && ((-108 < a17) && (111 >= a17)) )) && (a24==15)) && (a7==12))){ + a2 = (((a2 * 5) / -5) * 5); + a17 = ((((((a17 * 5) % 71)+ 184) * 5) % 71)- -152); + a24 = 14; + a5 = 7; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && (a24==15))))) && (a7==13))){ + a17 = (((a17 - -116942) * 5) * 1); + a24 = 13; + + return -1; + } else if(((a5==5) && ((a24==13) && ( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && ((a7==13) && (input == 4))))))){ + a17 = (((a17 * 5) - 554850) + -19327); + a24 = 14; + a5 = 7; + + return 23; + } else if((( ((-108 < a17) && (111 >= a17)) && (((((a7==13) || (a7==14)) && (input == 4)) && (a24==15)) && a2 <= 189 )) && (a5==7))){ + a17 = (((a17 / 5) + -465987) + -123095); + a7 = 12; + + return -1; + } else if((((((a24==13) && (((a7==13) || (a7==14)) && (input == 3))) && ((-108 < a17) && (111 >= a17)) ) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 % 71)+ 183) - 106273) - -106273); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==13) && ( ((-108 < a17) && (111 >= a17)) && (((a7==12) || (a7==13)) && (input == 5)))) && (a5==3)))){ + a2 = ((((a2 * -5) * 5) + 590510) - 671065); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && ((a5==5) && (((input == 6) && (a24==14)) && (a7==14)))) && a2 <= 189 )){ + a17 = ((((a17 * 5) * 10)/ -9) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((( a17 <= -108 && (a7==12)) && (a24==15)) || ((( 255 < a17 && (a7==13)) && (a24==14)) || ((a24==14) && ( 255 < a17 && (a7==14))))) && (input == 6)) && a2 <= 189 ) && (a5==7))){ + a17 = (((a17 / 5) - 232817) * 1); + a7 = 12; + a24 = 15; + + return -1; + } else if((( a2 <= 189 && (((input == 6) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==6))) && (a24==15))){ + a17 = (((((a17 % 299946)+ -300053) + 0) / 5) + -24082); + a7 = 14; + + return 23; + } else if((((a24==14) && (((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) && (input == 1)) && (a5==7))) && a2 <= 189 )){ + a17 = (((((a17 % 299872)- -256) * 1) / 5) - -44806); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a24==14) && ((( a2 <= 189 && ((input == 1) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==6)) && 255 < a17 ))){ + a2 = ((((((a2 / 5) % 45)+ 235) / 5) * 51)/ 10); + a17 = ((((((a17 / 5) % 109)+ 2) * 5) % 109)+ -3); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((( a2 <= 189 && ((a5==6) && (((a7==13) || (a7==14)) && (input == 4)))) && ((-108 < a17) && (111 >= a17)) ) && (a24==15))){ + a2 = ((((a2 + 216043) % 45)+ 236) - -1); + a17 = (((((a17 - 429059) + 308928) * 4) % 71)- -208); + a7 = 14; + a5 = 3; + + return 21; + } else if((((((((a7==13) || (a7==14)) && (input == 5)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==6))){ + a17 = (((a17 + -54487) - 92979) - 379120); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && (( ((189 < a2) && (281 >= a2)) && ((a5==6) && (((a7==12) || (a7==13)) && (input == 1)))) && (a24==13)))){ + a2 = (((a2 - 455132) - 98197) + -25953); + a17 = (((a17 + 255777) * 2) + -670603); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==14) && ((a5==3) && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -585771) + -2935) * 1); + a17 = (((((a17 * 9)/ 10) / 5) % 109)- -1); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==5) && (((a24==15) && ( a2 <= 189 && (((a7==12) || (a7==13)) && (input == 4)))) && ((-108 < a17) && (111 >= a17)) ))){ + a2 = ((((((a2 - 0) + 0) * 9)/ 10) % 45)- -234); + a17 = ((((a17 % 71)- -184) - 1) + 1); + a7 = 14; + a24 = 14; + a5 = 4; + + return 21; + } else if((((a5==5) && (((input == 6) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a24==14))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((((a17 * 9)/ 10) / 5) - 287459) % 109)- -2); + a7 = 12; + a5 = 4; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && ((a24==15) && ( ((189 < a2) && (281 >= a2)) && ((a7==14) && (input == 2))))) && (a5==3))){ + + return 26; + } else if(((( a2 <= 189 && ((a24==13) && ((input == 3) && ((-108 < a17) && (111 >= a17)) ))) && (a5==5)) && (a7==14))){ + a17 = ((((a17 / 5) * 5) / 5) - -181132); + a7 = 13; + a24 = 15; + a5 = 6; + + return 23; + } else if(( a2 <= 189 && ((((((a7==13) || (a7==14)) && (input == 2)) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==7)))){ + a17 = (((a17 - 261314) + 71142) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( 255 < a17 && (((a24==13) && ((input == 2) && ((a7==13) || (a7==14)))) && (a5==4))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * 5) + -450773) - 107216); + a17 = ((((((a17 % 71)+ 158) - 39) / 5) * 49)/ 10); + a7 = 14; + a24 = 14; + + return -1; + } else if(((( a2 <= 189 && (((((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 4))) && (a5==7)) && (a24==14))){ + a17 = (((((a17 * 9)/ 10) % 109)- -1) + 0); + a7 = 14; + a24 = 15; + a5 = 4; + + return 21; + } else if(((((a5==4) && ( ((189 < a2) && (281 >= a2)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 4)))) && (a24==15)) && a17 <= -108 )){ + a17 = (((((a17 % 71)- -182) + 0) / 5) - -96); + a7 = 13; + a24 = 14; + + return -1; + } else if(( a2 <= 189 && ((a5==6) && (((((a7==12) || (a7==13)) && (input == 5)) && (a24==15)) && 255 < a17 )))){ + a2 = ((((a2 % 45)- -236) + 127994) - 127995); + a17 = (((((a17 - 156755) * 1) * 1) % 109)- -2); + a7 = 13; + a5 = 3; + + return 21; + } else if(((a24==13) && (((a5==6) && ((input == 3) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && ((189 < a2) && (281 >= a2)) ))){ + a17 = (((((a17 / 5) * 5) + -36231) * -1)/ 10); + a7 = 14; + a5 = 4; + + return -1; + } else if(((((((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)) && (a24==15)) && a2 <= 189 ) && (a5==7))){ + a17 = (((((a17 + 0) / 5) + 400868) % 109)+ -80); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a24==15) && ((((input == 3) && ((a7==12) || (a7==13))) && 255 < a17 ) && (a5==5))) && a2 <= 189 )){ + a17 = (((a17 - 600131) - 103) + -13); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==14) && ((a5==5) && (((input == 5) && (((a7==12) && ((111 < a17) && (255 >= a17)) ) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = ((((a2 + 363060) - 21984) + -307797) * -5); + a17 = ((((a17 / 5) / 5) - -385642) - 385582); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a5==7) && ( a2 <= 189 && ((a24==15) && ((input == 4) && ((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))))))){ + a17 = ((((a17 - 0) % 299872)- -300127) + 1); + a7 = 13; + a24 = 14; + + return -1; + } else if((((((a5==5) && ((a24==13) && ((a7==13) && a17 <= -108 ))) || (((a5==4) && (( 255 < a17 && (a7==14)) && (a24==15))) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==5)))) && (input == 3)) && a2 <= 189 )){ + a17 = (((a17 / 5) - -222886) * 1); + a7 = 14; + a24 = 13; + a5 = 6; + + return 26; + } else if((((a5==6) && ((((input == 1) && ((a7==13) || (a7==14))) && a2 <= 189 ) && (a24==14))) && a17 <= -108 )){ + a2 = ((((((a2 % 45)+ 235) + -1) * 5) % 45)- -223); + a17 = ((((a17 % 109)+ 16) + -191467) - -191547); + a7 = 12; + a24 = 13; + a5 = 4; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && (((input == 1) && (a24==14)) && (a7==13)))) && (a5==4))){ + a2 = (((a2 * 5) * 5) - 342077); + a17 = ((((a17 * 5) / 5) % 71)+ 184); + a24 = 15; + + return 21; + } else if(((a5==5) && ( a2 <= 189 && (( ((111 < a17) && (255 >= a17)) && (((a7==12) || (a7==13)) && (input == 4))) && (a24==14))))){ + a2 = ((((a2 + 110417) % 45)- -236) * 1); + a17 = ((((a17 * 5) * 10)/ -9) - 228824); + a7 = 13; + a24 = 15; + a5 = 3; + + return 21; + } else if((((a24==13) && ( a2 <= 189 && ((input == 1) && ((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))))) && (a5==6))){ + a2 = (((((a2 % 45)+ 234) / 5) - -431906) + -431702); + a17 = (((((a17 + -434179) % 109)+ 30) + 138172) + -138140); + a7 = 14; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && (( a2 <= 189 && (((a24==13) && (input == 5)) && (a5==5))) && (a7==14)))){ + a17 = (((a17 + 592041) * 1) - -2226); + a7 = 12; + a24 = 14; + a5 = 7; + + return 26; + } else if(((((a24==13) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 5))) && (a5==7)) && a2 <= 189 )){ + a17 = (((((a17 % 71)+ 182) / 5) * 51)/ 10); + a7 = 12; + a5 = 5; + + return 21; + } else if((((a24==15) && (((a5==4) && ( ((-108 < a17) && (111 >= a17)) && (input == 5))) && (a7==12))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / 5) / -5) * 5); + a17 = (((a17 - -517716) / 5) * 5); + a7 = 13; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a5==5) && ((a24==13) && ( a2 <= 189 && ((input == 3) && (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )))))))){ + a17 = ((((a17 % 299946)+ -300053) - 1) - 1); + a7 = 12; + a24 = 15; + a5 = 6; + + return 26; + } else if(( a2 <= 189 && ((((a5==7) && (((a7==13) && a17 <= -108 ) && (a24==13))) || (((a5==6) && ((a24==15) && ( 255 < a17 && (a7==14)))) || ((a5==7) && ((a24==13) && ((a7==12) && a17 <= -108 ))))) && (input == 5)))){ + a2 = ((((a2 - -71451) % 45)- -236) + -1); + a17 = (((((a17 * 9)/ 10) % 109)- -2) + -1); + a7 = 13; + a24 = 15; + a5 = 3; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((((( 255 < a17 && (a7==14)) && (a24==14)) || (( a17 <= -108 && (a7==12)) && (a24==15))) && (input == 2)) && (a5==3)))){ + a2 = (((a2 * 5) - 448501) * 1); + a17 = (((((a17 % 71)- -182) / 5) / 5) + 165); + a7 = 12; + a24 = 13; + a5 = 7; + + return -1; + } else if((((((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12))) && (input == 3)) && a2 <= 189 ) && (a5==7)) && (a24==14))){ + a17 = ((((a17 % 299872)+ 256) - -48274) + 28236); + a7 = 12; + a24 = 13; + + return -1; + } else if((((( 255 < a17 && ((input == 4) && ((a7==14) || ((a7==12) || (a7==13))))) && (a5==5)) && (a24==13)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((a17 - 0) - 595306) - 4802); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((((input == 5) && (a24==13)) && (a5==4)) && (a7==12)) && a17 <= -108 ))){ + a2 = (((a2 / -5) / 5) - 315470); + a5 = 3; + + return -1; + } else if(((a24==15) && ((((input == 4) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==6)) && a2 <= 189 ))){ + a17 = ((((a17 - -17630) - 6795) % 109)- -1); + a7 = 12; + + return 26; + } else if((((((((a7==12) || (a7==13)) && (input == 2)) && (a24==15)) && 255 < a17 ) && a2 <= 189 ) && (a5==4))){ + a17 = (((a17 + 0) - 600231) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && ((a5==5) && ((a24==14) && ((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ))))){ + a17 = ((((a17 + 0) % 71)- -167) + 11); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==4) && (( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 6) && (a7==13)))) && ((-108 < a17) && (111 >= a17)) ))){ + + return 23; + } else if((( a17 <= -108 && ((((input == 6) && ((a7==12) || (a7==13))) && (a5==5)) && ((189 < a2) && (281 >= a2)) )) && (a24==14))){ + a17 = ((((a17 / 5) % 109)- -109) / 5); + a7 = 13; + a5 = 4; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 3)) && (a24==13)) && (a5==5)))){ + a2 = (((a2 / -5) * 5) - 263640); + a17 = ((((a17 * 9)/ 10) + -31880) - 20940); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a24==15) && ( a2 <= 189 && (((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 2)))) && (a5==5))){ + a17 = (((a17 + 26382) - 539571) - 38393); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a17 <= -108 && ((a5==6) && ((((a7==12) && (input == 1)) && (a24==13)) && a2 <= 189 )))){ + + a5 = 3; + + return -1; + } else if(((a5==3) && (((((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 6)) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))){ + a17 = ((((a17 - 0) % 109)- -2) - -1); + a7 = 12; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 2) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && (a5==4))){ + a2 = ((((a2 / -5) + 523985) * 1) + -866052); + a17 = (((((a17 % 109)+ 2) + -1) - -574310) + -574309); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a24==15) && (((a7==12) && ((a5==6) && (input == 1))) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 )){ + a2 = ((((a2 + 0) + 6154) % 45)- -236); + a17 = (((a17 / 5) / 5) + -109); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if((((( a17 <= -108 && (((a7==12) || (a7==13)) && (input == 3))) && ((189 < a2) && (281 >= a2)) ) && (a5==6)) && (a24==13))){ + a17 = ((((a17 * 9)/ 10) * 1) - -571423); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if((((a24==15) && ((a7==14) && (((input == 4) && 255 < a17 ) && (a5==5)))) && a2 <= 189 )){ + a2 = (((((a2 % 45)- -235) * 1) / 5) - -166); + a17 = ((((a17 * 9)/ 10) / 5) + -557397); + a24 = 14; + + return 23; + } else if((((((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 4)) && ((189 < a2) && (281 >= a2)) ) && (a24==14)) && (a5==4))){ + a2 = ((((a2 - -6843) - 234103) - -260659) + -346865); + a17 = (((((a17 % 71)+ 182) - -2) - -415451) - 415452); + a7 = 13; + a24 = 15; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ((a5==5) && ((a24==15) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && (input == 5)))))){ + a2 = ((((((a2 % 45)- -235) - -220353) * 2) % 45)- -192); + a17 = (((((a17 % 109)- -1) - 487372) / 5) + 97389); + a7 = 12; + a5 = 4; + + return 26; + } else if((((a7==13) && ((((input == 4) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )) && (a24==13))){ + + a24 = 14; + a5 = 4; + + return -1; + } else if((((a7==13) && ((((input == 3) && a2 <= 189 ) && (a24==13)) && 255 < a17 )) && (a5==7))){ + a17 = (((((a17 % 71)- -147) * 5) % 71)- -157); + a5 = 5; + + return 26; + } else if(((( 255 < a17 && ((a5==5) && ((input == 4) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a24==15)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -324872) - 111167) - 140231); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(((a5==7) && (((input == 3) && ((((a7==12) && a17 <= -108 ) && (a24==15)) || ((((a7==13) && 255 < a17 ) && (a24==14)) || (((a7==14) && 255 < a17 ) && (a24==14))))) && a2 <= 189 ))){ + a17 = ((((a17 % 299872)+ 300127) + 0) - -1); + a7 = 14; + a24 = 14; + + return 23; + } else if(( a2 <= 189 && (((((( 255 < a17 && (a7==14)) && (a24==13)) || ((a24==14) && ( a17 <= -108 && (a7==12)))) || ((a24==14) && ((a7==13) && a17 <= -108 ))) && (input == 1)) && (a5==5)))){ + a17 = ((((a17 % 299872)+ 300127) - 0) - 0); + a7 = 13; + a24 = 15; + a5 = 7; + + return 23; + } else if(((((a5==7) && ((((a7==13) || (a7==14)) && (input == 1)) && a2 <= 189 )) && (a24==15)) && 255 < a17 )){ + + a7 = 13; + a24 = 14; + + return -1; + } else if((((((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 3)) && (a24==13)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = (((a2 - 228436) / 5) * 5); + a17 = ((((a17 * 9)/ 10) - -37438) - 617865); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if((((((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 4)) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a5==5))){ + a2 = (((a2 * -5) + -362469) + 206807); + a17 = (((((a17 / 5) / 5) / 5) % 71)+ 183); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==14) && (((a5==5) && ( 255 < a17 && ((input == 4) && ((a7==13) || (a7==14))))) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 13; + + return 26; + } else if((( a2 <= 189 && ((((a24==14) && ( a17 <= -108 && (a7==13))) || (((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ((a7==12) && a17 <= -108 )))) && (input == 5))) && (a5==5))){ + a2 = ((((a2 / 5) % 45)- -235) + 1); + a17 = (((a17 / 5) - 256291) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return 26; + } else if(((a24==15) && (( a17 <= -108 && ((a5==6) && ((a7==13) && (input == 1)))) && a2 <= 189 ))){ + a2 = (((((a2 / 5) * 4) / 5) % 45)- -234); + a17 = ((((a17 - -120776) / 5) % 109)- -2); + a24 = 13; + a5 = 4; + + return 21; + } else if((((a5==4) && (( a2 <= 189 && ((input == 6) && ((a7==13) || (a7==14)))) && (a24==15))) && ((111 < a17) && (255 >= a17)) )){ + a17 = (((((a17 * -1)/ 10) * 10)/ 9) + -47); + a7 = 13; + a5 = 5; + + return 21; + } else if(((a5==6) && ((a24==13) && ((( ((189 < a2) && (281 >= a2)) && (input == 4)) && 255 < a17 ) && (a7==13))))){ + a2 = (((a2 / -5) * 5) + -60399); + a17 = ((((a17 / 5) % 109)+ -92) / 5); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if((((((a5==5) && ((input == 3) && ((a7==12) || (a7==13)))) && a2 <= 189 ) && (a24==14)) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((((a2 + 399174) % 45)+ 234) - 119189) + 119189); + a17 = (((a17 + -440715) / 5) + 88187); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a24==13) && ( a17 <= -108 && (((a5==6) && (((a7==12) || (a7==13)) && (input == 1))) && ((189 < a2) && (281 >= a2)) )))){ + a17 = ((((a17 + 0) + 354212) % 109)+ 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && (((a5==4) && (((a7==13) || (a7==14)) && (input == 1))) && a2 <= 189 )) && ((111 < a17) && (255 >= a17)) )){ + a17 = (((a17 * 5) - 379915) - -55808); + a7 = 14; + a5 = 5; + + return 23; + } else if(((a5==4) && ( a2 <= 189 && (((((a7==13) || (a7==14)) && (input == 5)) && a17 <= -108 ) && (a24==15))))){ + a17 = ((((((a17 % 71)- -187) * 5) * 5) % 71)- -127); + a7 = 12; + + return 23; + } else if((((a5==4) && (( 255 < a17 && ((input == 6) && ((a7==13) || (a7==14)))) && ((189 < a2) && (281 >= a2)) )) && (a24==13))){ + a17 = ((((a17 / 5) + -588303) % 71)+ 218); + a7 = 12; + + return -1; + } else if(( a2 <= 189 && ((input == 1) && (((a5==7) && ((a24==13) && ((a7==13) && a17 <= -108 ))) || (((((a7==14) && 255 < a17 ) && (a24==15)) && (a5==6)) || ((a5==7) && ((a24==13) && ((a7==12) && a17 <= -108 )))))))){ + a17 = ((((((a17 * 9)/ 10) * 1) * 1) % 299946)- 300053); + a7 = 12; + a24 = 13; + a5 = 7; + + return 21; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((((a24==14) && ((a7==14) && 255 < a17 )) || (( a17 <= -108 && (a7==12)) && (a24==15))) && (input == 3))))){ + a2 = (((a2 + -143123) + -98171) * 2); + a17 = (((((a17 % 71)- -184) * 5) % 71)+ 132); + a7 = 12; + a24 = 14; + a5 = 5; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && ((a5==4) && (((a7==12) && (input == 3)) && (a24==15)))))){ + a2 = (((a2 * -5) * 5) - 163900); + a17 = (((a17 - 263174) * 2) / 5); + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ( ((189 < a2) && (281 >= a2)) && (((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 4)) && (a24==14))))){ + a2 = (((a2 / -5) / 5) + -193140); + a17 = ((((a17 % 299946)- 300053) - 2) + 0); + a7 = 12; + a5 = 7; + + return -1; + } else if((((input == 6) && ((((a5==4) && ((a24==15) && ( 255 < a17 && (a7==14)))) || (((a24==13) && ((a7==12) && a17 <= -108 )) && (a5==5))) || (((a24==13) && ((a7==13) && a17 <= -108 )) && (a5==5)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / -5) * 5) * 10)/ 9); + a17 = (((((a17 % 299872)+ 300127) + 0) - 193833) - -193835); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 2))))) && (a5==5))){ + a2 = (((a2 / 5) * -5) - 445381); + a17 = (((a17 - 533326) - 24751) + -42172); + a7 = 12; + a24 = 13; + a5 = 4; + + return -1; + } else if(((( a2 <= 189 && ((((a7==12) || (a7==13)) && (input == 2)) && 255 < a17 )) && (a24==13)) && (a5==5))){ + a17 = ((((a17 * 9)/ 10) - 571338) / 5); + a7 = 12; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ((((input == 6) && (((a7==13) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && (a24==15)) && (a5==5)))){ + a17 = (((a17 * 5) + -240915) + -308966); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((input == 5) && (((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (a24==14))) && (a5==4))){ + a2 = (((a2 - 446402) + -60965) * 1); + a17 = ((((a17 % 299946)- 300053) * 1) * 1); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a24==14) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 3)) && ((189 < a2) && (281 >= a2)) )) && (a5==5))){ + a2 = (((a2 - 299989) - 282684) + -11091); + a17 = ((((a17 + -13195) * 10)/ 9) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((a24==15) && (input == 1)) && (a5==5)) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 ) && (a7==14))){ + a2 = (((((a2 % 45)+ 234) + 93283) + 429518) + -522800); + a17 = ((((a17 - 192) - 1) + 44565) - 44563); + a7 = 13; + a24 = 13; + + return 23; + } else if(( ((111 < a17) && (255 >= a17)) && ((((a5==5) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 4))) && ((189 < a2) && (281 >= a2)) ) && (a24==13)))){ + a2 = (((a2 * 5) - 529848) + -4150); + a17 = (((a17 / 5) / 5) - 39); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if(((( a17 <= -108 && ((a24==14) && ((input == 4) && ((a7==13) || (a7==14))))) && a2 <= 189 ) && (a5==6))){ + + a7 = 13; + a24 = 13; + a5 = 5; + + return 26; + } else if((( a2 <= 189 && ((a5==5) && ( ((111 < a17) && (255 >= a17)) && (((a7==12) || (a7==13)) && (input == 6))))) && (a24==14))){ + a2 = ((((a2 % 45)+ 234) * 5) / 5); + a7 = 14; + a5 = 3; + + return 21; + } else if(((a24==15) && ( a2 <= 189 && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14)))) && (input == 2)) && (a5==7))))){ + a17 = ((((a17 % 299946)+ -300053) + -2) + 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((input == 4) && ((((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==4)) || (((a24==13) && ((a7==12) && a17 <= -108 )) && (a5==5))) || ((((a7==13) && a17 <= -108 ) && (a24==13)) && (a5==5)))))){ + a2 = (((a2 - -563886) * -1) + 466041); + a17 = ((((a17 % 109)- -2) + 1) - 1); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && (((((a7==14) || ((a7==12) || (a7==13))) && (input == 2)) && ((189 < a2) && (281 >= a2)) ) && (a24==15))) && (a5==5))){ + a2 = (((a2 / -5) - 416146) / 5); + a17 = (((a17 - 462537) + -101249) + 137036); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && ((a5==5) && ((input == 4) && ((a7==13) || (a7==14)))))))){ + a17 = ((((a17 + 115929) / 5) + -404240) + 381192); + a7 = 14; + a24 = 13; + + return -1; + } else if((((a24==15) && ((a5==6) && ( 255 < a17 && (((a7==12) || (a7==13)) && (input == 4))))) && a2 <= 189 )){ + a17 = (((((a17 + -82645) / 5) / 5) % 109)+ 1); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if(((a24==13) && (( a17 <= -108 && (((input == 4) && ((a7==13) || (a7==14))) && ((189 < a2) && (281 >= a2)) )) && (a5==3)))){ + a2 = (((a2 * -5) + -23430) * 5); + a7 = 14; + a24 = 14; + a5 = 5; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((a7==12) && ((a24==15) && ((input == 1) && (a5==4))))))){ + a2 = ((((a2 - 86020) + -319001) - -534468) - 217545); + a17 = (((a17 - -503276) + 60279) / 5); + a7 = 13; + a5 = 7; + + return -1; + } else if(((((a5==5) && ( a2 <= 189 && ((input == 4) && ((a7==12) || (a7==13))))) && (a24==15)) && a17 <= -108 )){ + a2 = ((((a2 % 45)- -236) - 1) * 1); + a7 = 13; + a24 = 14; + a5 = 4; + + return 26; + } else if(((((a5==3) && ((input == 6) && (((a7==12) && 255 < a17 ) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))))) && (a24==13)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 + -429873) % 299872)+ 300127) - 39771) - -39773); + a7 = 12; + + return 23; + } else if((((((((a7==12) || (a7==13)) && (input == 1)) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && ((189 < a2) && (281 >= a2)) ) && (a5==3))){ + + a7 = 13; + + return 26; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && (((input == 6) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))) && (a5==4))))){ + a2 = (((a2 * 5) * 5) - 126327); + a17 = (((a17 + -140957) * 4) - -269430); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((( ((-108 < a17) && (111 >= a17)) && ((a24==15) && (input == 4))) && (a7==12)) && (a5==4)))){ + a2 = (((a2 - 514328) - 2041) - -399856); + a7 = 14; + a5 = 7; + + return -1; + } else if((((a5==3) && ((a24==13) && ((input == 3) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 ))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 307516) - 193341) * 1); + a17 = (((((a17 % 71)+ 181) - -293974) / 5) + -58626); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==7) && ( a2 <= 189 && ((((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ((a7==12) && a17 <= -108 ))) && (input == 1))))){ + a17 = (((((a17 % 71)+ 183) - 1) - -531843) - 531841); + a7 = 13; + a24 = 13; + a5 = 5; + + return -1; + } else if((((((a24==13) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 1))) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && 255 < a17 )){ + a2 = ((((a2 + -443081) * 10)/ 9) * 1); + a17 = ((((((a17 % 71)- -174) * 5) * 5) % 71)- -133); + a7 = 13; + a5 = 7; + + return -1; + } else if((((((input == 1) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 ))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = ((((a2 + -122718) * 10)/ 9) - -74204); + a17 = ((((a17 % 109)- -2) + -34) + 9); + a7 = 14; + a5 = 7; + + return -1; + } else if(((a5==4) && ((((a24==15) && ((input == 2) && (((a7==12) || (a7==13)) || (a7==14)))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ))){ + a2 = ((((a2 - -117222) - 186157) - -508770) - 673504); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==7) && ((((a7==13) || (a7==14)) && (input == 1)) && (a24==15))) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) )){ + a17 = ((((((a17 % 71)- -183) * 1) * 5) % 71)- -154); + a7 = 12; + a24 = 14; + + return -1; + } else if(((((((( 255 < a17 && (a7==13)) && (a24==13)) || (( 255 < a17 && (a7==14)) && (a24==13))) || (((a7==12) && a17 <= -108 ) && (a24==14))) && (input == 6)) && (a5==3)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 596397) + -1500) + -536); + a17 = (((((a17 * 9)/ 10) % 109)+ 2) + -1); + a7 = 13; + a24 = 14; + a5 = 5; + + return 26; + } else if(((a24==13) && (( ((-108 < a17) && (111 >= a17)) && ((a5==6) && ((input == 5) && ((a7==12) || (a7==13))))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 + -92113) - 295718) + -53625); + a17 = (((a17 / 5) / 5) - 76916); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ((input == 5) && ((a7==13) || (a7==14))))) && a2 <= 189 ) && (a5==6))){ + a2 = ((((a2 % 45)- -236) - -1) + -3); + a17 = ((((a17 + -62237) % 71)+ 199) + -15); + a7 = 13; + a5 = 3; + + return 26; + } else if(( a17 <= -108 && (((a24==13) && ( ((189 < a2) && (281 >= a2)) && (((a7==12) || (a7==13)) && (input == 6)))) && (a5==6)))){ + a17 = (((((a17 % 71)- -223) * 5) % 71)- -154); + a7 = 13; + a24 = 14; + a5 = 5; + + return -1; + } else if(((((((input == 2) && ((a7==12) || (a7==13))) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && (a24==14)) && a17 <= -108 )){ + a2 = ((((a2 - 55102) - -372533) - 62328) * -2); + a17 = (((((a17 * 9)/ 10) * 1) / 5) + 203115); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a17 <= -108 && (((a5==3) && ((a7==12) && (input == 6))) && ((189 < a2) && (281 >= a2)) )) && (a24==13))){ + a2 = (((a2 / -5) / 5) * 5); + a17 = ((((((a17 % 71)- -247) + 8) * 5) % 71)+ 139); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && (( 255 < a17 && ((((a7==12) || (a7==13)) && (input == 5)) && (a5==4))) && (a24==15)))){ + a17 = (((a17 + -600167) * 1) + -74); + a7 = 12; + a24 = 13; + a5 = 6; + + return 21; + } else if(( ((111 < a17) && (255 >= a17)) && ((a5==3) && ((a24==14) && (((input == 1) && ((189 < a2) && (281 >= a2)) ) && (a7==13)))))){ + a2 = (((a2 + 97520) - -476171) + -703390); + a17 = (((a17 - 192516) + 192347) + 14); + a7 = 14; + a5 = 4; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==15) && ( a17 <= -108 && ((input == 6) && (((a7==12) || (a7==13)) || (a7==14))))) && (a5==4)))){ + a2 = (((a2 / 5) - -274462) - 512632); + a17 = (((((a17 % 71)- -206) - -20) - 351411) + 351407); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a5==5) && ( a2 <= 189 && ( 255 < a17 && (((a7==12) || (a7==13)) && (input == 3))))) && (a24==13))){ + a17 = (((((a17 % 71)+ 123) - 11) + 84970) + -84956); + a7 = 14; + a24 = 15; + a5 = 7; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && (( ((111 < a17) && (255 >= a17)) && ((input == 1) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==5))))){ + a17 = ((((a17 * 5) % 109)- 71) - -9); + a7 = 13; + a24 = 14; + + return -1; + } else if((((((((a7==13) || (a7==14)) && (input == 6)) && (a5==5)) && 255 < a17 ) && (a24==14)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - -501110) / -5) + -432351); + a17 = (((((a17 % 71)+ 148) + -248919) + -89135) - -338038); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((( 255 < a17 && ((a7==13) && ((a24==13) && (input == 5)))) && (a5==7)) && a2 <= 189 )){ + + return -1; + } else if(((((a5==5) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 4)) && a2 <= 189 )) && (a24==14)) && 255 < a17 )){ + a17 = (((a17 + -600231) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((-108 < a17) && (111 >= a17)) && (((input == 6) && (a7==13)) && a2 <= 189 )) && (a24==14)) && (a5==7))){ + + return 21; + } else if(( 255 < a17 && ((a5==6) && ( a2 <= 189 && ((a24==15) && (((a7==12) || (a7==13)) && (input == 1))))))){ + a17 = ((((a17 % 109)- 52) - 44) + -3); + a7 = 13; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((((((a7==14) || ((a7==12) || (a7==13))) && (input == 1)) && (a5==6)) && (a24==14)) && a2 <= 189 ))){ + a17 = ((((a17 / 5) + 148) * 9)/ 10); + a7 = 12; + a24 = 13; + a5 = 7; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==6) && ((a24==13) && ((input == 1) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))))))){ + a17 = ((((((a17 + 0) % 109)- 20) * 5) % 109)+ 1); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((((a7==13) || (a7==14)) && (input == 6)) && (a24==13)))) && (a5==4))){ + a17 = (((((a17 - 297061) - -413246) * 5) % 71)- -126); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a24==15) && ((a5==4) && ((input == 2) && (( ((111 < a17) && (255 >= a17)) && (a7==13)) || (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - -381050) + -586556) - 318711); + a17 = (((a17 * 5) * 5) - 315241); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ((((((a7==13) && a17 <= -108 ) && (a24==14)) || ((( 255 < a17 && (a7==14)) && (a24==13)) || (((a7==12) && a17 <= -108 ) && (a24==14)))) && (input == 2)) && a2 <= 189 ))){ + a17 = ((((a17 % 299946)+ -300053) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((( ((111 < a17) && (255 >= a17)) && ((input == 3) && (a7==14))) && (a24==14)) && a2 <= 189 ) && (a5==5))){ + a2 = ((((a2 % 45)- -235) + -1) - 0); + a17 = (((((a17 / 5) * 10)/ 9) * 10)/ 9); + a24 = 15; + a5 = 3; + + return 23; + } else if(( a2 <= 189 && ((a24==14) && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 ))) && (input == 1)) && (a5==7))))){ + a17 = ((((a17 / 5) * 4) % 109)+ 2); + a7 = 13; + a24 = 15; + a5 = 4; + + return 21; + } else if((( a17 <= -108 && (((((a7==12) || (a7==13)) && (input == 3)) && a2 <= 189 ) && (a5==5))) && (a24==15))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((a24==15) && (input == 3)) && (a5==5)) && (a7==14)) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 )){ + a2 = ((((a2 % 45)- -236) * 1) - 1); + a17 = ((((a17 - 477741) * 10)/ 9) + -8957); + a24 = 13; + + return 23; + } else if(((((((input == 6) && ((a7==13) || (a7==14))) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==6))){ + + a7 = 12; + a24 = 13; + a5 = 7; + + return 21; + } else if(((( ((189 < a2) && (281 >= a2)) && ((( 255 < a17 && (a7==12)) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))) && (input == 6))) && (a5==6)) && (a24==13))){ + a2 = (((a2 / 5) - 67976) + -37056); + a17 = ((((a17 % 109)+ -50) + 36) / 5); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(( 255 < a17 && ((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((a5==4) && ((input == 3) && ((a7==13) || (a7==14)))))))){ + a2 = (((a2 + -368535) + -129446) * 1); + a17 = (((((a17 * 9)/ 10) * 1) / 5) - 289303); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a24==14) && ((a5==4) && ( ((189 < a2) && (281 >= a2)) && (((a7==12) || (a7==13)) && (input == 6))))) && a17 <= -108 )){ + a2 = (((a2 / 5) + -164157) * 3); + a7 = 13; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && ((a24==15) && ((a5==7) && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 3)))))){ + a17 = (((((a17 % 109)- -2) + -1) + 462727) + -462726); + a7 = 14; + a24 = 14; + + return -1; + } else if(((((a5==3) && ((input == 2) && ((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && ((189 < a2) && (281 >= a2)) ) && (a24==14))){ + a17 = ((((a17 % 109)- -2) + -1) - -2); + a7 = 14; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((((a7==14) && 255 < a17 ) && (a24==14)) || ((a24==15) && ((a7==12) && a17 <= -108 ))) && (input == 1))))){ + a17 = (((((a17 / 5) % 71)- -184) / 5) + 143); + a7 = 13; + a24 = 14; + + return -1; + } else if(((( a2 <= 189 && (( ((111 < a17) && (255 >= a17)) && (input == 5)) && (a24==15))) && (a5==5)) && (a7==14))){ + a2 = ((((((a2 - 0) * 9)/ 10) - 15643) % 45)+ 276); + a17 = (((a17 / 5) / 5) - -310668); + a7 = 13; + a5 = 4; + + return 23; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==15) && (((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==5)))) && a17 <= -108 )){ + a2 = ((((a2 + 140796) / 5) / 5) * -5); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 5) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))))) && (a24==13)) && (a5==4)))){ + a17 = (((a17 / 5) / 5) + -194917); + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((a5==4) && ( a17 <= -108 && ((input == 2) && ((a7==13) || (a7==14)))))) && (a24==15))){ + a17 = ((((a17 % 109)- -85) + -84) - 0); + a7 = 12; + + return 21; + } else if(((a5==6) && (( 255 < a17 && ((((a7==12) || (a7==13)) && (input == 6)) && a2 <= 189 )) && (a24==15)))){ + a2 = (((((a2 % 45)- -235) / 5) / 5) + 244); + a7 = 13; + a5 = 3; + + return 26; + } else if(((a5==3) && (((a24==13) && ((( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 5))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 - -580869) + -652808) * 5); + a17 = ((((a17 % 109)- -3) + -41) + 9); + a7 = 12; + a24 = 14; + a5 = 5; + + return -1; + } else if(((((a24==15) && ((((a7==12) || (a7==13)) && (input == 1)) && a17 <= -108 )) && (a5==5)) && a2 <= 189 )){ + a2 = (((((a2 * 9)/ 10) + -16953) % 45)+ 272); + a17 = ((((((a17 % 71)+ 236) * 5) + 502892) % 71)+ 132); + a7 = 13; + a24 = 13; + a5 = 4; + + return 23; + } else if(((((a24==13) && ((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && (a5==3)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) + 409580) + -457191); + a17 = (((a17 - -196150) + 128540) - -116144); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==15) && ((a5==4) && ((( ((-108 < a17) && (111 >= a17)) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a7==13))))){ + + return -1; + } else if((((((((a7==12) || (a7==13)) && (input == 3)) && (a5==5)) && ((-108 < a17) && (111 >= a17)) ) && a2 <= 189 ) && (a24==15))){ + a2 = ((((a2 % 45)+ 234) - -448340) + -448339); + a17 = (((a17 * 5) / 5) - -211113); + a7 = 13; + a24 = 14; + a5 = 4; + + return 26; + } else if((((a24==13) && (((((a7==12) && 255 < a17 ) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )) && (a5==6))){ + a2 = (((a2 / 5) / 5) * -5); + a17 = (((((a17 % 299872)+ 256) + 239410) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==5) && ((a24==14) && ( a2 <= 189 && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 2)) && 255 < a17 ))))){ + a2 = (((((a2 % 45)+ 236) * 5) % 45)- -195); + a17 = (((a17 - 600134) * 1) - 48); + a7 = 13; + a24 = 13; + a5 = 4; + + return 23; + } else if(( a2 <= 189 && ((a24==15) && (((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 1)) && (a5==6))))){ + a17 = (((((a17 * 9)/ 10) * 1) / 5) - 216856); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==6) && (((input == 5) && (( 255 < a17 && (a7==12)) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && a2 <= 189 )))){ + a17 = ((((a17 % 109)- -1) - 83) - -75); + a7 = 12; + a24 = 15; + a5 = 4; + + return 26; + } else if((((a5==7) && (((input == 1) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))))) && a2 <= 189 )) && (a24==13))){ + a17 = (((((a17 - 274936) + 211306) * 1) % 71)+ 182); + a7 = 13; + a5 = 5; + + return -1; + } else if(((a5==6) && ((a24==13) && (((((a7==12) || (a7==13)) && (input == 6)) && ((-108 < a17) && (111 >= a17)) ) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + -87407) - -312987) - 526695); + a17 = (((a17 + 556571) * 1) * 1); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if((( a2 <= 189 && ((a5==6) && ((((a7==13) || (a7==14)) && (input == 2)) && (a24==14)))) && a17 <= -108 )){ + + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if(((a24==15) && (((a7==12) && (((input == 6) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) )) && (a5==4)))){ + a17 = (((((a17 % 71)+ 182) + 0) + -506914) - -506916); + a24 = 13; + a5 = 5; + + return 21; + } else if(((( a17 <= -108 && (((a5==5) && (input == 5)) && a2 <= 189 )) && (a7==14)) && (a24==14))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (((( a17 <= -108 && (a7==12)) && (a24==14)) || ((((a7==13) && 255 < a17 ) && (a24==13)) || ((a24==13) && ((a7==14) && 255 < a17 )))) && (input == 5))) && (a5==6))){ + a2 = (((((a2 % 45)+ 234) / 5) / 5) + 253); + a17 = ((((a17 % 299872)+ 300127) + 0) + 0); + a7 = 13; + a24 = 14; + a5 = 3; + + return 26; + } + return calculate_output4(input); + } + + int calculate_output4(int input) { + + + if((( ((-108 < a17) && (111 >= a17)) && ((((input == 6) && ((a7==13) || (a7==14))) && (a24==15)) && a2 <= 189 )) && (a5==7))){ + + a7 = 13; + + return -1; + } else if(((((((input == 6) && a2 <= 189 ) && (a24==13)) && (a7==12)) && (a5==5)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 - -162890) - -143056) * 10)/ -9); + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==15) && (((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && (a5==5)))) && a17 <= -108 )){ + a17 = (((((a17 + 326777) + 251227) - 58119) % 109)+ 1); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==14) && ((a7==13) && ((( ((189 < a2) && (281 >= a2)) && (input == 5)) && ((-108 < a17) && (111 >= a17)) ) && (a5==4))))){ + + return 23; + } else if(( a2 <= 189 && ((((((a7==13) || (a7==14)) && (input == 3)) && (a24==15)) && (a5==6)) && ((111 < a17) && (255 >= a17)) ))){ + + a7 = 14; + + return 21; + } else if(((a7==13) && ( a17 <= -108 && ( a2 <= 189 && (((input == 5) && (a24==15)) && (a5==6)))))){ + + return 23; + } else if(((a24==14) && (((a5==5) && (( a2 <= 189 && (input == 6)) && a17 <= -108 )) && (a7==14)))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && ((a5==5) && ( a17 <= -108 && ((input == 4) && (((a7==12) || (a7==13)) || (a7==14)))))))){ + + a7 = 14; + a24 = 14; + + return -1; + } else if(((((((((a7==12) || (a7==13)) || (a7==14)) && (input == 1)) && (a5==7)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15))){ + + a7 = 12; + a24 = 14; + + return -1; + } else if(( a2 <= 189 && ((((((a24==15) && ( 255 < a17 && (a7==14))) && (a5==4)) || ((a5==5) && (( a17 <= -108 && (a7==12)) && (a24==13)))) || ((a5==5) && (((a7==13) && a17 <= -108 ) && (a24==13)))) && (input == 5)))){ + a17 = ((((a17 % 299946)- 300053) + -1) + 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && (((a5==6) && (((input == 6) && (a24==13)) && ((189 < a2) && (281 >= a2)) )) && (a7==13)))){ + a2 = (((a2 + -559930) - -930633) - 537732); + a17 = (((a17 - 600136) * 1) - 66); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && (((a24==15) && ((input == 2) && ((a7==13) || (a7==14)))) && (a5==5))))){ + a2 = ((((a2 * -5) * 10)/ 9) * 5); + a17 = (((a17 - 416379) / 5) * 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && ((a24==15) && ((input == 3) && (((a7==12) || (a7==13)) || (a7==14))))) && a17 <= -108 ) && (a5==4))){ + a2 = (((a2 / 5) + -106387) + -147146); + a17 = ((((a17 % 299872)- -300127) - -270865) + 27768); + a7 = 12; + a5 = 7; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && ((a5==5) && ((a24==15) && (input == 5)))) && (a7==12)) && ((-108 < a17) && (111 >= a17)) )){ + a17 = (((a17 - -533048) + 40396) * 1); + a7 = 13; + a24 = 13; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((input == 6) && (a24==15)) && (a5==4)) && (a7==12))) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 * -5) * 5) * 5); + a17 = (((a17 - 418037) * 1) - -234835); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((input == 4) && (a24==13)) && (a5==6)) && a17 <= -108 ) && (a7==14)) && ((189 < a2) && (281 >= a2)) )){ + + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==5) && ( a2 <= 189 && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || (((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (input == 2)))))){ + a17 = ((((a17 - -453354) % 299946)+ -300053) * 1); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 ))) && (input == 5)) && (a5==7))))){ + a17 = ((((a17 - 0) % 299872)+ 300127) * 1); + a7 = 13; + a24 = 13; + a5 = 5; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((a7==13) && (((input == 6) && (a5==3)) && ((111 < a17) && (255 >= a17)) ))))){ + + return 26; + } else if(( 255 < a17 && ((a24==13) && (((a7==13) && ((input == 6) && a2 <= 189 )) && (a5==7))))){ + a17 = (((((a17 % 109)+ 3) - 249216) * 2) - -498320); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a24==14) && ( ((111 < a17) && (255 >= a17)) && (((a5==6) && ((input == 5) && ((a7==14) || ((a7==12) || (a7==13))))) && a2 <= 189 )))){ + a2 = (((((a2 % 45)+ 234) * 5) % 45)- -233); + a17 = ((((((a17 * 10)/ -9) + 137075) * 4) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 4; + + return 26; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==4) && ((a24==14) && ((input == 5) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))))))){ + a2 = (((a2 / -5) + -474783) / 5); + a17 = (((a17 - 32453) * 5) / 5); + a7 = 14; + a24 = 15; + a5 = 5; + + return 23; + } else if(( 255 < a17 && ((a24==15) && ((a5==5) && ( ((189 < a2) && (281 >= a2)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 2))))))){ + a2 = (((a2 + -107856) - 174986) / 5); + a17 = (((a17 - 83582) + -516569) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==5) && (((a24==13) && (input == 2)) && a2 <= 189 )) && (a7==13)) && ((111 < a17) && (255 >= a17)) )){ + a17 = (((a17 - 3949) * 5) * 5); + a7 = 12; + a5 = 3; + + return -1; + } + return -2; + } + +int main2() +{ + // default output + int output = -1; + + // main i/o-loop + while(1) + { + // read input + int input; + input = __VERIFIER_nondet_int(); + if ((input != 1) && (input != 2) && (input != 3) && (input != 4) && (input != 5) && (input != 6)) return -2; + + // operate eca engine + output = calculate_output(input); + } +}int main() +{ + if(__VERIFIER_nondet_int()) + main1(); + else + main2(); +} diff --git a/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c new file mode 100644 index 0000000000..f0261d2008 --- /dev/null +++ b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c @@ -0,0 +1,260 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --64 --write-ktests %s 2>&1 | FileCheck %s +// CHECK: KLEE: WARNING: 100.00% Reachable Reachable + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2020 Aman Goel +// SPDX-FileCopyrightText: 2022 The SV-Benchmarks Community +// +// SPDX-License-Identifier: GPL-3.0-or-later + +// This C program is converted from Btor2 by Btor2C version bfcfb8b +// with arguments: { architecture=64, lazy_modulo=true, use_memmove=false, unroll_inner_loops=false, shortest_type=true, diff_type=true, decimal_constant=true, zero_init=false, sra_extend_sign=true } +// Comments from the original Btor2 file: +// ; source: https://github.com/aman-goel/avr/tree/92362931700b66684418a991d018c9fbdbebc06f/tests +// ; BTOR description generated by Yosys 0.9+431 (git sha1 4a3b5437, clang 4.0.1-6 -fPIC -Os) for module main. +extern void abort(void); +void reach_error() {} +extern unsigned char __VERIFIER_nondet_uchar(); +extern unsigned short __VERIFIER_nondet_ushort(); +extern unsigned int __VERIFIER_nondet_uint(); +extern unsigned long __VERIFIER_nondet_ulong(); +extern unsigned __int128 __VERIFIER_nondet_uint128(); +void __VERIFIER_assert(int cond) { if (!(cond)) { ERROR: { reach_error(); abort(); } } } +void assume_abort_if_not(int cond) { if (!cond) { abort(); } } +int main() { + // Defining sorts ... + typedef unsigned char SORT_1; // BV with 1 bits + const SORT_1 mask_SORT_1 = (SORT_1)-1 >> (sizeof(SORT_1) * 8 - 1); + const SORT_1 msb_SORT_1 = (SORT_1)1 << (1 - 1); + typedef unsigned long SORT_5; // BV with 64 bits + const SORT_5 mask_SORT_5 = (SORT_5)-1 >> (sizeof(SORT_5) * 8 - 64); + const SORT_5 msb_SORT_5 = (SORT_5)1 << (64 - 1); + typedef unsigned short SORT_8; // BV with 10 bits + const SORT_8 mask_SORT_8 = (SORT_8)-1 >> (sizeof(SORT_8) * 8 - 10); + const SORT_8 msb_SORT_8 = (SORT_8)1 << (10 - 1); + typedef unsigned __int128 SORT_14; // BV with 128 bits + const SORT_14 mask_SORT_14 = (SORT_14)-1 >> (sizeof(SORT_14) * 8 - 128); + const SORT_14 msb_SORT_14 = (SORT_14)1 << (128 - 1); + typedef unsigned int SORT_57; // BV with 32 bits + const SORT_57 mask_SORT_57 = (SORT_57)-1 >> (sizeof(SORT_57) * 8 - 32); + const SORT_57 msb_SORT_57 = (SORT_57)1 << (32 - 1); + // Initializing constants ... + const SORT_1 var_10 = 0; + const SORT_14 var_15 = 0; + const SORT_1 var_24 = 1; + const SORT_5 var_28 = 0; + const SORT_8 var_35 = 0; + const SORT_57 var_58 = 1; + const SORT_57 var_62 = 1000; + const SORT_5 var_64 = 9223372036854775807; + const SORT_5 var_67 = 12245771; + // Collecting input declarations ... + SORT_1 input_2; + SORT_1 input_3; + SORT_1 input_4; + SORT_5 input_6; + SORT_5 input_7; + SORT_8 input_9; + // Collecting state declarations ... + SORT_1 state_11 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_14 state_16 = __VERIFIER_nondet_uint128() & mask_SORT_14; + SORT_14 state_18 = __VERIFIER_nondet_uint128() & mask_SORT_14; + SORT_5 state_29 = __VERIFIER_nondet_ulong() & mask_SORT_5; + SORT_5 state_31 = __VERIFIER_nondet_ulong() & mask_SORT_5; + SORT_8 state_36 = __VERIFIER_nondet_ushort() & mask_SORT_8; + SORT_1 state_38 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_40 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_5 state_42 = __VERIFIER_nondet_ulong() & mask_SORT_5; + SORT_5 state_44 = __VERIFIER_nondet_ulong() & mask_SORT_5; + // Initializing states ... + SORT_1 init_12_arg_1 = var_10; + state_11 = init_12_arg_1; + SORT_14 init_17_arg_1 = var_15; + state_16 = init_17_arg_1; + SORT_14 init_19_arg_1 = var_15; + state_18 = init_19_arg_1; + SORT_5 init_30_arg_1 = var_28; + state_29 = init_30_arg_1; + SORT_5 init_32_arg_1 = var_28; + state_31 = init_32_arg_1; + SORT_8 init_37_arg_1 = var_35; + state_36 = init_37_arg_1; + SORT_1 init_39_arg_1 = var_24; + state_38 = init_39_arg_1; + SORT_1 init_41_arg_1 = var_24; + state_40 = init_41_arg_1; + SORT_5 init_43_arg_1 = var_28; + state_42 = init_43_arg_1; + SORT_5 init_45_arg_1 = var_28; + state_44 = init_45_arg_1; + for (;;) { + // Getting external input values ... + input_2 = __VERIFIER_nondet_uchar(); + input_3 = __VERIFIER_nondet_uchar(); + input_3 = input_3 & mask_SORT_1; + input_4 = __VERIFIER_nondet_uchar(); + input_4 = input_4 & mask_SORT_1; + input_6 = __VERIFIER_nondet_ulong(); + input_6 = input_6 & mask_SORT_5; + input_7 = __VERIFIER_nondet_ulong(); + input_7 = input_7 & mask_SORT_5; + input_9 = __VERIFIER_nondet_ushort(); + // Assuming invariants ... + // Asserting properties ... + SORT_1 var_13_arg_0 = state_11; + SORT_1 var_13 = ~var_13_arg_0; + SORT_14 var_20_arg_0 = state_16; + SORT_14 var_20_arg_1 = state_18; + SORT_1 var_20 = var_20_arg_0 == var_20_arg_1; + SORT_1 var_21_arg_0 = var_13; + SORT_1 var_21_arg_1 = var_20; + SORT_1 var_21 = var_21_arg_0 | var_21_arg_1; + SORT_1 var_25_arg_0 = var_21; + SORT_1 var_25 = ~var_25_arg_0; + SORT_1 var_26_arg_0 = var_24; + SORT_1 var_26_arg_1 = var_25; + SORT_1 var_26 = var_26_arg_0 & var_26_arg_1; + var_26 = var_26 & mask_SORT_1; + SORT_1 bad_27_arg_0 = var_26; + __VERIFIER_assert(!(bad_27_arg_0)); + // Computing next states ... + SORT_1 next_51_arg_1 = var_24; + SORT_1 var_33_arg_0 = state_11; + SORT_1 var_33 = ~var_33_arg_0; + var_33 = var_33 & mask_SORT_1; + SORT_5 var_52_arg_0 = state_29; + var_52_arg_0 = var_52_arg_0 & mask_SORT_5; + SORT_14 var_52 = var_52_arg_0; + SORT_5 var_53_arg_0 = state_31; + var_53_arg_0 = var_53_arg_0 & mask_SORT_5; + SORT_14 var_53 = var_53_arg_0; + SORT_14 var_54_arg_0 = var_52; + SORT_14 var_54_arg_1 = var_53; + SORT_14 var_54 = var_54_arg_0 * var_54_arg_1; + SORT_1 var_55_arg_0 = var_33; + SORT_14 var_55_arg_1 = var_15; + SORT_14 var_55_arg_2 = var_54; + SORT_14 var_55 = var_55_arg_0 ? var_55_arg_1 : var_55_arg_2; + var_55 = var_55 & mask_SORT_14; + SORT_14 next_56_arg_1 = var_55; + SORT_1 var_71_arg_0 = state_38; + SORT_1 var_71_arg_1 = state_40; + SORT_1 var_71 = var_71_arg_0 | var_71_arg_1; + var_71 = var_71 & mask_SORT_1; + SORT_8 var_61_arg_0 = state_36; + var_61_arg_0 = var_61_arg_0 & mask_SORT_8; + SORT_57 var_61 = var_61_arg_0; + SORT_57 var_63_arg_0 = var_61; + SORT_57 var_63_arg_1 = var_62; + SORT_1 var_63 = var_63_arg_0 > var_63_arg_1; + SORT_5 var_65_arg_0 = input_6; + SORT_5 var_65_arg_1 = var_64; + SORT_1 var_65 = var_65_arg_0 == var_65_arg_1; + SORT_1 var_66_arg_0 = var_63; + SORT_1 var_66_arg_1 = var_65; + SORT_1 var_66 = var_66_arg_0 & var_66_arg_1; + SORT_5 var_68_arg_0 = input_7; + SORT_5 var_68_arg_1 = var_67; + SORT_1 var_68 = var_68_arg_0 == var_68_arg_1; + SORT_1 var_69_arg_0 = var_66; + SORT_1 var_69_arg_1 = var_68; + SORT_1 var_69 = var_69_arg_0 & var_69_arg_1; + var_69 = var_69 & mask_SORT_1; + SORT_5 var_46_arg_0 = state_42; + var_46_arg_0 = var_46_arg_0 & mask_SORT_5; + SORT_14 var_46 = var_46_arg_0; + SORT_5 var_47_arg_0 = state_44; + var_47_arg_0 = var_47_arg_0 & mask_SORT_5; + SORT_14 var_47 = var_47_arg_0; + SORT_14 var_48_arg_0 = var_46; + SORT_14 var_48_arg_1 = var_47; + SORT_14 var_48 = var_48_arg_0 * var_48_arg_1; + SORT_57 var_59_arg_0 = var_58; + var_59_arg_0 = var_59_arg_0 & mask_SORT_57; + SORT_14 var_59 = var_59_arg_0; + SORT_14 var_60_arg_0 = var_48; + SORT_14 var_60_arg_1 = var_59; + SORT_14 var_60 = var_60_arg_0 + var_60_arg_1; + SORT_1 var_70_arg_0 = var_69; + SORT_14 var_70_arg_1 = var_60; + SORT_14 var_70_arg_2 = var_48; + SORT_14 var_70 = var_70_arg_0 ? var_70_arg_1 : var_70_arg_2; + SORT_1 var_72_arg_0 = var_71; + SORT_14 var_72_arg_1 = var_70; + SORT_14 var_72_arg_2 = state_18; + SORT_14 var_72 = var_72_arg_0 ? var_72_arg_1 : var_72_arg_2; + SORT_1 var_73_arg_0 = var_33; + SORT_14 var_73_arg_1 = var_15; + SORT_14 var_73_arg_2 = var_72; + SORT_14 var_73 = var_73_arg_0 ? var_73_arg_1 : var_73_arg_2; + var_73 = var_73 & mask_SORT_14; + SORT_14 next_74_arg_1 = var_73; + SORT_1 var_75_arg_0 = input_3; + SORT_5 var_75_arg_1 = input_6; + SORT_5 var_75_arg_2 = state_29; + SORT_5 var_75 = var_75_arg_0 ? var_75_arg_1 : var_75_arg_2; + SORT_1 var_76_arg_0 = var_33; + SORT_5 var_76_arg_1 = var_28; + SORT_5 var_76_arg_2 = var_75; + SORT_5 var_76 = var_76_arg_0 ? var_76_arg_1 : var_76_arg_2; + SORT_5 next_77_arg_1 = var_76; + SORT_1 var_78_arg_0 = input_4; + SORT_5 var_78_arg_1 = input_7; + SORT_5 var_78_arg_2 = state_31; + SORT_5 var_78 = var_78_arg_0 ? var_78_arg_1 : var_78_arg_2; + SORT_1 var_79_arg_0 = var_33; + SORT_5 var_79_arg_1 = var_28; + SORT_5 var_79_arg_2 = var_78; + SORT_5 var_79 = var_79_arg_0 ? var_79_arg_1 : var_79_arg_2; + SORT_5 next_80_arg_1 = var_79; + SORT_1 var_81_arg_0 = var_33; + SORT_8 var_81_arg_1 = input_9; + SORT_8 var_81_arg_2 = state_36; + SORT_8 var_81 = var_81_arg_0 ? var_81_arg_1 : var_81_arg_2; + SORT_8 next_82_arg_1 = var_81; + SORT_1 var_83_arg_0 = var_33; + SORT_1 var_83_arg_1 = var_24; + SORT_1 var_83_arg_2 = input_3; + SORT_1 var_83 = var_83_arg_0 ? var_83_arg_1 : var_83_arg_2; + SORT_1 next_84_arg_1 = var_83; + SORT_1 var_85_arg_0 = var_33; + SORT_1 var_85_arg_1 = var_24; + SORT_1 var_85_arg_2 = input_4; + SORT_1 var_85 = var_85_arg_0 ? var_85_arg_1 : var_85_arg_2; + SORT_1 next_86_arg_1 = var_85; + SORT_1 var_87_arg_0 = input_3; + SORT_5 var_87_arg_1 = input_6; + SORT_5 var_87_arg_2 = state_42; + SORT_5 var_87 = var_87_arg_0 ? var_87_arg_1 : var_87_arg_2; + SORT_1 var_88_arg_0 = var_33; + SORT_5 var_88_arg_1 = var_28; + SORT_5 var_88_arg_2 = var_87; + SORT_5 var_88 = var_88_arg_0 ? var_88_arg_1 : var_88_arg_2; + SORT_5 next_89_arg_1 = var_88; + SORT_1 var_90_arg_0 = input_4; + SORT_5 var_90_arg_1 = input_7; + SORT_5 var_90_arg_2 = state_44; + SORT_5 var_90 = var_90_arg_0 ? var_90_arg_1 : var_90_arg_2; + SORT_1 var_91_arg_0 = var_33; + SORT_5 var_91_arg_1 = var_28; + SORT_5 var_91_arg_2 = var_90; + SORT_5 var_91 = var_91_arg_0 ? var_91_arg_1 : var_91_arg_2; + SORT_5 next_92_arg_1 = var_91; + // Assigning next states ... + state_11 = next_51_arg_1; + state_16 = next_56_arg_1; + state_18 = next_74_arg_1; + state_29 = next_77_arg_1; + state_31 = next_80_arg_1; + state_36 = next_82_arg_1; + state_38 = next_84_arg_1; + state_40 = next_86_arg_1; + state_42 = next_89_arg_1; + state_44 = next_92_arg_1; + } + return 0; +} diff --git a/test/Industry/CoverageErrorCall/coverage-error-call.prp b/test/Industry/CoverageErrorCall/coverage-error-call.prp new file mode 100644 index 0000000000..496ed998fa --- /dev/null +++ b/test/Industry/CoverageErrorCall/coverage-error-call.prp @@ -0,0 +1,2 @@ +COVER( init(main()), FQL(COVER EDGES(@CALL(reach_error))) ) + diff --git a/test/Industry/FN_SecB_ForwardNull_filed.c b/test/Industry/FN_SecB_ForwardNull_filed.c index fad10a2644..6faaf136b9 100644 --- a/test/Industry/FN_SecB_ForwardNull_filed.c +++ b/test/Industry/FN_SecB_ForwardNull_filed.c @@ -1,8 +1,3 @@ -// REQUIRES: z3 -// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc -// RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s /* * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. * @description 空指针解引用 验收失败 @@ -44,8 +39,13 @@ void WB_BadCase_Field(UINT32 inputNum1, UINT32 inputNum2) void WB_BadCase_field2(DataInfo *data) { data->dataBuff = NULL; - *data->dataBuff = 'c'; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Negative at: {{.*}}test/Industry/FN_SecB_ForwardNull_filed.c:47 19 + *data->dataBuff = 'c'; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Negative at: {{.*}}test/Industry/FN_SecB_ForwardNull_filed.c:42 19 char *ptr = NULL; *ptr = 'c'; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 } + +// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s \ No newline at end of file diff --git a/test/Industry/FN_SecB_ForwardNull_filed.c.json b/test/Industry/FN_SecB_ForwardNull_filed.c.json index b54baa91f9..ec0f7d3101 100644 --- a/test/Industry/FN_SecB_ForwardNull_filed.c.json +++ b/test/Industry/FN_SecB_ForwardNull_filed.c.json @@ -20,7 +20,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/./FN_SecB_ForwardNull_filed.c" }, "region": { - "startLine": 49, + "startLine": 44, "startColumn": null } } @@ -33,7 +33,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/./FN_SecB_ForwardNull_filed.c" }, "region": { - "startLine": 50, + "startLine": 45, "startColumn": null } } @@ -52,7 +52,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/./FN_SecB_ForwardNull_filed.c" }, "region": { - "startLine": 50, + "startLine": 45, "startColumn": null } } diff --git a/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c b/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c index 4b77bd1b66..9a04367627 100644 --- a/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c +++ b/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c @@ -53,7 +53,6 @@ void call_func(int num) ResourceLeak_bad01(num); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --write-kqueries --max-cycles-before-stuck=0 --use-guided-search=error --check-out-of-memory --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_BadCase_WhiteBox01.c b/test/Industry/NullReturn_BadCase_WhiteBox01.c index 8ee8261adb..666c470216 100644 --- a/test/Industry/NullReturn_BadCase_WhiteBox01.c +++ b/test/Industry/NullReturn_BadCase_WhiteBox01.c @@ -1,8 +1,3 @@ -// REQUIRES: z3 -// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc -// RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --smart-resolve-entry-function --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s /* * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. * @@ -68,3 +63,8 @@ void NullReturn_BadCase_WhiteBox01(UINT8 index, SchedHarqStru *harqInfo) SendMsg(index, usrId, resultInfo); // (3) } } + +// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --smart-resolve-entry-function --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s \ No newline at end of file diff --git a/test/Industry/NullReturn_BadCase_WhiteBox01.c.json b/test/Industry/NullReturn_BadCase_WhiteBox01.c.json index 3372239023..42a4b510f1 100644 --- a/test/Industry/NullReturn_BadCase_WhiteBox01.c.json +++ b/test/Industry/NullReturn_BadCase_WhiteBox01.c.json @@ -20,7 +20,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 45, + "startLine": 40, "startColumn": 9 } } @@ -33,7 +33,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 66, + "startLine": 61, "startColumn": 34 } } @@ -46,7 +46,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 68, + "startLine": 63, "startColumn": 9 } } @@ -59,7 +59,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 56, + "startLine": 51, "startColumn": 30 } } @@ -78,7 +78,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 56, + "startLine": 51, "startColumn": 30 } } @@ -98,7 +98,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 45, + "startLine": 40, "startColumn": 9 } } @@ -111,7 +111,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 66, + "startLine": 61, "startColumn": 34 } } @@ -124,7 +124,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 68, + "startLine": 63, "startColumn": 9 } } @@ -137,7 +137,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 54, + "startLine": 49, "startColumn": 30 } } @@ -156,7 +156,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 54, + "startLine": 49, "startColumn": 30 } } diff --git a/test/Industry/NullReturn_Scene_BadCase01.c b/test/Industry/NullReturn_Scene_BadCase01.c index cfab0db844..45b8240318 100644 --- a/test/Industry/NullReturn_Scene_BadCase01.c +++ b/test/Industry/NullReturn_Scene_BadCase01.c @@ -39,7 +39,6 @@ void TestBad1() free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --external-calls=all --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase02.c b/test/Industry/NullReturn_Scene_BadCase02.c index 7042eb01b1..d25af79653 100644 --- a/test/Industry/NullReturn_Scene_BadCase02.c +++ b/test/Industry/NullReturn_Scene_BadCase02.c @@ -38,7 +38,6 @@ void TestBad2() printf("The second is %d", info->tm_sec); // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --mock-external-calls --check-out-of-memory --skip-not-symbolic-objects --skip-not-lazy-initialized --extern-calls-can-return-null --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase03.c b/test/Industry/NullReturn_Scene_BadCase03.c index f24ef754b6..c4190f9bb2 100644 --- a/test/Industry/NullReturn_Scene_BadCase03.c +++ b/test/Industry/NullReturn_Scene_BadCase03.c @@ -40,7 +40,6 @@ void TestBad3() free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase04.c b/test/Industry/NullReturn_Scene_BadCase04.c index d7054e5af2..377e4b9e19 100644 --- a/test/Industry/NullReturn_Scene_BadCase04.c +++ b/test/Industry/NullReturn_Scene_BadCase04.c @@ -44,7 +44,6 @@ void TestBad4() free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --mock-external-calls --libc=klee --external-calls=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase06.c b/test/Industry/NullReturn_Scene_BadCase06.c index 8ad07ac540..19b11d341b 100644 --- a/test/Industry/NullReturn_Scene_BadCase06.c +++ b/test/Industry/NullReturn_Scene_BadCase06.c @@ -52,7 +52,6 @@ void TestBad6(unsigned int count) free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase08.cpp b/test/Industry/NullReturn_Scene_BadCase08.cpp index 07870565a0..91e6dccdf8 100644 --- a/test/Industry/NullReturn_Scene_BadCase08.cpp +++ b/test/Industry/NullReturn_Scene_BadCase08.cpp @@ -37,7 +37,6 @@ void TestBad9() printf("the current integer is: %d", *p); // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clangxx %s -emit-llvm %O0opt -c -g -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --write-kqueries --use-guided-search=error --location-accuracy --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/SecB_ForwardNull.c b/test/Industry/SecB_ForwardNull.c index ef5866afbc..e3a8334c82 100644 --- a/test/Industry/SecB_ForwardNull.c +++ b/test/Industry/SecB_ForwardNull.c @@ -1,8 +1,3 @@ -// REQUIRES: z3 -// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc -// RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s /* * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. * @description 空指针解引用 验收失败 @@ -133,3 +128,8 @@ void badbad(char *ptr) ptr = NULL; *ptr = 'a'; // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } + +// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s \ No newline at end of file diff --git a/test/Industry/SecB_ForwardNull.c.json b/test/Industry/SecB_ForwardNull.c.json index d26344534b..ee8294c266 100644 --- a/test/Industry/SecB_ForwardNull.c.json +++ b/test/Industry/SecB_ForwardNull.c.json @@ -20,7 +20,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/SecB_ForwardNull.c" }, "region": { - "startLine": 133, + "startLine": 128, "startColumn": null } } @@ -33,7 +33,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/SecB_ForwardNull.c" }, "region": { - "startLine": 134, + "startLine": 129, "startColumn": null } } @@ -52,7 +52,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/SecB_ForwardNull.c" }, "region": { - "startLine": 134, + "startLine": 129, "startColumn": null } } diff --git a/test/Industry/UseAfterFree/Double_Free_BadCase01.c b/test/Industry/UseAfterFree/Double_Free_BadCase01.c index cece04e8a7..57d3600faa 100644 --- a/test/Industry/UseAfterFree/Double_Free_BadCase01.c +++ b/test/Industry/UseAfterFree/Double_Free_BadCase01.c @@ -16,8 +16,8 @@ * @author xwx356597;x00407107 * */ + #include -#include //@scene 指针释放后未置空导致双重释放 void DoubleFreeBad01() @@ -36,7 +36,6 @@ void DoubleFreeBad01() free(p); // CHECK: KLEE: WARNING: 100.00% DoubleFree True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/UseAfterFree/Double_Free_BadCase02.c b/test/Industry/UseAfterFree/Double_Free_BadCase02.c index e6e93818d8..be8f1c52c1 100644 --- a/test/Industry/UseAfterFree/Double_Free_BadCase02.c +++ b/test/Industry/UseAfterFree/Double_Free_BadCase02.c @@ -16,8 +16,8 @@ * @author xwx356597;x00407107 * */ + #include -#include //@scene 指针释放后未置空,有条件地再再次释放导致双重释放 void DoubleFreeBad02(int flag) @@ -39,7 +39,6 @@ void DoubleFreeBad02(int flag) } } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp b/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp index 6c15434bf4..90a32d9903 100644 --- a/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp +++ b/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp @@ -17,7 +17,6 @@ * */ -#include #include #include @@ -34,6 +33,7 @@ typedef struct { int a; char *pname; }Data; + //全局变量 分支结束前要重新赋值 char *MSG = (char*)malloc(1000); @@ -75,7 +75,6 @@ int main() return 0; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c b/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c index 9c171549e9..7742d31afd 100644 --- a/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c +++ b/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c @@ -33,7 +33,6 @@ void UseAfterFree() return; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/ZeroDeref_Scene_BadCase02.c b/test/Industry/ZeroDeref_Scene_BadCase02.c index 0e65b66155..dd0fe063ac 100644 --- a/test/Industry/ZeroDeref_Scene_BadCase02.c +++ b/test/Industry/ZeroDeref_Scene_BadCase02.c @@ -38,7 +38,6 @@ void TestBad9() memcpy(pDest, p, BUFFERSIZE); // CHECK-DAG: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/ZeroDeref_Scene_BadCase05.c b/test/Industry/ZeroDeref_Scene_BadCase05.c index d094cea77b..3afb67837e 100644 --- a/test/Industry/ZeroDeref_Scene_BadCase05.c +++ b/test/Industry/ZeroDeref_Scene_BadCase05.c @@ -62,7 +62,6 @@ void TestBad18(struct STU *stu) HelpBadTest1(NULL); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --mock-external-calls --libc=klee --external-calls=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/egcd3-ll_valuebound10.c b/test/Industry/egcd3-ll_valuebound10.c new file mode 100644 index 0000000000..5811f1f44d --- /dev/null +++ b/test/Industry/egcd3-ll_valuebound10.c @@ -0,0 +1,112 @@ +// REQUIRES: not-darwin, not-san +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --max-solver-time=5s --track-coverage=branches --use-iterative-deepening-search=max-cycles --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=all --search=dfs --search=random-state %t1.bc + +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// Branch coverage 100%, the number of branches is 1: +// CHECK: Lines executed:87.93% of 58 +// CHECK-NEXT: Branches executed:100.00% of 18 +// CHECK-NEXT: Taken at least once:83.33% of 18 + +#include "klee-test-comp.c" +/* extended Euclid's algorithm */ +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); +#endif +} + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "egcd3-ll.c", 4, "reach_error"); } +extern int __VERIFIER_nondet_int(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort_prog();} +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: + {reach_error();} + } + return; +} + +int main() { + int x, y; + long long a, b, p, q, r, s; + x = __VERIFIER_nondet_int(); + assume_abort_if_not(x>=0 && x<=10); + y = __VERIFIER_nondet_int(); + assume_abort_if_not(y>=0 && y<=10); + assume_abort_if_not(x >= 1); + assume_abort_if_not(y >= 1); + + a = x; + b = y; + p = 1; + q = 0; + r = 0; + s = 1; + + while (1) { + if (!(b != 0)) + break; + long long c, k; + c = a; + k = 0; + + while (1) { + if (!(c >= b)) + break; + long long d, v; + d = 1; + v = b; + + while (1) { + __VERIFIER_assert(a == y * r + x * p); + __VERIFIER_assert(b == x * q + y * s); + __VERIFIER_assert(a == k * b + c); + __VERIFIER_assert(v == b * d); + + if (!(c >= 2 * v)) + break; + d = 2 * d; + v = 2 * v; + } + c = c - v; + k = k + d; + } + + a = b; + b = c; + long long temp; + temp = p; + p = q; + q = temp - q * k; + temp = r; + r = s; + s = temp - s * k; + } + __VERIFIER_assert(p*x - q*x + r*y - s*y == a); + return 0; +} diff --git a/test/Industry/fn_reverse_null.c b/test/Industry/fn_reverse_null.c index 0e02ebc842..aff52b8f68 100644 --- a/test/Industry/fn_reverse_null.c +++ b/test/Industry/fn_reverse_null.c @@ -53,7 +53,6 @@ void TestErr4(TreeNode *head) return; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --external-calls=all --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/fp_forward_null_address.c b/test/Industry/fp_forward_null_address.c index f39297d2a4..e090051722 100644 --- a/test/Industry/fp_forward_null_address.c +++ b/test/Industry/fp_forward_null_address.c @@ -22,7 +22,6 @@ void foo() int v = *p; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --max-cycles-before-stuck=150 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/fp_null_returns_self_define.c b/test/Industry/fp_null_returns_self_define.c index 2ed62cfb68..fa331108b6 100644 --- a/test/Industry/fp_null_returns_self_define.c +++ b/test/Industry/fp_null_returns_self_define.c @@ -1,4 +1,3 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/fp_null_returns_self_define2.c b/test/Industry/fp_null_returns_self_define2.c index f737f18cc5..6606140676 100644 --- a/test/Industry/fp_null_returns_self_define2.c +++ b/test/Industry/fp_null_returns_self_define2.c @@ -26,7 +26,6 @@ void TEST_NullReturns004(unsigned short index) sink(value); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/if2.c b/test/Industry/if2.c index 27f414ed01..b35cb487bf 100644 --- a/test/Industry/if2.c +++ b/test/Industry/if2.c @@ -8,11 +8,10 @@ int main(int x) { return *p; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --search=bfs --max-stepped-instructions=19 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --search=bfs --max-stepped-instructions=20 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -check-prefix=CHECK-NONE // CHECK-NONE: KLEE: WARNING: 50.00% NullPointerException False Positive at trace 1 // RUN: FileCheck -input-file=%t.klee-out/messages.txt %s -check-prefix=CHECK-DISTANCE -// CHECK-DISTANCE: KLEE: (0, 1, 1) for Target 1: error in function main (lines 8 to 8) +// CHECK-DISTANCE: KLEE: (0, 1, 0) for Target 1: error in function main (lines 8 to 8) diff --git a/test/Industry/ll_create_rec-alloca-2.c b/test/Industry/ll_create_rec-alloca-2.c new file mode 100644 index 0000000000..27b037bf35 --- /dev/null +++ b/test/Industry/ll_create_rec-alloca-2.c @@ -0,0 +1,57 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --track-coverage=branches --delete-dead-loops=false --cex-cache-validity-cores --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs --search=random-path %t1.bc +// RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck -check-prefix=CHECK-BRANCH -input-file=%t.stats %s + +// Branch coverage 100%, and instruction coverage may vary: +// CHECK-BRANCH: ICov(%),BCov(%) +// CHECK-BRANCH-NEXT: {{([1-9][0-9]\.[0-9][0-9])}},100.00 + +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --track-coverage=blocks --delete-dead-loops=false --cex-cache-validity-cores --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs --search=random-path %t1.bc +// RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck -check-prefix=CHECK-BLOCK -input-file=%t.stats %s + +// Branch coverage 100%, and instruction 100%: +// CHECK-BLOCK: ICov(%),BCov(%) +// CHECK-BLOCK-NEXT: 100.00,100.00 + + +#include "klee-test-comp.c" + +/* + * Date: 30/09/2015 + * Created by: + * Ton Chanh Le (chanhle@comp.nus.edu.sg) and + * Duc Muoi Tran (muoitranduc@gmail.com) + */ + +extern int __VERIFIER_nondet_int(); + +typedef struct node { + int val; + struct node* next; +} node_t; + +// Create a new linked list with length n when n >= 0 +// or non-terminating when n < 0 +node_t* new_ll(int n) +{ + if (n == 0) + return 0; + node_t* head = malloc(sizeof(node_t)); + head->val = n; + head->next = new_ll(n-1); + return head; +} + +int main () +{ + int n = __VERIFIER_nondet_int(); + if (n < 0) { + return 0; + } + node_t* head = new_ll(n); + return 0; +} diff --git a/test/Industry/test.c b/test/Industry/test.c index 9d84770da0..5b08e0cd97 100644 --- a/test/Industry/test.c +++ b/test/Industry/test.c @@ -19,7 +19,6 @@ void TestBad8(int len) buf[0] = 'a'; // CHECK-NUM: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } // CHECK-UID: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 8389b1896658d867c9e15267acfe8c32 -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/while_true.c b/test/Industry/while_true.c index a2eebdcc0a..f0566cce12 100644 --- a/test/Industry/while_true.c +++ b/test/Industry/while_true.c @@ -8,7 +8,6 @@ int main() { return *p; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out-1 // RUN: %klee --output-dir=%t.klee-out-1 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=10 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c b/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c new file mode 100644 index 0000000000..8314734367 --- /dev/null +++ b/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c @@ -0,0 +1,566 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false -max-memory=6008 --optimize=true --skip-not-lazy-initialized -output-source=true --output-stats=false --output-istats=false --write-xml-tests --write-ktests=false --xml-metadata-programfile=wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c --xml-metadata-programhash=a18daeacf63b42ad6e1cb490555b7cdecd71ad6e58b167ed0f5626c03bc3d772 --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error --dump-states-on-halt=all -exit-on-error-type=Assert --search=dfs --search=random-path -max-time=20 %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s + +// RUN: test -f %t.klee-out/test000001.xml +// RUN: not test -f %t.klee-out/test000001.ktest + +// CHECK-VERDICT: KLEE: WARNING: 100.00% Reachable Reachable at trace + +//RUN: FileCheck %s -input-file=%t.klee-out/assembly.ll +// the only forking br is in __VERIFIER_assert +// that is, all ternary ifs are turned into `select` instructions +// CHECK: {{call.*reach_error}} +// CHECK-COUNT-11: {{ phi }} + + + + + + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2007 - 2022 Radek Pelánek +// SPDX-FileCopyrightText: 2022 The SV-Benchmarks Community +// +// SPDX-License-Identifier: Apache-2.0 + +// This C program is converted from Btor2 by Btor2C version bfcfb8b +// with arguments: { architecture=64, lazy_modulo=true, use_memmove=false, unroll_inner_loops=false, shortest_type=true, diff_type=true, decimal_constant=true, zero_init=false, sra_extend_sign=true } +// Comments from the original Btor2 file: +// ; source: http://fmv.jku.at/hwmcc19/beem_btor.tar.xz +// ; Model in BTOR format generated by stepout.py 0.41 +#include "klee-test-comp.c" +extern void abort(void); +void reach_error() {} + +extern unsigned char __VERIFIER_nondet_uchar(); +extern unsigned short __VERIFIER_nondet_ushort(); +extern unsigned int __VERIFIER_nondet_uint(); +extern unsigned long __VERIFIER_nondet_ulong(); +void __VERIFIER_assert(int cond) { if (!(cond)) { ERROR: { reach_error(); abort(); } } } +void assume_abort_if_not(int cond) { if (!cond) { abort(); } } +int main() { + // Defining sorts ... + typedef unsigned char SORT_1; // BV with 1 bits + const SORT_1 mask_SORT_1 = (SORT_1)-1 >> (sizeof(SORT_1) * 8 - 1); + const SORT_1 msb_SORT_1 = (SORT_1)1 << (1 - 1); + typedef unsigned char SORT_2; // BV with 5 bits + const SORT_2 mask_SORT_2 = (SORT_2)-1 >> (sizeof(SORT_2) * 8 - 5); + const SORT_2 msb_SORT_2 = (SORT_2)1 << (5 - 1); + typedef unsigned short SORT_3; // BV with 16 bits + const SORT_3 mask_SORT_3 = (SORT_3)-1 >> (sizeof(SORT_3) * 8 - 16); + const SORT_3 msb_SORT_3 = (SORT_3)1 << (16 - 1); + typedef unsigned int SORT_4; // BV with 32 bits + const SORT_4 mask_SORT_4 = (SORT_4)-1 >> (sizeof(SORT_4) * 8 - 32); + const SORT_4 msb_SORT_4 = (SORT_4)1 << (32 - 1); + // Initializing constants ... + const SORT_3 var_5 = 0; + const SORT_1 var_12 = 0; + const SORT_3 var_34 = 1; + const SORT_3 var_37 = 0; + const SORT_1 var_62 = 1; + const SORT_4 var_65 = 20; + const SORT_3 var_66 = 0; + const SORT_4 var_68 = 16; + const SORT_4 var_171 = 17; + // Collecting input declarations ... + SORT_3 input_44; + SORT_3 input_46; + SORT_3 input_48; + SORT_1 input_50; + SORT_1 input_52; + SORT_1 input_54; + SORT_1 input_56; + SORT_1 input_58; + SORT_1 input_60; + SORT_1 input_64; + SORT_1 input_74; + SORT_1 input_78; + SORT_1 input_81; + SORT_1 input_96; + SORT_1 input_100; + // Collecting state declarations ... + SORT_3 state_6 = __VERIFIER_nondet_ushort() & mask_SORT_3; + SORT_3 state_8 = __VERIFIER_nondet_ushort() & mask_SORT_3; + SORT_3 state_10 = __VERIFIER_nondet_ushort() & mask_SORT_3; + SORT_1 state_13 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_15 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_17 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_19 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_21 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_23 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_25 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_27 = __VERIFIER_nondet_uchar() & mask_SORT_1; + // Initializing states ... + SORT_3 init_7_arg_1 = var_5; + state_6 = init_7_arg_1; + SORT_3 init_9_arg_1 = var_5; + state_8 = init_9_arg_1; + SORT_3 init_11_arg_1 = var_5; + state_10 = init_11_arg_1; + SORT_1 init_14_arg_1 = var_12; + state_13 = init_14_arg_1; + SORT_1 init_16_arg_1 = var_12; + state_15 = init_16_arg_1; + SORT_1 init_18_arg_1 = var_12; + state_17 = init_18_arg_1; + SORT_1 init_20_arg_1 = var_12; + state_19 = init_20_arg_1; + SORT_1 init_22_arg_1 = var_12; + state_21 = init_22_arg_1; + SORT_1 init_24_arg_1 = var_12; + state_23 = init_24_arg_1; + SORT_1 init_26_arg_1 = var_12; + state_25 = init_26_arg_1; + SORT_1 init_28_arg_1 = var_12; + state_27 = init_28_arg_1; + for (;;) { + // Getting external input values ... + input_44 = __VERIFIER_nondet_ushort(); + input_44 = input_44 & mask_SORT_3; + input_46 = __VERIFIER_nondet_ushort(); + input_46 = input_46 & mask_SORT_3; + input_48 = __VERIFIER_nondet_ushort(); + input_48 = input_48 & mask_SORT_3; + input_50 = __VERIFIER_nondet_uchar(); + input_50 = input_50 & mask_SORT_1; + input_52 = __VERIFIER_nondet_uchar(); + input_52 = input_52 & mask_SORT_1; + input_54 = __VERIFIER_nondet_uchar(); + input_54 = input_54 & mask_SORT_1; + input_56 = __VERIFIER_nondet_uchar(); + input_56 = input_56 & mask_SORT_1; + input_58 = __VERIFIER_nondet_uchar(); + input_58 = input_58 & mask_SORT_1; + input_60 = __VERIFIER_nondet_uchar(); + input_60 = input_60 & mask_SORT_1; + input_64 = __VERIFIER_nondet_uchar(); + input_64 = input_64 & mask_SORT_1; + input_74 = __VERIFIER_nondet_uchar(); + input_74 = input_74 & mask_SORT_1; + input_78 = __VERIFIER_nondet_uchar(); + input_78 = input_78 & mask_SORT_1; + input_81 = __VERIFIER_nondet_uchar(); + input_81 = input_81 & mask_SORT_1; + input_96 = __VERIFIER_nondet_uchar(); + input_96 = input_96 & mask_SORT_1; + input_100 = __VERIFIER_nondet_uchar(); + input_100 = input_100 & mask_SORT_1; + // Assuming invariants ... + // Asserting properties ... + SORT_1 var_29_arg_0 = state_13; + SORT_1 var_29_arg_1 = ~state_15; + var_29_arg_1 = var_29_arg_1 & mask_SORT_1; + SORT_1 var_29 = var_29_arg_0 & var_29_arg_1; + SORT_1 var_30_arg_0 = var_29; + SORT_1 var_30_arg_1 = ~state_17; + var_30_arg_1 = var_30_arg_1 & mask_SORT_1; + SORT_1 var_30 = var_30_arg_0 & var_30_arg_1; + SORT_1 var_31_arg_0 = var_30; + SORT_1 var_31_arg_1 = state_19; + SORT_1 var_31 = var_31_arg_0 & var_31_arg_1; + SORT_1 var_32_arg_0 = var_31; + SORT_1 var_32_arg_1 = ~state_21; + var_32_arg_1 = var_32_arg_1 & mask_SORT_1; + SORT_1 var_32 = var_32_arg_0 & var_32_arg_1; + SORT_1 var_33_arg_0 = var_32; + SORT_1 var_33_arg_1 = ~state_23; + var_33_arg_1 = var_33_arg_1 & mask_SORT_1; + SORT_1 var_33 = var_33_arg_0 & var_33_arg_1; + SORT_3 var_35_arg_0 = var_34; + SORT_3 var_35_arg_1 = state_6; + SORT_1 var_35 = var_35_arg_0 == var_35_arg_1; + SORT_1 var_36_arg_0 = var_33; + SORT_1 var_36_arg_1 = var_35; + SORT_1 var_36 = var_36_arg_0 & var_36_arg_1; + SORT_3 var_38_arg_0 = var_37; + SORT_3 var_38_arg_1 = state_8; + SORT_1 var_38 = var_38_arg_0 == var_38_arg_1; + SORT_1 var_39_arg_0 = var_36; + SORT_1 var_39_arg_1 = var_38; + SORT_1 var_39 = var_39_arg_0 & var_39_arg_1; + SORT_3 var_40_arg_0 = var_37; + SORT_3 var_40_arg_1 = state_10; + SORT_1 var_40 = var_40_arg_0 == var_40_arg_1; + SORT_1 var_41_arg_0 = var_39; + SORT_1 var_41_arg_1 = var_40; + SORT_1 var_41 = var_41_arg_0 & var_41_arg_1; + SORT_1 var_42_arg_0 = state_27; + SORT_1 var_42_arg_1 = var_41; + SORT_1 var_42 = var_42_arg_0 & var_42_arg_1; + var_42 = var_42 & mask_SORT_1; + SORT_1 bad_43_arg_0 = var_42; + __VERIFIER_assert(!(bad_43_arg_0)); + // Computing next states ... + SORT_3 next_45_arg_1 = input_44; + SORT_3 next_47_arg_1 = input_46; + SORT_3 next_49_arg_1 = input_48; + SORT_1 next_51_arg_1 = input_50; + SORT_1 next_53_arg_1 = input_52; + SORT_1 next_55_arg_1 = input_54; + SORT_1 next_57_arg_1 = input_56; + SORT_1 next_59_arg_1 = input_58; + SORT_1 next_61_arg_1 = input_60; + SORT_1 next_63_arg_1 = var_62; + SORT_3 var_67_arg_0 = input_44; + SORT_3 var_67_arg_1 = var_66; + SORT_4 var_67 = ((SORT_4)var_67_arg_0 << 16) | var_67_arg_1; + SORT_4 var_69_arg_0 = var_67; + var_69_arg_0 = (var_69_arg_0 & msb_SORT_4) ? (var_69_arg_0 | ~mask_SORT_4) : (var_69_arg_0 & mask_SORT_4); + SORT_4 var_69_arg_1 = var_68; + SORT_4 var_69 = (int)var_69_arg_0 >> var_69_arg_1; + var_69 = (var_69_arg_0 & msb_SORT_4) ? (var_69 | ~(mask_SORT_4 >> var_69_arg_1)) : var_69; + var_69 = var_69 & mask_SORT_4; + SORT_4 var_70_arg_0 = var_65; + SORT_4 var_70_arg_1 = var_69; + SORT_1 var_70 = var_70_arg_0 <= var_70_arg_1; + SORT_1 var_71_arg_0 = input_50; + SORT_1 var_71_arg_1 = ~var_70; + var_71_arg_1 = var_71_arg_1 & mask_SORT_1; + SORT_1 var_71 = var_71_arg_0 & var_71_arg_1; + SORT_1 var_72_arg_0 = ~input_64; + var_72_arg_0 = var_72_arg_0 & mask_SORT_1; + SORT_1 var_72_arg_1 = var_71; + SORT_1 var_72 = var_72_arg_0 | var_72_arg_1; + SORT_1 var_73_arg_0 = input_52; + SORT_1 var_73_arg_1 = input_64; + SORT_1 var_73 = var_73_arg_0 | var_73_arg_1; + SORT_1 var_75_arg_0 = var_73; + SORT_1 var_75_arg_1 = ~input_74; + var_75_arg_1 = var_75_arg_1 & mask_SORT_1; + SORT_1 var_75 = var_75_arg_0 | var_75_arg_1; + SORT_1 var_76_arg_0 = var_72; + SORT_1 var_76_arg_1 = var_75; + SORT_1 var_76 = var_76_arg_0 & var_76_arg_1; + SORT_1 var_77_arg_0 = input_54; + SORT_1 var_77_arg_1 = input_74; + SORT_1 var_77 = var_77_arg_0 | var_77_arg_1; + SORT_1 var_79_arg_0 = var_77; + SORT_1 var_79_arg_1 = ~input_78; + var_79_arg_1 = var_79_arg_1 & mask_SORT_1; + SORT_1 var_79 = var_79_arg_0 | var_79_arg_1; + SORT_1 var_80_arg_0 = var_76; + SORT_1 var_80_arg_1 = var_79; + SORT_1 var_80 = var_80_arg_0 & var_80_arg_1; + SORT_1 var_82_arg_0 = input_64; + SORT_3 var_82_arg_1 = input_44; + SORT_3 var_82_arg_2 = input_46; + SORT_3 var_82 = var_82_arg_0 ? var_82_arg_1 : var_82_arg_2; + SORT_3 var_83_arg_0 = var_82; + SORT_3 var_83_arg_1 = var_66; + SORT_4 var_83 = ((SORT_4)var_83_arg_0 << 16) | var_83_arg_1; + SORT_4 var_84_arg_0 = var_83; + var_84_arg_0 = (var_84_arg_0 & msb_SORT_4) ? (var_84_arg_0 | ~mask_SORT_4) : (var_84_arg_0 & mask_SORT_4); + SORT_4 var_84_arg_1 = var_68; + SORT_4 var_84 = (int)var_84_arg_0 >> var_84_arg_1; + var_84 = (var_84_arg_0 & msb_SORT_4) ? (var_84 | ~(mask_SORT_4 >> var_84_arg_1)) : var_84; + SORT_4 var_85_arg_0 = var_69; + SORT_4 var_85_arg_1 = var_84; + SORT_4 var_85 = var_85_arg_0 + var_85_arg_1; + SORT_4 var_86_arg_0 = var_85; + SORT_3 var_86 = var_86_arg_0 >> 0; + SORT_1 var_87_arg_0 = input_74; + SORT_3 var_87_arg_1 = var_86; + SORT_3 var_87_arg_2 = var_82; + SORT_3 var_87 = var_87_arg_0 ? var_87_arg_1 : var_87_arg_2; + var_87 = var_87 & mask_SORT_3; + SORT_1 var_88_arg_0 = input_78; + SORT_3 var_88_arg_1 = var_87; + SORT_3 var_88_arg_2 = input_44; + SORT_3 var_88 = var_88_arg_0 ? var_88_arg_1 : var_88_arg_2; + SORT_3 var_89_arg_0 = var_88; + SORT_3 var_89_arg_1 = var_66; + SORT_4 var_89 = ((SORT_4)var_89_arg_0 << 16) | var_89_arg_1; + SORT_4 var_90_arg_0 = var_89; + var_90_arg_0 = (var_90_arg_0 & msb_SORT_4) ? (var_90_arg_0 | ~mask_SORT_4) : (var_90_arg_0 & mask_SORT_4); + SORT_4 var_90_arg_1 = var_68; + SORT_4 var_90 = (int)var_90_arg_0 >> var_90_arg_1; + var_90 = (var_90_arg_0 & msb_SORT_4) ? (var_90 | ~(mask_SORT_4 >> var_90_arg_1)) : var_90; + var_90 = var_90 & mask_SORT_4; + SORT_4 var_91_arg_0 = var_65; + SORT_4 var_91_arg_1 = var_90; + SORT_1 var_91 = var_91_arg_0 <= var_91_arg_1; + SORT_1 var_92_arg_0 = input_56; + SORT_1 var_92_arg_1 = ~var_91; + var_92_arg_1 = var_92_arg_1 & mask_SORT_1; + SORT_1 var_92 = var_92_arg_0 & var_92_arg_1; + SORT_1 var_93_arg_0 = ~input_81; + var_93_arg_0 = var_93_arg_0 & mask_SORT_1; + SORT_1 var_93_arg_1 = var_92; + SORT_1 var_93 = var_93_arg_0 | var_93_arg_1; + SORT_1 var_94_arg_0 = var_80; + SORT_1 var_94_arg_1 = var_93; + SORT_1 var_94 = var_94_arg_0 & var_94_arg_1; + SORT_1 var_95_arg_0 = input_58; + SORT_1 var_95_arg_1 = input_81; + SORT_1 var_95 = var_95_arg_0 | var_95_arg_1; + SORT_1 var_97_arg_0 = var_95; + SORT_1 var_97_arg_1 = ~input_96; + var_97_arg_1 = var_97_arg_1 & mask_SORT_1; + SORT_1 var_97 = var_97_arg_0 | var_97_arg_1; + SORT_1 var_98_arg_0 = var_94; + SORT_1 var_98_arg_1 = var_97; + SORT_1 var_98 = var_98_arg_0 & var_98_arg_1; + SORT_1 var_99_arg_0 = input_60; + SORT_1 var_99_arg_1 = input_96; + SORT_1 var_99 = var_99_arg_0 | var_99_arg_1; + SORT_1 var_101_arg_0 = var_99; + SORT_1 var_101_arg_1 = ~input_100; + var_101_arg_1 = var_101_arg_1 & mask_SORT_1; + SORT_1 var_101 = var_101_arg_0 | var_101_arg_1; + SORT_1 var_102_arg_0 = var_98; + SORT_1 var_102_arg_1 = var_101; + SORT_1 var_102 = var_102_arg_0 & var_102_arg_1; + SORT_1 var_103_arg_0 = input_64; + SORT_1 var_103_arg_1 = input_74; + SORT_1 var_103 = var_103_arg_0 | var_103_arg_1; + SORT_1 var_104_arg_0 = input_78; + SORT_1 var_104_arg_1 = var_103; + SORT_1 var_104 = var_104_arg_0 | var_104_arg_1; + SORT_1 var_105_arg_0 = input_81; + SORT_1 var_105_arg_1 = var_104; + SORT_1 var_105 = var_105_arg_0 | var_105_arg_1; + SORT_1 var_106_arg_0 = input_96; + SORT_1 var_106_arg_1 = var_105; + SORT_1 var_106 = var_106_arg_0 | var_106_arg_1; + SORT_1 var_107_arg_0 = input_100; + SORT_1 var_107_arg_1 = var_106; + SORT_1 var_107 = var_107_arg_0 | var_107_arg_1; + SORT_1 var_108_arg_0 = var_102; + SORT_1 var_108_arg_1 = var_107; + SORT_1 var_108 = var_108_arg_0 & var_108_arg_1; + SORT_1 var_109_arg_0 = input_50; + SORT_1 var_109_arg_1 = input_52; + SORT_1 var_109 = var_109_arg_0 & var_109_arg_1; + SORT_1 var_110_arg_0 = input_50; + SORT_1 var_110_arg_1 = input_52; + SORT_1 var_110 = var_110_arg_0 | var_110_arg_1; + SORT_1 var_111_arg_0 = input_54; + SORT_1 var_111_arg_1 = var_110; + SORT_1 var_111 = var_111_arg_0 & var_111_arg_1; + SORT_1 var_112_arg_0 = var_109; + SORT_1 var_112_arg_1 = var_111; + SORT_1 var_112 = var_112_arg_0 | var_112_arg_1; + SORT_1 var_113_arg_0 = input_54; + SORT_1 var_113_arg_1 = var_110; + SORT_1 var_113 = var_113_arg_0 | var_113_arg_1; + SORT_1 var_114_arg_0 = ~var_112; + var_114_arg_0 = var_114_arg_0 & mask_SORT_1; + SORT_1 var_114_arg_1 = var_113; + SORT_1 var_114 = var_114_arg_0 & var_114_arg_1; + SORT_1 var_115_arg_0 = input_56; + SORT_1 var_115_arg_1 = input_58; + SORT_1 var_115 = var_115_arg_0 & var_115_arg_1; + SORT_1 var_116_arg_0 = input_56; + SORT_1 var_116_arg_1 = input_58; + SORT_1 var_116 = var_116_arg_0 | var_116_arg_1; + SORT_1 var_117_arg_0 = input_60; + SORT_1 var_117_arg_1 = var_116; + SORT_1 var_117 = var_117_arg_0 & var_117_arg_1; + SORT_1 var_118_arg_0 = var_115; + SORT_1 var_118_arg_1 = var_117; + SORT_1 var_118 = var_118_arg_0 | var_118_arg_1; + SORT_1 var_119_arg_0 = var_114; + SORT_1 var_119_arg_1 = ~var_118; + var_119_arg_1 = var_119_arg_1 & mask_SORT_1; + SORT_1 var_119 = var_119_arg_0 & var_119_arg_1; + SORT_1 var_120_arg_0 = input_60; + SORT_1 var_120_arg_1 = var_116; + SORT_1 var_120 = var_120_arg_0 | var_120_arg_1; + SORT_1 var_121_arg_0 = var_119; + SORT_1 var_121_arg_1 = var_120; + SORT_1 var_121 = var_121_arg_0 & var_121_arg_1; + SORT_1 var_122_arg_0 = var_108; + SORT_1 var_122_arg_1 = var_121; + SORT_1 var_122 = var_122_arg_0 & var_122_arg_1; + SORT_1 var_123_arg_0 = var_73; + SORT_1 var_123_arg_1 = ~input_74; + var_123_arg_1 = var_123_arg_1 & mask_SORT_1; + SORT_1 var_123 = var_123_arg_0 & var_123_arg_1; + var_123 = var_123 & mask_SORT_1; + SORT_1 var_124_arg_0 = input_50; + SORT_1 var_124_arg_1 = ~input_64; + var_124_arg_1 = var_124_arg_1 & mask_SORT_1; + SORT_1 var_124 = var_124_arg_0 & var_124_arg_1; + SORT_1 var_125_arg_0 = var_124; + SORT_1 var_125_arg_1 = input_78; + SORT_1 var_125 = var_125_arg_0 | var_125_arg_1; + var_125 = var_125 & mask_SORT_1; + SORT_1 var_126_arg_0 = var_123; + SORT_1 var_126_arg_1 = var_125; + SORT_1 var_126 = var_126_arg_0 & var_126_arg_1; + SORT_1 var_127_arg_0 = var_77; + SORT_1 var_127_arg_1 = ~input_78; + var_127_arg_1 = var_127_arg_1 & mask_SORT_1; + SORT_1 var_127 = var_127_arg_0 & var_127_arg_1; + var_127 = var_127 & mask_SORT_1; + SORT_1 var_128_arg_0 = var_123; + SORT_1 var_128_arg_1 = var_125; + SORT_1 var_128 = var_128_arg_0 | var_128_arg_1; + SORT_1 var_129_arg_0 = var_127; + SORT_1 var_129_arg_1 = var_128; + SORT_1 var_129 = var_129_arg_0 & var_129_arg_1; + SORT_1 var_130_arg_0 = var_126; + SORT_1 var_130_arg_1 = var_129; + SORT_1 var_130 = var_130_arg_0 | var_130_arg_1; + SORT_1 var_131_arg_0 = var_127; + SORT_1 var_131_arg_1 = var_128; + SORT_1 var_131 = var_131_arg_0 | var_131_arg_1; + SORT_1 var_132_arg_0 = ~var_130; + var_132_arg_0 = var_132_arg_0 & mask_SORT_1; + SORT_1 var_132_arg_1 = var_131; + SORT_1 var_132 = var_132_arg_0 & var_132_arg_1; + SORT_1 var_133_arg_0 = var_95; + SORT_1 var_133_arg_1 = ~input_96; + var_133_arg_1 = var_133_arg_1 & mask_SORT_1; + SORT_1 var_133 = var_133_arg_0 & var_133_arg_1; + var_133 = var_133 & mask_SORT_1; + SORT_1 var_134_arg_0 = input_56; + SORT_1 var_134_arg_1 = ~input_81; + var_134_arg_1 = var_134_arg_1 & mask_SORT_1; + SORT_1 var_134 = var_134_arg_0 & var_134_arg_1; + SORT_1 var_135_arg_0 = var_134; + SORT_1 var_135_arg_1 = input_100; + SORT_1 var_135 = var_135_arg_0 | var_135_arg_1; + var_135 = var_135 & mask_SORT_1; + SORT_1 var_136_arg_0 = var_133; + SORT_1 var_136_arg_1 = var_135; + SORT_1 var_136 = var_136_arg_0 & var_136_arg_1; + SORT_1 var_137_arg_0 = var_99; + SORT_1 var_137_arg_1 = ~input_100; + var_137_arg_1 = var_137_arg_1 & mask_SORT_1; + SORT_1 var_137 = var_137_arg_0 & var_137_arg_1; + var_137 = var_137 & mask_SORT_1; + SORT_1 var_138_arg_0 = var_133; + SORT_1 var_138_arg_1 = var_135; + SORT_1 var_138 = var_138_arg_0 | var_138_arg_1; + SORT_1 var_139_arg_0 = var_137; + SORT_1 var_139_arg_1 = var_138; + SORT_1 var_139 = var_139_arg_0 & var_139_arg_1; + SORT_1 var_140_arg_0 = var_136; + SORT_1 var_140_arg_1 = var_139; + SORT_1 var_140 = var_140_arg_0 | var_140_arg_1; + SORT_1 var_141_arg_0 = var_132; + SORT_1 var_141_arg_1 = ~var_140; + var_141_arg_1 = var_141_arg_1 & mask_SORT_1; + SORT_1 var_141 = var_141_arg_0 & var_141_arg_1; + SORT_1 var_142_arg_0 = var_137; + SORT_1 var_142_arg_1 = var_138; + SORT_1 var_142 = var_142_arg_0 | var_142_arg_1; + SORT_1 var_143_arg_0 = var_141; + SORT_1 var_143_arg_1 = var_142; + SORT_1 var_143 = var_143_arg_0 & var_143_arg_1; + SORT_1 var_144_arg_0 = var_122; + SORT_1 var_144_arg_1 = var_143; + SORT_1 var_144 = var_144_arg_0 & var_144_arg_1; + SORT_1 var_145_arg_0 = input_81; + SORT_3 var_145_arg_1 = var_88; + SORT_3 var_145_arg_2 = input_48; + SORT_3 var_145 = var_145_arg_0 ? var_145_arg_1 : var_145_arg_2; + SORT_3 var_146_arg_0 = var_145; + SORT_3 var_146_arg_1 = var_66; + SORT_4 var_146 = ((SORT_4)var_146_arg_0 << 16) | var_146_arg_1; + SORT_4 var_147_arg_0 = var_146; + var_147_arg_0 = (var_147_arg_0 & msb_SORT_4) ? (var_147_arg_0 | ~mask_SORT_4) : (var_147_arg_0 & mask_SORT_4); + SORT_4 var_147_arg_1 = var_68; + SORT_4 var_147 = (int)var_147_arg_0 >> var_147_arg_1; + var_147 = (var_147_arg_0 & msb_SORT_4) ? (var_147 | ~(mask_SORT_4 >> var_147_arg_1)) : var_147; + SORT_4 var_148_arg_0 = var_90; + SORT_4 var_148_arg_1 = var_147; + SORT_4 var_148 = var_148_arg_0 + var_148_arg_1; + SORT_4 var_149_arg_0 = var_148; + SORT_3 var_149 = var_149_arg_0 >> 0; + SORT_1 var_150_arg_0 = input_96; + SORT_3 var_150_arg_1 = var_149; + SORT_3 var_150_arg_2 = var_145; + SORT_3 var_150 = var_150_arg_0 ? var_150_arg_1 : var_150_arg_2; + var_150 = var_150 & mask_SORT_3; + SORT_1 var_151_arg_0 = input_100; + SORT_3 var_151_arg_1 = var_150; + SORT_3 var_151_arg_2 = var_88; + SORT_3 var_151 = var_151_arg_0 ? var_151_arg_1 : var_151_arg_2; + var_151 = var_151 & mask_SORT_3; + SORT_3 var_152_arg_0 = var_151; + SORT_3 var_152_arg_1 = state_6; + SORT_1 var_152 = var_152_arg_0 == var_152_arg_1; + SORT_1 var_153_arg_0 = var_144; + SORT_1 var_153_arg_1 = var_152; + SORT_1 var_153 = var_153_arg_0 & var_153_arg_1; + SORT_3 var_154_arg_0 = var_87; + SORT_3 var_154_arg_1 = state_8; + SORT_1 var_154 = var_154_arg_0 == var_154_arg_1; + SORT_1 var_155_arg_0 = var_153; + SORT_1 var_155_arg_1 = var_154; + SORT_1 var_155 = var_155_arg_0 & var_155_arg_1; + SORT_3 var_156_arg_0 = var_150; + SORT_3 var_156_arg_1 = state_10; + SORT_1 var_156 = var_156_arg_0 == var_156_arg_1; + SORT_1 var_157_arg_0 = var_155; + SORT_1 var_157_arg_1 = var_156; + SORT_1 var_157 = var_157_arg_0 & var_157_arg_1; + SORT_1 var_158_arg_0 = var_125; + SORT_1 var_158_arg_1 = state_13; + SORT_1 var_158 = var_158_arg_0 == var_158_arg_1; + SORT_1 var_159_arg_0 = var_157; + SORT_1 var_159_arg_1 = var_158; + SORT_1 var_159 = var_159_arg_0 & var_159_arg_1; + SORT_1 var_160_arg_0 = var_123; + SORT_1 var_160_arg_1 = state_15; + SORT_1 var_160 = var_160_arg_0 == var_160_arg_1; + SORT_1 var_161_arg_0 = var_159; + SORT_1 var_161_arg_1 = var_160; + SORT_1 var_161 = var_161_arg_0 & var_161_arg_1; + SORT_1 var_162_arg_0 = var_127; + SORT_1 var_162_arg_1 = state_17; + SORT_1 var_162 = var_162_arg_0 == var_162_arg_1; + SORT_1 var_163_arg_0 = var_161; + SORT_1 var_163_arg_1 = var_162; + SORT_1 var_163 = var_163_arg_0 & var_163_arg_1; + SORT_1 var_164_arg_0 = var_135; + SORT_1 var_164_arg_1 = state_19; + SORT_1 var_164 = var_164_arg_0 == var_164_arg_1; + SORT_1 var_165_arg_0 = var_163; + SORT_1 var_165_arg_1 = var_164; + SORT_1 var_165 = var_165_arg_0 & var_165_arg_1; + SORT_1 var_166_arg_0 = var_133; + SORT_1 var_166_arg_1 = state_21; + SORT_1 var_166 = var_166_arg_0 == var_166_arg_1; + SORT_1 var_167_arg_0 = var_165; + SORT_1 var_167_arg_1 = var_166; + SORT_1 var_167 = var_167_arg_0 & var_167_arg_1; + SORT_1 var_168_arg_0 = var_137; + SORT_1 var_168_arg_1 = state_23; + SORT_1 var_168 = var_168_arg_0 == var_168_arg_1; + SORT_1 var_169_arg_0 = var_167; + SORT_1 var_169_arg_1 = var_168; + SORT_1 var_169 = var_169_arg_0 & var_169_arg_1; + SORT_1 var_170_arg_0 = var_169; + SORT_1 var_170_arg_1 = state_27; + SORT_1 var_170 = var_170_arg_0 & var_170_arg_1; + SORT_4 var_172_arg_0 = var_171; + SORT_4 var_172_arg_1 = var_69; + SORT_1 var_172 = var_172_arg_0 == var_172_arg_1; + SORT_1 var_173_arg_0 = state_25; + SORT_1 var_173_arg_1 = var_170; + SORT_1 var_173_arg_2 = var_172; + SORT_1 var_173 = var_173_arg_0 ? var_173_arg_1 : var_173_arg_2; + SORT_1 next_174_arg_1 = var_173; + // Assigning next states ... + state_6 = next_45_arg_1; + state_8 = next_47_arg_1; + state_10 = next_49_arg_1; + state_13 = next_51_arg_1; + state_15 = next_53_arg_1; + state_17 = next_55_arg_1; + state_19 = next_57_arg_1; + state_21 = next_59_arg_1; + state_23 = next_61_arg_1; + state_25 = next_63_arg_1; + state_27 = next_174_arg_1; + } + return 0; +} \ No newline at end of file diff --git a/test/InteractiveMode/interactive_mode.c b/test/InteractiveMode/interactive_mode.c index 1adb5e01f2..8ae3cb75c1 100644 --- a/test/InteractiveMode/interactive_mode.c +++ b/test/InteractiveMode/interactive_mode.c @@ -1,4 +1,5 @@ -// REQUIRES: not-ubsan +/* The test is flaky and the feature isn't importatnt now */ +// REQUIRES: not-ubsan, not-darwin // RUN: %clang %s -emit-llvm -g %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out %t.entrypoints // RUN: echo sign_sum >> %t.entrypoints diff --git a/test/Replay/libkleeruntest/replay_invalid_klee_assume.c b/test/Replay/libkleeruntest/replay_invalid_klee_assume.c index 89584d6a29..b83cce79e6 100644 --- a/test/Replay/libkleeruntest/replay_invalid_klee_assume.c +++ b/test/Replay/libkleeruntest/replay_invalid_klee_assume.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_klee_choose.c b/test/Replay/libkleeruntest/replay_invalid_klee_choose.c index 32cd136489..9f114d74d9 100644 --- a/test/Replay/libkleeruntest/replay_invalid_klee_choose.c +++ b/test/Replay/libkleeruntest/replay_invalid_klee_choose.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_klee_range.c b/test/Replay/libkleeruntest/replay_invalid_klee_range.c index f342a56aca..7cb016dd28 100644 --- a/test/Replay/libkleeruntest/replay_invalid_klee_range.c +++ b/test/Replay/libkleeruntest/replay_invalid_klee_range.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_num_objects.c b/test/Replay/libkleeruntest/replay_invalid_num_objects.c index ca5615ccc0..8bc5d08d1b 100644 --- a/test/Replay/libkleeruntest/replay_invalid_num_objects.c +++ b/test/Replay/libkleeruntest/replay_invalid_num_objects.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_object_names.c b/test/Replay/libkleeruntest/replay_invalid_object_names.c index 88e81e1bd8..4111da54d5 100644 --- a/test/Replay/libkleeruntest/replay_invalid_object_names.c +++ b/test/Replay/libkleeruntest/replay_invalid_object_names.c @@ -12,7 +12,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_object_size.c b/test/Replay/libkleeruntest/replay_invalid_object_size.c index 4de37bbf7a..6a1e50e28f 100644 --- a/test/Replay/libkleeruntest/replay_invalid_object_size.c +++ b/test/Replay/libkleeruntest/replay_invalid_object_size.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include #include diff --git a/test/Solver/2016-04-12-array-parsing-bug.kquery b/test/Solver/2016-04-12-array-parsing-bug.kquery index 044144ba6a..2fe11893e5 100644 --- a/test/Solver/2016-04-12-array-parsing-bug.kquery +++ b/test/Solver/2016-04-12-array-parsing-bug.kquery @@ -5,8 +5,8 @@ makeSymbolic0 : (array (w64 8) (makeSymbolic A_data 0)) makeSymbolic1 : (array (w64 144) (makeSymbolic A_data_stat 0)) makeSymbolic2 : (array (w64 3) (makeSymbolic arg0 0)) makeSymbolic3 : (array (w64 3) (makeSymbolic arg1 0)) -constant4 : (array (w64 768) (constant [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 3 32 2 32 2 32 2 32 2 32 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 96 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 213 8 213 8 213 8 213 8 213 8 213 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 4 192 4 192 4 192 4 192 4 192 4 192 8 214 8 214 8 214 8 214 8 214 8 214 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 4 192 4 192 4 192 4 192 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0])) -constant5 : (array (w64 277) (constant [0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 24 2 2 25 2 2 2 2 2 2 2 2 2 2 23 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21])) +constant4 : (array (w64 768) (constant [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 3 32 2 32 2 32 2 32 2 32 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 96 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 213 8 213 8 213 8 213 8 213 8 213 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 4 192 4 192 4 192 4 192 4 192 4 192 8 214 8 214 8 214 8 214 8 214 8 214 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 4 192 4 192 4 192 4 192 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] default: 0)) +constant5 : (array (w64 277) (constant [0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 24 2 2 25 2 2 2 2 2 2 2 2 2 2 23 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21] default: 0)) makeSymbolic6 : (array (w64 4) (makeSymbolic model_version 0)) makeSymbolic7 : (array (w64 4) (makeSymbolic n_args 0)) makeSymbolic8 : (array (w64 4) (makeSymbolic n_args_1 0)) diff --git a/test/Solver/AlphaEquivalenceCheck.c b/test/Solver/AlphaEquivalenceCheck.c new file mode 100644 index 0000000000..160fdee515 --- /dev/null +++ b/test/Solver/AlphaEquivalenceCheck.c @@ -0,0 +1,19 @@ +// RUN: %clang %s -emit-llvm -g %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out +// RUN: %klee --output-dir=%t1.klee-out --use-alpha-equivalence=false --use-cex-cache=true --use-query-log=solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log +// RUN: rm -rf %t2.klee-out +// RUN: %klee --output-dir=%t2.klee-out --use-alpha-equivalence=true --use-cex-cache=true --use-query-log=solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log +// RUN: grep "^; Query" %t1.klee-out/solver-queries.smt2 | wc -l | grep -q 2 +// RUN: grep "^; Query" %t2.klee-out/solver-queries.smt2 | wc -l | grep -q 1 + +#include "klee/klee.h" + +int main(int argc, char **argv) { + int a, b, c, d; + klee_make_symbolic(&a, sizeof(a), "a"); + klee_make_symbolic(&b, sizeof(b), "b"); + klee_make_symbolic(&c, sizeof(c), "c"); + klee_make_symbolic(&d, sizeof(d), "d"); + klee_assume(a + b == 0); + klee_assume(c + d == 0); +} diff --git a/test/Solver/CallComputeValue.c b/test/Solver/CallComputeValue.c new file mode 100644 index 0000000000..3e0dbe408f --- /dev/null +++ b/test/Solver/CallComputeValue.c @@ -0,0 +1,21 @@ +// REQUIRES: z3 +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s + +#include "klee/klee.h" + +int main() { + int y; + klee_make_symbolic(&y, sizeof(y), "y"); + int *x; + klee_make_symbolic(&x, sizeof(x), "x"); + if (!x) + return 0; + if (*x == y) + return 1; + return 2; +} + +// CHECK: KLEE: done: completed paths = 17 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CexCacheCheckBinding.c b/test/Solver/CexCacheCheckBinding.c new file mode 100644 index 0000000000..4743ef1027 --- /dev/null +++ b/test/Solver/CexCacheCheckBinding.c @@ -0,0 +1,8 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --debug-cex-cache-check-binding --search=bfs --use-guided-search=none --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CexCacheValidityCoresCheck.c b/test/Solver/CexCacheValidityCoresCheck.c index 26ba133d63..0e48f6f24f 100644 --- a/test/Solver/CexCacheValidityCoresCheck.c +++ b/test/Solver/CexCacheValidityCoresCheck.c @@ -30,6 +30,6 @@ int main(int argc, char **argv) { } } // CHECK-CACHE-ON: QCexCacheHits,SolverQueries -// CHECK-CACHE-ON: 1461,202 +// CHECK-CACHE-ON: 1460,202 // CHECK-CACHE-OFF: QCexCacheHits,SolverQueries -// CHECK-CACHE-OFF: 1011,652 +// CHECK-CACHE-OFF: 1010,652 diff --git a/test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c b/test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c new file mode 100644 index 0000000000..f0e1dfc757 --- /dev/null +++ b/test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c @@ -0,0 +1,11 @@ +// REQUIRES: bitwuzla +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=bitwuzla --debug-bitwuzla-validate-models --debug-assignment-validating-solver --use-cex-cache=false --use-guided-search=none %t1.bc 2>&1 | FileCheck %s +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=dfs --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=64 --debug-crosscheck-core-solver=bitwuzla --debug-bitwuzla-validate-models --debug-assignment-validating-solver --use-cex-cache=false --use-guided-search=none %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CrosscheckCoreStpZ3.c b/test/Solver/CrosscheckCoreStpZ3.c index 9847d8a69b..968cc8a795 100644 --- a/test/Solver/CrosscheckCoreStpZ3.c +++ b/test/Solver/CrosscheckCoreStpZ3.c @@ -2,9 +2,9 @@ // REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=stp --use-forked-solver=false --debug-crosscheck-core-solver=z3 %t1.bc +// RUN: %klee --output-dir=%t.klee-out --solver-backend=stp --use-forked-solver=false --debug-crosscheck-core-solver=z3 --use-guided-search=none %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" -// CHECK: KLEE: done: completed paths = 15 +// CHECK: KLEE: done: completed paths = 18 // CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CrosscheckCoreZ3Bitwuzla.c b/test/Solver/CrosscheckCoreZ3Bitwuzla.c new file mode 100644 index 0000000000..f50a0dd2fc --- /dev/null +++ b/test/Solver/CrosscheckCoreZ3Bitwuzla.c @@ -0,0 +1,10 @@ +// REQUIRES: z3 +// REQUIRES: bitwuzla +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-forked-solver=false --debug-crosscheck-core-solver=bitwuzla --use-guided-search=none %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CrosscheckZ3AndZ3TreeInc.c b/test/Solver/CrosscheckZ3AndZ3TreeInc.c new file mode 100644 index 0000000000..b29050cd4a --- /dev/null +++ b/test/Solver/CrosscheckZ3AndZ3TreeInc.c @@ -0,0 +1,11 @@ +// REQUIRES: z3 +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false --use-guided-search=none %t1.bc 2>&1 | FileCheck %s +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=dfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=64 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false --use-guided-search=none %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/DummySolver.c b/test/Solver/DummySolver.c index f6fe3671be..54d94b5b2c 100644 --- a/test/Solver/DummySolver.c +++ b/test/Solver/DummySolver.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=dummy %t1.bc +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=dummy --use-guided-search=none --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" diff --git a/test/Solver/NoBitwuzla.c b/test/Solver/NoBitwuzla.c new file mode 100644 index 0000000000..a4a915a9d6 --- /dev/null +++ b/test/Solver/NoBitwuzla.c @@ -0,0 +1,10 @@ +// REQUIRES: not-bitwuzla +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: not %klee --output-dir=%t.klee-out --solver-backend=bitwuzla %t1.bc 2>&1 | FileCheck %s +// CHECK: Not compiled with Bitwuzla support +// CHECK: ERROR: Failed to create core solver + +int main(int argc, char **argv) { + return 0; +} diff --git a/test/Solver/ValidatingSolver.c b/test/Solver/ValidatingSolver.c index 86799a85f2..6af3496f82 100644 --- a/test/Solver/ValidatingSolver.c +++ b/test/Solver/ValidatingSolver.c @@ -1,8 +1,8 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --debug-validate-solver --debug-assignment-validating-solver %t1.bc +// RUN: %klee --output-dir=%t.klee-out --search=bfs --debug-validate-solver --debug-assignment-validating-solver --use-guided-search=none %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" -// CHECK: KLEE: done: completed paths = 15 +// CHECK: KLEE: done: completed paths = 18 // CHECK: KLEE: done: partially completed paths = 0 \ No newline at end of file diff --git a/test/Solver/Z3ConstantArray.c b/test/Solver/Z3ConstantArray.c index e0452e3106..419c67d124 100644 --- a/test/Solver/Z3ConstantArray.c +++ b/test/Solver/Z3ConstantArray.c @@ -9,14 +9,14 @@ #include "klee/klee.h" int main(int argc, char **argv) { - // CHECK-DAG: (assert (= (select constant11 #x00000000) #x67)) - // CHECK-DAG: (assert (= (select constant11 #x00000001) #x79)) - // CHECK-DAG: (assert (= (select constant11 #x00000002) #x7a)) - // CHECK-DAG: (assert (= (select constant11 #x00000003) #x00)) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv0 32) ) (_ bv103 8) ) ) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv1 32) ) (_ bv121 8) ) ) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv2 32) ) (_ bv122 8) ) ) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) + // CHECK-DAG: (assert (= (select constant01 #x00000000) #x67)) + // CHECK-DAG: (assert (= (select constant01 #x00000001) #x79)) + // CHECK-DAG: (assert (= (select constant01 #x00000002) #x7a)) + // CHECK-DAG: (assert (= (select constant01 #x00000003) #x00)) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv0 32) ) (_ bv103 8) ) ) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv1 32) ) (_ bv121 8) ) ) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv2 32) ) (_ bv122 8) ) ) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) char c[4] = {'g', 'y', 'z', '\0'}; unsigned i; klee_make_symbolic(&i, sizeof i, "i"); diff --git a/test/Solver/Z3LargeConstantArray.kquery b/test/Solver/Z3LargeConstantArray.kquery index d3ccf51e4a..898edd9e22 100644 --- a/test/Solver/Z3LargeConstantArray.kquery +++ b/test/Solver/Z3LargeConstantArray.kquery @@ -1,7 +1,7 @@ # REQUIRES: z3 # RUN: %kleaver --solver-backend=z3 -max-solver-time=20 -debug-z3-dump-queries=%t.smt2 %s &> /dev/null # RUN: grep '(assert (= (select constant0' %t.smt2 -c | grep 3770 -constant0 : (array (w64 3770) (constant [32 0 0 0 192 193 124 5 0 0 0 0 64 242 107 41 0 0 0 0 48 235 107 41 0 0 0 0 0 0 0 0 0 0 0 0 144 0 0 0 14 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 144 33 0 0 65 42 0 0 5 0 0 0 0 0 0 0 7 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 83 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 75 204 147 90 0 0 0 0 55 110 115 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 121 0 0 0 100 101 102 105 110 101 40 96 98 39 44 32 96 117 39 41 10 100 101 102 105 110 101 40 96 104 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 105 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 121 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 65 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 110 39 44 32 50 41 10 100 101 102 105 110 101 40 96 80 39 44 32 50 41 10 0 10 0 10 0 10 128 2 0 0 3 0 0 0 0 0 0 0 200 67 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 249 77 23 3 0 0 0 0 160 42 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 64 13 129 41 0 0 0 0 56 217 22 3 0 0 0 0 96 168 132 41 0 0 0 0 255 255 255 255 255 255 255 255 33 4 0 0 0 0 0 0 48 24 129 41 0 0 0 0 80 43 125 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 248 255 255 255 255 255 255 255 176 23 129 41 0 0 0 0 252 255 255 255 255 255 255 255 16 14 129 41 0 0 0 0 252 255 255 255 255 255 255 255 32 227 132 41 0 0 0 0 252 255 255 255 255 255 255 255 208 251 132 41 0 0 0 0 252 255 255 255 255 255 255 255 144 16 129 41 0 0 0 0 252 255 255 255 255 255 255 255 192 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 96 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 176 26 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 27 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 51 124 41 0 0 0 0 252 255 255 255 255 255 255 255 48 59 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 68 0 0 0 105 110 116 101 114 110 97 108 32 101 114 114 111 114 32 100 101 116 101 99 116 101 100 59 32 112 108 101 97 115 101 32 114 101 112 111 114 116 32 116 104 105 115 32 98 117 103 32 116 111 32 60 98 117 103 45 109 52 64 103 110 117 46 111 114 103 62 0 19 0 0 0 83 101 103 109 101 110 116 97 116 105 111 110 32 102 97 117 108 116 0 8 0 0 0 65 98 111 114 116 101 100 0 20 0 0 0 73 108 108 101 103 97 108 32 105 110 115 116 114 117 99 116 105 111 110 0 25 0 0 0 70 108 111 97 116 105 110 103 32 112 111 105 110 116 32 101 120 99 101 112 116 105 111 110 0 10 0 0 0 66 117 115 32 101 114 114 111 114 0 2 0 0 0 96 0 2 0 0 0 39 0 2 0 0 0 35 0 2 0 0 0 10 0 40 0 0 0 32 136 117 41 0 0 0 0 24 107 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 1 0 0 20 25 100 59 116 43 0 0 2 27 100 59 116 43 0 0 223 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 189 22 100 59 116 43 0 0 181 25 100 59 116 43 0 0 140 30 100 59 116 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 58 24 100 59 116 43 0 0 228 29 100 59 116 43 0 0 242 22 100 59 116 43 0 0 5 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 1 29 100 59 116 43 0 0 167 24 100 59 116 43 0 0 148 23 100 59 116 43 0 0 134 22 100 59 116 43 0 0 114 27 100 59 116 43 0 0 219 21 100 59 116 43 0 0 96 23 100 59 116 43 0 0 0 0 0 0 0 0 0 0 236 25 100 59 116 43 0 0 0 0 0 0 0 0 0 0 60 29 100 59 116 43 0 0 126 25 100 59 116 43 0 0 37 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 28 30 100 59 116 43 0 0 41 23 100 59 116 43 0 0 116 29 100 59 116 43 0 0 81 22 100 59 116 43 0 0 148 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 224 27 100 59 116 43 0 0 74 25 100 59 116 43 0 0 84 30 100 59 116 43 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 22 100 59 116 43 0 0 2 0 0 0 0 48 0 0 248 158 196 4 0 0 0 0 10 0 0 0 99 104 97 110 103 101 99 111 109 0 40 0 0 0 204 23 100 59 116 43 0 0 0 0 128 48 0 0 0 0 65 22 100 59 116 43 0 0 2 0 0 0 170 133 41 0 248 160 196 4 0 0 0 0 12 0 0 0 99 104 97 110 103 101 113 117 111 116 101 0 40 0 0 0 172 29 100 59 116 43 0 0 8 0 0 0 0 0 0 0 125 22 100 59 116 43 0 0 2 0 0 0 0 0 0 38 200 163 196 4 0 0 0 0 5 0 0 0 100 101 99 114 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 80 120 0 0 0 0 178 22 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 166 196 4 0 0 0 0 7 0 0 0 100 101 102 105 110 101 0 40 0 0 0 25 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 233 22 100 59 116 43 0 0 2 0 0 0 17 148 64 0 88 170 196 4 0 0 0 0 5 0 0 0 100 101 102 110 0 40 0 0 0 112 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 30 23 100 59 116 43 0 0 2 0 0 0 160 0 32 7 56 172 196 4 0 0 0 0 7 0 0 0 100 105 118 101 114 116 0 40 0 0 0 81 28 100 59 116 43 0 0 0 0 0 0 0 0 0 0 85 23 100 59 116 43 0 0 2 0 0 0 0 0 0 48 40 173 196 4 0 0 0 0 7 0 0 0 100 105 118 110 117 109 0 40 0 0 0 93 26 100 59 116 43 0 0 0 154 4 0 0 0 0 0 140 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 174 196 4 0 0 0 0 4 0 0 0 100 110 108 0 40 0 0 0 59 27 100 59 116 43 0 0 0 121 34 0 0 0 0 0 192 23 100 59 116 43 0 0 2 0 0 0 160 176 133 41 8 175 196 4 0 0 0 0 8 0 0 0 100 117 109 112 100 101 102 0 40 0 0 0 138 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 248 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 236 197 4 0 0 0 0 9 0 0 0 101 114 114 112 114 105 110 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 64 0 0 0 0 49 24 100 59 116 43 0 0 2 0 0 0 1 0 0 0 24 242 197 4 0 0 0 0 5 0 0 0 101 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 102 24 100 59 116 43 0 0 2 0 0 0 0 0 73 1 152 243 197 4 0 0 0 0 6 0 0 0 105 102 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 156 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 244 197 4 0 0 0 0 7 0 0 0 105 102 101 108 115 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 203 0 0 0 0 0 0 211 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 245 197 4 0 0 0 0 8 0 0 0 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 11 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 246 197 4 0 0 0 0 5 0 0 0 105 110 99 114 0 40 0 0 0 195 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 64 25 100 59 116 43 0 0 2 0 0 0 96 176 133 41 88 247 197 4 0 0 0 0 6 0 0 0 105 110 100 101 120 0 40 0 0 0 204 26 100 59 116 43 0 0 8 0 0 0 0 0 0 0 118 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 249 197 4 0 0 0 0 4 0 0 0 108 101 110 0 40 0 0 0 0 0 0 0 0 0 0 0 0 52 33 0 0 0 0 0 170 25 100 59 116 43 0 0 2 0 0 0 9 63 116 43 88 250 197 4 0 0 0 0 7 0 0 0 109 52 101 120 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 225 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 72 251 197 4 0 0 0 0 7 0 0 0 109 52 119 114 97 112 0 40 0 0 0 169 27 100 59 116 43 0 0 8 0 0 0 0 0 0 0 24 26 100 59 116 43 0 0 2 0 0 0 20 0 0 30 88 118 196 4 0 0 0 0 9 0 0 0 109 97 107 101 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 81 26 100 59 116 43 0 0 2 0 0 0 8 0 0 0 40 121 196 4 0 0 0 0 8 0 0 0 109 107 115 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 137 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 168 7 198 4 0 0 0 0 7 0 0 0 112 111 112 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 0 64 0 0 0 0 192 26 100 59 116 43 0 0 2 0 0 0 192 122 127 41 152 8 198 4 0 0 0 0 8 0 0 0 112 117 115 104 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 248 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 120 10 198 4 0 0 0 0 6 0 0 0 115 104 105 102 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 46 27 100 59 116 43 0 0 2 0 0 0 0 0 52 0 104 11 198 4 0 0 0 0 9 0 0 0 115 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 103 27 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 12 198 4 0 0 0 0 7 0 0 0 115 117 98 115 116 114 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 158 27 100 59 116 43 0 0 2 0 0 0 0 0 64 11 72 13 198 4 0 0 0 0 7 0 0 0 115 121 115 99 109 100 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 27 100 59 116 43 0 0 2 0 0 0 0 0 0 48 56 14 198 4 0 0 0 0 7 0 0 0 115 121 115 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 0 0 0 0 12 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 40 15 198 4 0 0 0 0 9 0 0 0 116 114 97 99 101 111 102 102 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 69 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 8 234 197 4 0 0 0 0 8 0 0 0 116 114 97 99 101 111 110 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 125 28 100 59 116 43 0 0 2 0 0 0 0 0 0 192 248 234 197 4 0 0 0 0 9 0 0 0 116 114 97 110 115 108 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 182 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 200 22 198 4 0 0 0 0 9 0 0 0 117 110 100 101 102 105 110 101 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 239 28 100 59 116 43 0 0 2 0 0 0 0 112 8 0 184 23 198 4 0 0 0 0 9 0 0 0 117 110 100 105 118 101 114 116 0 1 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 99 8 0 0 0 0 0 45 29 100 59 116 43 0 0 1 0 0 0 0 0 0 224 252 28 100 59 116 43 0 0 5 0 0 0 117 110 105 120 0 2 0 0 0 117 0 40 0 0 0 0 0 0 0 0 0 0 0 0 255 95 52 0 0 0 0 104 29 100 59 116 43 0 0 1 0 0 0 240 43 134 41 54 29 100 59 116 43 0 0 2 0 0 0 98 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 29 100 59 116 43 0 0 1 0 0 0 87 0 0 0 110 29 100 59 116 43 0 0 2 0 0 0 104 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 216 29 100 59 116 43 0 0 1 0 0 0 3 24 0 128 166 29 100 59 116 43 0 0 2 0 0 0 105 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 30 100 59 116 43 0 0 1 0 0 0 64 236 0 0 222 29 100 59 116 43 0 0 2 0 0 0 121 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 30 100 59 116 43 0 0 1 0 0 0 48 0 0 0 22 30 100 59 116 43 0 0 2 0 0 0 65 0 2 0 0 0 50 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 30 100 59 116 43 0 0 1 0 0 0 48 120 134 41 78 30 100 59 116 43 0 0 2 0 0 0 110 0 2 0 0 0 50 0 40 0 0 0 21 22 100 59 116 43 0 0 0 0 0 0 0 0 0 0 184 30 100 59 116 43 0 0 1 0 0 0 0 0 0 0 134 30 100 59 116 43 0 0 2 0 0 0 80 0])) +constant0 : (array (w64 3770) (constant [32 0 0 0 192 193 124 5 0 0 0 0 64 242 107 41 0 0 0 0 48 235 107 41 0 0 0 0 0 0 0 0 0 0 0 0 144 0 0 0 14 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 144 33 0 0 65 42 0 0 5 0 0 0 0 0 0 0 7 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 83 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 75 204 147 90 0 0 0 0 55 110 115 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 121 0 0 0 100 101 102 105 110 101 40 96 98 39 44 32 96 117 39 41 10 100 101 102 105 110 101 40 96 104 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 105 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 121 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 65 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 110 39 44 32 50 41 10 100 101 102 105 110 101 40 96 80 39 44 32 50 41 10 0 10 0 10 0 10 128 2 0 0 3 0 0 0 0 0 0 0 200 67 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 249 77 23 3 0 0 0 0 160 42 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 64 13 129 41 0 0 0 0 56 217 22 3 0 0 0 0 96 168 132 41 0 0 0 0 255 255 255 255 255 255 255 255 33 4 0 0 0 0 0 0 48 24 129 41 0 0 0 0 80 43 125 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 248 255 255 255 255 255 255 255 176 23 129 41 0 0 0 0 252 255 255 255 255 255 255 255 16 14 129 41 0 0 0 0 252 255 255 255 255 255 255 255 32 227 132 41 0 0 0 0 252 255 255 255 255 255 255 255 208 251 132 41 0 0 0 0 252 255 255 255 255 255 255 255 144 16 129 41 0 0 0 0 252 255 255 255 255 255 255 255 192 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 96 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 176 26 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 27 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 51 124 41 0 0 0 0 252 255 255 255 255 255 255 255 48 59 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 68 0 0 0 105 110 116 101 114 110 97 108 32 101 114 114 111 114 32 100 101 116 101 99 116 101 100 59 32 112 108 101 97 115 101 32 114 101 112 111 114 116 32 116 104 105 115 32 98 117 103 32 116 111 32 60 98 117 103 45 109 52 64 103 110 117 46 111 114 103 62 0 19 0 0 0 83 101 103 109 101 110 116 97 116 105 111 110 32 102 97 117 108 116 0 8 0 0 0 65 98 111 114 116 101 100 0 20 0 0 0 73 108 108 101 103 97 108 32 105 110 115 116 114 117 99 116 105 111 110 0 25 0 0 0 70 108 111 97 116 105 110 103 32 112 111 105 110 116 32 101 120 99 101 112 116 105 111 110 0 10 0 0 0 66 117 115 32 101 114 114 111 114 0 2 0 0 0 96 0 2 0 0 0 39 0 2 0 0 0 35 0 2 0 0 0 10 0 40 0 0 0 32 136 117 41 0 0 0 0 24 107 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 1 0 0 20 25 100 59 116 43 0 0 2 27 100 59 116 43 0 0 223 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 189 22 100 59 116 43 0 0 181 25 100 59 116 43 0 0 140 30 100 59 116 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 58 24 100 59 116 43 0 0 228 29 100 59 116 43 0 0 242 22 100 59 116 43 0 0 5 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 1 29 100 59 116 43 0 0 167 24 100 59 116 43 0 0 148 23 100 59 116 43 0 0 134 22 100 59 116 43 0 0 114 27 100 59 116 43 0 0 219 21 100 59 116 43 0 0 96 23 100 59 116 43 0 0 0 0 0 0 0 0 0 0 236 25 100 59 116 43 0 0 0 0 0 0 0 0 0 0 60 29 100 59 116 43 0 0 126 25 100 59 116 43 0 0 37 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 28 30 100 59 116 43 0 0 41 23 100 59 116 43 0 0 116 29 100 59 116 43 0 0 81 22 100 59 116 43 0 0 148 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 224 27 100 59 116 43 0 0 74 25 100 59 116 43 0 0 84 30 100 59 116 43 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 22 100 59 116 43 0 0 2 0 0 0 0 48 0 0 248 158 196 4 0 0 0 0 10 0 0 0 99 104 97 110 103 101 99 111 109 0 40 0 0 0 204 23 100 59 116 43 0 0 0 0 128 48 0 0 0 0 65 22 100 59 116 43 0 0 2 0 0 0 170 133 41 0 248 160 196 4 0 0 0 0 12 0 0 0 99 104 97 110 103 101 113 117 111 116 101 0 40 0 0 0 172 29 100 59 116 43 0 0 8 0 0 0 0 0 0 0 125 22 100 59 116 43 0 0 2 0 0 0 0 0 0 38 200 163 196 4 0 0 0 0 5 0 0 0 100 101 99 114 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 80 120 0 0 0 0 178 22 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 166 196 4 0 0 0 0 7 0 0 0 100 101 102 105 110 101 0 40 0 0 0 25 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 233 22 100 59 116 43 0 0 2 0 0 0 17 148 64 0 88 170 196 4 0 0 0 0 5 0 0 0 100 101 102 110 0 40 0 0 0 112 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 30 23 100 59 116 43 0 0 2 0 0 0 160 0 32 7 56 172 196 4 0 0 0 0 7 0 0 0 100 105 118 101 114 116 0 40 0 0 0 81 28 100 59 116 43 0 0 0 0 0 0 0 0 0 0 85 23 100 59 116 43 0 0 2 0 0 0 0 0 0 48 40 173 196 4 0 0 0 0 7 0 0 0 100 105 118 110 117 109 0 40 0 0 0 93 26 100 59 116 43 0 0 0 154 4 0 0 0 0 0 140 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 174 196 4 0 0 0 0 4 0 0 0 100 110 108 0 40 0 0 0 59 27 100 59 116 43 0 0 0 121 34 0 0 0 0 0 192 23 100 59 116 43 0 0 2 0 0 0 160 176 133 41 8 175 196 4 0 0 0 0 8 0 0 0 100 117 109 112 100 101 102 0 40 0 0 0 138 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 248 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 236 197 4 0 0 0 0 9 0 0 0 101 114 114 112 114 105 110 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 64 0 0 0 0 49 24 100 59 116 43 0 0 2 0 0 0 1 0 0 0 24 242 197 4 0 0 0 0 5 0 0 0 101 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 102 24 100 59 116 43 0 0 2 0 0 0 0 0 73 1 152 243 197 4 0 0 0 0 6 0 0 0 105 102 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 156 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 244 197 4 0 0 0 0 7 0 0 0 105 102 101 108 115 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 203 0 0 0 0 0 0 211 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 245 197 4 0 0 0 0 8 0 0 0 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 11 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 246 197 4 0 0 0 0 5 0 0 0 105 110 99 114 0 40 0 0 0 195 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 64 25 100 59 116 43 0 0 2 0 0 0 96 176 133 41 88 247 197 4 0 0 0 0 6 0 0 0 105 110 100 101 120 0 40 0 0 0 204 26 100 59 116 43 0 0 8 0 0 0 0 0 0 0 118 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 249 197 4 0 0 0 0 4 0 0 0 108 101 110 0 40 0 0 0 0 0 0 0 0 0 0 0 0 52 33 0 0 0 0 0 170 25 100 59 116 43 0 0 2 0 0 0 9 63 116 43 88 250 197 4 0 0 0 0 7 0 0 0 109 52 101 120 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 225 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 72 251 197 4 0 0 0 0 7 0 0 0 109 52 119 114 97 112 0 40 0 0 0 169 27 100 59 116 43 0 0 8 0 0 0 0 0 0 0 24 26 100 59 116 43 0 0 2 0 0 0 20 0 0 30 88 118 196 4 0 0 0 0 9 0 0 0 109 97 107 101 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 81 26 100 59 116 43 0 0 2 0 0 0 8 0 0 0 40 121 196 4 0 0 0 0 8 0 0 0 109 107 115 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 137 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 168 7 198 4 0 0 0 0 7 0 0 0 112 111 112 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 0 64 0 0 0 0 192 26 100 59 116 43 0 0 2 0 0 0 192 122 127 41 152 8 198 4 0 0 0 0 8 0 0 0 112 117 115 104 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 248 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 120 10 198 4 0 0 0 0 6 0 0 0 115 104 105 102 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 46 27 100 59 116 43 0 0 2 0 0 0 0 0 52 0 104 11 198 4 0 0 0 0 9 0 0 0 115 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 103 27 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 12 198 4 0 0 0 0 7 0 0 0 115 117 98 115 116 114 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 158 27 100 59 116 43 0 0 2 0 0 0 0 0 64 11 72 13 198 4 0 0 0 0 7 0 0 0 115 121 115 99 109 100 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 27 100 59 116 43 0 0 2 0 0 0 0 0 0 48 56 14 198 4 0 0 0 0 7 0 0 0 115 121 115 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 0 0 0 0 12 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 40 15 198 4 0 0 0 0 9 0 0 0 116 114 97 99 101 111 102 102 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 69 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 8 234 197 4 0 0 0 0 8 0 0 0 116 114 97 99 101 111 110 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 125 28 100 59 116 43 0 0 2 0 0 0 0 0 0 192 248 234 197 4 0 0 0 0 9 0 0 0 116 114 97 110 115 108 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 182 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 200 22 198 4 0 0 0 0 9 0 0 0 117 110 100 101 102 105 110 101 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 239 28 100 59 116 43 0 0 2 0 0 0 0 112 8 0 184 23 198 4 0 0 0 0 9 0 0 0 117 110 100 105 118 101 114 116 0 1 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 99 8 0 0 0 0 0 45 29 100 59 116 43 0 0 1 0 0 0 0 0 0 224 252 28 100 59 116 43 0 0 5 0 0 0 117 110 105 120 0 2 0 0 0 117 0 40 0 0 0 0 0 0 0 0 0 0 0 0 255 95 52 0 0 0 0 104 29 100 59 116 43 0 0 1 0 0 0 240 43 134 41 54 29 100 59 116 43 0 0 2 0 0 0 98 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 29 100 59 116 43 0 0 1 0 0 0 87 0 0 0 110 29 100 59 116 43 0 0 2 0 0 0 104 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 216 29 100 59 116 43 0 0 1 0 0 0 3 24 0 128 166 29 100 59 116 43 0 0 2 0 0 0 105 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 30 100 59 116 43 0 0 1 0 0 0 64 236 0 0 222 29 100 59 116 43 0 0 2 0 0 0 121 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 30 100 59 116 43 0 0 1 0 0 0 48 0 0 0 22 30 100 59 116 43 0 0 2 0 0 0 65 0 2 0 0 0 50 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 30 100 59 116 43 0 0 1 0 0 0 48 120 134 41 78 30 100 59 116 43 0 0 2 0 0 0 110 0 2 0 0 0 50 0 40 0 0 0 21 22 100 59 116 43 0 0 0 0 0 0 0 0 0 0 184 30 100 59 116 43 0 0 1 0 0 0 0 0 0 0 134 30 100 59 116 43 0 0 2 0 0 0 80 0] default: 0)) makeSymbolic1 : (array (w64 121) (makeSymbolic stdin 0)) diff --git a/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c b/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c new file mode 100644 index 0000000000..fb8ace55c5 --- /dev/null +++ b/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c @@ -0,0 +1,2775 @@ +// REQUIRES: z3 +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3-tree --max-solvers-approx-tree-inc=16 --optimize-aggressive=false --track-coverage=branches -max-memory=6008 --optimize --skip-not-lazy-initialized -output-source=false --output-stats=false --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error -dump-states-on-halt=all -exit-on-error-type=Assert --search=dfs -max-instructions=6000 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s +// CHECK-VERDICT: KLEE: done: total instructions = 6000 +#include "klee-test-comp.c" + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "pals_floodmax.5.2.ufo.BOUNDED-10.pals.c", 3, "reach_error"); } + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://github.com/sosy-lab/sv-benchmarks +// +// SPDX-FileCopyrightText: 2013 Carnegie Mellon University +// SPDX-FileCopyrightText: 2014-2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: LicenseRef-BSD-3-Clause-Attribution-CMU + +/* Generated by CIL v. 1.6.0 */ +/* print_CIL_Input is true */ + +char __VERIFIER_nondet_char(void); +_Bool __VERIFIER_nondet_bool(void); +void assert(_Bool arg); +void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +typedef char msg_t; +typedef int port_t; +extern void read(port_t p, msg_t m); +extern void write(port_t p, msg_t m); +msg_t nomsg = (msg_t)-1; +port_t p12; +char p12_old; +char p12_new; +_Bool ep12; +port_t p13; +char p13_old; +char p13_new; +_Bool ep13; +port_t p14; +char p14_old; +char p14_new; +_Bool ep14; +port_t p15; +char p15_old; +char p15_new; +_Bool ep15; +port_t p21; +char p21_old; +char p21_new; +_Bool ep21; +port_t p23; +char p23_old; +char p23_new; +_Bool ep23; +port_t p24; +char p24_old; +char p24_new; +_Bool ep24; +port_t p25; +char p25_old; +char p25_new; +_Bool ep25; +port_t p31; +char p31_old; +char p31_new; +_Bool ep31; +port_t p32; +char p32_old; +char p32_new; +_Bool ep32; +port_t p34; +char p34_old; +char p34_new; +_Bool ep34; +port_t p35; +char p35_old; +char p35_new; +_Bool ep35; +port_t p41; +char p41_old; +char p41_new; +_Bool ep41; +port_t p42; +char p42_old; +char p42_new; +_Bool ep42; +port_t p43; +char p43_old; +char p43_new; +_Bool ep43; +port_t p45; +char p45_old; +char p45_new; +_Bool ep45; +port_t p51; +char p51_old; +char p51_new; +_Bool ep51; +port_t p52; +char p52_old; +char p52_new; +_Bool ep52; +port_t p53; +char p53_old; +char p53_new; +_Bool ep53; +port_t p54; +char p54_old; +char p54_new; +_Bool ep54; +char id1; +char r1; +char st1; +char nl1; +char m1; +char max1; +_Bool mode1; +char id2; +char r2; +char st2; +char nl2; +char m2; +char max2; +_Bool mode2; +char id3; +char r3; +char st3; +char nl3; +char m3; +char max3; +_Bool mode3; +char id4; +char r4; +char st4; +char nl4; +char m4; +char max4; +_Bool mode4; +char id5; +char r5; +char st5; +char nl5; +char m5; +char max5; +_Bool mode5; +void node1(void) { + + { + if (mode1) { + r1 = (char)((int)r1 + 1); + if (ep21) { + m1 = p21_old; + p21_old = nomsg; + if ((int)m1 > (int)max1) { + max1 = m1; + } + } + if (ep31) { + m1 = p31_old; + p31_old = nomsg; + if ((int)m1 > (int)max1) { + max1 = m1; + } + } + if (ep41) { + m1 = p41_old; + p41_old = nomsg; + if ((int)m1 > (int)max1) { + max1 = m1; + } + } + if (ep51) { + m1 = p51_old; + p51_old = nomsg; + if ((int)m1 > (int)max1) { + max1 = m1; + } + } + if ((int)r1 == 3) { + if ((int)max1 == (int)id1) { + st1 = (char)1; + } else { + nl1 = (char)1; + } + } + mode1 = (_Bool)0; + } else { + if ((int)r1 < 4) { + if (ep12) { + p12_new = max1 != nomsg && p12_new == nomsg ? max1 : p12_new; + } + if (ep13) { + p13_new = max1 != nomsg && p13_new == nomsg ? max1 : p13_new; + } + if (ep14) { + p14_new = max1 != nomsg && p14_new == nomsg ? max1 : p14_new; + } + if (ep15) { + p15_new = max1 != nomsg && p15_new == nomsg ? max1 : p15_new; + } + } + mode1 = (_Bool)1; + } + return; + } +} +void node2(void) { + + { + if (mode2) { + r2 = (char)((int)r2 + 1); + if (ep12) { + m2 = p12_old; + p12_old = nomsg; + if ((int)m2 > (int)max2) { + max2 = m2; + } + } + if (ep32) { + m2 = p32_old; + p32_old = nomsg; + if ((int)m2 > (int)max2) { + max2 = m2; + } + } + if (ep42) { + m2 = p42_old; + p42_old = nomsg; + if ((int)m2 > (int)max2) { + max2 = m2; + } + } + if (ep52) { + m2 = p52_old; + p52_old = nomsg; + if ((int)m2 > (int)max2) { + max2 = m2; + } + } + if ((int)r2 == 4) { + if ((int)max2 == (int)id2) { + st2 = (char)1; + } else { + nl2 = (char)1; + } + } + mode2 = (_Bool)0; + } else { + if ((int)r2 < 4) { + if (ep21) { + p21_new = max2 != nomsg && p21_new == nomsg ? max2 : p21_new; + } + if (ep23) { + p23_new = max2 != nomsg && p23_new == nomsg ? max2 : p23_new; + } + if (ep24) { + p24_new = max2 != nomsg && p24_new == nomsg ? max2 : p24_new; + } + if (ep25) { + p25_new = max2 != nomsg && p25_new == nomsg ? max2 : p25_new; + } + } + mode2 = (_Bool)1; + } + return; + } +} +void node3(void) { + + { + if (mode3) { + r3 = (char)((int)r3 + 1); + if (ep13) { + m3 = p13_old; + p13_old = nomsg; + if ((int)m3 > (int)max3) { + max3 = m3; + } + } + if (ep23) { + m3 = p23_old; + p23_old = nomsg; + if ((int)m3 > (int)max3) { + max3 = m3; + } + } + if (ep43) { + m3 = p43_old; + p43_old = nomsg; + if ((int)m3 > (int)max3) { + max3 = m3; + } + } + if (ep53) { + m3 = p53_old; + p53_old = nomsg; + if ((int)m3 > (int)max3) { + max3 = m3; + } + } + if ((int)r3 == 4) { + if ((int)max3 == (int)id3) { + st3 = (char)1; + } else { + nl3 = (char)1; + } + } + mode3 = (_Bool)0; + } else { + if ((int)r3 < 4) { + if (ep31) { + p31_new = max3 != nomsg && p31_new == nomsg ? max3 : p31_new; + } + if (ep32) { + p32_new = max3 != nomsg && p32_new == nomsg ? max3 : p32_new; + } + if (ep34) { + p34_new = max3 != nomsg && p34_new == nomsg ? max3 : p34_new; + } + if (ep35) { + p35_new = max3 != nomsg && p35_new == nomsg ? max3 : p35_new; + } + } + mode3 = (_Bool)1; + } + return; + } +} +void node4(void) { + + { + if (mode4) { + r4 = (char)((int)r4 + 1); + if (ep14) { + m4 = p14_old; + p14_old = nomsg; + if ((int)m4 > (int)max4) { + max4 = m4; + } + } + if (ep24) { + m4 = p24_old; + p24_old = nomsg; + if ((int)m4 > (int)max4) { + max4 = m4; + } + } + if (ep34) { + m4 = p34_old; + p34_old = nomsg; + if ((int)m4 > (int)max4) { + max4 = m4; + } + } + if (ep54) { + m4 = p54_old; + p54_old = nomsg; + if ((int)m4 > (int)max4) { + max4 = m4; + } + } + if ((int)r4 == 4) { + if ((int)max4 == (int)id4) { + st4 = (char)1; + } else { + nl4 = (char)1; + } + } + mode4 = (_Bool)0; + } else { + if ((int)r4 < 4) { + if (ep41) { + p41_new = max4 != nomsg && p41_new == nomsg ? max4 : p41_new; + } + if (ep42) { + p42_new = max4 != nomsg && p42_new == nomsg ? max4 : p42_new; + } + if (ep43) { + p43_new = max4 != nomsg && p43_new == nomsg ? max4 : p43_new; + } + if (ep45) { + p45_new = max4 != nomsg && p45_new == nomsg ? max4 : p45_new; + } + } + mode4 = (_Bool)1; + } + return; + } +} +void node5(void) { + + { + if (mode5) { + r5 = (char)((int)r5 + 1); + if (ep15) { + m5 = p15_old; + p15_old = nomsg; + if ((int)m5 > (int)max5) { + max5 = m5; + } + } + if (ep25) { + m5 = p25_old; + p25_old = nomsg; + if ((int)m5 > (int)max5) { + max5 = m5; + } + } + if (ep35) { + m5 = p35_old; + p35_old = nomsg; + if ((int)m5 > (int)max5) { + max5 = m5; + } + } + if (ep45) { + m5 = p45_old; + p45_old = nomsg; + if ((int)m5 > (int)max5) { + max5 = m5; + } + } + if ((int)r5 == 4) { + if ((int)max5 == (int)id5) { + st5 = (char)1; + } else { + nl5 = (char)1; + } + } + mode5 = (_Bool)0; + } else { + if ((int)r5 < 4) { + if (ep51) { + p51_new = max5 != nomsg && p51_new == nomsg ? max5 : p51_new; + } + if (ep52) { + p52_new = max5 != nomsg && p52_new == nomsg ? max5 : p52_new; + } + if (ep53) { + p53_new = max5 != nomsg && p53_new == nomsg ? max5 : p53_new; + } + if (ep54) { + p54_new = max5 != nomsg && p54_new == nomsg ? max5 : p54_new; + } + } + mode5 = (_Bool)1; + } + return; + } +} +int init(void) { + _Bool r121; + _Bool r131; + _Bool r141; + _Bool r151; + _Bool r211; + _Bool r231; + _Bool r241; + _Bool r251; + _Bool r311; + _Bool r321; + _Bool r341; + _Bool r351; + _Bool r411; + _Bool r421; + _Bool r431; + _Bool r451; + _Bool r511; + _Bool r521; + _Bool r531; + _Bool r541; + _Bool r122; + int tmp; + _Bool r132; + int tmp___0; + _Bool r142; + int tmp___1; + _Bool r152; + int tmp___2; + _Bool r212; + int tmp___3; + _Bool r232; + int tmp___4; + _Bool r242; + int tmp___5; + _Bool r252; + int tmp___6; + _Bool r312; + int tmp___7; + _Bool r322; + int tmp___8; + _Bool r342; + int tmp___9; + _Bool r352; + int tmp___10; + _Bool r412; + int tmp___11; + _Bool r422; + int tmp___12; + _Bool r432; + int tmp___13; + _Bool r452; + int tmp___14; + _Bool r512; + int tmp___15; + _Bool r522; + int tmp___16; + _Bool r532; + int tmp___17; + _Bool r542; + int tmp___18; + _Bool r123; + int tmp___19; + _Bool r133; + int tmp___20; + _Bool r143; + int tmp___21; + _Bool r153; + int tmp___22; + _Bool r213; + int tmp___23; + _Bool r233; + int tmp___24; + _Bool r243; + int tmp___25; + _Bool r253; + int tmp___26; + _Bool r313; + int tmp___27; + _Bool r323; + int tmp___28; + _Bool r343; + int tmp___29; + _Bool r353; + int tmp___30; + _Bool r413; + int tmp___31; + _Bool r423; + int tmp___32; + _Bool r433; + int tmp___33; + _Bool r453; + int tmp___34; + _Bool r513; + int tmp___35; + _Bool r523; + int tmp___36; + _Bool r533; + int tmp___37; + _Bool r543; + int tmp___38; + _Bool r124; + int tmp___39; + _Bool r134; + int tmp___40; + _Bool r144; + int tmp___41; + _Bool r154; + int tmp___42; + _Bool r214; + int tmp___43; + _Bool r234; + int tmp___44; + _Bool r244; + int tmp___45; + _Bool r254; + int tmp___46; + _Bool r314; + int tmp___47; + _Bool r324; + int tmp___48; + _Bool r344; + int tmp___49; + _Bool r354; + int tmp___50; + _Bool r414; + int tmp___51; + _Bool r424; + int tmp___52; + _Bool r434; + int tmp___53; + _Bool r454; + int tmp___54; + _Bool r514; + int tmp___55; + _Bool r524; + int tmp___56; + _Bool r534; + int tmp___57; + _Bool r544; + int tmp___58; + int tmp___59; + + { + r121 = ep12; + r131 = ep13; + r141 = ep14; + r151 = ep15; + r211 = ep21; + r231 = ep23; + r241 = ep24; + r251 = ep25; + r311 = ep31; + r321 = ep32; + r341 = ep34; + r351 = ep35; + r411 = ep41; + r421 = ep42; + r431 = ep43; + r451 = ep45; + r511 = ep51; + r521 = ep52; + r531 = ep53; + r541 = ep54; + if (r121) { + tmp = 1; + } else if (r131) { + if (ep32) { + tmp = 1; + } else { + goto _L___0; + } + } else + _L___0: /* CIL Label */ + if (r141) { + if (ep42) { + tmp = 1; + } else { + goto _L; + } + } else + _L: /* CIL Label */ + if (r151) { + if (ep52) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + r122 = (_Bool)tmp; + if (r131) { + tmp___0 = 1; + } else if (r121) { + if (ep23) { + tmp___0 = 1; + } else { + goto _L___2; + } + } else + _L___2: /* CIL Label */ + if (r141) { + if (ep43) { + tmp___0 = 1; + } else { + goto _L___1; + } + } else + _L___1: /* CIL Label */ + if (r151) { + if (ep53) { + tmp___0 = 1; + } else { + tmp___0 = 0; + } + } else { + tmp___0 = 0; + } + r132 = (_Bool)tmp___0; + if (r141) { + tmp___1 = 1; + } else if (r121) { + if (ep24) { + tmp___1 = 1; + } else { + goto _L___4; + } + } else + _L___4: /* CIL Label */ + if (r131) { + if (ep34) { + tmp___1 = 1; + } else { + goto _L___3; + } + } else + _L___3: /* CIL Label */ + if (r151) { + if (ep54) { + tmp___1 = 1; + } else { + tmp___1 = 0; + } + } else { + tmp___1 = 0; + } + r142 = (_Bool)tmp___1; + if (r151) { + tmp___2 = 1; + } else if (r121) { + if (ep25) { + tmp___2 = 1; + } else { + goto _L___6; + } + } else + _L___6: /* CIL Label */ + if (r131) { + if (ep35) { + tmp___2 = 1; + } else { + goto _L___5; + } + } else + _L___5: /* CIL Label */ + if (r141) { + if (ep45) { + tmp___2 = 1; + } else { + tmp___2 = 0; + } + } else { + tmp___2 = 0; + } + r152 = (_Bool)tmp___2; + if (r211) { + tmp___3 = 1; + } else if (r231) { + if (ep31) { + tmp___3 = 1; + } else { + goto _L___8; + } + } else + _L___8: /* CIL Label */ + if (r241) { + if (ep41) { + tmp___3 = 1; + } else { + goto _L___7; + } + } else + _L___7: /* CIL Label */ + if (r251) { + if (ep51) { + tmp___3 = 1; + } else { + tmp___3 = 0; + } + } else { + tmp___3 = 0; + } + r212 = (_Bool)tmp___3; + if (r231) { + tmp___4 = 1; + } else if (r211) { + if (ep13) { + tmp___4 = 1; + } else { + goto _L___10; + } + } else + _L___10: /* CIL Label */ + if (r241) { + if (ep43) { + tmp___4 = 1; + } else { + goto _L___9; + } + } else + _L___9: /* CIL Label */ + if (r251) { + if (ep53) { + tmp___4 = 1; + } else { + tmp___4 = 0; + } + } else { + tmp___4 = 0; + } + r232 = (_Bool)tmp___4; + if (r241) { + tmp___5 = 1; + } else if (r211) { + if (ep14) { + tmp___5 = 1; + } else { + goto _L___12; + } + } else + _L___12: /* CIL Label */ + if (r231) { + if (ep34) { + tmp___5 = 1; + } else { + goto _L___11; + } + } else + _L___11: /* CIL Label */ + if (r251) { + if (ep54) { + tmp___5 = 1; + } else { + tmp___5 = 0; + } + } else { + tmp___5 = 0; + } + r242 = (_Bool)tmp___5; + if (r251) { + tmp___6 = 1; + } else if (r211) { + if (ep15) { + tmp___6 = 1; + } else { + goto _L___14; + } + } else + _L___14: /* CIL Label */ + if (r231) { + if (ep35) { + tmp___6 = 1; + } else { + goto _L___13; + } + } else + _L___13: /* CIL Label */ + if (r241) { + if (ep45) { + tmp___6 = 1; + } else { + tmp___6 = 0; + } + } else { + tmp___6 = 0; + } + r252 = (_Bool)tmp___6; + if (r311) { + tmp___7 = 1; + } else if (r321) { + if (ep21) { + tmp___7 = 1; + } else { + goto _L___16; + } + } else + _L___16: /* CIL Label */ + if (r341) { + if (ep41) { + tmp___7 = 1; + } else { + goto _L___15; + } + } else + _L___15: /* CIL Label */ + if (r351) { + if (ep51) { + tmp___7 = 1; + } else { + tmp___7 = 0; + } + } else { + tmp___7 = 0; + } + r312 = (_Bool)tmp___7; + if (r321) { + tmp___8 = 1; + } else if (r311) { + if (ep12) { + tmp___8 = 1; + } else { + goto _L___18; + } + } else + _L___18: /* CIL Label */ + if (r341) { + if (ep42) { + tmp___8 = 1; + } else { + goto _L___17; + } + } else + _L___17: /* CIL Label */ + if (r351) { + if (ep52) { + tmp___8 = 1; + } else { + tmp___8 = 0; + } + } else { + tmp___8 = 0; + } + r322 = (_Bool)tmp___8; + if (r341) { + tmp___9 = 1; + } else if (r311) { + if (ep14) { + tmp___9 = 1; + } else { + goto _L___20; + } + } else + _L___20: /* CIL Label */ + if (r321) { + if (ep24) { + tmp___9 = 1; + } else { + goto _L___19; + } + } else + _L___19: /* CIL Label */ + if (r351) { + if (ep54) { + tmp___9 = 1; + } else { + tmp___9 = 0; + } + } else { + tmp___9 = 0; + } + r342 = (_Bool)tmp___9; + if (r351) { + tmp___10 = 1; + } else if (r311) { + if (ep15) { + tmp___10 = 1; + } else { + goto _L___22; + } + } else + _L___22: /* CIL Label */ + if (r321) { + if (ep25) { + tmp___10 = 1; + } else { + goto _L___21; + } + } else + _L___21: /* CIL Label */ + if (r341) { + if (ep45) { + tmp___10 = 1; + } else { + tmp___10 = 0; + } + } else { + tmp___10 = 0; + } + r352 = (_Bool)tmp___10; + if (r411) { + tmp___11 = 1; + } else if (r421) { + if (ep21) { + tmp___11 = 1; + } else { + goto _L___24; + } + } else + _L___24: /* CIL Label */ + if (r431) { + if (ep31) { + tmp___11 = 1; + } else { + goto _L___23; + } + } else + _L___23: /* CIL Label */ + if (r451) { + if (ep51) { + tmp___11 = 1; + } else { + tmp___11 = 0; + } + } else { + tmp___11 = 0; + } + r412 = (_Bool)tmp___11; + if (r421) { + tmp___12 = 1; + } else if (r411) { + if (ep12) { + tmp___12 = 1; + } else { + goto _L___26; + } + } else + _L___26: /* CIL Label */ + if (r431) { + if (ep32) { + tmp___12 = 1; + } else { + goto _L___25; + } + } else + _L___25: /* CIL Label */ + if (r451) { + if (ep52) { + tmp___12 = 1; + } else { + tmp___12 = 0; + } + } else { + tmp___12 = 0; + } + r422 = (_Bool)tmp___12; + if (r431) { + tmp___13 = 1; + } else if (r411) { + if (ep13) { + tmp___13 = 1; + } else { + goto _L___28; + } + } else + _L___28: /* CIL Label */ + if (r421) { + if (ep23) { + tmp___13 = 1; + } else { + goto _L___27; + } + } else + _L___27: /* CIL Label */ + if (r451) { + if (ep53) { + tmp___13 = 1; + } else { + tmp___13 = 0; + } + } else { + tmp___13 = 0; + } + r432 = (_Bool)tmp___13; + if (r451) { + tmp___14 = 1; + } else if (r411) { + if (ep15) { + tmp___14 = 1; + } else { + goto _L___30; + } + } else + _L___30: /* CIL Label */ + if (r421) { + if (ep25) { + tmp___14 = 1; + } else { + goto _L___29; + } + } else + _L___29: /* CIL Label */ + if (r431) { + if (ep35) { + tmp___14 = 1; + } else { + tmp___14 = 0; + } + } else { + tmp___14 = 0; + } + r452 = (_Bool)tmp___14; + if (r511) { + tmp___15 = 1; + } else if (r521) { + if (ep21) { + tmp___15 = 1; + } else { + goto _L___32; + } + } else + _L___32: /* CIL Label */ + if (r531) { + if (ep31) { + tmp___15 = 1; + } else { + goto _L___31; + } + } else + _L___31: /* CIL Label */ + if (r541) { + if (ep41) { + tmp___15 = 1; + } else { + tmp___15 = 0; + } + } else { + tmp___15 = 0; + } + r512 = (_Bool)tmp___15; + if (r521) { + tmp___16 = 1; + } else if (r511) { + if (ep12) { + tmp___16 = 1; + } else { + goto _L___34; + } + } else + _L___34: /* CIL Label */ + if (r531) { + if (ep32) { + tmp___16 = 1; + } else { + goto _L___33; + } + } else + _L___33: /* CIL Label */ + if (r541) { + if (ep42) { + tmp___16 = 1; + } else { + tmp___16 = 0; + } + } else { + tmp___16 = 0; + } + r522 = (_Bool)tmp___16; + if (r531) { + tmp___17 = 1; + } else if (r511) { + if (ep13) { + tmp___17 = 1; + } else { + goto _L___36; + } + } else + _L___36: /* CIL Label */ + if (r521) { + if (ep23) { + tmp___17 = 1; + } else { + goto _L___35; + } + } else + _L___35: /* CIL Label */ + if (r541) { + if (ep43) { + tmp___17 = 1; + } else { + tmp___17 = 0; + } + } else { + tmp___17 = 0; + } + r532 = (_Bool)tmp___17; + if (r541) { + tmp___18 = 1; + } else if (r511) { + if (ep14) { + tmp___18 = 1; + } else { + goto _L___38; + } + } else + _L___38: /* CIL Label */ + if (r521) { + if (ep24) { + tmp___18 = 1; + } else { + goto _L___37; + } + } else + _L___37: /* CIL Label */ + if (r531) { + if (ep34) { + tmp___18 = 1; + } else { + tmp___18 = 0; + } + } else { + tmp___18 = 0; + } + r542 = (_Bool)tmp___18; + if (r122) { + tmp___19 = 1; + } else if (r132) { + if (ep32) { + tmp___19 = 1; + } else { + goto _L___40; + } + } else + _L___40: /* CIL Label */ + if (r142) { + if (ep42) { + tmp___19 = 1; + } else { + goto _L___39; + } + } else + _L___39: /* CIL Label */ + if (r152) { + if (ep52) { + tmp___19 = 1; + } else { + tmp___19 = 0; + } + } else { + tmp___19 = 0; + } + r123 = (_Bool)tmp___19; + if (r132) { + tmp___20 = 1; + } else if (r122) { + if (ep23) { + tmp___20 = 1; + } else { + goto _L___42; + } + } else + _L___42: /* CIL Label */ + if (r142) { + if (ep43) { + tmp___20 = 1; + } else { + goto _L___41; + } + } else + _L___41: /* CIL Label */ + if (r152) { + if (ep53) { + tmp___20 = 1; + } else { + tmp___20 = 0; + } + } else { + tmp___20 = 0; + } + r133 = (_Bool)tmp___20; + if (r142) { + tmp___21 = 1; + } else if (r122) { + if (ep24) { + tmp___21 = 1; + } else { + goto _L___44; + } + } else + _L___44: /* CIL Label */ + if (r132) { + if (ep34) { + tmp___21 = 1; + } else { + goto _L___43; + } + } else + _L___43: /* CIL Label */ + if (r152) { + if (ep54) { + tmp___21 = 1; + } else { + tmp___21 = 0; + } + } else { + tmp___21 = 0; + } + r143 = (_Bool)tmp___21; + if (r152) { + tmp___22 = 1; + } else if (r122) { + if (ep25) { + tmp___22 = 1; + } else { + goto _L___46; + } + } else + _L___46: /* CIL Label */ + if (r132) { + if (ep35) { + tmp___22 = 1; + } else { + goto _L___45; + } + } else + _L___45: /* CIL Label */ + if (r142) { + if (ep45) { + tmp___22 = 1; + } else { + tmp___22 = 0; + } + } else { + tmp___22 = 0; + } + r153 = (_Bool)tmp___22; + if (r212) { + tmp___23 = 1; + } else if (r232) { + if (ep31) { + tmp___23 = 1; + } else { + goto _L___48; + } + } else + _L___48: /* CIL Label */ + if (r242) { + if (ep41) { + tmp___23 = 1; + } else { + goto _L___47; + } + } else + _L___47: /* CIL Label */ + if (r252) { + if (ep51) { + tmp___23 = 1; + } else { + tmp___23 = 0; + } + } else { + tmp___23 = 0; + } + r213 = (_Bool)tmp___23; + if (r232) { + tmp___24 = 1; + } else if (r212) { + if (ep13) { + tmp___24 = 1; + } else { + goto _L___50; + } + } else + _L___50: /* CIL Label */ + if (r242) { + if (ep43) { + tmp___24 = 1; + } else { + goto _L___49; + } + } else + _L___49: /* CIL Label */ + if (r252) { + if (ep53) { + tmp___24 = 1; + } else { + tmp___24 = 0; + } + } else { + tmp___24 = 0; + } + r233 = (_Bool)tmp___24; + if (r242) { + tmp___25 = 1; + } else if (r212) { + if (ep14) { + tmp___25 = 1; + } else { + goto _L___52; + } + } else + _L___52: /* CIL Label */ + if (r232) { + if (ep34) { + tmp___25 = 1; + } else { + goto _L___51; + } + } else + _L___51: /* CIL Label */ + if (r252) { + if (ep54) { + tmp___25 = 1; + } else { + tmp___25 = 0; + } + } else { + tmp___25 = 0; + } + r243 = (_Bool)tmp___25; + if (r252) { + tmp___26 = 1; + } else if (r212) { + if (ep15) { + tmp___26 = 1; + } else { + goto _L___54; + } + } else + _L___54: /* CIL Label */ + if (r232) { + if (ep35) { + tmp___26 = 1; + } else { + goto _L___53; + } + } else + _L___53: /* CIL Label */ + if (r242) { + if (ep45) { + tmp___26 = 1; + } else { + tmp___26 = 0; + } + } else { + tmp___26 = 0; + } + r253 = (_Bool)tmp___26; + if (r312) { + tmp___27 = 1; + } else if (r322) { + if (ep21) { + tmp___27 = 1; + } else { + goto _L___56; + } + } else + _L___56: /* CIL Label */ + if (r342) { + if (ep41) { + tmp___27 = 1; + } else { + goto _L___55; + } + } else + _L___55: /* CIL Label */ + if (r352) { + if (ep51) { + tmp___27 = 1; + } else { + tmp___27 = 0; + } + } else { + tmp___27 = 0; + } + r313 = (_Bool)tmp___27; + if (r322) { + tmp___28 = 1; + } else if (r312) { + if (ep12) { + tmp___28 = 1; + } else { + goto _L___58; + } + } else + _L___58: /* CIL Label */ + if (r342) { + if (ep42) { + tmp___28 = 1; + } else { + goto _L___57; + } + } else + _L___57: /* CIL Label */ + if (r352) { + if (ep52) { + tmp___28 = 1; + } else { + tmp___28 = 0; + } + } else { + tmp___28 = 0; + } + r323 = (_Bool)tmp___28; + if (r342) { + tmp___29 = 1; + } else if (r312) { + if (ep14) { + tmp___29 = 1; + } else { + goto _L___60; + } + } else + _L___60: /* CIL Label */ + if (r322) { + if (ep24) { + tmp___29 = 1; + } else { + goto _L___59; + } + } else + _L___59: /* CIL Label */ + if (r352) { + if (ep54) { + tmp___29 = 1; + } else { + tmp___29 = 0; + } + } else { + tmp___29 = 0; + } + r343 = (_Bool)tmp___29; + if (r352) { + tmp___30 = 1; + } else if (r312) { + if (ep15) { + tmp___30 = 1; + } else { + goto _L___62; + } + } else + _L___62: /* CIL Label */ + if (r322) { + if (ep25) { + tmp___30 = 1; + } else { + goto _L___61; + } + } else + _L___61: /* CIL Label */ + if (r342) { + if (ep45) { + tmp___30 = 1; + } else { + tmp___30 = 0; + } + } else { + tmp___30 = 0; + } + r353 = (_Bool)tmp___30; + if (r412) { + tmp___31 = 1; + } else if (r422) { + if (ep21) { + tmp___31 = 1; + } else { + goto _L___64; + } + } else + _L___64: /* CIL Label */ + if (r432) { + if (ep31) { + tmp___31 = 1; + } else { + goto _L___63; + } + } else + _L___63: /* CIL Label */ + if (r452) { + if (ep51) { + tmp___31 = 1; + } else { + tmp___31 = 0; + } + } else { + tmp___31 = 0; + } + r413 = (_Bool)tmp___31; + if (r422) { + tmp___32 = 1; + } else if (r412) { + if (ep12) { + tmp___32 = 1; + } else { + goto _L___66; + } + } else + _L___66: /* CIL Label */ + if (r432) { + if (ep32) { + tmp___32 = 1; + } else { + goto _L___65; + } + } else + _L___65: /* CIL Label */ + if (r452) { + if (ep52) { + tmp___32 = 1; + } else { + tmp___32 = 0; + } + } else { + tmp___32 = 0; + } + r423 = (_Bool)tmp___32; + if (r432) { + tmp___33 = 1; + } else if (r412) { + if (ep13) { + tmp___33 = 1; + } else { + goto _L___68; + } + } else + _L___68: /* CIL Label */ + if (r422) { + if (ep23) { + tmp___33 = 1; + } else { + goto _L___67; + } + } else + _L___67: /* CIL Label */ + if (r452) { + if (ep53) { + tmp___33 = 1; + } else { + tmp___33 = 0; + } + } else { + tmp___33 = 0; + } + r433 = (_Bool)tmp___33; + if (r452) { + tmp___34 = 1; + } else if (r412) { + if (ep15) { + tmp___34 = 1; + } else { + goto _L___70; + } + } else + _L___70: /* CIL Label */ + if (r422) { + if (ep25) { + tmp___34 = 1; + } else { + goto _L___69; + } + } else + _L___69: /* CIL Label */ + if (r432) { + if (ep35) { + tmp___34 = 1; + } else { + tmp___34 = 0; + } + } else { + tmp___34 = 0; + } + r453 = (_Bool)tmp___34; + if (r512) { + tmp___35 = 1; + } else if (r522) { + if (ep21) { + tmp___35 = 1; + } else { + goto _L___72; + } + } else + _L___72: /* CIL Label */ + if (r532) { + if (ep31) { + tmp___35 = 1; + } else { + goto _L___71; + } + } else + _L___71: /* CIL Label */ + if (r542) { + if (ep41) { + tmp___35 = 1; + } else { + tmp___35 = 0; + } + } else { + tmp___35 = 0; + } + r513 = (_Bool)tmp___35; + if (r522) { + tmp___36 = 1; + } else if (r512) { + if (ep12) { + tmp___36 = 1; + } else { + goto _L___74; + } + } else + _L___74: /* CIL Label */ + if (r532) { + if (ep32) { + tmp___36 = 1; + } else { + goto _L___73; + } + } else + _L___73: /* CIL Label */ + if (r542) { + if (ep42) { + tmp___36 = 1; + } else { + tmp___36 = 0; + } + } else { + tmp___36 = 0; + } + r523 = (_Bool)tmp___36; + if (r532) { + tmp___37 = 1; + } else if (r512) { + if (ep13) { + tmp___37 = 1; + } else { + goto _L___76; + } + } else + _L___76: /* CIL Label */ + if (r522) { + if (ep23) { + tmp___37 = 1; + } else { + goto _L___75; + } + } else + _L___75: /* CIL Label */ + if (r542) { + if (ep43) { + tmp___37 = 1; + } else { + tmp___37 = 0; + } + } else { + tmp___37 = 0; + } + r533 = (_Bool)tmp___37; + if (r542) { + tmp___38 = 1; + } else if (r512) { + if (ep14) { + tmp___38 = 1; + } else { + goto _L___78; + } + } else + _L___78: /* CIL Label */ + if (r522) { + if (ep24) { + tmp___38 = 1; + } else { + goto _L___77; + } + } else + _L___77: /* CIL Label */ + if (r532) { + if (ep34) { + tmp___38 = 1; + } else { + tmp___38 = 0; + } + } else { + tmp___38 = 0; + } + r543 = (_Bool)tmp___38; + if (r123) { + tmp___39 = 1; + } else if (r133) { + if (ep32) { + tmp___39 = 1; + } else { + goto _L___80; + } + } else + _L___80: /* CIL Label */ + if (r143) { + if (ep42) { + tmp___39 = 1; + } else { + goto _L___79; + } + } else + _L___79: /* CIL Label */ + if (r153) { + if (ep52) { + tmp___39 = 1; + } else { + tmp___39 = 0; + } + } else { + tmp___39 = 0; + } + r124 = (_Bool)tmp___39; + if (r133) { + tmp___40 = 1; + } else if (r123) { + if (ep23) { + tmp___40 = 1; + } else { + goto _L___82; + } + } else + _L___82: /* CIL Label */ + if (r143) { + if (ep43) { + tmp___40 = 1; + } else { + goto _L___81; + } + } else + _L___81: /* CIL Label */ + if (r153) { + if (ep53) { + tmp___40 = 1; + } else { + tmp___40 = 0; + } + } else { + tmp___40 = 0; + } + r134 = (_Bool)tmp___40; + if (r143) { + tmp___41 = 1; + } else if (r123) { + if (ep24) { + tmp___41 = 1; + } else { + goto _L___84; + } + } else + _L___84: /* CIL Label */ + if (r133) { + if (ep34) { + tmp___41 = 1; + } else { + goto _L___83; + } + } else + _L___83: /* CIL Label */ + if (r153) { + if (ep54) { + tmp___41 = 1; + } else { + tmp___41 = 0; + } + } else { + tmp___41 = 0; + } + r144 = (_Bool)tmp___41; + if (r153) { + tmp___42 = 1; + } else if (r123) { + if (ep25) { + tmp___42 = 1; + } else { + goto _L___86; + } + } else + _L___86: /* CIL Label */ + if (r133) { + if (ep35) { + tmp___42 = 1; + } else { + goto _L___85; + } + } else + _L___85: /* CIL Label */ + if (r143) { + if (ep45) { + tmp___42 = 1; + } else { + tmp___42 = 0; + } + } else { + tmp___42 = 0; + } + r154 = (_Bool)tmp___42; + if (r213) { + tmp___43 = 1; + } else if (r233) { + if (ep31) { + tmp___43 = 1; + } else { + goto _L___88; + } + } else + _L___88: /* CIL Label */ + if (r243) { + if (ep41) { + tmp___43 = 1; + } else { + goto _L___87; + } + } else + _L___87: /* CIL Label */ + if (r253) { + if (ep51) { + tmp___43 = 1; + } else { + tmp___43 = 0; + } + } else { + tmp___43 = 0; + } + r214 = (_Bool)tmp___43; + if (r233) { + tmp___44 = 1; + } else if (r213) { + if (ep13) { + tmp___44 = 1; + } else { + goto _L___90; + } + } else + _L___90: /* CIL Label */ + if (r243) { + if (ep43) { + tmp___44 = 1; + } else { + goto _L___89; + } + } else + _L___89: /* CIL Label */ + if (r253) { + if (ep53) { + tmp___44 = 1; + } else { + tmp___44 = 0; + } + } else { + tmp___44 = 0; + } + r234 = (_Bool)tmp___44; + if (r243) { + tmp___45 = 1; + } else if (r213) { + if (ep14) { + tmp___45 = 1; + } else { + goto _L___92; + } + } else + _L___92: /* CIL Label */ + if (r233) { + if (ep34) { + tmp___45 = 1; + } else { + goto _L___91; + } + } else + _L___91: /* CIL Label */ + if (r253) { + if (ep54) { + tmp___45 = 1; + } else { + tmp___45 = 0; + } + } else { + tmp___45 = 0; + } + r244 = (_Bool)tmp___45; + if (r253) { + tmp___46 = 1; + } else if (r213) { + if (ep15) { + tmp___46 = 1; + } else { + goto _L___94; + } + } else + _L___94: /* CIL Label */ + if (r233) { + if (ep35) { + tmp___46 = 1; + } else { + goto _L___93; + } + } else + _L___93: /* CIL Label */ + if (r243) { + if (ep45) { + tmp___46 = 1; + } else { + tmp___46 = 0; + } + } else { + tmp___46 = 0; + } + r254 = (_Bool)tmp___46; + if (r313) { + tmp___47 = 1; + } else if (r323) { + if (ep21) { + tmp___47 = 1; + } else { + goto _L___96; + } + } else + _L___96: /* CIL Label */ + if (r343) { + if (ep41) { + tmp___47 = 1; + } else { + goto _L___95; + } + } else + _L___95: /* CIL Label */ + if (r353) { + if (ep51) { + tmp___47 = 1; + } else { + tmp___47 = 0; + } + } else { + tmp___47 = 0; + } + r314 = (_Bool)tmp___47; + if (r323) { + tmp___48 = 1; + } else if (r313) { + if (ep12) { + tmp___48 = 1; + } else { + goto _L___98; + } + } else + _L___98: /* CIL Label */ + if (r343) { + if (ep42) { + tmp___48 = 1; + } else { + goto _L___97; + } + } else + _L___97: /* CIL Label */ + if (r353) { + if (ep52) { + tmp___48 = 1; + } else { + tmp___48 = 0; + } + } else { + tmp___48 = 0; + } + r324 = (_Bool)tmp___48; + if (r343) { + tmp___49 = 1; + } else if (r313) { + if (ep14) { + tmp___49 = 1; + } else { + goto _L___100; + } + } else + _L___100: /* CIL Label */ + if (r323) { + if (ep24) { + tmp___49 = 1; + } else { + goto _L___99; + } + } else + _L___99: /* CIL Label */ + if (r353) { + if (ep54) { + tmp___49 = 1; + } else { + tmp___49 = 0; + } + } else { + tmp___49 = 0; + } + r344 = (_Bool)tmp___49; + if (r353) { + tmp___50 = 1; + } else if (r313) { + if (ep15) { + tmp___50 = 1; + } else { + goto _L___102; + } + } else + _L___102: /* CIL Label */ + if (r323) { + if (ep25) { + tmp___50 = 1; + } else { + goto _L___101; + } + } else + _L___101: /* CIL Label */ + if (r343) { + if (ep45) { + tmp___50 = 1; + } else { + tmp___50 = 0; + } + } else { + tmp___50 = 0; + } + r354 = (_Bool)tmp___50; + if (r413) { + tmp___51 = 1; + } else if (r423) { + if (ep21) { + tmp___51 = 1; + } else { + goto _L___104; + } + } else + _L___104: /* CIL Label */ + if (r433) { + if (ep31) { + tmp___51 = 1; + } else { + goto _L___103; + } + } else + _L___103: /* CIL Label */ + if (r453) { + if (ep51) { + tmp___51 = 1; + } else { + tmp___51 = 0; + } + } else { + tmp___51 = 0; + } + r414 = (_Bool)tmp___51; + if (r423) { + tmp___52 = 1; + } else if (r413) { + if (ep12) { + tmp___52 = 1; + } else { + goto _L___106; + } + } else + _L___106: /* CIL Label */ + if (r433) { + if (ep32) { + tmp___52 = 1; + } else { + goto _L___105; + } + } else + _L___105: /* CIL Label */ + if (r453) { + if (ep52) { + tmp___52 = 1; + } else { + tmp___52 = 0; + } + } else { + tmp___52 = 0; + } + r424 = (_Bool)tmp___52; + if (r433) { + tmp___53 = 1; + } else if (r413) { + if (ep13) { + tmp___53 = 1; + } else { + goto _L___108; + } + } else + _L___108: /* CIL Label */ + if (r423) { + if (ep23) { + tmp___53 = 1; + } else { + goto _L___107; + } + } else + _L___107: /* CIL Label */ + if (r453) { + if (ep53) { + tmp___53 = 1; + } else { + tmp___53 = 0; + } + } else { + tmp___53 = 0; + } + r434 = (_Bool)tmp___53; + if (r453) { + tmp___54 = 1; + } else if (r413) { + if (ep15) { + tmp___54 = 1; + } else { + goto _L___110; + } + } else + _L___110: /* CIL Label */ + if (r423) { + if (ep25) { + tmp___54 = 1; + } else { + goto _L___109; + } + } else + _L___109: /* CIL Label */ + if (r433) { + if (ep35) { + tmp___54 = 1; + } else { + tmp___54 = 0; + } + } else { + tmp___54 = 0; + } + r454 = (_Bool)tmp___54; + if (r513) { + tmp___55 = 1; + } else if (r523) { + if (ep21) { + tmp___55 = 1; + } else { + goto _L___112; + } + } else + _L___112: /* CIL Label */ + if (r533) { + if (ep31) { + tmp___55 = 1; + } else { + goto _L___111; + } + } else + _L___111: /* CIL Label */ + if (r543) { + if (ep41) { + tmp___55 = 1; + } else { + tmp___55 = 0; + } + } else { + tmp___55 = 0; + } + r514 = (_Bool)tmp___55; + if (r523) { + tmp___56 = 1; + } else if (r513) { + if (ep12) { + tmp___56 = 1; + } else { + goto _L___114; + } + } else + _L___114: /* CIL Label */ + if (r533) { + if (ep32) { + tmp___56 = 1; + } else { + goto _L___113; + } + } else + _L___113: /* CIL Label */ + if (r543) { + if (ep42) { + tmp___56 = 1; + } else { + tmp___56 = 0; + } + } else { + tmp___56 = 0; + } + r524 = (_Bool)tmp___56; + if (r533) { + tmp___57 = 1; + } else if (r513) { + if (ep13) { + tmp___57 = 1; + } else { + goto _L___116; + } + } else + _L___116: /* CIL Label */ + if (r523) { + if (ep23) { + tmp___57 = 1; + } else { + goto _L___115; + } + } else + _L___115: /* CIL Label */ + if (r543) { + if (ep43) { + tmp___57 = 1; + } else { + tmp___57 = 0; + } + } else { + tmp___57 = 0; + } + r534 = (_Bool)tmp___57; + if (r543) { + tmp___58 = 1; + } else if (r513) { + if (ep14) { + tmp___58 = 1; + } else { + goto _L___118; + } + } else + _L___118: /* CIL Label */ + if (r523) { + if (ep24) { + tmp___58 = 1; + } else { + goto _L___117; + } + } else + _L___117: /* CIL Label */ + if (r533) { + if (ep34) { + tmp___58 = 1; + } else { + tmp___58 = 0; + } + } else { + tmp___58 = 0; + } + r544 = (_Bool)tmp___58; + if ((int)id1 != (int)id2) { + if ((int)id1 != (int)id3) { + if ((int)id1 != (int)id4) { + if ((int)id1 != (int)id5) { + if ((int)id2 != (int)id3) { + if ((int)id2 != (int)id4) { + if ((int)id2 != (int)id5) { + if ((int)id3 != (int)id4) { + if ((int)id3 != (int)id5) { + if ((int)id4 != (int)id5) { + if ((int)id1 >= 0) { + if ((int)id2 >= 0) { + if ((int)id3 >= 0) { + if ((int)id4 >= 0) { + if ((int)id5 >= 0) { + if ((int)r1 == 0) { + if ((int)r2 == 0) { + if ((int)r3 == 0) { + if ((int)r4 == 0) { + if ((int)r5 == 0) { + if (r124) { + if (r134) { + if (r144) { + if (r154) { + if (r214) { + if (r234) { + if (r244) { + if (r254) { + if (r314) { + if (r324) { + if (r344) { + if (r354) { + if (r414) { + if (r424) { + if (r434) { + if (r454) { + if (r514) { + if (r524) { + if (r534) { + if (r544) { + if ((int)max1 == (int)id1) { + if ((int)max2 == (int)id2) { + if ((int)max3 == (int)id3) { + if ((int)max4 == (int)id4) { + if ((int)max5 == (int)id5) { + if ((int)st1 == 0) { + if ((int)st2 == 0) { + if ((int)st3 == 0) { + if ((int)st4 == 0) { + if ((int)st5 == 0) { + if ((int)nl1 == 0) { + if ((int)nl2 == 0) { + if ((int)nl3 == 0) { + if ((int)nl4 == 0) { + if ((int)nl5 == 0) { + if ((int)mode1 == 0) { + if ((int)mode2 == 0) { + if ((int)mode3 == 0) { + if ((int)mode4 == 0) { + if ((int)mode5 == 0) { + tmp___59 = 1; + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + return (tmp___59); + } +} +int check(void) { + int tmp; + + { + if (((((int)st1 + (int)st2) + (int)st3) + (int)st4) + (int)st5 <= 1) { + if ((int)st1 + (int)nl1 <= 1) { + if ((int)st2 + (int)nl2 <= 1) { + if ((int)st3 + (int)nl3 <= 1) { + if ((int)st4 + (int)nl4 <= 1) { + if ((int)st5 + (int)nl5 <= 1) { + if ((int)r1 >= 4) { + goto _L___1; + } else if (((((int)st1 + (int)st2) + (int)st3) + (int)st4) + (int)st5 == 0) { + _L___1: /* CIL Label */ + if ((int)r1 < 4) { + goto _L___0; + } else if (((((int)st1 + (int)st2) + (int)st3) + (int)st4) + (int)st5 == 1) { + _L___0: /* CIL Label */ + if ((int)r1 >= 4) { + goto _L; + } else if (((((int)nl1 + (int)nl2) + (int)nl3) + (int)nl4) + (int)nl5 == 0) { + _L: /* CIL Label */ + if ((int)r1 < 4) { + tmp = 1; + } else if (((((int)nl1 + (int)nl2) + (int)nl3) + (int)nl4) + (int)nl5 == 4) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + return (tmp); + } +} +int main(void) { + int c1; + int i2; + + { + c1 = 0; + ep12 = __VERIFIER_nondet_bool(); + ep13 = __VERIFIER_nondet_bool(); + ep14 = __VERIFIER_nondet_bool(); + ep15 = __VERIFIER_nondet_bool(); + ep21 = __VERIFIER_nondet_bool(); + ep23 = __VERIFIER_nondet_bool(); + ep24 = __VERIFIER_nondet_bool(); + ep25 = __VERIFIER_nondet_bool(); + ep31 = __VERIFIER_nondet_bool(); + ep32 = __VERIFIER_nondet_bool(); + ep34 = __VERIFIER_nondet_bool(); + ep35 = __VERIFIER_nondet_bool(); + ep41 = __VERIFIER_nondet_bool(); + ep42 = __VERIFIER_nondet_bool(); + ep43 = __VERIFIER_nondet_bool(); + ep45 = __VERIFIER_nondet_bool(); + ep51 = __VERIFIER_nondet_bool(); + ep52 = __VERIFIER_nondet_bool(); + ep53 = __VERIFIER_nondet_bool(); + ep54 = __VERIFIER_nondet_bool(); + id1 = __VERIFIER_nondet_char(); + r1 = __VERIFIER_nondet_char(); + st1 = __VERIFIER_nondet_char(); + nl1 = __VERIFIER_nondet_char(); + m1 = __VERIFIER_nondet_char(); + max1 = __VERIFIER_nondet_char(); + mode1 = __VERIFIER_nondet_bool(); + id2 = __VERIFIER_nondet_char(); + r2 = __VERIFIER_nondet_char(); + st2 = __VERIFIER_nondet_char(); + nl2 = __VERIFIER_nondet_char(); + m2 = __VERIFIER_nondet_char(); + max2 = __VERIFIER_nondet_char(); + mode2 = __VERIFIER_nondet_bool(); + id3 = __VERIFIER_nondet_char(); + r3 = __VERIFIER_nondet_char(); + st3 = __VERIFIER_nondet_char(); + nl3 = __VERIFIER_nondet_char(); + m3 = __VERIFIER_nondet_char(); + max3 = __VERIFIER_nondet_char(); + mode3 = __VERIFIER_nondet_bool(); + id4 = __VERIFIER_nondet_char(); + r4 = __VERIFIER_nondet_char(); + st4 = __VERIFIER_nondet_char(); + nl4 = __VERIFIER_nondet_char(); + m4 = __VERIFIER_nondet_char(); + max4 = __VERIFIER_nondet_char(); + mode4 = __VERIFIER_nondet_bool(); + id5 = __VERIFIER_nondet_char(); + r5 = __VERIFIER_nondet_char(); + st5 = __VERIFIER_nondet_char(); + nl5 = __VERIFIER_nondet_char(); + m5 = __VERIFIER_nondet_char(); + max5 = __VERIFIER_nondet_char(); + mode5 = __VERIFIER_nondet_bool(); + i2 = init(); + assume_abort_if_not(i2); + p12_old = nomsg; + p12_new = nomsg; + p13_old = nomsg; + p13_new = nomsg; + p14_old = nomsg; + p14_new = nomsg; + p15_old = nomsg; + p15_new = nomsg; + p21_old = nomsg; + p21_new = nomsg; + p23_old = nomsg; + p23_new = nomsg; + p24_old = nomsg; + p24_new = nomsg; + p25_old = nomsg; + p25_new = nomsg; + p31_old = nomsg; + p31_new = nomsg; + p32_old = nomsg; + p32_new = nomsg; + p34_old = nomsg; + p34_new = nomsg; + p35_old = nomsg; + p35_new = nomsg; + p41_old = nomsg; + p41_new = nomsg; + p42_old = nomsg; + p42_new = nomsg; + p43_old = nomsg; + p43_new = nomsg; + p45_old = nomsg; + p45_new = nomsg; + p51_old = nomsg; + p51_new = nomsg; + p52_old = nomsg; + p52_new = nomsg; + p53_old = nomsg; + p53_new = nomsg; + p54_old = nomsg; + p54_new = nomsg; + i2 = 0; + while (i2 < 10) { + { + node1(); + node2(); + node3(); + node4(); + node5(); + p12_old = p12_new; + p12_new = nomsg; + p13_old = p13_new; + p13_new = nomsg; + p14_old = p14_new; + p14_new = nomsg; + p15_old = p15_new; + p15_new = nomsg; + p21_old = p21_new; + p21_new = nomsg; + p23_old = p23_new; + p23_new = nomsg; + p24_old = p24_new; + p24_new = nomsg; + p25_old = p25_new; + p25_new = nomsg; + p31_old = p31_new; + p31_new = nomsg; + p32_old = p32_new; + p32_new = nomsg; + p34_old = p34_new; + p34_new = nomsg; + p35_old = p35_new; + p35_new = nomsg; + p41_old = p41_new; + p41_new = nomsg; + p42_old = p42_new; + p42_new = nomsg; + p43_old = p43_new; + p43_new = nomsg; + p45_old = p45_new; + p45_new = nomsg; + p51_old = p51_new; + p51_new = nomsg; + p52_old = p52_new; + p52_new = nomsg; + p53_old = p53_new; + p53_new = nomsg; + p54_old = p54_new; + p54_new = nomsg; + c1 = check(); + assert(c1); + i2++; + } + } + } + return 0; +} +void assert(_Bool arg) { + + { + if (!arg) { + { + ERROR : { + reach_error(); + abort(); + } + } + } + } +} diff --git a/test/Solver/sina2f.c b/test/Solver/sina2f.c new file mode 100644 index 0000000000..628a8e0e8b --- /dev/null +++ b/test/Solver/sina2f.c @@ -0,0 +1,67 @@ +// REQUIRES: bitwuzla +// REQUIRES: not-asan +// REQUIRES: not-msan +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --strip-unwanted-calls --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=16 --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=false --output-istats=false --use-sym-size-alloc=true --cex-cache-validity-cores --fp-runtime --x86FP-as-x87FP80 --symbolic-allocation-threshold=8192 --allocate-determ --allocate-determ-size=3072 --allocate-determ-start-address=0x00030000000 --mem-trigger-cof --use-alpha-equivalence=true --track-coverage=all --use-iterative-deepening-search=max-cycles --max-solver-time=5s --max-cycles-before-stuck=15 --only-output-states-covering-new --dump-states-on-halt=all --search=dfs --search=random-state --cover-on-the-fly=true --delay-cover-on-the-fly=27 --max-time=29 %t1.bc 2>&1 | FileCheck %s +#include "klee-test-comp.c" + +/* + * Benchmarks contributed by Divyesh Unadkat[1,2], Supratik Chakraborty[1], Ashutosh Gupta[1] + * [1] Indian Institute of Technology Bombay, Mumbai + * [2] TCS Innovation labs, Pune + * + */ + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "sina2f.c", 10, "reach_error"); } +extern void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR : { + reach_error(); + abort(); + } + } +} +extern int __VERIFIER_nondet_int(void); +void *malloc(unsigned int size); + +int N; + +int main() { + N = __VERIFIER_nondet_int(); + if (N <= 0) + return 1; + assume_abort_if_not(N <= 2147483647 / sizeof(int)); + + int i; + long long sum[1]; + long long *a = malloc(sizeof(long long) * N); + + sum[0] = 1; + for (i = 0; i < N; i++) { + a[i] = 1; + } + + for (i = 0; i < N; i++) { + sum[0] = sum[0] + a[i]; + } + + for (i = 0; i < N; i++) { + a[i] = a[i] + sum[0]; + } + + for (i = 0; i < N; i++) { + __VERIFIER_assert(a[i] == N); + } + return 1; +} + +// CHECK: KLEE: done diff --git a/test/lit.cfg b/test/lit.cfg index 75978e47b7..d2af70f065 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -113,6 +113,10 @@ config.substitutions.append( config.substitutions.append( ('%llvmlink', os.path.join(llvm_tools_dir, 'llvm-link')) ) +# Add a substitution for llvm-link +config.substitutions.append( + ('%llvmcov', os.path.join(llvm_tools_dir, 'llvm-cov')) +) # Add a substition for libkleeruntest config.substitutions.append( @@ -162,6 +166,10 @@ config.substitutions.append( ('%gentmp', os.path.join(klee_src_root, 'scripts/genTempFiles.sh')) ) +config.substitutions.append( + ('%replay', os.path.join(klee_src_root, 'scripts/replay.sh')) +) + config.substitutions.append( ('%libcxx_include', getattr(config, 'libcxx_include_dir', None))) @@ -198,6 +206,14 @@ if config.enable_z3: config.available_features.add('z3') else: config.available_features.add('not-z3') +if config.enable_metasmt: + config.available_features.add('metasmt') +else: + config.available_features.add('not-metasmt') +if config.enable_bitwuzla: + config.available_features.add('bitwuzla') +else: + config.available_features.add('not-bitwuzla') # Zlib config.available_features.add('zlib' if config.enable_zlib else 'not-zlib') @@ -251,3 +267,8 @@ config.available_features.add('{}32bit-support'.format('' if config.have_32bit_s config.available_features.add('{}asan'.format('' if config.have_asan else 'not-')) config.available_features.add('{}ubsan'.format('' if config.have_ubsan else 'not-')) config.available_features.add('{}msan'.format('' if config.have_msan else 'not-')) + +if config.have_asan or config.have_ubsan or config.have_msan: + config.available_features.add('san') +else: + config.available_features.add('not-san') diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 15bc4a20a5..fb4ed1c586 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -51,6 +51,8 @@ config.enable_eh_cxx = True if @SUPPORT_KLEE_EH_CXX@ == 1 else False config.have_selinux = True if @HAVE_SELINUX@ == 1 else False config.enable_stp = True if @ENABLE_STP@ == 1 else False config.enable_z3 = True if @ENABLE_Z3@ == 1 else False +config.enable_metasmt = True if @ENABLE_METASMT@ == 1 else False +config.enable_bitwuzla = True if @ENABLE_BITWUZLA@ == 1 else False config.enable_zlib = True if @HAVE_ZLIB_H@ == 1 else False config.have_asan = True if @IS_ASAN_BUILD@ == 1 else False config.have_ubsan = True if @IS_UBSAN_BUILD@ == 1 else False diff --git a/test/regression/2020-02-24-count-paths-nodump.c b/test/regression/2020-02-24-count-paths-nodump.c index c066886c20..83af8e919b 100644 --- a/test/regression/2020-02-24-count-paths-nodump.c +++ b/test/regression/2020-02-24-count-paths-nodump.c @@ -1,8 +1,8 @@ -// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=false +// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=none // REQUIRES: not-asan // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee -dump-states-on-halt=false -max-instructions=1 -output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s +// RUN: %klee -dump-states-on-halt=none -max-instructions=1 -output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s int main(int argc, char **argv) { // just do something diff --git a/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c b/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c index ec58f72187..6befbf686c 100644 --- a/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c +++ b/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c @@ -1,19 +1,12 @@ -// REQUIRES: not-darwin, z3 +// REQUIRES: not-darwin // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --libc=klee --posix-runtime --solver-backend=z3 --skip-not-lazy-initialized --skip-not-symbolic-objects %t.bc > %t.log - -// RUN: test -f %t.klee-out/test000006.ktest +// RUN: %klee --output-dir=%t.klee-out --libc=klee --posix-runtime --skip-not-lazy-initialized --skip-not-symbolic-objects %t.bc > %t.log // RUN: %cc %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000002.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000003.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000004.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000005.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000006.ktest %t_runner >> %t_runner.log - +// RUN: rm -f %t_runner.log +// RUN: %replay %t.klee-out %t_runner > %t_runner.log // RUN: FileCheck -input-file=%t_runner.log %s #include diff --git a/test/regression/2023-08-28-invalid-pointer-dereference.c b/test/regression/2023-08-28-invalid-pointer-dereference.c new file mode 100644 index 0000000000..cdd8388e71 --- /dev/null +++ b/test/regression/2023-08-28-invalid-pointer-dereference.c @@ -0,0 +1,22 @@ +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --use-sym-size-alloc --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s + +#pragma clang attribute push(__attribute__((optnone)), apply_to = function) + +int main() { + int length1 = klee_int("len"); + int length2 = klee_int("len"); + if (length1 < 1) { + length1 = 1; + } + if (length2 < 1) { + length2 = 1; + } + char *nondetString1 = (char *)__builtin_alloca(length1 * sizeof(char)); + char *nondetString2 = (char *)__builtin_alloca(length2 * sizeof(char)); + nondetString1[length1 - 1] = '\0'; + // CHECK-NOT: memory error: out of bound pointer + nondetString2[length2 - 1] = '\0'; +} +#pragma clang attribute pop diff --git a/test/regression/2023-10-02-test-from-mocked-global.c b/test/regression/2023-10-02-test-from-mocked-global.c new file mode 100644 index 0000000000..a62eeb9bba --- /dev/null +++ b/test/regression/2023-10-02-test-from-mocked-global.c @@ -0,0 +1,16 @@ +// Darwin does not support section attribute: `argument to 'section' attribute is not valid for this target: mach-o section specifier requires a segment whose length is between 1 and 16 characters` +// REQUIRES: not-darwin +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --mock-all-externals --write-xml-tests --output-dir=%t.klee-out %t1.bc +// RUN: FileCheck --input-file %t.klee-out/test000001.xml %s + +extern void *__crc_mc44s803_attach __attribute__((__weak__)); +static unsigned long const __kcrctab_mc44s803_attach __attribute__((__used__, __unused__, + __section__("___kcrctab+mc44s803_attach"))) = (unsigned long const)((unsigned long)(&__crc_mc44s803_attach)); + +int main() { + return 0; +} + +// CHECK-NOT: &1 | FileCheck -check-prefix=CHECK %s + +// RUN find %t.klee-out -type f -name "*.assert.err" | sed 's/assert\.err/ktest/' | xargs %ktest-tool | FileCheck -check-prefix=CHECK-TEST %s +// CHECK-TEST-NOT: object 20 + +#include "klee-test-comp.c" + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2011-2013 Alexander von Rhein, University of Passau +// SPDX-FileCopyrightText: 2011-2021 The SV-Benchmarks Community +// +// SPDX-License-Identifier: Apache-2.0 + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +// CHECK: email_spec0_product16.cil.c:[[@LINE+1]]: ASSERTION FAIL: 0 +void reach_error() { __assert_fail("0", "email_spec0_product16.cil.c", 3, "reach_error"); } + +extern int __VERIFIER_nondet_int(void); +/* Generated by CIL v. 1.3.7 */ +/* print_CIL_Input is true */ + +struct JoinPoint { + void **(*fp)(struct JoinPoint *); + void **args; + int argsCount; + char const **argsType; + void *(*arg)(int, struct JoinPoint *); + char const *(*argType)(int, struct JoinPoint *); + void **retValue; + char const *retType; + char const *funcName; + char const *targetName; + char const *fileName; + char const *kind; + void *excep_return; +}; +struct __UTAC__CFLOW_FUNC { + int (*func)(int, int); + int val; + struct __UTAC__CFLOW_FUNC *next; +}; +struct __UTAC__EXCEPTION { + void *jumpbuf; + unsigned long long prtValue; + int pops; + struct __UTAC__CFLOW_FUNC *cflowfuncs; +}; +typedef unsigned int size_t; +struct __ACC__ERR { + void *v; + struct __ACC__ERR *next; +}; +#pragma merger(0, "featureselect.i", "") +int __SELECTED_FEATURE_Base; +int __SELECTED_FEATURE_Keys; +int __SELECTED_FEATURE_Encrypt; +int __SELECTED_FEATURE_AutoResponder; +int __SELECTED_FEATURE_AddressBook; +int __SELECTED_FEATURE_Sign; +int __SELECTED_FEATURE_Forward; +int __SELECTED_FEATURE_Verify; +int __SELECTED_FEATURE_Decrypt; +int __GUIDSL_ROOT_PRODUCTION; +int __GUIDSL_NON_TERMINAL_main; +int select_one(void); +void select_features(void); +void select_helpers(void); +int valid_product(void); +int select_one(void) { + int retValue_acc; + int choice = __VERIFIER_nondet_int(); + + { + retValue_acc = choice; + return (retValue_acc); + return (retValue_acc); + } +} +void select_features(void) { + + { + return; + } +} +void select_helpers(void) { + + { + return; + } +} +int valid_product(void) { + int retValue_acc; + + { + retValue_acc = 1; + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "Test.i", "") +extern int printf(char const *__restrict __format, ...); +extern int puts(char const *__s); +void setClientPrivateKey(int handle, int value); +int createClientKeyringEntry(int handle); +int getClientKeyringUser(int handle, int index); +void setClientKeyringUser(int handle, int index, int value); +int getClientKeyringPublicKey(int handle, int index); +void setClientKeyringPublicKey(int handle, int index, int value); +void setClientForwardReceiver(int handle, int value); +void setClientId(int handle, int value); +int is_queue_empty(void); +int get_queued_client(void); +int get_queued_email(void); +void outgoing(int client, int msg); +void sendEmail(int sender, int receiver); +void generateKeyPair(int client, int seed); +int bob; +int rjh; +int chuck; +void setup_bob(int bob___0); +void setup_rjh(int rjh___0); +void setup_chuck(int chuck___0); +void bobToRjh(void); +void rjhToBob(void); +void test(void); +void setup(void); +int main(void); +void bobKeyAdd(void); +void bobKeyAddChuck(void); +void rjhKeyAdd(void); +void rjhKeyAddChuck(void); +void chuckKeyAdd(void); +void bobKeyChange(void); +void rjhKeyChange(void); +void rjhDeletePrivateKey(void); +void chuckKeyAddRjh(void); +void rjhEnableForwarding(void); +void setup_bob__wrappee__Base(int bob___0) { + + { + { + setClientId(bob___0, bob___0); + } + return; + } +} +void setup_bob(int bob___0) { + + { + { + setup_bob__wrappee__Base(bob___0); + setClientPrivateKey(bob___0, 123); + } + return; + } +} +void setup_rjh__wrappee__Base(int rjh___0) { + + { + { + setClientId(rjh___0, rjh___0); + } + return; + } +} +void setup_rjh(int rjh___0) { + + { + { + setup_rjh__wrappee__Base(rjh___0); + setClientPrivateKey(rjh___0, 456); + } + return; + } +} +void setup_chuck__wrappee__Base(int chuck___0) { + + { + { + setClientId(chuck___0, chuck___0); + } + return; + } +} +void setup_chuck(int chuck___0) { + + { + { + setup_chuck__wrappee__Base(chuck___0); + setClientPrivateKey(chuck___0, 789); + } + return; + } +} +void bobToRjh(void) { + int tmp; + int tmp___0; + int tmp___1; + + { + { + puts("Please enter a subject and a message body.\n"); + sendEmail(bob, rjh); + tmp___1 = is_queue_empty(); + } + if (tmp___1) { + + } else { + { + tmp = get_queued_email(); + tmp___0 = get_queued_client(); + outgoing(tmp___0, tmp); + } + } + return; + } +} +void rjhToBob(void) { + + { + { + puts("Please enter a subject and a message body.\n"); + sendEmail(rjh, bob); + } + return; + } +} +void setup(void) { + char const *__restrict __cil_tmp1; + char const *__restrict __cil_tmp2; + char const *__restrict __cil_tmp3; + + { + { + bob = 1; + setup_bob(bob); + __cil_tmp1 = (char const *__restrict)"bob: %d\n"; + printf(__cil_tmp1, bob); + rjh = 2; + setup_rjh(rjh); + __cil_tmp2 = (char const *__restrict)"rjh: %d\n"; + printf(__cil_tmp2, rjh); + chuck = 3; + setup_chuck(chuck); + __cil_tmp3 = (char const *__restrict)"chuck: %d\n"; + printf(__cil_tmp3, chuck); + } + return; + } +} +int main(void) { + int retValue_acc; + int tmp; + + { + { + select_helpers(); + select_features(); + tmp = valid_product(); + } + if (tmp) { + { + setup(); + test(); + } + } else { + } + return (retValue_acc); + } +} +void bobKeyAdd(void) { + int tmp; + int tmp___0; + char const *__restrict __cil_tmp3; + char const *__restrict __cil_tmp4; + + { + { + createClientKeyringEntry(bob); + setClientKeyringUser(bob, 0, 2); + setClientKeyringPublicKey(bob, 0, 456); + puts("bob added rjhs key"); + tmp = getClientKeyringUser(bob, 0); + __cil_tmp3 = (char const *__restrict)"%d\n"; + printf(__cil_tmp3, tmp); + tmp___0 = getClientKeyringPublicKey(bob, 0); + __cil_tmp4 = (char const *__restrict)"%d\n"; + printf(__cil_tmp4, tmp___0); + } + return; + } +} +void rjhKeyAdd(void) { + + { + { + createClientKeyringEntry(rjh); + setClientKeyringUser(rjh, 0, 1); + setClientKeyringPublicKey(rjh, 0, 123); + } + return; + } +} +void rjhKeyAddChuck(void) { + + { + { + createClientKeyringEntry(rjh); + setClientKeyringUser(rjh, 0, 3); + setClientKeyringPublicKey(rjh, 0, 789); + } + return; + } +} +void bobKeyAddChuck(void) { + + { + { + createClientKeyringEntry(bob); + setClientKeyringUser(bob, 1, 3); + setClientKeyringPublicKey(bob, 1, 789); + } + return; + } +} +void chuckKeyAdd(void) { + + { + { + createClientKeyringEntry(chuck); + setClientKeyringUser(chuck, 0, 1); + setClientKeyringPublicKey(chuck, 0, 123); + } + return; + } +} +void chuckKeyAddRjh(void) { + + { + { + createClientKeyringEntry(chuck); + setClientKeyringUser(chuck, 0, 2); + setClientKeyringPublicKey(chuck, 0, 456); + } + return; + } +} +void rjhDeletePrivateKey(void) { + + { + { + setClientPrivateKey(rjh, 0); + } + return; + } +} +void bobKeyChange(void) { + + { + { + generateKeyPair(bob, 777); + } + return; + } +} +void rjhKeyChange(void) { + + { + { + generateKeyPair(rjh, 666); + } + return; + } +} +void rjhEnableForwarding(void) { + + { + { + setClientForwardReceiver(rjh, chuck); + } + return; + } +} +#pragma merger(0, "wsllib_check.i", "") +void __automaton_fail(void) { + + { + ERROR : { + reach_error(); + abort(); + } + return; + } +} +#pragma merger(0, "Email.i", "") +int getEmailId(int handle); +int getEmailFrom(int handle); +void setEmailFrom(int handle, int value); +int getEmailTo(int handle); +void setEmailTo(int handle, int value); +int isEncrypted(int handle); +int getEmailEncryptionKey(int handle); +void printMail(int msg); +int isReadable(int msg); +int createEmail(int from, int to); +int cloneEmail(int msg); +void printMail__wrappee__Keys(int msg) { + int tmp; + int tmp___0; + int tmp___1; + int tmp___2; + char const *__restrict __cil_tmp6; + char const *__restrict __cil_tmp7; + char const *__restrict __cil_tmp8; + char const *__restrict __cil_tmp9; + + { + { + tmp = getEmailId(msg); + __cil_tmp6 = (char const *__restrict)"ID:\n %i\n"; + printf(__cil_tmp6, tmp); + tmp___0 = getEmailFrom(msg); + __cil_tmp7 = (char const *__restrict)"FROM:\n %i\n"; + printf(__cil_tmp7, tmp___0); + tmp___1 = getEmailTo(msg); + __cil_tmp8 = (char const *__restrict)"TO:\n %i\n"; + printf(__cil_tmp8, tmp___1); + tmp___2 = isReadable(msg); + __cil_tmp9 = (char const *__restrict)"IS_READABLE\n %i\n"; + printf(__cil_tmp9, tmp___2); + } + return; + } +} +void printMail(int msg) { + int tmp; + int tmp___0; + char const *__restrict __cil_tmp4; + char const *__restrict __cil_tmp5; + + { + { + printMail__wrappee__Keys(msg); + tmp = isEncrypted(msg); + __cil_tmp4 = (char const *__restrict)"ENCRYPTED\n %d\n"; + printf(__cil_tmp4, tmp); + tmp___0 = getEmailEncryptionKey(msg); + __cil_tmp5 = (char const *__restrict)"ENCRYPTION KEY\n %d\n"; + printf(__cil_tmp5, tmp___0); + } + return; + } +} +int isReadable__wrappee__Keys(int msg) { + int retValue_acc; + + { + retValue_acc = 1; + return (retValue_acc); + return (retValue_acc); + } +} +int isReadable(int msg) { + int retValue_acc; + int tmp; + + { + { + tmp = isEncrypted(msg); + } + if (tmp) { + retValue_acc = 0; + return (retValue_acc); + } else { + { + retValue_acc = isReadable__wrappee__Keys(msg); + } + return (retValue_acc); + } + return (retValue_acc); + } +} +int cloneEmail(int msg) { + int retValue_acc; + + { + retValue_acc = msg; + return (retValue_acc); + return (retValue_acc); + } +} +int createEmail(int from, int to) { + int retValue_acc; + int msg; + + { + { + msg = 1; + setEmailFrom(msg, from); + setEmailTo(msg, to); + retValue_acc = msg; + } + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "scenario.i", "") +void test(void) { + int op1; + int op2; + int op3; + int op4; + int op5; + int op6; + int op7; + int op8; + int op9; + int op10; + int op11; + int splverifierCounter; + int tmp; + int tmp___0; + int tmp___1; + int tmp___2; + int tmp___3; + int tmp___4; + int tmp___5; + int tmp___6; + int tmp___7; + int tmp___8; + int tmp___9; + + { + op1 = 0; + op2 = 0; + op3 = 0; + op4 = 0; + op5 = 0; + op6 = 0; + op7 = 0; + op8 = 0; + op9 = 0; + op10 = 0; + op11 = 0; + splverifierCounter = 0; + { + while (1) { + while_0_continue: /* CIL Label */; + if (splverifierCounter < 4) { + + } else { + goto while_0_break; + } + splverifierCounter = splverifierCounter + 1; + if (!op1) { + { + tmp___9 = __VERIFIER_nondet_int(); + } + if (tmp___9) { + { + bobKeyAdd(); + op1 = 1; + } + } else { + goto _L___8; + } + } else { + _L___8: /* CIL Label */ + if (!op2) { + { + tmp___8 = __VERIFIER_nondet_int(); + } + if (tmp___8) { + op2 = 1; + } else { + goto _L___7; + } + } else { + _L___7: /* CIL Label */ + if (!op3) { + { + tmp___7 = __VERIFIER_nondet_int(); + } + if (tmp___7) { + { + rjhDeletePrivateKey(); + op3 = 1; + } + } else { + goto _L___6; + } + } else { + _L___6: /* CIL Label */ + if (!op4) { + { + tmp___6 = __VERIFIER_nondet_int(); + } + if (tmp___6) { + { + rjhKeyAdd(); + op4 = 1; + } + } else { + goto _L___5; + } + } else { + _L___5: /* CIL Label */ + if (!op5) { + { + tmp___5 = __VERIFIER_nondet_int(); + } + if (tmp___5) { + { + chuckKeyAddRjh(); + op5 = 1; + } + } else { + goto _L___4; + } + } else { + _L___4: /* CIL Label */ + if (!op6) { + { + tmp___4 = __VERIFIER_nondet_int(); + } + if (tmp___4) { + { + rjhEnableForwarding(); + op6 = 1; + } + } else { + goto _L___3; + } + } else { + _L___3: /* CIL Label */ + if (!op7) { + { + tmp___3 = __VERIFIER_nondet_int(); + } + if (tmp___3) { + { + rjhKeyChange(); + op7 = 1; + } + } else { + goto _L___2; + } + } else { + _L___2: /* CIL Label */ + if (!op8) { + { + tmp___2 = __VERIFIER_nondet_int(); + } + if (tmp___2) { + op8 = 1; + } else { + goto _L___1; + } + } else { + _L___1: /* CIL Label */ + if (!op9) { + { + tmp___1 = __VERIFIER_nondet_int(); + } + if (tmp___1) { + { + chuckKeyAdd(); + op9 = 1; + } + } else { + goto _L___0; + } + } else { + _L___0: /* CIL Label */ + if (!op10) { + { + tmp___0 = __VERIFIER_nondet_int(); + } + if (tmp___0) { + { + bobKeyChange(); + op10 = 1; + } + } else { + goto _L; + } + } else { + _L: /* CIL Label */ + if (!op11) { + { + tmp = __VERIFIER_nondet_int(); + } + if (tmp) { + { + chuckKeyAdd(); + op11 = 1; + } + } else { + goto while_0_break; + } + } else { + goto while_0_break; + } + } + } + } + } + } + } + } + } + } + } + } + while_0_break: /* CIL Label */; + } + { + bobToRjh(); + } + return; + } +} +#pragma merger(0, "libacc.i", "") +extern __attribute__((__nothrow__, __noreturn__)) void __assert_fail(char const *__assertion, + char const *__file, + unsigned int __line, + char const *__function); +extern __attribute__((__nothrow__)) void *malloc(size_t __size) __attribute__((__malloc__)); +extern __attribute__((__nothrow__)) void free(void *__ptr); +void __utac__exception__cf_handler_set(void *exception, int (*cflow_func)(int, int), + int val) { + struct __UTAC__EXCEPTION *excep; + struct __UTAC__CFLOW_FUNC *cf; + void *tmp; + unsigned long __cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + unsigned long __cil_tmp10; + unsigned long __cil_tmp11; + unsigned long __cil_tmp12; + unsigned long __cil_tmp13; + unsigned long __cil_tmp14; + int (**mem_15)(int, int); + int *mem_16; + struct __UTAC__CFLOW_FUNC **mem_17; + struct __UTAC__CFLOW_FUNC **mem_18; + struct __UTAC__CFLOW_FUNC **mem_19; + + { + { + excep = (struct __UTAC__EXCEPTION *)exception; + tmp = malloc(24UL); + cf = (struct __UTAC__CFLOW_FUNC *)tmp; + mem_15 = (int (**)(int, int))cf; + *mem_15 = cflow_func; + __cil_tmp7 = (unsigned long)cf; + __cil_tmp8 = __cil_tmp7 + 8; + mem_16 = (int *)__cil_tmp8; + *mem_16 = val; + __cil_tmp9 = (unsigned long)cf; + __cil_tmp10 = __cil_tmp9 + 16; + __cil_tmp11 = (unsigned long)excep; + __cil_tmp12 = __cil_tmp11 + 24; + mem_17 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp10; + mem_18 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp12; + *mem_17 = *mem_18; + __cil_tmp13 = (unsigned long)excep; + __cil_tmp14 = __cil_tmp13 + 24; + mem_19 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp14; + *mem_19 = cf; + } + return; + } +} +void __utac__exception__cf_handler_free(void *exception) { + struct __UTAC__EXCEPTION *excep; + struct __UTAC__CFLOW_FUNC *cf; + struct __UTAC__CFLOW_FUNC *tmp; + unsigned long __cil_tmp5; + unsigned long __cil_tmp6; + struct __UTAC__CFLOW_FUNC *__cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + unsigned long __cil_tmp10; + unsigned long __cil_tmp11; + void *__cil_tmp12; + unsigned long __cil_tmp13; + unsigned long __cil_tmp14; + struct __UTAC__CFLOW_FUNC **mem_15; + struct __UTAC__CFLOW_FUNC **mem_16; + struct __UTAC__CFLOW_FUNC **mem_17; + + { + excep = (struct __UTAC__EXCEPTION *)exception; + __cil_tmp5 = (unsigned long)excep; + __cil_tmp6 = __cil_tmp5 + 24; + mem_15 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp6; + cf = *mem_15; + { + while (1) { + while_1_continue: /* CIL Label */; + { + __cil_tmp7 = (struct __UTAC__CFLOW_FUNC *)0; + __cil_tmp8 = (unsigned long)__cil_tmp7; + __cil_tmp9 = (unsigned long)cf; + if (__cil_tmp9 != __cil_tmp8) { + + } else { + goto while_1_break; + } + } + { + tmp = cf; + __cil_tmp10 = (unsigned long)cf; + __cil_tmp11 = __cil_tmp10 + 16; + mem_16 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp11; + cf = *mem_16; + __cil_tmp12 = (void *)tmp; + free(__cil_tmp12); + } + } + while_1_break: /* CIL Label */; + } + __cil_tmp13 = (unsigned long)excep; + __cil_tmp14 = __cil_tmp13 + 24; + mem_17 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp14; + *mem_17 = (struct __UTAC__CFLOW_FUNC *)0; + return; + } +} +void __utac__exception__cf_handler_reset(void *exception) { + struct __UTAC__EXCEPTION *excep; + struct __UTAC__CFLOW_FUNC *cf; + unsigned long __cil_tmp5; + unsigned long __cil_tmp6; + struct __UTAC__CFLOW_FUNC *__cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + int (*__cil_tmp10)(int, int); + unsigned long __cil_tmp11; + unsigned long __cil_tmp12; + int __cil_tmp13; + unsigned long __cil_tmp14; + unsigned long __cil_tmp15; + struct __UTAC__CFLOW_FUNC **mem_16; + int (**mem_17)(int, int); + int *mem_18; + struct __UTAC__CFLOW_FUNC **mem_19; + + { + excep = (struct __UTAC__EXCEPTION *)exception; + __cil_tmp5 = (unsigned long)excep; + __cil_tmp6 = __cil_tmp5 + 24; + mem_16 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp6; + cf = *mem_16; + { + while (1) { + while_2_continue: /* CIL Label */; + { + __cil_tmp7 = (struct __UTAC__CFLOW_FUNC *)0; + __cil_tmp8 = (unsigned long)__cil_tmp7; + __cil_tmp9 = (unsigned long)cf; + if (__cil_tmp9 != __cil_tmp8) { + + } else { + goto while_2_break; + } + } + { + mem_17 = (int (**)(int, int))cf; + __cil_tmp10 = *mem_17; + __cil_tmp11 = (unsigned long)cf; + __cil_tmp12 = __cil_tmp11 + 8; + mem_18 = (int *)__cil_tmp12; + __cil_tmp13 = *mem_18; + (*__cil_tmp10)(4, __cil_tmp13); + __cil_tmp14 = (unsigned long)cf; + __cil_tmp15 = __cil_tmp14 + 16; + mem_19 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp15; + cf = *mem_19; + } + } + while_2_break: /* CIL Label */; + } + { + __utac__exception__cf_handler_free(exception); + } + return; + } +} +void *__utac__error_stack_mgt(void *env, int mode, int count); +static struct __ACC__ERR *head = (struct __ACC__ERR *)0; +void *__utac__error_stack_mgt(void *env, int mode, int count) { + void *retValue_acc; + struct __ACC__ERR *new; + void *tmp; + struct __ACC__ERR *temp; + struct __ACC__ERR *next; + void *excep; + unsigned long __cil_tmp10; + unsigned long __cil_tmp11; + unsigned long __cil_tmp12; + unsigned long __cil_tmp13; + void *__cil_tmp14; + unsigned long __cil_tmp15; + unsigned long __cil_tmp16; + void *__cil_tmp17; + void **mem_18; + struct __ACC__ERR **mem_19; + struct __ACC__ERR **mem_20; + void **mem_21; + struct __ACC__ERR **mem_22; + void **mem_23; + void **mem_24; + + { + if (count == 0) { + return (retValue_acc); + } else { + } + if (mode == 0) { + { + tmp = malloc(16UL); + new = (struct __ACC__ERR *)tmp; + mem_18 = (void **)new; + *mem_18 = env; + __cil_tmp10 = (unsigned long)new; + __cil_tmp11 = __cil_tmp10 + 8; + mem_19 = (struct __ACC__ERR **)__cil_tmp11; + *mem_19 = head; + head = new; + retValue_acc = (void *)new; + } + return (retValue_acc); + } else { + } + if (mode == 1) { + temp = head; + { + while (1) { + while_3_continue: /* CIL Label */; + if (count > 1) { + + } else { + goto while_3_break; + } + { + __cil_tmp12 = (unsigned long)temp; + __cil_tmp13 = __cil_tmp12 + 8; + mem_20 = (struct __ACC__ERR **)__cil_tmp13; + next = *mem_20; + mem_21 = (void **)temp; + excep = *mem_21; + __cil_tmp14 = (void *)temp; + free(__cil_tmp14); + __utac__exception__cf_handler_reset(excep); + temp = next; + count = count - 1; + } + } + while_3_break: /* CIL Label */; + } + { + __cil_tmp15 = (unsigned long)temp; + __cil_tmp16 = __cil_tmp15 + 8; + mem_22 = (struct __ACC__ERR **)__cil_tmp16; + head = *mem_22; + mem_23 = (void **)temp; + excep = *mem_23; + __cil_tmp17 = (void *)temp; + free(__cil_tmp17); + __utac__exception__cf_handler_reset(excep); + retValue_acc = excep; + } + return (retValue_acc); + } else { + } + if (mode == 2) { + if (head) { + mem_24 = (void **)head; + retValue_acc = *mem_24; + return (retValue_acc); + } else { + retValue_acc = (void *)0; + return (retValue_acc); + } + } else { + } + return (retValue_acc); + } +} +void *__utac__get_this_arg(int i, struct JoinPoint *this) { + void *retValue_acc; + unsigned long __cil_tmp4; + unsigned long __cil_tmp5; + int __cil_tmp6; + int __cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + void **__cil_tmp10; + void **__cil_tmp11; + int *mem_12; + void ***mem_13; + + { + if (i > 0) { + { + __cil_tmp4 = (unsigned long)this; + __cil_tmp5 = __cil_tmp4 + 16; + mem_12 = (int *)__cil_tmp5; + __cil_tmp6 = *mem_12; + if (i <= __cil_tmp6) { + + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 123U, "__utac__get_this_arg"); + } + } + } + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 123U, "__utac__get_this_arg"); + } + } + __cil_tmp7 = i - 1; + __cil_tmp8 = (unsigned long)this; + __cil_tmp9 = __cil_tmp8 + 8; + mem_13 = (void ***)__cil_tmp9; + __cil_tmp10 = *mem_13; + __cil_tmp11 = __cil_tmp10 + __cil_tmp7; + retValue_acc = *__cil_tmp11; + return (retValue_acc); + return (retValue_acc); + } +} +char const *__utac__get_this_argtype(int i, struct JoinPoint *this) { + char const *retValue_acc; + unsigned long __cil_tmp4; + unsigned long __cil_tmp5; + int __cil_tmp6; + int __cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + char const **__cil_tmp10; + char const **__cil_tmp11; + int *mem_12; + char const ***mem_13; + + { + if (i > 0) { + { + __cil_tmp4 = (unsigned long)this; + __cil_tmp5 = __cil_tmp4 + 16; + mem_12 = (int *)__cil_tmp5; + __cil_tmp6 = *mem_12; + if (i <= __cil_tmp6) { + + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 131U, "__utac__get_this_argtype"); + } + } + } + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 131U, "__utac__get_this_argtype"); + } + } + __cil_tmp7 = i - 1; + __cil_tmp8 = (unsigned long)this; + __cil_tmp9 = __cil_tmp8 + 24; + mem_13 = (char const ***)__cil_tmp9; + __cil_tmp10 = *mem_13; + __cil_tmp11 = __cil_tmp10 + __cil_tmp7; + retValue_acc = *__cil_tmp11; + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "ClientLib.i", "") +int initClient(void); +char *getClientName(int handle); +void setClientName(int handle, char *value); +int getClientOutbuffer(int handle); +void setClientOutbuffer(int handle, int value); +int getClientAddressBookSize(int handle); +void setClientAddressBookSize(int handle, int value); +int createClientAddressBookEntry(int handle); +int getClientAddressBookAlias(int handle, int index); +void setClientAddressBookAlias(int handle, int index, int value); +int getClientAddressBookAddress(int handle, int index); +void setClientAddressBookAddress(int handle, int index, int value); +int getClientAutoResponse(int handle); +void setClientAutoResponse(int handle, int value); +int getClientPrivateKey(int handle); +int getClientKeyringSize(int handle); +int getClientForwardReceiver(int handle); +int getClientId(int handle); +int findPublicKey(int handle, int userid); +int findClientAddressBookAlias(int handle, int userid); +int __ste_Client_counter = 0; +int initClient(void) { + int retValue_acc; + + { + if (__ste_Client_counter < 3) { + __ste_Client_counter = __ste_Client_counter + 1; + retValue_acc = __ste_Client_counter; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +char *__ste_client_name0 = (char *)0; +char *__ste_client_name1 = (char *)0; +char *__ste_client_name2 = (char *)0; +char *getClientName(int handle) { + char *retValue_acc; + void *__cil_tmp3; + + { + if (handle == 1) { + retValue_acc = __ste_client_name0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_name1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_name2; + return (retValue_acc); + } else { + __cil_tmp3 = (void *)0; + retValue_acc = (char *)__cil_tmp3; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientName(int handle, char *value) { + + { + if (handle == 1) { + __ste_client_name0 = value; + } else { + if (handle == 2) { + __ste_client_name1 = value; + } else { + if (handle == 3) { + __ste_client_name2 = value; + } else { + } + } + } + return; + } +} +int __ste_client_outbuffer0 = 0; +int __ste_client_outbuffer1 = 0; +int __ste_client_outbuffer2 = 0; +int __ste_client_outbuffer3 = 0; +int getClientOutbuffer(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_outbuffer0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_outbuffer1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_outbuffer2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientOutbuffer(int handle, int value) { + + { + if (handle == 1) { + __ste_client_outbuffer0 = value; + } else { + if (handle == 2) { + __ste_client_outbuffer1 = value; + } else { + if (handle == 3) { + __ste_client_outbuffer2 = value; + } else { + } + } + } + return; + } +} +int __ste_ClientAddressBook_size0 = 0; +int __ste_ClientAddressBook_size1 = 0; +int __ste_ClientAddressBook_size2 = 0; +int getClientAddressBookSize(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_ClientAddressBook_size0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_ClientAddressBook_size1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_ClientAddressBook_size2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAddressBookSize(int handle, int value) { + + { + if (handle == 1) { + __ste_ClientAddressBook_size0 = value; + } else { + if (handle == 2) { + __ste_ClientAddressBook_size1 = value; + } else { + if (handle == 3) { + __ste_ClientAddressBook_size2 = value; + } else { + } + } + } + return; + } +} +int createClientAddressBookEntry(int handle) { + int retValue_acc; + int size; + int tmp; + int __cil_tmp5; + + { + { + tmp = getClientAddressBookSize(handle); + size = tmp; + } + if (size < 3) { + { + __cil_tmp5 = size + 1; + setClientAddressBookSize(handle, __cil_tmp5); + retValue_acc = size + 1; + } + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +int __ste_Client_AddressBook0_Alias0 = 0; +int __ste_Client_AddressBook0_Alias1 = 0; +int __ste_Client_AddressBook0_Alias2 = 0; +int __ste_Client_AddressBook1_Alias0 = 0; +int __ste_Client_AddressBook1_Alias1 = 0; +int __ste_Client_AddressBook1_Alias2 = 0; +int __ste_Client_AddressBook2_Alias0 = 0; +int __ste_Client_AddressBook2_Alias1 = 0; +int __ste_Client_AddressBook2_Alias2 = 0; +int getClientAddressBookAlias(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook0_Alias0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook0_Alias1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook0_Alias2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook1_Alias0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook1_Alias1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook1_Alias2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook2_Alias0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook2_Alias1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook2_Alias2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +int findClientAddressBookAlias(int handle, int userid) { + int retValue_acc; + + { + if (handle == 1) { + if (userid == __ste_Client_AddressBook0_Alias0) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook0_Alias1) { + retValue_acc = 1; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook0_Alias2) { + retValue_acc = 2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + } else { + if (handle == 2) { + if (userid == __ste_Client_AddressBook1_Alias0) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook1_Alias1) { + retValue_acc = 1; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook1_Alias2) { + retValue_acc = 2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + } else { + if (handle == 3) { + if (userid == __ste_Client_AddressBook2_Alias0) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook2_Alias1) { + retValue_acc = 1; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook2_Alias2) { + retValue_acc = 2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAddressBookAlias(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_AddressBook0_Alias0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook0_Alias1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook0_Alias2 = value; + } else { + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_AddressBook1_Alias0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook1_Alias1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook1_Alias2 = value; + } else { + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_AddressBook2_Alias0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook2_Alias1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook2_Alias2 = value; + } else { + } + } + } + } else { + } + } + } + return; + } +} +int __ste_Client_AddressBook0_Address0 = 0; +int __ste_Client_AddressBook0_Address1 = 0; +int __ste_Client_AddressBook0_Address2 = 0; +int __ste_Client_AddressBook1_Address0 = 0; +int __ste_Client_AddressBook1_Address1 = 0; +int __ste_Client_AddressBook1_Address2 = 0; +int __ste_Client_AddressBook2_Address0 = 0; +int __ste_Client_AddressBook2_Address1 = 0; +int __ste_Client_AddressBook2_Address2 = 0; +int getClientAddressBookAddress(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook0_Address0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook0_Address1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook0_Address2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook1_Address0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook1_Address1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook1_Address2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook2_Address0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook2_Address1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook2_Address2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAddressBookAddress(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_AddressBook0_Address0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook0_Address1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook0_Address2 = value; + } else { + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_AddressBook1_Address0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook1_Address1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook1_Address2 = value; + } else { + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_AddressBook2_Address0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook2_Address1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook2_Address2 = value; + } else { + } + } + } + } else { + } + } + } + return; + } +} +int __ste_client_autoResponse0 = 0; +int __ste_client_autoResponse1 = 0; +int __ste_client_autoResponse2 = 0; +int getClientAutoResponse(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_autoResponse0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_autoResponse1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_autoResponse2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAutoResponse(int handle, int value) { + + { + if (handle == 1) { + __ste_client_autoResponse0 = value; + } else { + if (handle == 2) { + __ste_client_autoResponse1 = value; + } else { + if (handle == 3) { + __ste_client_autoResponse2 = value; + } else { + } + } + } + return; + } +} +int __ste_client_privateKey0 = 0; +int __ste_client_privateKey1 = 0; +int __ste_client_privateKey2 = 0; +int getClientPrivateKey(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_privateKey0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_privateKey1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_privateKey2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientPrivateKey(int handle, int value) { + + { + if (handle == 1) { + __ste_client_privateKey0 = value; + } else { + if (handle == 2) { + __ste_client_privateKey1 = value; + } else { + if (handle == 3) { + __ste_client_privateKey2 = value; + } else { + } + } + } + return; + } +} +int __ste_ClientKeyring_size0 = 0; +int __ste_ClientKeyring_size1 = 0; +int __ste_ClientKeyring_size2 = 0; +int getClientKeyringSize(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_ClientKeyring_size0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_ClientKeyring_size1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_ClientKeyring_size2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientKeyringSize(int handle, int value) { + + { + if (handle == 1) { + __ste_ClientKeyring_size0 = value; + } else { + if (handle == 2) { + __ste_ClientKeyring_size1 = value; + } else { + if (handle == 3) { + __ste_ClientKeyring_size2 = value; + } else { + } + } + } + return; + } +} +int createClientKeyringEntry(int handle) { + int retValue_acc; + int size; + int tmp; + int __cil_tmp5; + + { + { + tmp = getClientKeyringSize(handle); + size = tmp; + } + if (size < 2) { + { + __cil_tmp5 = size + 1; + setClientKeyringSize(handle, __cil_tmp5); + retValue_acc = size + 1; + } + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +int __ste_Client_Keyring0_User0 = 0; +int __ste_Client_Keyring0_User1 = 0; +int __ste_Client_Keyring0_User2 = 0; +int __ste_Client_Keyring1_User0 = 0; +int __ste_Client_Keyring1_User1 = 0; +int __ste_Client_Keyring1_User2 = 0; +int __ste_Client_Keyring2_User0 = 0; +int __ste_Client_Keyring2_User1 = 0; +int __ste_Client_Keyring2_User2 = 0; +int getClientKeyringUser(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring0_User0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring0_User1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring1_User0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring1_User1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring2_User0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring2_User1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientKeyringUser(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_Keyring0_User0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring0_User1 = value; + } else { + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_Keyring1_User0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring1_User1 = value; + } else { + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_Keyring2_User0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring2_User1 = value; + } else { + } + } + } else { + } + } + } + return; + } +} +int __ste_Client_Keyring0_PublicKey0 = 0; +int __ste_Client_Keyring0_PublicKey1 = 0; +int __ste_Client_Keyring0_PublicKey2 = 0; +int __ste_Client_Keyring1_PublicKey0 = 0; +int __ste_Client_Keyring1_PublicKey1 = 0; +int __ste_Client_Keyring1_PublicKey2 = 0; +int __ste_Client_Keyring2_PublicKey0 = 0; +int __ste_Client_Keyring2_PublicKey1 = 0; +int __ste_Client_Keyring2_PublicKey2 = 0; +int getClientKeyringPublicKey(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring0_PublicKey0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring0_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring1_PublicKey0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring1_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring2_PublicKey0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring2_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +int findPublicKey(int handle, int userid) { + int retValue_acc; + + { + if (handle == 1) { + if (userid == __ste_Client_Keyring0_User0) { + retValue_acc = __ste_Client_Keyring0_PublicKey0; + return (retValue_acc); + } else { + if (userid == __ste_Client_Keyring0_User1) { + retValue_acc = __ste_Client_Keyring0_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 2) { + if (userid == __ste_Client_Keyring1_User0) { + retValue_acc = __ste_Client_Keyring1_PublicKey0; + return (retValue_acc); + } else { + if (userid == __ste_Client_Keyring1_User1) { + retValue_acc = __ste_Client_Keyring1_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 3) { + if (userid == __ste_Client_Keyring2_User0) { + retValue_acc = __ste_Client_Keyring2_PublicKey0; + return (retValue_acc); + } else { + if (userid == __ste_Client_Keyring2_User1) { + retValue_acc = __ste_Client_Keyring2_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientKeyringPublicKey(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_Keyring0_PublicKey0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring0_PublicKey1 = value; + } else { + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_Keyring1_PublicKey0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring1_PublicKey1 = value; + } else { + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_Keyring2_PublicKey0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring2_PublicKey1 = value; + } else { + } + } + } else { + } + } + } + return; + } +} +int __ste_client_forwardReceiver0 = 0; +int __ste_client_forwardReceiver1 = 0; +int __ste_client_forwardReceiver2 = 0; +int __ste_client_forwardReceiver3 = 0; +int getClientForwardReceiver(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_forwardReceiver0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_forwardReceiver1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_forwardReceiver2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientForwardReceiver(int handle, int value) { + + { + if (handle == 1) { + __ste_client_forwardReceiver0 = value; + } else { + if (handle == 2) { + __ste_client_forwardReceiver1 = value; + } else { + if (handle == 3) { + __ste_client_forwardReceiver2 = value; + } else { + } + } + } + return; + } +} +int __ste_client_idCounter0 = 0; +int __ste_client_idCounter1 = 0; +int __ste_client_idCounter2 = 0; +int getClientId(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_idCounter0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_idCounter1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_idCounter2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientId(int handle, int value) { + + { + if (handle == 1) { + __ste_client_idCounter0 = value; + } else { + if (handle == 2) { + __ste_client_idCounter1 = value; + } else { + if (handle == 3) { + __ste_client_idCounter2 = value; + } else { + } + } + } + return; + } +} +#pragma merger(0, "EmailLib.i", "") +int initEmail(void); +void setEmailId(int handle, int value); +char *getEmailSubject(int handle); +void setEmailSubject(int handle, char *value); +char *getEmailBody(int handle); +void setEmailBody(int handle, char *value); +void setEmailIsEncrypted(int handle, int value); +void setEmailEncryptionKey(int handle, int value); +int isSigned(int handle); +void setEmailIsSigned(int handle, int value); +int getEmailSignKey(int handle); +void setEmailSignKey(int handle, int value); +int isVerified(int handle); +void setEmailIsSignatureVerified(int handle, int value); +int __ste_Email_counter = 0; +int initEmail(void) { + int retValue_acc; + + { + if (__ste_Email_counter < 2) { + __ste_Email_counter = __ste_Email_counter + 1; + retValue_acc = __ste_Email_counter; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +int __ste_email_id0 = 0; +int __ste_email_id1 = 0; +int getEmailId(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_id0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_id1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailId(int handle, int value) { + + { + if (handle == 1) { + __ste_email_id0 = value; + } else { + if (handle == 2) { + __ste_email_id1 = value; + } else { + } + } + return; + } +} +int __ste_email_from0 = 0; +int __ste_email_from1 = 0; +int getEmailFrom(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_from0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_from1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailFrom(int handle, int value) { + + { + if (handle == 1) { + __ste_email_from0 = value; + } else { + if (handle == 2) { + __ste_email_from1 = value; + } else { + } + } + return; + } +} +int __ste_email_to0 = 0; +int __ste_email_to1 = 0; +int getEmailTo(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_to0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_to1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailTo(int handle, int value) { + + { + if (handle == 1) { + __ste_email_to0 = value; + } else { + if (handle == 2) { + __ste_email_to1 = value; + } else { + } + } + return; + } +} +char *__ste_email_subject0; +char *__ste_email_subject1; +char *getEmailSubject(int handle) { + char *retValue_acc; + void *__cil_tmp3; + + { + if (handle == 1) { + retValue_acc = __ste_email_subject0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_subject1; + return (retValue_acc); + } else { + __cil_tmp3 = (void *)0; + retValue_acc = (char *)__cil_tmp3; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailSubject(int handle, char *value) { + + { + if (handle == 1) { + __ste_email_subject0 = value; + } else { + if (handle == 2) { + __ste_email_subject1 = value; + } else { + } + } + return; + } +} +char *__ste_email_body0 = (char *)0; +char *__ste_email_body1 = (char *)0; +char *getEmailBody(int handle) { + char *retValue_acc; + void *__cil_tmp3; + + { + if (handle == 1) { + retValue_acc = __ste_email_body0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_body1; + return (retValue_acc); + } else { + __cil_tmp3 = (void *)0; + retValue_acc = (char *)__cil_tmp3; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailBody(int handle, char *value) { + + { + if (handle == 1) { + __ste_email_body0 = value; + } else { + if (handle == 2) { + __ste_email_body1 = value; + } else { + } + } + return; + } +} +int __ste_email_isEncrypted0 = 0; +int __ste_email_isEncrypted1 = 0; +int isEncrypted(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_isEncrypted0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_isEncrypted1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailIsEncrypted(int handle, int value) { + + { + if (handle == 1) { + __ste_email_isEncrypted0 = value; + } else { + if (handle == 2) { + __ste_email_isEncrypted1 = value; + } else { + } + } + return; + } +} +int __ste_email_encryptionKey0 = 0; +int __ste_email_encryptionKey1 = 0; +int getEmailEncryptionKey(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_encryptionKey0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_encryptionKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailEncryptionKey(int handle, int value) { + + { + if (handle == 1) { + __ste_email_encryptionKey0 = value; + } else { + if (handle == 2) { + __ste_email_encryptionKey1 = value; + } else { + } + } + return; + } +} +int __ste_email_isSigned0 = 0; +int __ste_email_isSigned1 = 0; +int isSigned(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_isSigned0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_isSigned1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailIsSigned(int handle, int value) { + + { + if (handle == 1) { + __ste_email_isSigned0 = value; + } else { + if (handle == 2) { + __ste_email_isSigned1 = value; + } else { + } + } + return; + } +} +int __ste_email_signKey0 = 0; +int __ste_email_signKey1 = 0; +int getEmailSignKey(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_signKey0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_signKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailSignKey(int handle, int value) { + + { + if (handle == 1) { + __ste_email_signKey0 = value; + } else { + if (handle == 2) { + __ste_email_signKey1 = value; + } else { + } + } + return; + } +} +int __ste_email_isSignatureVerified0; +int __ste_email_isSignatureVerified1; +int isVerified(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_isSignatureVerified0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_isSignatureVerified1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailIsSignatureVerified(int handle, int value) { + + { + if (handle == 1) { + __ste_email_isSignatureVerified0 = value; + } else { + if (handle == 2) { + __ste_email_isSignatureVerified1 = value; + } else { + } + } + return; + } +} +#pragma merger(0, "DecryptForward_spec.i", "") +inline static void __utac_acc__DecryptForward_spec__1(int msg) { + int tmp; + + { + { + puts("before forward\n"); + tmp = isReadable(msg); + } + if (tmp) { + + } else { + { + __automaton_fail(); + } + } + return; + } +} +#pragma merger(0, "Util.i", "") +int prompt(char *msg); +int prompt(char *msg) { + int retValue_acc; + int retval; + char const *__restrict __cil_tmp4; + + { + { + __cil_tmp4 = (char const *__restrict)"%s\n"; + printf(__cil_tmp4, msg); + retValue_acc = retval; + } + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "Client.i", "") +void queue(int client, int msg); +void mail(int client, int msg); +void deliver(int client, int msg); +void incoming(int client, int msg); +int createClient(char *name); +int isKeyPairValid(int publicKey, int privateKey); +void forward(int client, int msg); +int queue_empty = 1; +int queued_message; +int queued_client; +void mail(int client, int msg) { + int tmp; + + { + { + puts("mail sent"); + tmp = getEmailTo(msg); + incoming(tmp, msg); + } + return; + } +} +void outgoing__wrappee__Keys(int client, int msg) { + int tmp; + + { + { + tmp = getClientId(client); + setEmailFrom(msg, tmp); + mail(client, msg); + } + return; + } +} +void outgoing(int client, int msg) { + int receiver; + int tmp; + int pubkey; + int tmp___0; + + { + { + tmp = getEmailTo(msg); + receiver = tmp; + tmp___0 = findPublicKey(client, receiver); + pubkey = tmp___0; + } + if (pubkey) { + { + setEmailEncryptionKey(msg, pubkey); + setEmailIsEncrypted(msg, 1); + } + } else { + } + { + outgoing__wrappee__Keys(client, msg); + } + return; + } +} +void deliver(int client, int msg) { + + { + { + puts("mail delivered\n"); + } + return; + } +} +void incoming__wrappee__Encrypt(int client, int msg) { + + { + { + deliver(client, msg); + } + return; + } +} +void incoming__wrappee__Forward(int client, int msg) { + int fwreceiver; + int tmp; + + { + { + incoming__wrappee__Encrypt(client, msg); + tmp = getClientForwardReceiver(client); + fwreceiver = tmp; + } + if (fwreceiver) { + { + setEmailTo(msg, fwreceiver); + forward(client, msg); + } + } else { + } + return; + } +} +void incoming(int client, int msg) { + int privkey; + int tmp; + int tmp___0; + int tmp___1; + int tmp___2; + + { + { + tmp = getClientPrivateKey(client); + privkey = tmp; + } + if (privkey) { + { + tmp___0 = isEncrypted(msg); + } + if (tmp___0) { + { + tmp___1 = getEmailEncryptionKey(msg); + tmp___2 = isKeyPairValid(tmp___1, privkey); + } + if (tmp___2) { + { + setEmailIsEncrypted(msg, 0); + setEmailEncryptionKey(msg, 0); + } + } else { + } + } else { + } + } else { + } + { + incoming__wrappee__Forward(client, msg); + } + return; + } +} +int createClient(char *name) { + int retValue_acc; + int client; + int tmp; + + { + { + tmp = initClient(); + client = tmp; + retValue_acc = client; + } + return (retValue_acc); + return (retValue_acc); + } +} +void sendEmail(int sender, int receiver) { + int email; + int tmp; + + { + { + tmp = createEmail(0, receiver); + email = tmp; + outgoing(sender, email); + } + return; + } +} +void queue(int client, int msg) { + + { + queue_empty = 0; + queued_message = msg; + queued_client = client; + return; + } +} +int is_queue_empty(void) { + int retValue_acc; + + { + retValue_acc = queue_empty; + return (retValue_acc); + return (retValue_acc); + } +} +int get_queued_client(void) { + int retValue_acc; + + { + retValue_acc = queued_client; + return (retValue_acc); + return (retValue_acc); + } +} +int get_queued_email(void) { + int retValue_acc; + + { + retValue_acc = queued_message; + return (retValue_acc); + return (retValue_acc); + } +} +int isKeyPairValid(int publicKey, int privateKey) { + int retValue_acc; + char const *__restrict __cil_tmp4; + + { + { + __cil_tmp4 = (char const *__restrict)"keypair valid %d %d"; + printf(__cil_tmp4, publicKey, privateKey); + } + if (!publicKey) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (!privateKey) { + retValue_acc = 0; + return (retValue_acc); + } else { + } + } + retValue_acc = privateKey == publicKey; + return (retValue_acc); + return (retValue_acc); + } +} +void generateKeyPair(int client, int seed) { + + { + { + setClientPrivateKey(client, seed); + } + return; + } +} +void forward(int client, int msg) { + int __utac__ad__arg1; + + { + { + __utac__ad__arg1 = msg; + __utac_acc__DecryptForward_spec__1(__utac__ad__arg1); + puts("Forwarding message.\n"); + printMail(msg); + queue(client, msg); + } + return; + } +} diff --git a/test/regression/2023-10-06-Dubois-015.c b/test/regression/2023-10-06-Dubois-015.c new file mode 100644 index 0000000000..a7917dc82d --- /dev/null +++ b/test/regression/2023-10-06-Dubois-015.c @@ -0,0 +1,354 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=all --search=dfs %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s + +#include "klee-test-comp.c" + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://github.com/sosy-lab/sv-benchmarks +// +// SPDX-FileCopyrightText: 2016 Gilles Audemard +// SPDX-FileCopyrightText: 2020 Dirk Beyer +// SPDX-FileCopyrightText: 2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: MIT + +extern void abort(void) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +extern void __assert_fail(const char *, const char *, unsigned int, + const char *) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); +#endif + abort(); +} +int __VERIFIER_nondet_int(); +void reach_error() { + abort_prog(); + __assert_fail("0", "Dubois-015.c", 5, "reach_error"); +} +void assume(int cond) { + if (!cond) + abort_prog(); +} +int main() { + int cond0; + int dummy = 0; + int N; + int var0; + var0 = __VERIFIER_nondet_int(); + assume(var0 >= 0); + assume(var0 <= 1); + int var1; + var1 = __VERIFIER_nondet_int(); + assume(var1 >= 0); + assume(var1 <= 1); + int var2; + var2 = __VERIFIER_nondet_int(); + assume(var2 >= 0); + assume(var2 <= 1); + int var3; + var3 = __VERIFIER_nondet_int(); + assume(var3 >= 0); + assume(var3 <= 1); + int var4; + var4 = __VERIFIER_nondet_int(); + assume(var4 >= 0); + assume(var4 <= 1); + int var5; + var5 = __VERIFIER_nondet_int(); + assume(var5 >= 0); + assume(var5 <= 1); + int var6; + var6 = __VERIFIER_nondet_int(); + assume(var6 >= 0); + assume(var6 <= 1); + int var7; + var7 = __VERIFIER_nondet_int(); + assume(var7 >= 0); + assume(var7 <= 1); + int var8; + var8 = __VERIFIER_nondet_int(); + assume(var8 >= 0); + assume(var8 <= 1); + int var9; + var9 = __VERIFIER_nondet_int(); + assume(var9 >= 0); + assume(var9 <= 1); + int var10; + var10 = __VERIFIER_nondet_int(); + assume(var10 >= 0); + assume(var10 <= 1); + int var11; + var11 = __VERIFIER_nondet_int(); + assume(var11 >= 0); + assume(var11 <= 1); + int var12; + var12 = __VERIFIER_nondet_int(); + assume(var12 >= 0); + assume(var12 <= 1); + int var13; + var13 = __VERIFIER_nondet_int(); + assume(var13 >= 0); + assume(var13 <= 1); + int var14; + var14 = __VERIFIER_nondet_int(); + assume(var14 >= 0); + assume(var14 <= 1); + int var15; + var15 = __VERIFIER_nondet_int(); + assume(var15 >= 0); + assume(var15 <= 1); + int var16; + var16 = __VERIFIER_nondet_int(); + assume(var16 >= 0); + assume(var16 <= 1); + int var17; + var17 = __VERIFIER_nondet_int(); + assume(var17 >= 0); + assume(var17 <= 1); + int var18; + var18 = __VERIFIER_nondet_int(); + assume(var18 >= 0); + assume(var18 <= 1); + int var19; + var19 = __VERIFIER_nondet_int(); + assume(var19 >= 0); + assume(var19 <= 1); + int var20; + var20 = __VERIFIER_nondet_int(); + assume(var20 >= 0); + assume(var20 <= 1); + int var21; + var21 = __VERIFIER_nondet_int(); + assume(var21 >= 0); + assume(var21 <= 1); + int var22; + var22 = __VERIFIER_nondet_int(); + assume(var22 >= 0); + assume(var22 <= 1); + int var23; + var23 = __VERIFIER_nondet_int(); + assume(var23 >= 0); + assume(var23 <= 1); + int var24; + var24 = __VERIFIER_nondet_int(); + assume(var24 >= 0); + assume(var24 <= 1); + int var25; + var25 = __VERIFIER_nondet_int(); + assume(var25 >= 0); + assume(var25 <= 1); + int var26; + var26 = __VERIFIER_nondet_int(); + assume(var26 >= 0); + assume(var26 <= 1); + int var27; + var27 = __VERIFIER_nondet_int(); + assume(var27 >= 0); + assume(var27 <= 1); + int var28; + var28 = __VERIFIER_nondet_int(); + assume(var28 >= 0); + assume(var28 <= 1); + int var29; + var29 = __VERIFIER_nondet_int(); + assume(var29 >= 0); + assume(var29 <= 1); + int var30; + var30 = __VERIFIER_nondet_int(); + assume(var30 >= 0); + assume(var30 <= 1); + int var31; + var31 = __VERIFIER_nondet_int(); + assume(var31 >= 0); + assume(var31 <= 1); + int var32; + var32 = __VERIFIER_nondet_int(); + assume(var32 >= 0); + assume(var32 <= 1); + int var33; + var33 = __VERIFIER_nondet_int(); + assume(var33 >= 0); + assume(var33 <= 1); + int var34; + var34 = __VERIFIER_nondet_int(); + assume(var34 >= 0); + assume(var34 <= 1); + int var35; + var35 = __VERIFIER_nondet_int(); + assume(var35 >= 0); + assume(var35 <= 1); + int var36; + var36 = __VERIFIER_nondet_int(); + assume(var36 >= 0); + assume(var36 <= 1); + int var37; + var37 = __VERIFIER_nondet_int(); + assume(var37 >= 0); + assume(var37 <= 1); + int var38; + var38 = __VERIFIER_nondet_int(); + assume(var38 >= 0); + assume(var38 <= 1); + int var39; + var39 = __VERIFIER_nondet_int(); + assume(var39 >= 0); + assume(var39 <= 1); + int var40; + var40 = __VERIFIER_nondet_int(); + assume(var40 >= 0); + assume(var40 <= 1); + int var41; + var41 = __VERIFIER_nondet_int(); + assume(var41 >= 0); + assume(var41 <= 1); + int var42; + var42 = __VERIFIER_nondet_int(); + assume(var42 >= 0); + assume(var42 <= 1); + int var43; + var43 = __VERIFIER_nondet_int(); + assume(var43 >= 0); + assume(var43 <= 1); + int var44; + var44 = __VERIFIER_nondet_int(); + assume(var44 >= 0); + assume(var44 <= 1); + int myvar0 = 1; + assume((var28 == 0 & var29 == 0 & var0 == 1) | + (var28 == 0 & var29 == 1 & var0 == 0) | + (var28 == 1 & var29 == 0 & var0 == 0) | + (var28 == 1 & var29 == 1 & var0 == 1) | 0); + assume((var1 == 0 & var31 == 0 & var2 == 1) | + (var1 == 0 & var31 == 1 & var2 == 0) | + (var1 == 1 & var31 == 0 & var2 == 0) | + (var1 == 1 & var31 == 1 & var2 == 1) | 0); + assume((var2 == 0 & var32 == 0 & var3 == 1) | + (var2 == 0 & var32 == 1 & var3 == 0) | + (var2 == 1 & var32 == 0 & var3 == 0) | + (var2 == 1 & var32 == 1 & var3 == 1) | 0); + assume((var3 == 0 & var33 == 0 & var4 == 1) | + (var3 == 0 & var33 == 1 & var4 == 0) | + (var3 == 1 & var33 == 0 & var4 == 0) | + (var3 == 1 & var33 == 1 & var4 == 1) | 0); + assume((var4 == 0 & var34 == 0 & var5 == 1) | + (var4 == 0 & var34 == 1 & var5 == 0) | + (var4 == 1 & var34 == 0 & var5 == 0) | + (var4 == 1 & var34 == 1 & var5 == 1) | 0); + assume((var5 == 0 & var35 == 0 & var6 == 1) | + (var5 == 0 & var35 == 1 & var6 == 0) | + (var5 == 1 & var35 == 0 & var6 == 0) | + (var5 == 1 & var35 == 1 & var6 == 1) | 0); + assume((var6 == 0 & var36 == 0 & var7 == 1) | + (var6 == 0 & var36 == 1 & var7 == 0) | + (var6 == 1 & var36 == 0 & var7 == 0) | + (var6 == 1 & var36 == 1 & var7 == 1) | 0); + assume((var7 == 0 & var37 == 0 & var8 == 1) | + (var7 == 0 & var37 == 1 & var8 == 0) | + (var7 == 1 & var37 == 0 & var8 == 0) | + (var7 == 1 & var37 == 1 & var8 == 1) | 0); + assume((var8 == 0 & var38 == 0 & var9 == 1) | + (var8 == 0 & var38 == 1 & var9 == 0) | + (var8 == 1 & var38 == 0 & var9 == 0) | + (var8 == 1 & var38 == 1 & var9 == 1) | 0); + assume((var9 == 0 & var39 == 0 & var10 == 1) | + (var9 == 0 & var39 == 1 & var10 == 0) | + (var9 == 1 & var39 == 0 & var10 == 0) | + (var9 == 1 & var39 == 1 & var10 == 1) | 0); + assume((var10 == 0 & var40 == 0 & var11 == 1) | + (var10 == 0 & var40 == 1 & var11 == 0) | + (var10 == 1 & var40 == 0 & var11 == 0) | + (var10 == 1 & var40 == 1 & var11 == 1) | 0); + assume((var11 == 0 & var41 == 0 & var12 == 1) | + (var11 == 0 & var41 == 1 & var12 == 0) | + (var11 == 1 & var41 == 0 & var12 == 0) | + (var11 == 1 & var41 == 1 & var12 == 1) | 0); + assume((var12 == 0 & var42 == 0 & var13 == 1) | + (var12 == 0 & var42 == 1 & var13 == 0) | + (var12 == 1 & var42 == 0 & var13 == 0) | + (var12 == 1 & var42 == 1 & var13 == 1) | 0); + assume((var0 == 0 & var30 == 0 & var1 == 1) | + (var0 == 0 & var30 == 1 & var1 == 0) | + (var0 == 1 & var30 == 0 & var1 == 0) | + (var0 == 1 & var30 == 1 & var1 == 1) | 0); + assume((var14 == 0 & var43 == 0 & var44 == 1) | + (var14 == 0 & var43 == 1 & var44 == 0) | + (var14 == 1 & var43 == 0 & var44 == 0) | + (var14 == 1 & var43 == 1 & var44 == 1) | 0); + assume((var13 == 0 & var43 == 0 & var44 == 1) | + (var13 == 0 & var43 == 1 & var44 == 0) | + (var13 == 1 & var43 == 0 & var44 == 0) | + (var13 == 1 & var43 == 1 & var44 == 1) | 0); + assume((var16 == 0 & var41 == 0 & var15 == 1) | + (var16 == 0 & var41 == 1 & var15 == 0) | + (var16 == 1 & var41 == 0 & var15 == 0) | + (var16 == 1 & var41 == 1 & var15 == 1) | 0); + assume((var17 == 0 & var40 == 0 & var16 == 1) | + (var17 == 0 & var40 == 1 & var16 == 0) | + (var17 == 1 & var40 == 0 & var16 == 0) | + (var17 == 1 & var40 == 1 & var16 == 1) | 0); + assume((var18 == 0 & var39 == 0 & var17 == 1) | + (var18 == 0 & var39 == 1 & var17 == 0) | + (var18 == 1 & var39 == 0 & var17 == 0) | + (var18 == 1 & var39 == 1 & var17 == 1) | 0); + assume((var19 == 0 & var38 == 0 & var18 == 1) | + (var19 == 0 & var38 == 1 & var18 == 0) | + (var19 == 1 & var38 == 0 & var18 == 0) | + (var19 == 1 & var38 == 1 & var18 == 1) | 0); + assume((var20 == 0 & var37 == 0 & var19 == 1) | + (var20 == 0 & var37 == 1 & var19 == 0) | + (var20 == 1 & var37 == 0 & var19 == 0) | + (var20 == 1 & var37 == 1 & var19 == 1) | 0); + assume((var21 == 0 & var36 == 0 & var20 == 1) | + (var21 == 0 & var36 == 1 & var20 == 0) | + (var21 == 1 & var36 == 0 & var20 == 0) | + (var21 == 1 & var36 == 1 & var20 == 1) | 0); + assume((var22 == 0 & var35 == 0 & var21 == 1) | + (var22 == 0 & var35 == 1 & var21 == 0) | + (var22 == 1 & var35 == 0 & var21 == 0) | + (var22 == 1 & var35 == 1 & var21 == 1) | 0); + assume((var23 == 0 & var34 == 0 & var22 == 1) | + (var23 == 0 & var34 == 1 & var22 == 0) | + (var23 == 1 & var34 == 0 & var22 == 0) | + (var23 == 1 & var34 == 1 & var22 == 1) | 0); + assume((var24 == 0 & var33 == 0 & var23 == 1) | + (var24 == 0 & var33 == 1 & var23 == 0) | + (var24 == 1 & var33 == 0 & var23 == 0) | + (var24 == 1 & var33 == 1 & var23 == 1) | 0); + assume((var25 == 0 & var32 == 0 & var24 == 1) | + (var25 == 0 & var32 == 1 & var24 == 0) | + (var25 == 1 & var32 == 0 & var24 == 0) | + (var25 == 1 & var32 == 1 & var24 == 1) | 0); + assume((var26 == 0 & var31 == 0 & var25 == 1) | + (var26 == 0 & var31 == 1 & var25 == 0) | + (var26 == 1 & var31 == 0 & var25 == 0) | + (var26 == 1 & var31 == 1 & var25 == 1) | 0); + assume((var27 == 0 & var30 == 0 & var26 == 1) | + (var27 == 0 & var30 == 1 & var26 == 0) | + (var27 == 1 & var30 == 0 & var26 == 0) | + (var27 == 1 & var30 == 1 & var26 == 1) | 0); + assume((var15 == 0 & var42 == 0 & var14 == 1) | + (var15 == 0 & var42 == 1 & var14 == 0) | + (var15 == 1 & var42 == 0 & var14 == 0) | + (var15 == 1 & var42 == 1 & var14 == 1) | 0); + assume((var28 == 0 & var29 == 0 & var27 == 0) | + (var28 == 0 & var29 == 1 & var27 == 1) | + (var28 == 1 & var29 == 0 & var27 == 1) | + (var28 == 1 & var29 == 1 & var27 == 0) | 0); + reach_error(); + return 0; /* 0 x[0]1 x[1]2 x[2]3 x[3]4 x[4]5 x[5]6 x[6]7 x[7]8 x[8]9 x[9]10 + x[10]11 x[11]12 x[12]13 x[13]14 x[14]15 x[15]16 x[16]17 x[17]18 + x[18]19 x[19]20 x[20]21 x[21]22 x[22]23 x[23]24 x[24]25 x[25]26 + x[26]27 x[27]28 x[28]29 x[29]30 x[30]31 x[31]32 x[32]33 x[33]34 + x[34]35 x[35]36 x[36]37 x[37]38 x[38]39 x[39]40 x[40]41 x[41]42 + x[42]43 x[43]44 x[44] */ +} + +// CHECK: generated tests = 2 \ No newline at end of file diff --git a/test/regression/2023-10-12-inner-types-fix.c b/test/regression/2023-10-12-inner-types-fix.c new file mode 100644 index 0000000000..2484dc6a1f --- /dev/null +++ b/test/regression/2023-10-12-inner-types-fix.c @@ -0,0 +1,89 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --entry-point=klee_entry --skip-not-lazy-initialized --min-number-elements-li=1 %t1.bc 2>&1 +// RUN: %ktest-tool %t.klee-out/test000003.ktest | FileCheck %s + +#include "klee/klee.h" + +struct StructWithPointer { + int x; + int *y; +}; + +struct StructWithDoublePointer { + int x; + int **y; +}; + +struct StructWithArrayOfPointer { + int x; + int *y[2]; +}; + +struct StructWithStructWithPointer { + struct StructWithPointer swp; + struct StructWithDoublePointer *swdp; +}; + +struct StructManyPointers { + int a; + int *b; + int **c; + int ***d; +}; + +struct StructComplex { + int x; + int *y; + int **z; + struct StructWithPointer *swp; + struct StructWithDoublePointer **swdp; + struct StructManyPointers smp; +}; + +int sumStructWithPointer(struct StructWithPointer par) { + return par.x + *par.y; +} + +int sumStructWithPointerAsPointer(struct StructWithPointer *par) { + return par->x + *par->y; +} + +int sumStructWithDoublePointer(struct StructWithDoublePointer par) { + return par.x + **par.y; +} + +int sumStructWithArrayOfPointer(struct StructWithArrayOfPointer par) { + return par.x + *(par.y[0]) + *(par.y[1]); +} + +int sumStructWithStructWithPointer(struct StructWithStructWithPointer par) { + int sswp = sumStructWithPointer(par.swp); + int sswdp = sumStructWithDoublePointer(*par.swdp); + return sswp + sswdp; +} + +int sumStructManyPointers(struct StructManyPointers par) { + return par.a + *par.b + **par.c + ***par.d; +} + +int sumStructComplex(struct StructComplex par) { + int sswp = sumStructWithPointer(*par.swp); + int sswdp = sumStructWithDoublePointer(**par.swdp); + int ssmp = sumStructManyPointers(par.smp); + return par.x + *par.y + **par.z + sswp + sswdp + ssmp; +} + +// CHECK: object 2: pointers: [(8, 3, 0)] +int klee_entry(int utbot_argc, char **utbot_argv, char **utbot_envp) { + struct StructComplex par; + klee_make_symbolic(&par, sizeof(par), "par"); + klee_prefer_cex(&par, par.x >= -10 & par.x <= 10); + klee_prefer_cex(&par, par.smp.a >= -10 & par.smp.a <= 10); + //////////////////////////////////////////// + int utbot_result; + klee_make_symbolic(&utbot_result, sizeof(utbot_result), "utbot_result"); + int utbot_tmp = sumStructComplex(par); + klee_assume(utbot_tmp == utbot_result); + return 0; +} \ No newline at end of file diff --git a/test/regression/2023-10-13-kbfiltr.i.cil-2.c b/test/regression/2023-10-13-kbfiltr.i.cil-2.c new file mode 100644 index 0000000000..f65ab2393b --- /dev/null +++ b/test/regression/2023-10-13-kbfiltr.i.cil-2.c @@ -0,0 +1,3646 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --mock-all-externals --external-calls=all --use-forked-solver=false --max-memory=6008 --skip-not-lazy-initialized --istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --write-kqueries --write-xml-tests --only-output-states-covering-new=true --dump-states-on-halt=all --emit-all-errors=true --search=bfs %t1.bc +// RUN: ls %t.klee-out | grep _1.xml | wc -l | grep 8 + +#include "klee-test-comp.c" + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "kbfiltr.i.cil-2.c", 3, "reach_error"); } + +extern char __VERIFIER_nondet_char(void); +extern int __VERIFIER_nondet_int(void); +extern long __VERIFIER_nondet_long(void); +extern unsigned long __VERIFIER_nondet_ulong(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +/* Generated by CIL v. 1.3.6 */ +/* print_CIL_Input is true */ + +#pragma pack(push, 8) +#pragma pack(pop) +typedef unsigned short wchar_t; +typedef unsigned long ULONG_PTR; +typedef unsigned long *PULONG_PTR; +typedef ULONG_PTR SIZE_T; +typedef void *PVOID; +typedef char CHAR; +typedef short SHORT; +typedef long LONG; +typedef wchar_t WCHAR; +typedef WCHAR *PWSTR; +typedef WCHAR const *PCWSTR; +typedef CHAR *PCHAR; +typedef LONG *PLONG; +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG; +typedef UCHAR *PUCHAR; +typedef ULONG *PULONG; +typedef void *HANDLE; +typedef HANDLE *PHANDLE; +typedef char CCHAR; +typedef short CSHORT; +typedef ULONG LCID; +typedef LONG NTSTATUS; +typedef long long LONGLONG; +struct __anonstruct____missing_field_name_1 { + ULONG LowPart; + LONG HighPart; +}; +struct __anonstruct_u_2 { + ULONG LowPart; + LONG HighPart; +}; +union _LARGE_INTEGER { + struct __anonstruct____missing_field_name_1 __annonCompField1; + struct __anonstruct_u_2 u; + LONGLONG QuadPart; +}; +typedef union _LARGE_INTEGER LARGE_INTEGER; +typedef LARGE_INTEGER *PLARGE_INTEGER; +struct _LUID { + ULONG LowPart; + LONG HighPart; +}; +typedef struct _LUID LUID; +typedef LARGE_INTEGER PHYSICAL_ADDRESS; +enum _EVENT_TYPE { + NotificationEvent = 0, + SynchronizationEvent = 1 +}; +typedef enum _EVENT_TYPE EVENT_TYPE; +typedef char const *PCSZ; +struct _STRING { + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +}; +typedef struct _STRING STRING; +typedef STRING *PSTRING; +typedef PSTRING PANSI_STRING; +struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +}; +typedef struct _UNICODE_STRING UNICODE_STRING; +typedef UNICODE_STRING *PUNICODE_STRING; +typedef UCHAR BOOLEAN; +typedef BOOLEAN *PBOOLEAN; +struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +}; +typedef struct _LIST_ENTRY LIST_ENTRY; +typedef struct _LIST_ENTRY *PLIST_ENTRY; +struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +}; +typedef struct _OBJECT_ATTRIBUTES OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; +struct _GUID { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}; +typedef struct _GUID GUID; +typedef unsigned int size_t; +typedef UCHAR KIRQL; +struct _KTHREAD; +typedef struct _KTHREAD *PKTHREAD; +struct _ETHREAD; +typedef struct _ETHREAD *PETHREAD; +struct _EPROCESS; +typedef struct _EPROCESS *PEPROCESS; +struct _IO_TIMER; +typedef struct _IO_TIMER *PIO_TIMER; +struct _OBJECT_TYPE; +typedef struct _OBJECT_TYPE *POBJECT_TYPE; +typedef CCHAR KPROCESSOR_MODE; +struct _KAPC; +struct _KAPC; +typedef void (*PKNORMAL_ROUTINE)(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2); +struct _KAPC { + CSHORT Type; + CSHORT Size; + ULONG Spare0; + struct _KTHREAD *Thread; + LIST_ENTRY ApcListEntry; + void (*KernelRoutine)(struct _KAPC *Apc, PKNORMAL_ROUTINE *NormalRoutine, PVOID *NormalContext, + PVOID *SystemArgument1, PVOID *SystemArgument2); + void (*RundownRoutine)(struct _KAPC *Apc); + void (*NormalRoutine)(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2); + PVOID NormalContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + CCHAR ApcStateIndex; + KPROCESSOR_MODE ApcMode; + BOOLEAN Inserted; +}; +typedef struct _KAPC KAPC; +struct _KDPC; +struct _KDPC; +struct _KDPC { + CSHORT Type; + UCHAR Number; + UCHAR Importance; + LIST_ENTRY DpcListEntry; + void (*DeferredRoutine)(struct _KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, + PVOID SystemArgument2); + PVOID DeferredContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + PULONG_PTR Lock; +}; +typedef struct _KDPC KDPC; +typedef struct _KDPC *PKDPC; +struct _MDL { + struct _MDL *Next; + CSHORT Size; + CSHORT MdlFlags; + struct _EPROCESS *Process; + PVOID MappedSystemVa; + PVOID StartVa; + ULONG ByteCount; + ULONG ByteOffset; +}; +typedef struct _MDL MDL; +typedef struct _MDL *PMDL; +typedef PVOID PACCESS_TOKEN; +typedef PVOID PSECURITY_DESCRIPTOR; +typedef ULONG ACCESS_MASK; +#pragma pack(push, 4) +struct _LUID_AND_ATTRIBUTES { + LUID Luid; + ULONG Attributes; +}; +typedef struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES; +#pragma pack(pop) +struct _PRIVILEGE_SET { + ULONG PrivilegeCount; + ULONG Control; + LUID_AND_ATTRIBUTES Privilege[1]; +}; +typedef struct _PRIVILEGE_SET PRIVILEGE_SET; +enum _SECURITY_IMPERSONATION_LEVEL { + SecurityAnonymous = 0, + SecurityIdentification = 1, + SecurityImpersonation = 2, + SecurityDelegation = 3 +}; +typedef enum _SECURITY_IMPERSONATION_LEVEL SECURITY_IMPERSONATION_LEVEL; +typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE; +struct _SECURITY_QUALITY_OF_SERVICE { + ULONG Length; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode; + BOOLEAN EffectiveOnly; +}; +typedef struct _SECURITY_QUALITY_OF_SERVICE *PSECURITY_QUALITY_OF_SERVICE; +typedef ULONG SECURITY_INFORMATION; +typedef LONG KPRIORITY; +typedef ULONG_PTR KSPIN_LOCK; +typedef KSPIN_LOCK *PKSPIN_LOCK; +struct _RTL_QUERY_REGISTRY_TABLE { + NTSTATUS(*QueryRoutine) + (PWSTR ValueName, ULONG ValueType, + PVOID ValueData, ULONG ValueLength, + PVOID Context, PVOID EntryContext); + ULONG Flags; + PWSTR Name; + PVOID EntryContext; + ULONG DefaultType; + PVOID DefaultData; + ULONG DefaultLength; +}; +typedef struct _RTL_QUERY_REGISTRY_TABLE *PRTL_QUERY_REGISTRY_TABLE; +union __anonunion____missing_field_name_6 { + NTSTATUS Status; + PVOID Pointer; +}; +struct _IO_STATUS_BLOCK { + union __anonunion____missing_field_name_6 __annonCompField4; + ULONG_PTR Information; +}; +typedef struct _IO_STATUS_BLOCK IO_STATUS_BLOCK; +typedef struct _IO_STATUS_BLOCK *PIO_STATUS_BLOCK; +enum _FILE_INFORMATION_CLASS { + FileDirectoryInformation = 1, + FileFullDirectoryInformation = 2, + FileBothDirectoryInformation = 3, + FileBasicInformation = 4, + FileStandardInformation = 5, + FileInternalInformation = 6, + FileEaInformation = 7, + FileAccessInformation = 8, + FileNameInformation = 9, + FileRenameInformation = 10, + FileLinkInformation = 11, + FileNamesInformation = 12, + FileDispositionInformation = 13, + FilePositionInformation = 14, + FileFullEaInformation = 15, + FileModeInformation = 16, + FileAlignmentInformation = 17, + FileAllInformation = 18, + FileAllocationInformation = 19, + FileEndOfFileInformation = 20, + FileAlternateNameInformation = 21, + FileStreamInformation = 22, + FilePipeInformation = 23, + FilePipeLocalInformation = 24, + FilePipeRemoteInformation = 25, + FileMailslotQueryInformation = 26, + FileMailslotSetInformation = 27, + FileCompressionInformation = 28, + FileObjectIdInformation = 29, + FileCompletionInformation = 30, + FileMoveClusterInformation = 31, + FileQuotaInformation = 32, + FileReparsePointInformation = 33, + FileNetworkOpenInformation = 34, + FileAttributeTagInformation = 35, + FileTrackingInformation = 36, + FileMaximumInformation = 37 +}; +typedef enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS; +struct _FILE_BASIC_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + ULONG FileAttributes; +}; +typedef struct _FILE_BASIC_INFORMATION *PFILE_BASIC_INFORMATION; +struct _FILE_STANDARD_INFORMATION { + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; +}; +typedef struct _FILE_STANDARD_INFORMATION *PFILE_STANDARD_INFORMATION; +struct _FILE_NETWORK_OPEN_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; +}; +typedef struct _FILE_NETWORK_OPEN_INFORMATION *PFILE_NETWORK_OPEN_INFORMATION; +enum _FSINFOCLASS { + FileFsVolumeInformation = 1, + FileFsLabelInformation = 2, + FileFsSizeInformation = 3, + FileFsDeviceInformation = 4, + FileFsAttributeInformation = 5, + FileFsControlInformation = 6, + FileFsFullSizeInformation = 7, + FileFsObjectIdInformation = 8, + FileFsMaximumInformation = 9 +}; +typedef enum _FSINFOCLASS FS_INFORMATION_CLASS; +enum _INTERFACE_TYPE { + InterfaceTypeUndefined = -1, + Internal = 0, + Isa = 1, + Eisa = 2, + MicroChannel = 3, + TurboChannel = 4, + PCIBus = 5, + VMEBus = 6, + NuBus = 7, + PCMCIABus = 8, + CBus = 9, + MPIBus = 10, + MPSABus = 11, + ProcessorInternal = 12, + InternalPowerBus = 13, + PNPISABus = 14, + PNPBus = 15, + MaximumInterfaceType = 16 +}; +typedef enum _INTERFACE_TYPE INTERFACE_TYPE; +typedef enum _INTERFACE_TYPE *PINTERFACE_TYPE; +struct _IO_ERROR_LOG_PACKET { + UCHAR MajorFunctionCode; + UCHAR RetryCount; + USHORT DumpDataSize; + USHORT NumberOfStrings; + USHORT StringOffset; + USHORT EventCategory; + NTSTATUS ErrorCode; + ULONG UniqueErrorValue; + NTSTATUS FinalStatus; + ULONG SequenceNumber; + ULONG IoControlCode; + LARGE_INTEGER DeviceOffset; + ULONG DumpData[1]; +}; +typedef struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET; +struct _KEY_VALUE_FULL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + WCHAR Name[1]; +}; +typedef struct _KEY_VALUE_FULL_INFORMATION *PKEY_VALUE_FULL_INFORMATION; +struct _CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +}; +typedef struct _CLIENT_ID CLIENT_ID; +typedef CLIENT_ID *PCLIENT_ID; +enum _SYSTEM_POWER_STATE { + PowerSystemUnspecified = 0, + PowerSystemWorking = 1, + PowerSystemSleeping1 = 2, + PowerSystemSleeping2 = 3, + PowerSystemSleeping3 = 4, + PowerSystemHibernate = 5, + PowerSystemShutdown = 6, + PowerSystemMaximum = 7 +}; +typedef enum _SYSTEM_POWER_STATE SYSTEM_POWER_STATE; +enum __anonenum_POWER_ACTION_11 { + PowerActionNone = 0, + PowerActionReserved = 1, + PowerActionSleep = 2, + PowerActionHibernate = 3, + PowerActionShutdown = 4, + PowerActionShutdownReset = 5, + PowerActionShutdownOff = 6, + PowerActionWarmEject = 7 +}; +typedef enum __anonenum_POWER_ACTION_11 POWER_ACTION; +enum _DEVICE_POWER_STATE { + PowerDeviceUnspecified = 0, + PowerDeviceD0 = 1, + PowerDeviceD1 = 2, + PowerDeviceD2 = 3, + PowerDeviceD3 = 4, + PowerDeviceMaximum = 5 +}; +typedef enum _DEVICE_POWER_STATE DEVICE_POWER_STATE; +union _POWER_STATE { + SYSTEM_POWER_STATE SystemState; + DEVICE_POWER_STATE DeviceState; +}; +typedef union _POWER_STATE POWER_STATE; +enum _POWER_STATE_TYPE { + SystemPowerState = 0, + DevicePowerState = 1 +}; +typedef enum _POWER_STATE_TYPE POWER_STATE_TYPE; +typedef PVOID PASSIGNED_RESOURCE; +#pragma pack(push, 4) +struct __anonstruct_Generic_16 { + PHYSICAL_ADDRESS Start; + ULONG Length; +}; +struct __anonstruct_Port_17 { + PHYSICAL_ADDRESS Start; + ULONG Length; +}; +struct __anonstruct_Interrupt_18 { + ULONG Level; + ULONG Vector; + ULONG Affinity; +}; +struct __anonstruct_Memory_19 { + PHYSICAL_ADDRESS Start; + ULONG Length; +}; +struct __anonstruct_Dma_20 { + ULONG Channel; + ULONG Port; + ULONG Reserved1; +}; +struct __anonstruct_DevicePrivate_21 { + ULONG Data[3]; +}; +struct __anonstruct_BusNumber_22 { + ULONG Start; + ULONG Length; + ULONG Reserved; +}; +struct __anonstruct_DeviceSpecificData_23 { + ULONG DataSize; + ULONG Reserved1; + ULONG Reserved2; +}; +union __anonunion_u_15 { + struct __anonstruct_Generic_16 Generic; + struct __anonstruct_Port_17 Port; + struct __anonstruct_Interrupt_18 Interrupt; + struct __anonstruct_Memory_19 Memory; + struct __anonstruct_Dma_20 Dma; + struct __anonstruct_DevicePrivate_21 DevicePrivate; + struct __anonstruct_BusNumber_22 BusNumber; + struct __anonstruct_DeviceSpecificData_23 DeviceSpecificData; +}; +struct _CM_PARTIAL_RESOURCE_DESCRIPTOR { + UCHAR Type; + UCHAR ShareDisposition; + USHORT Flags; + union __anonunion_u_15 u; +}; +typedef struct _CM_PARTIAL_RESOURCE_DESCRIPTOR CM_PARTIAL_RESOURCE_DESCRIPTOR; +#pragma pack(pop) +struct _CM_PARTIAL_RESOURCE_LIST { + USHORT Version; + USHORT Revision; + ULONG Count; + CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]; +}; +typedef struct _CM_PARTIAL_RESOURCE_LIST CM_PARTIAL_RESOURCE_LIST; +struct _CM_FULL_RESOURCE_DESCRIPTOR { + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + CM_PARTIAL_RESOURCE_LIST PartialResourceList; +}; +typedef struct _CM_FULL_RESOURCE_DESCRIPTOR CM_FULL_RESOURCE_DESCRIPTOR; +struct _CM_RESOURCE_LIST { + ULONG Count; + CM_FULL_RESOURCE_DESCRIPTOR List[1]; +}; +typedef struct _CM_RESOURCE_LIST *PCM_RESOURCE_LIST; +#pragma pack(push, 1) +#pragma pack(pop) +struct __anonstruct_Port_25 { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; +}; +struct __anonstruct_Memory_26 { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; +}; +struct __anonstruct_Interrupt_27 { + ULONG MinimumVector; + ULONG MaximumVector; +}; +struct __anonstruct_Dma_28 { + ULONG MinimumChannel; + ULONG MaximumChannel; +}; +struct __anonstruct_Generic_29 { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; +}; +struct __anonstruct_DevicePrivate_30 { + ULONG Data[3]; +}; +struct __anonstruct_BusNumber_31 { + ULONG Length; + ULONG MinBusNumber; + ULONG MaxBusNumber; + ULONG Reserved; +}; +struct __anonstruct_AssignedResource_32 { + PASSIGNED_RESOURCE AssignedResource; +}; +struct __anonstruct_SubAllocateFrom_33 { + UCHAR Type; + UCHAR Reserved[3]; + PASSIGNED_RESOURCE AssignedResource; + PHYSICAL_ADDRESS Transformation; +}; +struct __anonstruct_ConfigData_34 { + ULONG Priority; + ULONG Reserved1; + ULONG Reserved2; +}; +union __anonunion_u_24 { + struct __anonstruct_Port_25 Port; + struct __anonstruct_Memory_26 Memory; + struct __anonstruct_Interrupt_27 Interrupt; + struct __anonstruct_Dma_28 Dma; + struct __anonstruct_Generic_29 Generic; + struct __anonstruct_DevicePrivate_30 DevicePrivate; + struct __anonstruct_BusNumber_31 BusNumber; + struct __anonstruct_AssignedResource_32 AssignedResource; + struct __anonstruct_SubAllocateFrom_33 SubAllocateFrom; + struct __anonstruct_ConfigData_34 ConfigData; +}; +struct _IO_RESOURCE_DESCRIPTOR { + UCHAR Option; + UCHAR Type; + UCHAR ShareDisposition; + UCHAR Spare1; + USHORT Flags; + USHORT Spare2; + union __anonunion_u_24 u; +}; +typedef struct _IO_RESOURCE_DESCRIPTOR IO_RESOURCE_DESCRIPTOR; +struct _IO_RESOURCE_LIST { + USHORT Version; + USHORT Revision; + ULONG Count; + IO_RESOURCE_DESCRIPTOR Descriptors[1]; +}; +typedef struct _IO_RESOURCE_LIST IO_RESOURCE_LIST; +struct _IO_RESOURCE_REQUIREMENTS_LIST { + ULONG ListSize; + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + ULONG SlotNumber; + ULONG Reserved[3]; + ULONG AlternativeLists; + IO_RESOURCE_LIST List[1]; +}; +typedef struct _IO_RESOURCE_REQUIREMENTS_LIST *PIO_RESOURCE_REQUIREMENTS_LIST; +enum _CONFIGURATION_TYPE { + ArcSystem = 0, + CentralProcessor = 1, + FloatingPointProcessor = 2, + PrimaryIcache = 3, + PrimaryDcache = 4, + SecondaryIcache = 5, + SecondaryDcache = 6, + SecondaryCache = 7, + EisaAdapter = 8, + TcAdapter = 9, + ScsiAdapter = 10, + DtiAdapter = 11, + MultiFunctionAdapter = 12, + DiskController = 13, + TapeController = 14, + CdromController = 15, + WormController = 16, + SerialController = 17, + NetworkController = 18, + DisplayController = 19, + ParallelController = 20, + PointerController = 21, + KeyboardController = 22, + AudioController = 23, + OtherController = 24, + DiskPeripheral = 25, + FloppyDiskPeripheral = 26, + TapePeripheral = 27, + ModemPeripheral = 28, + MonitorPeripheral = 29, + PrinterPeripheral = 30, + PointerPeripheral = 31, + KeyboardPeripheral = 32, + TerminalPeripheral = 33, + OtherPeripheral = 34, + LinePeripheral = 35, + NetworkPeripheral = 36, + SystemMemory = 37, + DockingInformation = 38, + RealModeIrqRoutingTable = 39, + MaximumType = 40 +}; +typedef enum _CONFIGURATION_TYPE CONFIGURATION_TYPE; +typedef enum _CONFIGURATION_TYPE *PCONFIGURATION_TYPE; +enum _KWAIT_REASON { + Executive = 0, + FreePage = 1, + PageIn = 2, + PoolAllocation = 3, + DelayExecution = 4, + Suspended = 5, + UserRequest = 6, + WrExecutive = 7, + WrFreePage = 8, + WrPageIn = 9, + WrPoolAllocation = 10, + WrDelayExecution = 11, + WrSuspended = 12, + WrUserRequest = 13, + WrEventPair = 14, + WrQueue = 15, + WrLpcReceive = 16, + WrLpcReply = 17, + WrVirtualMemory = 18, + WrPageOut = 19, + WrRendezvous = 20, + Spare2 = 21, + Spare3 = 22, + Spare4 = 23, + Spare5 = 24, + Spare6 = 25, + WrKernel = 26, + MaximumWaitReason = 27 +}; +typedef enum _KWAIT_REASON KWAIT_REASON; +struct _DISPATCHER_HEADER { + UCHAR Type; + UCHAR Absolute; + UCHAR Size; + UCHAR Inserted; + LONG SignalState; + LIST_ENTRY WaitListHead; +}; +typedef struct _DISPATCHER_HEADER DISPATCHER_HEADER; +struct _KDEVICE_QUEUE { + CSHORT Type; + CSHORT Size; + LIST_ENTRY DeviceListHead; + KSPIN_LOCK Lock; + BOOLEAN Busy; +}; +typedef struct _KDEVICE_QUEUE KDEVICE_QUEUE; +struct _KDEVICE_QUEUE_ENTRY { + LIST_ENTRY DeviceListEntry; + ULONG SortKey; + BOOLEAN Inserted; +}; +typedef struct _KDEVICE_QUEUE_ENTRY KDEVICE_QUEUE_ENTRY; +struct _KEVENT { + DISPATCHER_HEADER Header; +}; +typedef struct _KEVENT KEVENT; +typedef struct _KEVENT *PKEVENT; +typedef struct _KEVENT *PRKEVENT; +struct _KSEMAPHORE { + DISPATCHER_HEADER Header; + LONG Limit; +}; +typedef struct _KSEMAPHORE *PKSEMAPHORE; +typedef struct _KSEMAPHORE *PRKSEMAPHORE; +enum _MEMORY_CACHING_TYPE { + MmNonCached = 0, + MmCached = 1, + MmWriteCombined = 2, + MmHardwareCoherentCached = 3, + MmNonCachedUnordered = 4, + MmUSWCCached = 5, + MmMaximumCacheType = 6 +}; +typedef enum _MEMORY_CACHING_TYPE MEMORY_CACHING_TYPE; +enum _POOL_TYPE { + NonPagedPool = 0, + PagedPool = 1, + NonPagedPoolMustSucceed = 2, + DontUseThisType = 3, + NonPagedPoolCacheAligned = 4, + PagedPoolCacheAligned = 5, + NonPagedPoolCacheAlignedMustS = 6, + MaxPoolType = 7, + NonPagedPoolSession = 32, + PagedPoolSession = 33, + NonPagedPoolMustSucceedSession = 34, + DontUseThisTypeSession = 35, + NonPagedPoolCacheAlignedSession = 36, + PagedPoolCacheAlignedSession = 37, + NonPagedPoolCacheAlignedMustSSession = 38 +}; +typedef enum _POOL_TYPE POOL_TYPE; +struct _FAST_MUTEX { + LONG Count; + PKTHREAD Owner; + ULONG Contention; + KEVENT Event; + ULONG OldIrql; +}; +typedef struct _FAST_MUTEX *PFAST_MUTEX; +typedef ULONG_PTR ERESOURCE_THREAD; +union __anonunion____missing_field_name_38 { + LONG OwnerCount; + ULONG TableSize; +}; +struct _OWNER_ENTRY { + ERESOURCE_THREAD OwnerThread; + union __anonunion____missing_field_name_38 __annonCompField10; +}; +typedef struct _OWNER_ENTRY OWNER_ENTRY; +typedef struct _OWNER_ENTRY *POWNER_ENTRY; +union __anonunion____missing_field_name_39 { + PVOID Address; + ULONG_PTR CreatorBackTraceIndex; +}; +struct _ERESOURCE { + LIST_ENTRY SystemResourcesList; + POWNER_ENTRY OwnerTable; + SHORT ActiveCount; + USHORT Flag; + PKSEMAPHORE SharedWaiters; + PKEVENT ExclusiveWaiters; + OWNER_ENTRY OwnerThreads[2]; + ULONG ContentionCount; + USHORT NumberOfSharedWaiters; + USHORT NumberOfExclusiveWaiters; + union __anonunion____missing_field_name_39 __annonCompField11; + KSPIN_LOCK SpinLock; +}; +enum _MM_PAGE_PRIORITY { + LowPagePriority = 0, + NormalPagePriority = 16, + HighPagePriority = 32 +}; +typedef enum _MM_PAGE_PRIORITY MM_PAGE_PRIORITY; +struct _DRIVER_OBJECT; +struct _DRIVER_OBJECT; +struct _SECURITY_SUBJECT_CONTEXT { + PACCESS_TOKEN ClientToken; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + PACCESS_TOKEN PrimaryToken; + PVOID ProcessAuditId; +}; +typedef struct _SECURITY_SUBJECT_CONTEXT SECURITY_SUBJECT_CONTEXT; +struct _INITIAL_PRIVILEGE_SET { + ULONG PrivilegeCount; + ULONG Control; + LUID_AND_ATTRIBUTES Privilege[3]; +}; +typedef struct _INITIAL_PRIVILEGE_SET INITIAL_PRIVILEGE_SET; +union __anonunion_Privileges_40 { + INITIAL_PRIVILEGE_SET InitialPrivilegeSet; + PRIVILEGE_SET PrivilegeSet; +}; +struct _ACCESS_STATE { + LUID OperationID; + BOOLEAN SecurityEvaluated; + BOOLEAN GenerateAudit; + BOOLEAN GenerateOnClose; + BOOLEAN PrivilegesAllocated; + ULONG Flags; + ACCESS_MASK RemainingDesiredAccess; + ACCESS_MASK PreviouslyGrantedAccess; + ACCESS_MASK OriginalDesiredAccess; + SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; + PSECURITY_DESCRIPTOR SecurityDescriptor; + PVOID AuxData; + union __anonunion_Privileges_40 Privileges; + BOOLEAN AuditPrivileges; + UNICODE_STRING ObjectName; + UNICODE_STRING ObjectTypeName; +}; +typedef struct _ACCESS_STATE *PACCESS_STATE; +struct _DEVICE_OBJECT; +struct _DEVICE_OBJECT; +struct _DRIVER_OBJECT; +struct _FILE_OBJECT; +struct _FILE_OBJECT; +struct _IRP; +struct _IRP; +struct _SCSI_REQUEST_BLOCK; +struct _SCSI_REQUEST_BLOCK; +typedef NTSTATUS (*PDRIVER_DISPATCH)(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp); +struct _COMPRESSED_DATA_INFO; +struct _FAST_IO_DISPATCH { + ULONG SizeOfFastIoDispatch; + BOOLEAN(*FastIoCheckIfPossible) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, BOOLEAN Wait, ULONG LockKey, + BOOLEAN CheckForReadOperation, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoRead) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoWrite) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoQueryBasicInfo) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + PFILE_BASIC_INFORMATION Buffer, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoQueryStandardInfo) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + PFILE_STANDARD_INFORMATION Buffer, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoLock) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, + BOOLEAN FailImmediately, BOOLEAN ExclusiveLock, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoUnlockSingle) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoUnlockAll) + (struct _FILE_OBJECT *FileObject, PEPROCESS ProcessId, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoUnlockAllByKey) + (struct _FILE_OBJECT *FileObject, PVOID ProcessId, + ULONG Key, PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoDeviceControl) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, + ULONG OutputBufferLength, ULONG IoControlCode, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + void (*AcquireFileForNtCreateSection)(struct _FILE_OBJECT *FileObject); + void (*ReleaseFileForNtCreateSection)(struct _FILE_OBJECT *FileObject); + void (*FastIoDetachDevice)(struct _DEVICE_OBJECT *SourceDevice, struct _DEVICE_OBJECT *TargetDevice); + BOOLEAN(*FastIoQueryNetworkOpenInfo) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + struct _FILE_NETWORK_OPEN_INFORMATION *Buffer, + struct _IO_STATUS_BLOCK *IoStatus, struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*AcquireForModWrite) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER EndingOffset, + struct _ERESOURCE **ResourceToRelease, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlRead) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlReadComplete) + (struct _FILE_OBJECT *FileObject, PMDL MdlChain, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*PrepareMdlWrite) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlWriteComplete) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PMDL MdlChain, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoReadCompressed) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PVOID Buffer, PMDL *MdlChain, + PIO_STATUS_BLOCK IoStatus, struct _COMPRESSED_DATA_INFO *CompressedDataInfo, + ULONG CompressedDataInfoLength, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoWriteCompressed) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PVOID Buffer, + PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, struct _COMPRESSED_DATA_INFO *CompressedDataInfo, + ULONG CompressedDataInfoLength, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlReadCompleteCompressed) + (struct _FILE_OBJECT *FileObject, PMDL MdlChain, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlWriteCompleteCompressed) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PMDL MdlChain, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoQueryOpen) + (struct _IRP *Irp, PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, + struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*ReleaseForModWrite) + (struct _FILE_OBJECT *FileObject, struct _ERESOURCE *ResourceToRelease, + struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*AcquireForCcFlush) + (struct _FILE_OBJECT *FileObject, struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*ReleaseForCcFlush) + (struct _FILE_OBJECT *FileObject, struct _DEVICE_OBJECT *DeviceObject); +}; +typedef struct _FAST_IO_DISPATCH *PFAST_IO_DISPATCH; +enum _IO_ALLOCATION_ACTION { + KeepObject = 1, + DeallocateObject = 2, + DeallocateObjectKeepRegisters = 3 +}; +typedef enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION; +struct _IO_SECURITY_CONTEXT { + PSECURITY_QUALITY_OF_SERVICE SecurityQos; + PACCESS_STATE AccessState; + ACCESS_MASK DesiredAccess; + ULONG FullCreateOptions; +}; +typedef struct _IO_SECURITY_CONTEXT *PIO_SECURITY_CONTEXT; +struct _VPB { + CSHORT Type; + CSHORT Size; + USHORT Flags; + USHORT VolumeLabelLength; + struct _DEVICE_OBJECT *DeviceObject; + struct _DEVICE_OBJECT *RealDevice; + ULONG SerialNumber; + ULONG ReferenceCount; + WCHAR VolumeLabel[(32U * sizeof(WCHAR)) / sizeof(WCHAR)]; +}; +typedef struct _VPB *PVPB; +struct _WAIT_CONTEXT_BLOCK { + KDEVICE_QUEUE_ENTRY WaitQueueEntry; + IO_ALLOCATION_ACTION(*DeviceRoutine) + (struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp, + PVOID MapRegisterBase, PVOID Context); + PVOID DeviceContext; + ULONG NumberOfMapRegisters; + PVOID DeviceObject; + PVOID CurrentIrp; + PKDPC BufferChainingDpc; +}; +typedef struct _WAIT_CONTEXT_BLOCK WAIT_CONTEXT_BLOCK; +union __anonunion_Queue_43 { + LIST_ENTRY ListEntry; + WAIT_CONTEXT_BLOCK Wcb; +}; +struct _DEVOBJ_EXTENSION; +struct _DEVICE_OBJECT { + CSHORT Type; + USHORT Size; + LONG ReferenceCount; + struct _DRIVER_OBJECT *DriverObject; + struct _DEVICE_OBJECT *NextDevice; + struct _DEVICE_OBJECT *AttachedDevice; + struct _IRP *CurrentIrp; + PIO_TIMER Timer; + ULONG Flags; + ULONG Characteristics; + PVPB Vpb; + PVOID DeviceExtension; + ULONG DeviceType; + CCHAR StackSize; + union __anonunion_Queue_43 Queue; + ULONG AlignmentRequirement; + KDEVICE_QUEUE DeviceQueue; + KDPC Dpc; + ULONG ActiveThreadCount; + PSECURITY_DESCRIPTOR SecurityDescriptor; + KEVENT DeviceLock; + USHORT SectorSize; + USHORT Spare1; + struct _DEVOBJ_EXTENSION *DeviceObjectExtension; + PVOID Reserved; +}; +typedef struct _DEVICE_OBJECT DEVICE_OBJECT; +typedef struct _DEVICE_OBJECT *PDEVICE_OBJECT; +struct _DEVOBJ_EXTENSION { + CSHORT Type; + USHORT Size; + PDEVICE_OBJECT DeviceObject; +}; +struct _DRIVER_EXTENSION { + struct _DRIVER_OBJECT *DriverObject; + NTSTATUS(*AddDevice) + (struct _DRIVER_OBJECT *DriverObject, struct _DEVICE_OBJECT *PhysicalDeviceObject); + ULONG Count; + UNICODE_STRING ServiceKeyName; +}; +typedef struct _DRIVER_EXTENSION *PDRIVER_EXTENSION; +struct _DRIVER_OBJECT { + CSHORT Type; + CSHORT Size; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; + PVOID DriverStart; + ULONG DriverSize; + PVOID DriverSection; + PDRIVER_EXTENSION DriverExtension; + UNICODE_STRING DriverName; + PUNICODE_STRING HardwareDatabase; + PFAST_IO_DISPATCH FastIoDispatch; + NTSTATUS(*DriverInit) + (struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath); + void (*DriverStartIo)(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp); + void (*DriverUnload)(struct _DRIVER_OBJECT *DriverObject); + PDRIVER_DISPATCH MajorFunction[28]; +}; +typedef struct _DRIVER_OBJECT DRIVER_OBJECT; +typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT; +struct _SECTION_OBJECT_POINTERS { + PVOID DataSectionObject; + PVOID SharedCacheMap; + PVOID ImageSectionObject; +}; +typedef struct _SECTION_OBJECT_POINTERS SECTION_OBJECT_POINTERS; +typedef SECTION_OBJECT_POINTERS *PSECTION_OBJECT_POINTERS; +struct _IO_COMPLETION_CONTEXT { + PVOID Port; + PVOID Key; +}; +typedef struct _IO_COMPLETION_CONTEXT *PIO_COMPLETION_CONTEXT; +struct _FILE_OBJECT { + CSHORT Type; + CSHORT Size; + PDEVICE_OBJECT DeviceObject; + PVPB Vpb; + PVOID FsContext; + PVOID FsContext2; + PSECTION_OBJECT_POINTERS SectionObjectPointer; + PVOID PrivateCacheMap; + NTSTATUS FinalStatus; + struct _FILE_OBJECT *RelatedFileObject; + BOOLEAN LockOperation; + BOOLEAN DeletePending; + BOOLEAN ReadAccess; + BOOLEAN WriteAccess; + BOOLEAN DeleteAccess; + BOOLEAN SharedRead; + BOOLEAN SharedWrite; + BOOLEAN SharedDelete; + ULONG Flags; + UNICODE_STRING FileName; + LARGE_INTEGER CurrentByteOffset; + ULONG Waiters; + ULONG Busy; + PVOID LastLock; + KEVENT Lock; + KEVENT Event; + PIO_COMPLETION_CONTEXT CompletionContext; +}; +typedef struct _FILE_OBJECT *PFILE_OBJECT; +union __anonunion_AssociatedIrp_44 { + struct _IRP *MasterIrp; + LONG IrpCount; + PVOID SystemBuffer; +}; +struct __anonstruct_AsynchronousParameters_46 { + void (*UserApcRoutine)(PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved); + PVOID UserApcContext; +}; +union __anonunion_Overlay_45 { + struct __anonstruct_AsynchronousParameters_46 AsynchronousParameters; + LARGE_INTEGER AllocationSize; +}; +struct __anonstruct____missing_field_name_50 { + PVOID DriverContext[4]; +}; +union __anonunion____missing_field_name_49 { + KDEVICE_QUEUE_ENTRY DeviceQueueEntry; + struct __anonstruct____missing_field_name_50 __annonCompField14; +}; +struct _IO_STACK_LOCATION; +union __anonunion____missing_field_name_52 { + struct _IO_STACK_LOCATION *CurrentStackLocation; + ULONG PacketType; +}; +struct __anonstruct____missing_field_name_51 { + LIST_ENTRY ListEntry; + union __anonunion____missing_field_name_52 __annonCompField16; +}; +struct __anonstruct_Overlay_48 { + union __anonunion____missing_field_name_49 __annonCompField15; + PETHREAD Thread; + PCHAR AuxiliaryBuffer; + struct __anonstruct____missing_field_name_51 __annonCompField17; + PFILE_OBJECT OriginalFileObject; +}; +union __anonunion_Tail_47 { + struct __anonstruct_Overlay_48 Overlay; + KAPC Apc; + PVOID CompletionKey; +}; +struct _IRP { + CSHORT Type; + USHORT Size; + PMDL MdlAddress; + ULONG Flags; + union __anonunion_AssociatedIrp_44 AssociatedIrp; + LIST_ENTRY ThreadListEntry; + IO_STATUS_BLOCK IoStatus; + KPROCESSOR_MODE RequestorMode; + BOOLEAN PendingReturned; + CHAR StackCount; + CHAR CurrentLocation; + BOOLEAN Cancel; + KIRQL CancelIrql; + CCHAR ApcEnvironment; + UCHAR AllocationFlags; + PIO_STATUS_BLOCK UserIosb; + PKEVENT UserEvent; + union __anonunion_Overlay_45 Overlay; + void (*CancelRoutine)(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp); + PVOID UserBuffer; + union __anonunion_Tail_47 Tail; +}; +typedef struct _IRP IRP; +typedef struct _IRP *PIRP; +enum _DEVICE_RELATION_TYPE { + BusRelations = 0, + EjectionRelations = 1, + PowerRelations = 2, + RemovalRelations = 3, + TargetDeviceRelation = 4 +}; +typedef enum _DEVICE_RELATION_TYPE DEVICE_RELATION_TYPE; +enum _DEVICE_USAGE_NOTIFICATION_TYPE { + DeviceUsageTypeUndefined = 0, + DeviceUsageTypePaging = 1, + DeviceUsageTypeHibernation = 2, + DeviceUsageTypeDumpFile = 3 +}; +typedef enum _DEVICE_USAGE_NOTIFICATION_TYPE DEVICE_USAGE_NOTIFICATION_TYPE; +struct _INTERFACE { + USHORT Size; + USHORT Version; + PVOID Context; + void (*InterfaceReference)(PVOID Context); + void (*InterfaceDereference)(PVOID Context); +}; +typedef struct _INTERFACE *PINTERFACE; +struct _DEVICE_CAPABILITIES { + USHORT Size; + USHORT Version; + ULONG DeviceD1 : 1; + ULONG DeviceD2 : 1; + ULONG LockSupported : 1; + ULONG EjectSupported : 1; + ULONG Removable : 1; + ULONG DockDevice : 1; + ULONG UniqueID : 1; + ULONG SilentInstall : 1; + ULONG RawDeviceOK : 1; + ULONG SurpriseRemovalOK : 1; + ULONG WakeFromD0 : 1; + ULONG WakeFromD1 : 1; + ULONG WakeFromD2 : 1; + ULONG WakeFromD3 : 1; + ULONG HardwareDisabled : 1; + ULONG NonDynamic : 1; + ULONG WarmEjectSupported : 1; + ULONG Reserved : 15; + ULONG Address; + ULONG UINumber; + DEVICE_POWER_STATE DeviceState[7]; + SYSTEM_POWER_STATE SystemWake; + DEVICE_POWER_STATE DeviceWake; + ULONG D1Latency; + ULONG D2Latency; + ULONG D3Latency; +}; +typedef struct _DEVICE_CAPABILITIES *PDEVICE_CAPABILITIES; +struct _POWER_SEQUENCE { + ULONG SequenceD1; + ULONG SequenceD2; + ULONG SequenceD3; +}; +typedef struct _POWER_SEQUENCE *PPOWER_SEQUENCE; +enum __anonenum_BUS_QUERY_ID_TYPE_53 { + BusQueryDeviceID = 0, + BusQueryHardwareIDs = 1, + BusQueryCompatibleIDs = 2, + BusQueryInstanceID = 3, + BusQueryDeviceSerialNumber = 4 +}; +typedef enum __anonenum_BUS_QUERY_ID_TYPE_53 BUS_QUERY_ID_TYPE; +enum __anonenum_DEVICE_TEXT_TYPE_54 { + DeviceTextDescription = 0, + DeviceTextLocationInformation = 1 +}; +typedef enum __anonenum_DEVICE_TEXT_TYPE_54 DEVICE_TEXT_TYPE; +#pragma pack(push, 4) +struct __anonstruct_Create_56 { + PIO_SECURITY_CONTEXT SecurityContext; + ULONG Options; + USHORT FileAttributes; + USHORT ShareAccess; + ULONG EaLength; +}; +struct __anonstruct_Read_57 { + ULONG Length; + ULONG Key; + LARGE_INTEGER ByteOffset; +}; +struct __anonstruct_Write_58 { + ULONG Length; + ULONG Key; + LARGE_INTEGER ByteOffset; +}; +struct __anonstruct_QueryFile_59 { + ULONG Length; + FILE_INFORMATION_CLASS FileInformationClass; +}; +struct __anonstruct____missing_field_name_62 { + BOOLEAN ReplaceIfExists; + BOOLEAN AdvanceOnly; +}; +union __anonunion____missing_field_name_61 { + struct __anonstruct____missing_field_name_62 __annonCompField18; + ULONG ClusterCount; + HANDLE DeleteHandle; +}; +struct __anonstruct_SetFile_60 { + ULONG Length; + FILE_INFORMATION_CLASS FileInformationClass; + PFILE_OBJECT FileObject; + union __anonunion____missing_field_name_61 __annonCompField19; +}; +struct __anonstruct_QueryVolume_63 { + ULONG Length; + FS_INFORMATION_CLASS FsInformationClass; +}; +struct __anonstruct_DeviceIoControl_64 { + ULONG OutputBufferLength; + ULONG InputBufferLength; + ULONG IoControlCode; + PVOID Type3InputBuffer; +}; +struct __anonstruct_QuerySecurity_65 { + SECURITY_INFORMATION SecurityInformation; + ULONG Length; +}; +struct __anonstruct_SetSecurity_66 { + SECURITY_INFORMATION SecurityInformation; + PSECURITY_DESCRIPTOR SecurityDescriptor; +}; +struct __anonstruct_MountVolume_67 { + PVPB Vpb; + PDEVICE_OBJECT DeviceObject; +}; +struct __anonstruct_VerifyVolume_68 { + PVPB Vpb; + PDEVICE_OBJECT DeviceObject; +}; +struct __anonstruct_Scsi_69 { + struct _SCSI_REQUEST_BLOCK *Srb; +}; +struct __anonstruct_QueryDeviceRelations_70 { + DEVICE_RELATION_TYPE Type; +}; +struct __anonstruct_QueryInterface_71 { + GUID const *InterfaceType; + USHORT Size; + USHORT Version; + PINTERFACE Interface; + PVOID InterfaceSpecificData; +}; +struct __anonstruct_DeviceCapabilities_72 { + PDEVICE_CAPABILITIES Capabilities; +}; +struct __anonstruct_FilterResourceRequirements_73 { + PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList; +}; +struct __anonstruct_ReadWriteConfig_74 { + ULONG WhichSpace; + PVOID Buffer; + ULONG Offset; + ULONG Length; +}; +struct __anonstruct_SetLock_75 { + BOOLEAN Lock; +}; +struct __anonstruct_QueryId_76 { + BUS_QUERY_ID_TYPE IdType; +}; +struct __anonstruct_QueryDeviceText_77 { + DEVICE_TEXT_TYPE DeviceTextType; + LCID LocaleId; +}; +struct __anonstruct_UsageNotification_78 { + BOOLEAN InPath; + BOOLEAN Reserved[3]; + DEVICE_USAGE_NOTIFICATION_TYPE Type; +}; +struct __anonstruct_WaitWake_79 { + SYSTEM_POWER_STATE PowerState; +}; +struct __anonstruct_PowerSequence_80 { + PPOWER_SEQUENCE PowerSequence; +}; +struct __anonstruct_Power_81 { + ULONG SystemContext; + POWER_STATE_TYPE Type; + POWER_STATE State; + POWER_ACTION ShutdownType; +}; +struct __anonstruct_StartDevice_82 { + PCM_RESOURCE_LIST AllocatedResources; + PCM_RESOURCE_LIST AllocatedResourcesTranslated; +}; +struct __anonstruct_WMI_83 { + ULONG_PTR ProviderId; + PVOID DataPath; + ULONG BufferSize; + PVOID Buffer; +}; +struct __anonstruct_Others_84 { + PVOID Argument1; + PVOID Argument2; + PVOID Argument3; + PVOID Argument4; +}; +union __anonunion_Parameters_55 { + struct __anonstruct_Create_56 Create; + struct __anonstruct_Read_57 Read; + struct __anonstruct_Write_58 Write; + struct __anonstruct_QueryFile_59 QueryFile; + struct __anonstruct_SetFile_60 SetFile; + struct __anonstruct_QueryVolume_63 QueryVolume; + struct __anonstruct_DeviceIoControl_64 DeviceIoControl; + struct __anonstruct_QuerySecurity_65 QuerySecurity; + struct __anonstruct_SetSecurity_66 SetSecurity; + struct __anonstruct_MountVolume_67 MountVolume; + struct __anonstruct_VerifyVolume_68 VerifyVolume; + struct __anonstruct_Scsi_69 Scsi; + struct __anonstruct_QueryDeviceRelations_70 QueryDeviceRelations; + struct __anonstruct_QueryInterface_71 QueryInterface; + struct __anonstruct_DeviceCapabilities_72 DeviceCapabilities; + struct __anonstruct_FilterResourceRequirements_73 FilterResourceRequirements; + struct __anonstruct_ReadWriteConfig_74 ReadWriteConfig; + struct __anonstruct_SetLock_75 SetLock; + struct __anonstruct_QueryId_76 QueryId; + struct __anonstruct_QueryDeviceText_77 QueryDeviceText; + struct __anonstruct_UsageNotification_78 UsageNotification; + struct __anonstruct_WaitWake_79 WaitWake; + struct __anonstruct_PowerSequence_80 PowerSequence; + struct __anonstruct_Power_81 Power; + struct __anonstruct_StartDevice_82 StartDevice; + struct __anonstruct_WMI_83 WMI; + struct __anonstruct_Others_84 Others; +}; +struct _IO_STACK_LOCATION { + UCHAR MajorFunction; + UCHAR MinorFunction; + UCHAR Flags; + UCHAR Control; + union __anonunion_Parameters_55 Parameters; + PDEVICE_OBJECT DeviceObject; + PFILE_OBJECT FileObject; + NTSTATUS(*CompletionRoutine) + (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context); + PVOID Context; +}; +typedef struct _IO_STACK_LOCATION IO_STACK_LOCATION; +typedef struct _IO_STACK_LOCATION *PIO_STACK_LOCATION; +#pragma pack(pop) +struct _CONFIGURATION_INFORMATION { + ULONG DiskCount; + ULONG FloppyCount; + ULONG CdRomCount; + ULONG TapeCount; + ULONG ScsiPortCount; + ULONG SerialCount; + ULONG ParallelCount; + BOOLEAN AtDiskPrimaryAddressClaimed; + BOOLEAN AtDiskSecondaryAddressClaimed; + ULONG Version; + ULONG MediumChangerCount; +}; +typedef struct _CONFIGURATION_INFORMATION CONFIGURATION_INFORMATION; +typedef struct _CONFIGURATION_INFORMATION *PCONFIGURATION_INFORMATION; +struct _OBJECT_HANDLE_INFORMATION { + ULONG HandleAttributes; + ACCESS_MASK GrantedAccess; +}; +typedef struct _OBJECT_HANDLE_INFORMATION *POBJECT_HANDLE_INFORMATION; +struct _KEYBOARD_INPUT_DATA { + USHORT UnitId; + USHORT MakeCode; + USHORT Flags; + USHORT Reserved; + ULONG ExtraInformation; +}; +typedef struct _KEYBOARD_INPUT_DATA *PKEYBOARD_INPUT_DATA; +struct _CONNECT_DATA { + PDEVICE_OBJECT ClassDeviceObject; + PVOID ClassService; +}; +typedef struct _CONNECT_DATA CONNECT_DATA; +typedef struct _CONNECT_DATA *PCONNECT_DATA; +enum _TRANSMIT_STATE { + Idle = 0, + SendingBytes = 1 +}; +typedef enum _TRANSMIT_STATE TRANSMIT_STATE; +struct _OUTPUT_PACKET { + PUCHAR Bytes; + ULONG CurrentByte; + ULONG ByteCount; + TRANSMIT_STATE State; +}; +typedef struct _OUTPUT_PACKET *POUTPUT_PACKET; +enum _KEYBOARD_SCAN_STATE { + Normal = 0, + GotE0 = 1, + GotE1 = 2 +}; +typedef enum _KEYBOARD_SCAN_STATE *PKEYBOARD_SCAN_STATE; +struct _INTERNAL_I8042_HOOK_KEYBOARD { + PVOID Context; + NTSTATUS(*InitializationRoutine) + (PVOID InitializationContext, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, + UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn); + BOOLEAN(*IsrRoutine) + (PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, PUCHAR Byte, PBOOLEAN ContinueProcessing, + PKEYBOARD_SCAN_STATE ScanState); + void (*IsrWritePort)(PVOID Context, UCHAR Value); + void (*QueueKeyboardPacket)(PVOID Context); + PVOID CallContext; +}; +typedef struct _INTERNAL_I8042_HOOK_KEYBOARD INTERNAL_I8042_HOOK_KEYBOARD; +typedef struct _INTERNAL_I8042_HOOK_KEYBOARD *PINTERNAL_I8042_HOOK_KEYBOARD; +struct _DEVICE_EXTENSION { + PDEVICE_OBJECT Self; + PDEVICE_OBJECT PDO; + PDEVICE_OBJECT TopOfStack; + LONG EnableCount; + CONNECT_DATA UpperConnectData; + PVOID UpperContext; + NTSTATUS(*UpperInitializationRoutine) + (PVOID InitializationContext, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn); + BOOLEAN(*UpperIsrHook) + (PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR Byte, + PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState); + void (*IsrWritePort)(PVOID Context, UCHAR Value); + void (*QueueKeyboardPacket)(PVOID Context); + PVOID CallContext; + DEVICE_POWER_STATE DeviceState; + BOOLEAN Started; + BOOLEAN SurpriseRemoved; + BOOLEAN Removed; +}; +typedef struct _DEVICE_EXTENSION DEVICE_EXTENSION; +typedef struct _DEVICE_EXTENSION *PDEVICE_EXTENSION; +#pragma pack(push, 8) +#pragma pack(pop) +struct _KAPC; +struct _KDPC; +#pragma pack(push, 4) +#pragma pack(pop) +#pragma pack(push, 4) +#pragma pack(pop) +#pragma pack(push, 1) +#pragma pack(pop) +struct _DRIVER_OBJECT; +struct _DEVICE_OBJECT; +struct _DRIVER_OBJECT; +struct _FILE_OBJECT; +struct _IRP; +struct _SCSI_REQUEST_BLOCK; +#pragma pack(push, 4) +#pragma pack(pop) +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +extern void *memcpy(void *, void const *, size_t); +extern void *memmove(void *, void const *, size_t); +extern void *memset(void *, int, size_t); +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +NTSTATUS RtlQueryRegistryValues(ULONG RelativeTo, + PCWSTR Path, + PRTL_QUERY_REGISTRY_TABLE QueryTable, + PVOID Context, + PVOID Environment); +NTSTATUS RtlDeleteRegistryValue(ULONG RelativeTo, + PCWSTR Path, + PCWSTR ValueName); +void RtlInitString(PSTRING DestinationString, + PCSZ SourceString); +void RtlInitUnicodeString(PUNICODE_STRING DestinationString, + PCWSTR SourceString); +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString); +void RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString); +void RtlFreeUnicodeString(PUNICODE_STRING UnicodeString); +SIZE_T RtlCompareMemory(void const *Source1, + void const *Source2, + SIZE_T Length); +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +LONG InterlockedIncrement(PLONG Addend) { + return ++(*Addend); +} +LONG InterlockedDecrement(PLONG Addend) { + return --(*Addend); +} +#pragma warning(disable : 4035) +#pragma warning(push) +#pragma warning(disable : 4164) +#pragma function(_enable) +#pragma function(_disable) +#pragma warning(pop) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +void KeInitializeEvent(PRKEVENT Event, EVENT_TYPE Type, + BOOLEAN State); +LONG KeSetEvent(PRKEVENT Event, KPRIORITY Increment, + BOOLEAN Wait); +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore, + LONG Count, LONG Limit); +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore, KPRIORITY Increment, + LONG Adjustment, BOOLEAN Wait); +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Interval); +NTSTATUS KeWaitForSingleObject(PVOID Object, KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout); +void KeInitializeSpinLock(PKSPIN_LOCK SpinLock); +void KfReleaseSpinLock(PKSPIN_LOCK SpinLock, + KIRQL NewIrql); +PVOID ExAllocatePoolWithTag(POOL_TYPE PoolType, + SIZE_T NumberOfBytes, + ULONG Tag); +void ExFreePool(PVOID P); +void ExAcquireFastMutex(PFAST_MUTEX FastMutex); +void ExReleaseFastMutex(PFAST_MUTEX FastMutex); +PLIST_ENTRY ExfInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedRemoveHeadList(PLIST_ENTRY ListHead, + PKSPIN_LOCK Lock); +void MmUnlockPages(PMDL MemoryDescriptorList); +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList, + KPROCESSOR_MODE AccessMode, + MEMORY_CACHING_TYPE CacheType, + PVOID BaseAddress, + ULONG BugCheckOnFailure, + MM_PAGE_PRIORITY Priority); +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes, + PHYSICAL_ADDRESS HighestAcceptableAddress); +void MmFreeContiguousMemory(PVOID BaseAddress); +void MmResetDriverPaging(PVOID AddressWithinSection); +PVOID MmPageEntireDriver(PVOID AddressWithinSection); +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, + ULONG DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + void (*StartRoutine)(PVOID StartContext), + PVOID StartContext); +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus); +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +PMDL IoAllocateMdl(PVOID VirtualAddress, ULONG Length, + BOOLEAN SecondaryBuffer, BOOLEAN ChargeQuota, + PIRP Irp); +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, + PDEVICE_OBJECT TargetDevice); +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock); +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode, + PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + BOOLEAN InternalDeviceIoControl, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock); +NTSTATUS IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +void IofCompleteRequest(PIRP Irp, + CCHAR PriorityBoost); +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject, + ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, + ULONG DeviceType, ULONG DeviceCharacteristics, + BOOLEAN Exclusive, PDEVICE_OBJECT *DeviceObject); +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName); +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject); +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName); +void IoDetachDevice(PDEVICE_OBJECT TargetDevice); +void IoFreeIrp(PIRP Irp); +void IoFreeMdl(PMDL Mdl); +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void); +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType, + PULONG BusNumber, + PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, + PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, + NTSTATUS (*CalloutRoutine)(PVOID Context, + PUNICODE_STRING PathName, + INTERFACE_TYPE BusType, + ULONG BusNumber, + PKEY_VALUE_FULL_INFORMATION *BusInformation, + CONFIGURATION_TYPE ControllerType, + ULONG ControllerNumber, + PKEY_VALUE_FULL_INFORMATION *ControllerInformation, + CONFIGURATION_TYPE PeripheralType, + ULONG PeripheralNumber, + PKEY_VALUE_FULL_INFORMATION *PeripheralInformation), + PVOID Context); +void IoReleaseCancelSpinLock(KIRQL Irql); +void IoSetHardErrorOrVerifyDevice(PIRP Irp, PDEVICE_OBJECT DeviceObject); +NTSTATUS IoRegisterDeviceInterface(PDEVICE_OBJECT PhysicalDeviceObject, + GUID const *InterfaceClassGuid, + PUNICODE_STRING ReferenceString, + PUNICODE_STRING SymbolicLinkName); +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName, + BOOLEAN Enable); +#pragma warning(disable : 4200) +#pragma warning(default : 4200) +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +void PoStartNextPowerIrp(PIRP Irp); +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID *Object, + POBJECT_HANDLE_INFORMATION HandleInformation); +void ObfDereferenceObject(PVOID Object); +NTSTATUS ZwClose(HANDLE Handle); +NTSTATUS KbFilter_AddDevice(PDRIVER_OBJECT Driver, PDEVICE_OBJECT PDO); +NTSTATUS KbFilter_CreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_DispatchPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_InternIoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_IoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + if (__VERIFIER_nondet_int()) { + return 0L; + } else if (__VERIFIER_nondet_int()) { + return -1L; + } else { + return 259L; + } +} +NTSTATUS KbFilter_PnP(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_Power(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_InitializationRoutine(PDEVICE_OBJECT DeviceObject, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn); +BOOLEAN KbFilter_IsrHook(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR DataByte, + PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState); +void KbFilter_ServiceCallback(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA InputDataStart, + PKEYBOARD_INPUT_DATA InputDataEnd, PULONG InputDataConsumed); +void KbFilter_Unload(PDRIVER_OBJECT Driver); +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); +#pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(PAGE, KbFilter_AddDevice) +#pragma alloc_text(PAGE, KbFilter_CreateClose) +#pragma alloc_text(PAGE, KbFilter_IoCtl) +#pragma alloc_text(PAGE, KbFilter_InternIoCtl) +#pragma alloc_text(PAGE, KbFilter_Unload) +#pragma alloc_text(PAGE, KbFilter_DispatchPassThrough) +#pragma alloc_text(PAGE, KbFilter_PnP) +#pragma alloc_text(PAGE, KbFilter_Power) +extern void *malloc(size_t); +void errorFn(void) { + + { + ERROR : { + reach_error(); + abort(); + } + } +} +int s; +int UNLOADED; +int NP; +int DC; +int SKIP1; +int SKIP2; +int MPR1; +int MPR3; +int IPC; +int pended; +NTSTATUS(*compFptr) +(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context); +int compRegistered; +int lowerDriverReturn; +int setEventCalled; +int customIrp; +int myStatus; +void _BLAST_init(void) { + + { + UNLOADED = 0; + NP = 1; + DC = 2; + SKIP1 = 3; + SKIP2 = 4; + MPR1 = 5; + MPR3 = 6; + IPC = 7; + s = UNLOADED; + pended = 0; + compFptr = 0; + compRegistered = 0; + lowerDriverReturn = 0; + setEventCalled = 0; + customIrp = 0; + return; + } +} +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { + ULONG i = __VERIFIER_nondet_long(); + assume_abort_if_not(i < 28); + + { + DriverObject->MajorFunction[i] = &KbFilter_DispatchPassThrough; + DriverObject->MajorFunction[0] = &KbFilter_CreateClose; + DriverObject->MajorFunction[2] = &KbFilter_CreateClose; + DriverObject->MajorFunction[27] = &KbFilter_PnP; + DriverObject->MajorFunction[22] = &KbFilter_Power; + DriverObject->MajorFunction[15] = &KbFilter_InternIoCtl; + DriverObject->DriverUnload = &KbFilter_Unload; + (DriverObject->DriverExtension)->AddDevice = &KbFilter_AddDevice; + return (0L); + } +} +NTSTATUS KbFilter_AddDevice(PDRIVER_OBJECT Driver, PDEVICE_OBJECT PDO) { + PDEVICE_EXTENSION devExt; + PDEVICE_OBJECT device; + NTSTATUS status; + + { + { + status = 0L; + status = IoCreateDevice(Driver, sizeof(DEVICE_EXTENSION), (void *)0, 11, 0, 0, + &device); + } + if (!(status >= 0L)) { + return (status); + } else { + } + { + memset(device->DeviceExtension, 0, sizeof(DEVICE_EXTENSION)); + devExt = (struct _DEVICE_EXTENSION *)device->DeviceExtension; + devExt->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO); + devExt->Self = device; + devExt->PDO = PDO; + devExt->DeviceState = 1; + devExt->SurpriseRemoved = 0; + devExt->Removed = 0; + devExt->Started = 0; + device->Flags |= 8196UL; + device->Flags &= 4294967167UL; + } + return (status); + } +} +NTSTATUS KbFilter_Complete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) { + PKEVENT event; + + { + { + event = (struct _KEVENT *)Context; + KeSetEvent(event, 0, 0); + } + return (-1073741802L); + } +} +NTSTATUS KbFilter_CreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + NTSTATUS status; + PDEVICE_EXTENSION devExt; + LONG tmp; + LONG tmp___0; + NTSTATUS tmp___1; + + { + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + status = Irp->IoStatus.__annonCompField4.Status; + status = myStatus; + if (irpStack->MajorFunction == 0) { + goto switch_0_0; + } else { + if (irpStack->MajorFunction == 2) { + goto switch_0_2; + } else { + if (0) { + switch_0_0: /* CIL Label */; + if ((unsigned int)((void *)0) == (unsigned int)devExt->UpperConnectData.ClassService) { + status = -1073741436L; + } else { + { + tmp = InterlockedIncrement(&devExt->EnableCount); + } + if (1L == tmp) { + + } else { + } + } + goto switch_0_break; + switch_0_2 : /* CIL Label */ + { + tmp___0 = InterlockedDecrement(&devExt->EnableCount); + } + if (0L == tmp___0) { + + } else { + } + goto switch_0_break; + } else { + switch_0_break: /* CIL Label */; + } + } + } + { + Irp->IoStatus.__annonCompField4.Status = status; + myStatus = status; + tmp___1 = KbFilter_DispatchPassThrough(DeviceObject, Irp); + } + return (tmp___1); + } +} +NTSTATUS KbFilter_DispatchPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + NTSTATUS tmp; + + { + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + tmp = IofCallDriver(((struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->TopOfStack, + Irp); + } + return (tmp); + } +} +NTSTATUS KbFilter_InternIoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + PDEVICE_EXTENSION devExt; + PINTERNAL_I8042_HOOK_KEYBOARD hookKeyboard; + PCONNECT_DATA connectData; + NTSTATUS status; + NTSTATUS tmp; + + { + status = 0L; + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + Irp->IoStatus.Information = 0; + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + if (irpStack->Parameters.DeviceIoControl.IoControlCode == (((11 << 16) | (128 << 2)) | 3)) { + goto switch_1_exp_0; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == (((11 << 16) | (256 << 2)) | 3)) { + goto switch_1_exp_1; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == (((11 << 16) | (4080 << 2)) | 3)) { + goto switch_1_exp_2; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == 11 << 16) { + goto switch_1_exp_3; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (32 << 2))) { + goto switch_1_exp_4; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (16 << 2))) { + goto switch_1_exp_5; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (2 << 2))) { + goto switch_1_exp_6; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (8 << 2))) { + goto switch_1_exp_7; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (1 << 2))) { + goto switch_1_exp_8; + } else { + if (0) { + switch_1_exp_0: /* CIL Label */; + if ((unsigned int)devExt->UpperConnectData.ClassService != (unsigned int)((void *)0)) { + status = -1073741757L; + goto switch_1_break; + } else { + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < (ULONG)sizeof(CONNECT_DATA)) { + status = -1073741811L; + goto switch_1_break; + } else { + } + } + connectData = (struct _CONNECT_DATA *)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; + devExt->UpperConnectData = *connectData; + connectData->ClassDeviceObject = devExt->Self; + connectData->ClassService = &KbFilter_ServiceCallback; + goto switch_1_break; + switch_1_exp_1: /* CIL Label */ + status = -1073741822L; + goto switch_1_break; + switch_1_exp_2: /* CIL Label */; + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < (ULONG)sizeof(INTERNAL_I8042_HOOK_KEYBOARD)) { + status = -1073741811L; + goto switch_1_break; + } else { + } + hookKeyboard = (struct _INTERNAL_I8042_HOOK_KEYBOARD *)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; + devExt->UpperContext = hookKeyboard->Context; + hookKeyboard->Context = (void *)DeviceObject; + if (hookKeyboard->InitializationRoutine) { + devExt->UpperInitializationRoutine = hookKeyboard->InitializationRoutine; + } else { + } + hookKeyboard->InitializationRoutine = (NTSTATUS(*)(PVOID InitializationContext, + PVOID SynchFuncContext, + NTSTATUS(*ReadPort)(PVOID Context, + PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS(*WritePort)(PVOID Context, + UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn))(&KbFilter_InitializationRoutine); + if (hookKeyboard->IsrRoutine) { + devExt->UpperIsrHook = hookKeyboard->IsrRoutine; + } else { + } + hookKeyboard->IsrRoutine = (BOOLEAN(*)(PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, PUCHAR Byte, + PBOOLEAN ContinueProcessing, + PKEYBOARD_SCAN_STATE ScanState))(&KbFilter_IsrHook); + devExt->IsrWritePort = hookKeyboard->IsrWritePort; + devExt->QueueKeyboardPacket = hookKeyboard->QueueKeyboardPacket; + devExt->CallContext = hookKeyboard->CallContext; + status = 0L; + goto switch_1_break; + switch_1_exp_3: /* CIL Label */; + switch_1_exp_4: /* CIL Label */; + switch_1_exp_5: /* CIL Label */; + switch_1_exp_6: /* CIL Label */; + switch_1_exp_7: /* CIL Label */; + switch_1_exp_8: /* CIL Label */; + goto switch_1_break; + } else { + switch_1_break: /* CIL Label */; + } + } + } + } + } + } + } + } + } + } + if (!(status >= 0L)) { + { + Irp->IoStatus.__annonCompField4.Status = status; + myStatus = status; + IofCompleteRequest(Irp, 0); + } + return (status); + } else { + } + { + tmp = KbFilter_DispatchPassThrough(DeviceObject, Irp); + } + return (tmp); + } +} +NTSTATUS KbFilter_PnP(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PDEVICE_EXTENSION devExt; + PIO_STACK_LOCATION irpStack; + NTSTATUS status; + KEVENT event; + PIO_STACK_LOCATION irpSp; + PIO_STACK_LOCATION nextIrpSp; + PIO_STACK_LOCATION irpSp___0; + + { + status = 0L; + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + if (irpStack->MinorFunction == 0) { + goto switch_2_0; + } else { + if (irpStack->MinorFunction == 23) { + goto switch_2_23; + } else { + if (irpStack->MinorFunction == 2) { + goto switch_2_2; + } else { + if (irpStack->MinorFunction == 1) { + goto switch_2_1; + } else { + if (irpStack->MinorFunction == 5) { + goto switch_2_5; + } else { + if (irpStack->MinorFunction == 3) { + goto switch_2_3; + } else { + if (irpStack->MinorFunction == 6) { + goto switch_2_6; + } else { + if (irpStack->MinorFunction == 13) { + goto switch_2_13; + } else { + if (irpStack->MinorFunction == 4) { + goto switch_2_4; + } else { + if (irpStack->MinorFunction == 7) { + goto switch_2_7; + } else { + if (irpStack->MinorFunction == 8) { + goto switch_2_8; + } else { + if (irpStack->MinorFunction == 9) { + goto switch_2_9; + } else { + if (irpStack->MinorFunction == 12) { + goto switch_2_12; + } else { + if (irpStack->MinorFunction == 10) { + goto switch_2_10; + } else { + if (irpStack->MinorFunction == 11) { + goto switch_2_11; + } else { + if (irpStack->MinorFunction == 15) { + goto switch_2_15; + } else { + if (irpStack->MinorFunction == 16) { + goto switch_2_16; + } else { + if (irpStack->MinorFunction == 17) { + goto switch_2_17; + } else { + if (irpStack->MinorFunction == 18) { + goto switch_2_18; + } else { + if (irpStack->MinorFunction == 19) { + goto switch_2_19; + } else { + if (irpStack->MinorFunction == 20) { + goto switch_2_20; + } else { + { + goto switch_2_default; + if (0) { + switch_2_0 : /* CIL Label */ + { + irpSp = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + nextIrpSp = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation - 1; + memmove(nextIrpSp, irpSp, (long)(&((IO_STACK_LOCATION *)0)->CompletionRoutine)); + nextIrpSp->Control = 0; + /* KeInitializeEvent(& event, 0, 0); */ /* INLINED */ + } + if (s != NP) { + { + errorFn(); + } + } else { + if (compRegistered != 0) { + { + errorFn(); + } + } else { + compRegistered = 1; + compFptr = &KbFilter_Complete; + } + } + { + irpSp___0 = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation - 1; + irpSp___0->CompletionRoutine = &KbFilter_Complete; + irpSp___0->Context = &event; + irpSp___0->Control = 0; + irpSp___0->Control = 64; + irpSp___0->Control = (int)irpSp___0->Control | 128; + irpSp___0->Control = (int)irpSp___0->Control | 32; + status = IofCallDriver(devExt->TopOfStack, + Irp); + } + if (259L == status) { + { + KeWaitForSingleObject(&event, 0, + 0, 0, (void *)0); + } + } else { + } + if (status >= 0L) { + if ((long)myStatus >= 0L) { + devExt->Started = 1; + devExt->Removed = 0; + devExt->SurpriseRemoved = 0; + } else { + } + } else { + } + { + Irp->IoStatus.__annonCompField4.Status = status; + myStatus = status; + Irp->IoStatus.Information = 0; + IofCompleteRequest(Irp, 0); + } + goto switch_2_break; + switch_2_23: /* CIL Label */ + devExt->SurpriseRemoved = 1; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + status = IofCallDriver(devExt->TopOfStack, + Irp); + } + goto switch_2_break; + switch_2_2: /* CIL Label */ + devExt->Removed = 1; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + IofCallDriver(devExt->TopOfStack, Irp); + /* IoDetachDevice(devExt->TopOfStack); */ /* INLINED */ + /* IoDeleteDevice(DeviceObject); */ /* INLINED */ + status = 0L; + } + goto switch_2_break; + switch_2_1: /* CIL Label */; + switch_2_5: /* CIL Label */; + switch_2_3: /* CIL Label */; + switch_2_6: /* CIL Label */; + switch_2_13: /* CIL Label */; + switch_2_4: /* CIL Label */; + switch_2_7: /* CIL Label */; + switch_2_8: /* CIL Label */; + switch_2_9: /* CIL Label */; + switch_2_12: /* CIL Label */; + switch_2_10: /* CIL Label */; + switch_2_11: /* CIL Label */; + switch_2_15: /* CIL Label */; + switch_2_16: /* CIL Label */; + switch_2_17: /* CIL Label */; + switch_2_18: /* CIL Label */; + switch_2_19: /* CIL Label */; + switch_2_20: /* CIL Label */; + switch_2_default: /* CIL Label */; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + status = IofCallDriver(devExt->TopOfStack, + Irp); + } + goto switch_2_break; + } else { + switch_2_break: /* CIL Label */; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return (status); + } +} +NTSTATUS KbFilter_Power(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + PDEVICE_EXTENSION devExt; + POWER_STATE powerState; + POWER_STATE_TYPE powerType; + NTSTATUS tmp; + + { + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + powerType = irpStack->Parameters.Power.Type; + powerState = irpStack->Parameters.Power.State; + if (irpStack->MinorFunction == 2) { + goto switch_3_2; + } else { + if (irpStack->MinorFunction == 1) { + goto switch_3_1; + } else { + if (irpStack->MinorFunction == 0) { + goto switch_3_0; + } else { + if (irpStack->MinorFunction == 3) { + goto switch_3_3; + } else { + { + goto switch_3_default; + if (0) { + switch_3_2: /* CIL Label */; + if ((int)powerType == 1) { + devExt->DeviceState = powerState.DeviceState; + } else { + } + switch_3_1: /* CIL Label */; + switch_3_0: /* CIL Label */; + switch_3_3: /* CIL Label */; + switch_3_default: /* CIL Label */; + goto switch_3_break; + } else { + switch_3_break: /* CIL Label */; + } + } + } + } + } + } + { + /* PoStartNextPowerIrp(Irp); */ /* INLINED */ + } + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + tmp = PoCallDriver(devExt->TopOfStack, Irp); + } + return (tmp); + } +} +NTSTATUS KbFilter_InitializationRoutine(PDEVICE_OBJECT DeviceObject, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn) { + PDEVICE_EXTENSION devExt; + NTSTATUS status; + + { + status = 0L; + devExt = DeviceObject->DeviceExtension; + if (devExt->UpperInitializationRoutine) { + { + status = (*(devExt->UpperInitializationRoutine))(devExt->UpperContext, SynchFuncContext, + ReadPort, WritePort, TurnTranslationOn); + } + if (!(status >= 0L)) { + return (status); + } else { + } + } else { + } + *TurnTranslationOn = 1; + return (status); + } +} +BOOLEAN KbFilter_IsrHook(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR DataByte, + PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState) { + PDEVICE_EXTENSION devExt; + BOOLEAN retVal; + + { + retVal = 1; + devExt = DeviceObject->DeviceExtension; + if (devExt->UpperIsrHook) { + { + retVal = (*(devExt->UpperIsrHook))(devExt->UpperContext, CurrentInput, CurrentOutput, + StatusByte, DataByte, ContinueProcessing, ScanState); + } + if (!retVal) { + return (retVal); + } else { + if (!*ContinueProcessing) { + return (retVal); + } else { + } + } + } else { + } + *ContinueProcessing = 1; + return (retVal); + } +} +void KbFilter_ServiceCallback(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA InputDataStart, + PKEYBOARD_INPUT_DATA InputDataEnd, PULONG InputDataConsumed) { + PDEVICE_EXTENSION devExt; + + { + { + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + (*((void (*)(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2, + PVOID SystemArgument3))devExt->UpperConnectData.ClassService))(devExt->UpperConnectData.ClassDeviceObject, + InputDataStart, + InputDataEnd, + InputDataConsumed); + } + return; + } +} +void KbFilter_Unload(PDRIVER_OBJECT Driver) { + + { + return; + } +} +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +#pragma warning(disable : 4035) +#pragma warning(push) +#pragma warning(disable : 4164) +#pragma function(_enable) +#pragma function(_disable) +#pragma warning(pop) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4200) +#pragma warning(default : 4200) +IRP *pirp; +void stub_driver_init(void) { + + { + s = NP; + pended = 0; + compFptr = 0; + compRegistered = 0; + lowerDriverReturn = 0; + setEventCalled = 0; + customIrp = 0; + return; + } +} +extern unsigned char __VERIFIER_nondet_uchar(void); +int main(void) { + DRIVER_OBJECT d; + UNICODE_STRING u; + NTSTATUS status; + int we_should_unload = __VERIFIER_nondet_int(); + IRP irp; + int __BLAST_NONDET = __VERIFIER_nondet_int(); + int irp_choice = __VERIFIER_nondet_int(); + DEVICE_EXTENSION devext; + DEVICE_OBJECT devobj; + devobj.DeviceExtension = &devext; + struct _DRIVER_EXTENSION ext; + d.DriverExtension = &ext; + + INTERNAL_I8042_HOOK_KEYBOARD hookkb; + struct _IO_STACK_LOCATION stack[3]; + + stack[0].MajorFunction = __VERIFIER_nondet_uchar(); + stack[1].MajorFunction = __VERIFIER_nondet_uchar(); + stack[2].MajorFunction = __VERIFIER_nondet_uchar(); + stack[0].MinorFunction = __VERIFIER_nondet_uchar(); + stack[1].MinorFunction = __VERIFIER_nondet_uchar(); + stack[2].MinorFunction = __VERIFIER_nondet_uchar(); + + stack[0].Parameters.DeviceIoControl.Type3InputBuffer = &hookkb; + stack[1].Parameters.DeviceIoControl.Type3InputBuffer = &hookkb; + stack[2].Parameters.DeviceIoControl.Type3InputBuffer = &hookkb; + + stack[0].Parameters.DeviceIoControl.InputBufferLength = __VERIFIER_nondet_ulong(); + stack[1].Parameters.DeviceIoControl.InputBufferLength = __VERIFIER_nondet_ulong(); + stack[2].Parameters.DeviceIoControl.InputBufferLength = __VERIFIER_nondet_ulong(); + + stack[0].Parameters.DeviceIoControl.IoControlCode = __VERIFIER_nondet_ulong(); + stack[1].Parameters.DeviceIoControl.IoControlCode = __VERIFIER_nondet_ulong(); + stack[2].Parameters.DeviceIoControl.IoControlCode = __VERIFIER_nondet_ulong(); + + irp.Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation = &stack[1]; + + { + { + pirp = &irp; + _BLAST_init(); + status = DriverEntry(&d, &u); + } + if (status >= 0L) { + s = NP; + customIrp = 0; + setEventCalled = customIrp; + lowerDriverReturn = setEventCalled; + compRegistered = lowerDriverReturn; + compFptr = compRegistered; + pended = compFptr; + pirp->IoStatus.__annonCompField4.Status = 0L; + myStatus = 0L; + if (irp_choice == 0) { + pirp->IoStatus.__annonCompField4.Status = -1073741637L; + myStatus = -1073741637L; + } else { + } + { + status = KbFilter_AddDevice(&d, &devobj); + stub_driver_init(); + } + if (!(status >= 0L)) { + return (-1); + } else { + } + if (__BLAST_NONDET == 0) { + goto switch_4_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_4_1; + } else { + if (__BLAST_NONDET == 2) { + goto switch_4_2; + } else { + if (__BLAST_NONDET == 3) { + goto switch_4_3; + } else { + if (__BLAST_NONDET == 4) { + goto switch_4_4; + } else { + if (__BLAST_NONDET == 8) { + goto switch_4_8; + } else { + { + goto switch_4_default; + if (0) { + switch_4_0 : /* CIL Label */ + { + status = KbFilter_CreateClose(&devobj, pirp); + } + goto switch_4_break; + switch_4_1 : /* CIL Label */ + { + status = KbFilter_CreateClose(&devobj, pirp); + } + goto switch_4_break; + switch_4_2 : /* CIL Label */ + { + status = KbFilter_IoCtl(&devobj, pirp); + } + goto switch_4_break; + switch_4_3 : /* CIL Label */ + { + status = KbFilter_PnP(&devobj, pirp); + } + goto switch_4_break; + switch_4_4 : /* CIL Label */ + { + status = KbFilter_Power(&devobj, pirp); + } + goto switch_4_break; + switch_4_8 : /* CIL Label */ + { + status = KbFilter_InternIoCtl(&devobj, pirp); + } + goto switch_4_break; + switch_4_default: /* CIL Label */; + return (-1); + } else { + switch_4_break: /* CIL Label */; + } + } + } + } + } + } + } + } + if (we_should_unload) { + { + /* KbFilter_Unload(& d); */ /* INLINED */ + } + } else { + } + } else { + } + if (pended == 1) { + if (s == NP) { + s = NP; + } else { + goto _L___2; + } + } else { + _L___2: /* CIL Label */ + if (pended == 1) { + if (s == MPR3) { + s = MPR3; + } else { + goto _L___1; + } + } else { + _L___1: /* CIL Label */ + if (s == UNLOADED) { + + } else { + if (status == -1L) { + + } else { + if (s != SKIP2) { + if (s != IPC) { + if (s != DC) { + + } else { + goto _L___0; + } + } else { + goto _L___0; + } + } else { + _L___0: /* CIL Label */ + if (pended == 1) { + if (status != 259L) { + { + errorFn(); + } + } else { + } + } else { + if (s == DC) { + if (status == 259L) { + { + errorFn(); + } + } else { + } + } else { + if (status != (NTSTATUS)lowerDriverReturn) { + + } else { + } + } + } + } + } + } + } + } + return (status); + } +} +char _SLAM_alloc_dummy; +void ExAcquireFastMutex(PFAST_MUTEX FastMutex); +void ExAcquireFastMutex(PFAST_MUTEX FastMutex) { + + { + return; + } +} +void ExReleaseFastMutex(PFAST_MUTEX FastMutex); +void ExReleaseFastMutex(PFAST_MUTEX FastMutex) { + + { + return; + } +} +PVOID ExAllocatePoolWithTag(POOL_TYPE PoolType, + SIZE_T NumberOfBytes, + ULONG Tag); +PVOID ExAllocatePoolWithTag(POOL_TYPE PoolType, SIZE_T NumberOfBytes, + ULONG Tag) { + PVOID x; + char *tmp; + + { + { + tmp = malloc(NumberOfBytes); + x = tmp; + } + return (x); + } +} +void ExFreePool(PVOID P); +void ExFreePool(PVOID P) { + + { + return; + } +} +PLIST_ENTRY ExfInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock) { + + { + return ((void *)0); + } +} +PLIST_ENTRY ExfInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock) { + + { + return ((void *)0); + } +} +PLIST_ENTRY ExfInterlockedRemoveHeadList(PLIST_ENTRY ListHead, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedRemoveHeadList(PLIST_ENTRY ListHead, + PKSPIN_LOCK Lock) { + + { + return ((void *)0); + } +} +PMDL IoAllocateMdl(PVOID VirtualAddress, ULONG Length, + BOOLEAN SecondaryBuffer, BOOLEAN ChargeQuota, + PIRP Irp); +PMDL IoAllocateMdl(PVOID VirtualAddress, ULONG Length, BOOLEAN SecondaryBuffer, + BOOLEAN ChargeQuota, PIRP Irp) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + if (__BLAST_NONDET == 0) { + goto switch_5_0; + } else { + { + goto switch_5_default; + if (0) { + switch_5_0 : /* CIL Label */ + { + tmp = malloc(sizeof(MDL)); + } + return ((void *)tmp); + switch_5_default: /* CIL Label */; + return ((void *)0); + } else { + switch_5_break: /* CIL Label */; + } + } + } + } +} +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, + PDEVICE_OBJECT TargetDevice); +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, PDEVICE_OBJECT TargetDevice) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_6_0; + } else { + { + goto switch_6_default; + if (0) { + switch_6_0: /* CIL Label */; + return (TargetDevice); + switch_6_default: /* CIL Label */; + return ((void *)0); + } else { + switch_6_break: /* CIL Label */; + } + } + } + } +} +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock); +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction, PDEVICE_OBJECT DeviceObject, + PVOID Buffer, ULONG Length, PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + customIrp = 1; + if (__BLAST_NONDET == 0) { + goto switch_7_0; + } else { + { + goto switch_7_default; + if (0) { + switch_7_0 : /* CIL Label */ + { + tmp = malloc(sizeof(IRP)); + } + return ((void *)tmp); + switch_7_default: /* CIL Label */; + return ((void *)0); + } else { + switch_7_break: /* CIL Label */; + } + } + } + } +} +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode, + PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + BOOLEAN InternalDeviceIoControl, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock); +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode, PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, + ULONG OutputBufferLength, BOOLEAN InternalDeviceIoControl, + PKEVENT Event, PIO_STATUS_BLOCK IoStatusBlock) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + customIrp = 1; + if (__BLAST_NONDET == 0) { + goto switch_8_0; + } else { + { + goto switch_8_default; + if (0) { + switch_8_0 : /* CIL Label */ + { + tmp = malloc(sizeof(IRP)); + } + return ((void *)tmp); + switch_8_default: /* CIL Label */; + return ((void *)0); + } else { + switch_8_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject, + ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, + ULONG DeviceType, ULONG DeviceCharacteristics, + BOOLEAN Exclusive, PDEVICE_OBJECT *DeviceObject); +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject, ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, ULONG DeviceType, ULONG DeviceCharacteristics, + BOOLEAN Exclusive, PDEVICE_OBJECT *DeviceObject) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + if (__BLAST_NONDET == 0) { + goto switch_9_0; + } else { + { + goto switch_9_default; + if (0) { + switch_9_0 : /* CIL Label */ + { + tmp = malloc(sizeof(DEVICE_OBJECT)); + *DeviceObject = (void *)tmp; + (*DeviceObject)->DeviceExtension = malloc(DeviceExtensionSize); + } + return (0L); + switch_9_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_9_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName); +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, PUNICODE_STRING DeviceName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_10_0; + } else { + { + goto switch_10_default; + if (0) { + switch_10_0: /* CIL Label */; + return (0L); + switch_10_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_10_break: /* CIL Label */; + } + } + } + } +} +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject); +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject) { + + { + return; + } +} +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName); +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_11_0; + } else { + { + goto switch_11_default; + if (0) { + switch_11_0: /* CIL Label */; + return (0L); + switch_11_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_11_break: /* CIL Label */; + } + } + } + } +} +void IoDetachDevice(PDEVICE_OBJECT TargetDevice); +void IoDetachDevice(PDEVICE_OBJECT TargetDevice) { + + { + return; + } +} +void IoFreeIrp(PIRP Irp); +void IoFreeIrp(PIRP Irp) { + + { + return; + } +} +void IoFreeMdl(PMDL Mdl); +void IoFreeMdl(PMDL Mdl) { + + { + return; + } +} +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void); +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void) { + char *tmp; + + { + { + tmp = malloc(sizeof(CONFIGURATION_INFORMATION)); + } + return ((void *)tmp); + } +} +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType, + PULONG BusNumber, + PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, + PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, + NTSTATUS (*CalloutRoutine)(PVOID Context, + PUNICODE_STRING PathName, + INTERFACE_TYPE BusType, + ULONG BusNumber, + PKEY_VALUE_FULL_INFORMATION *BusInformation, + CONFIGURATION_TYPE ControllerType, + ULONG ControllerNumber, + PKEY_VALUE_FULL_INFORMATION *ControllerInformation, + CONFIGURATION_TYPE PeripheralType, + ULONG PeripheralNumber, + PKEY_VALUE_FULL_INFORMATION *PeripheralInformation), + PVOID Context); +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType, PULONG BusNumber, PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, NTSTATUS (*CalloutRoutine)(PVOID Context, PUNICODE_STRING PathName, INTERFACE_TYPE BusType, ULONG BusNumber, PKEY_VALUE_FULL_INFORMATION *BusInformation, CONFIGURATION_TYPE ControllerType, ULONG ControllerNumber, PKEY_VALUE_FULL_INFORMATION *ControllerInformation, CONFIGURATION_TYPE PeripheralType, ULONG PeripheralNumber, PKEY_VALUE_FULL_INFORMATION *PeripheralInformation), + PVOID Context) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_12_0; + } else { + { + goto switch_12_default; + if (0) { + switch_12_0: /* CIL Label */; + return (0L); + switch_12_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_12_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS IoRegisterDeviceInterface(PDEVICE_OBJECT PhysicalDeviceObject, + GUID const *InterfaceClassGuid, + PUNICODE_STRING ReferenceString, + PUNICODE_STRING SymbolicLinkName); +NTSTATUS IoRegisterDeviceInterface(PDEVICE_OBJECT PhysicalDeviceObject, + GUID const *InterfaceClassGuid, + PUNICODE_STRING ReferenceString, + PUNICODE_STRING SymbolicLinkName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_13_0; + } else { + { + goto switch_13_default; + if (0) { + switch_13_0: /* CIL Label */; + return (0L); + switch_13_default: /* CIL Label */; + return (-1073741808L); + } else { + switch_13_break: /* CIL Label */; + } + } + } + } +} +void IoReleaseCancelSpinLock(KIRQL Irql); +void IoReleaseCancelSpinLock(KIRQL Irql) { + + { + return; + } +} +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName, + BOOLEAN Enable); +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName, BOOLEAN Enable) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_14_0; + } else { + { + goto switch_14_default; + if (0) { + switch_14_0: /* CIL Label */; + return (0L); + switch_14_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_14_break: /* CIL Label */; + } + } + } + } +} +void IoSetHardErrorOrVerifyDevice(PIRP Irp, PDEVICE_OBJECT DeviceObject); +void IoSetHardErrorOrVerifyDevice(PIRP Irp, PDEVICE_OBJECT DeviceObject) { + + { + return; + } +} +void stubMoreProcessingRequired(void) { + + { + if (s == NP) { + s = MPR1; + } else { + { + errorFn(); + } + } + return; + } +} +NTSTATUS IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +NTSTATUS IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + NTSTATUS returnVal2; + int compRetStatus; + PVOID lcontext = 0; + NTSTATUS tmp; + + { + if (compRegistered) { + { + tmp = KbFilter_Complete(DeviceObject, Irp, lcontext); + compRetStatus = tmp; + } + if ((long)compRetStatus == -1073741802L) { + { + stubMoreProcessingRequired(); + } + } else { + } + } else { + } + if (__BLAST_NONDET == 0) { + goto switch_15_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_15_1; + } else { + { + goto switch_15_default; + if (0) { + switch_15_0: /* CIL Label */ + returnVal2 = 0L; + goto switch_15_break; + switch_15_1: /* CIL Label */ + returnVal2 = -1073741823L; + goto switch_15_break; + switch_15_default: /* CIL Label */ + returnVal2 = 259L; + goto switch_15_break; + } else { + switch_15_break: /* CIL Label */; + } + } + } + } + if (s == NP) { + s = IPC; + lowerDriverReturn = returnVal2; + } else { + if (s == MPR1) { + if (returnVal2 == 259L) { + s = MPR3; + lowerDriverReturn = returnVal2; + } else { + s = NP; + lowerDriverReturn = returnVal2; + } + } else { + if (s == SKIP1) { + s = SKIP2; + lowerDriverReturn = returnVal2; + } else { + { + errorFn(); + } + } + } + } + return (returnVal2); + } +} +void IofCompleteRequest(PIRP Irp, + CCHAR PriorityBoost); +void IofCompleteRequest(PIRP Irp, CCHAR PriorityBoost) { + + { + if (s == NP) { + s = DC; + } else { + { + errorFn(); + } + } + return; + } +} +KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock); +KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock) { + + { + return ((unsigned char)0); + } +} +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Interval); +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, BOOLEAN Alertable, PLARGE_INTEGER Interval) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_16_0; + } else { + { + goto switch_16_default; + if (0) { + switch_16_0: /* CIL Label */; + return (0L); + switch_16_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_16_break: /* CIL Label */; + } + } + } + } +} +void KeInitializeEvent(PRKEVENT Event, EVENT_TYPE Type, + BOOLEAN State); +void KeInitializeEvent(PRKEVENT Event, EVENT_TYPE Type, BOOLEAN State) { + + { + return; + } +} +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore, + LONG Count, LONG Limit); +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore, LONG Count, LONG Limit) { + + { + return; + } +} +void KeInitializeSpinLock(PKSPIN_LOCK SpinLock); +void KeInitializeSpinLock(PKSPIN_LOCK SpinLock) { + + { + return; + } +} +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore, KPRIORITY Increment, + LONG Adjustment, BOOLEAN Wait); +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore, KPRIORITY Increment, LONG Adjustment, + BOOLEAN Wait) { + LONG r = __VERIFIER_nondet_long(); + + { + return (r); + } +} +void KfReleaseSpinLock(PKSPIN_LOCK SpinLock, + KIRQL NewIrql); +void KfReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL NewIrql) { + + { + return; + } +} +LONG KeSetEvent(PRKEVENT Event, KPRIORITY Increment, + BOOLEAN Wait); +LONG KeSetEvent(PRKEVENT Event, KPRIORITY Increment, BOOLEAN Wait) { + LONG l = __VERIFIER_nondet_long(); + + { + setEventCalled = 1; + return (l); + } +} +NTSTATUS KeWaitForSingleObject(PVOID Object, KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout); +NTSTATUS KeWaitForSingleObject(PVOID Object, KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, PLARGE_INTEGER Timeout) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (s == MPR3) { + if (setEventCalled == 1) { + s = NP; + setEventCalled = 0; + } else { + goto _L; + } + } else { + _L: /* CIL Label */ + if (customIrp == 1) { + s = NP; + customIrp = 0; + } else { + if (s == MPR3) { + { + errorFn(); + } + } else { + } + } + } + if (__BLAST_NONDET == 0) { + goto switch_17_0; + } else { + { + goto switch_17_default; + if (0) { + switch_17_0: /* CIL Label */; + return (0L); + switch_17_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_17_break: /* CIL Label */; + } + } + } + } +} +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes, + PHYSICAL_ADDRESS HighestAcceptableAddress); +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes, PHYSICAL_ADDRESS HighestAcceptableAddress) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + if (__BLAST_NONDET == 0) { + goto switch_18_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_18_1; + } else { + if (0) { + switch_18_0 : /* CIL Label */ + { + tmp = malloc(NumberOfBytes); + } + return (tmp); + switch_18_1: /* CIL Label */; + return ((void *)0); + } else { + switch_18_break: /* CIL Label */; + } + } + } + return ((void *)0); + } +} +void MmFreeContiguousMemory(PVOID BaseAddress); +void MmFreeContiguousMemory(PVOID BaseAddress) { + + { + return; + } +} +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList, + KPROCESSOR_MODE AccessMode, + MEMORY_CACHING_TYPE CacheType, + PVOID BaseAddress, + ULONG BugCheckOnFailure, + MM_PAGE_PRIORITY Priority); +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList, KPROCESSOR_MODE AccessMode, + MEMORY_CACHING_TYPE CacheType, PVOID BaseAddress, + ULONG BugCheckOnFailure, MM_PAGE_PRIORITY Priority) { + + { + return ((void *)0); + } +} +PVOID MmPageEntireDriver(PVOID AddressWithinSection); +PVOID MmPageEntireDriver(PVOID AddressWithinSection) { + + { + return ((void *)0); + } +} +void MmResetDriverPaging(PVOID AddressWithinSection); +void MmResetDriverPaging(PVOID AddressWithinSection) { + + { + return; + } +} +void MmUnlockPages(PMDL MemoryDescriptorList); +void MmUnlockPages(PMDL MemoryDescriptorList) { + + { + return; + } +} +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID *Object, + POBJECT_HANDLE_INFORMATION HandleInformation); +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, PVOID *Object, POBJECT_HANDLE_INFORMATION HandleInformation) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_19_0; + } else { + { + goto switch_19_default; + if (0) { + switch_19_0: /* CIL Label */; + return (0L); + switch_19_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_19_break: /* CIL Label */; + } + } + } + } +} +void ObfDereferenceObject(PVOID Object); +void ObfDereferenceObject(PVOID Object) { + + { + return; + } +} +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + int compRetStatus; + NTSTATUS returnVal; + PVOID lcontext = 0; + NTSTATUS tmp; + + { + if (compRegistered) { + { + tmp = KbFilter_Complete(DeviceObject, Irp, lcontext); + compRetStatus = tmp; + } + if ((long)compRetStatus == -1073741802L) { + { + stubMoreProcessingRequired(); + } + } else { + } + } else { + } + if (__BLAST_NONDET == 0) { + goto switch_20_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_20_1; + } else { + { + goto switch_20_default; + if (0) { + switch_20_0: /* CIL Label */ + returnVal = 0L; + goto switch_20_break; + switch_20_1: /* CIL Label */ + returnVal = -1073741823L; + goto switch_20_break; + switch_20_default: /* CIL Label */ + returnVal = 259L; + goto switch_20_break; + } else { + switch_20_break: /* CIL Label */; + } + } + } + } + if (s == NP) { + s = IPC; + lowerDriverReturn = returnVal; + } else { + if (s == MPR1) { + if (returnVal == 259L) { + s = MPR3; + lowerDriverReturn = returnVal; + } else { + s = NP; + lowerDriverReturn = returnVal; + } + } else { + if (s == SKIP1) { + s = SKIP2; + lowerDriverReturn = returnVal; + } else { + { + errorFn(); + } + } + } + } + return (returnVal); + } +} +void PoStartNextPowerIrp(PIRP Irp); +void PoStartNextPowerIrp(PIRP Irp) { + + { + return; + } +} +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, + ULONG DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + void (*StartRoutine)(PVOID StartContext), + PVOID StartContext); +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, ULONG DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, PCLIENT_ID ClientId, void (*StartRoutine)(PVOID StartContext), + PVOID StartContext) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_21_0; + } else { + { + goto switch_21_default; + if (0) { + switch_21_0: /* CIL Label */; + return (0L); + switch_21_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_21_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus); +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_22_0; + } else { + { + goto switch_22_default; + if (0) { + switch_22_0: /* CIL Label */; + return (0L); + switch_22_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_22_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString); +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_23_0; + } else { + { + goto switch_23_default; + if (0) { + switch_23_0: /* CIL Label */; + return (0L); + switch_23_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_23_break: /* CIL Label */; + } + } + } + } +} +SIZE_T RtlCompareMemory(void const *Source1, + void const *Source2, + SIZE_T Length); +SIZE_T RtlCompareMemory(void const *Source1, void const *Source2, + SIZE_T Length) { + SIZE_T r = __VERIFIER_nondet_long(); + + { + return (r); + } +} +void RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString); +void RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString) { + + { + return; + } +} +NTSTATUS RtlDeleteRegistryValue(ULONG RelativeTo, + PCWSTR Path, + PCWSTR ValueName); +NTSTATUS RtlDeleteRegistryValue(ULONG RelativeTo, + PCWSTR Path, PCWSTR ValueName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_24_0; + } else { + { + goto switch_24_default; + if (0) { + switch_24_0: /* CIL Label */; + return (0L); + switch_24_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_24_break: /* CIL Label */; + } + } + } + } +} +void RtlFreeUnicodeString(PUNICODE_STRING UnicodeString); +void RtlFreeUnicodeString(PUNICODE_STRING UnicodeString) { + + { + return; + } +} +void RtlInitString(PSTRING DestinationString, + PCSZ SourceString); +void RtlInitString(PSTRING DestinationString, PCSZ SourceString) { + + { + return; + } +} +void RtlInitUnicodeString(PUNICODE_STRING DestinationString, + PCWSTR SourceString); +void RtlInitUnicodeString(PUNICODE_STRING DestinationString, + PCWSTR SourceString) { + + { + return; + } +} +NTSTATUS RtlQueryRegistryValues(ULONG RelativeTo, + PCWSTR Path, + PRTL_QUERY_REGISTRY_TABLE QueryTable, + PVOID Context, + PVOID Environment); +NTSTATUS RtlQueryRegistryValues(ULONG RelativeTo, + PCWSTR Path, PRTL_QUERY_REGISTRY_TABLE QueryTable, + PVOID Context, PVOID Environment) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_25_0; + } else { + { + goto switch_25_default; + if (0) { + switch_25_0: /* CIL Label */; + return (0L); + switch_25_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_25_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS ZwClose(HANDLE Handle); +NTSTATUS ZwClose(HANDLE Handle) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_26_0; + } else { + { + goto switch_26_default; + if (0) { + switch_26_0: /* CIL Label */; + return (0L); + switch_26_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_26_break: /* CIL Label */; + } + } + } + } +} diff --git a/test/regression/2023-10-13-uninitialized-memory.c b/test/regression/2023-10-13-uninitialized-memory.c new file mode 100644 index 0000000000..bf13fd0986 --- /dev/null +++ b/test/regression/2023-10-13-uninitialized-memory.c @@ -0,0 +1,21 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +#include "klee/klee.h" + +#include +#include +#include + +int main() { + char *s1 = (char *)malloc(1); + char *s2 = (char *)malloc(1); + if (s1[0] == s2[0]) { + printf("1) eq\n"); + } else { + printf("1) not eq\n"); + } + + // CHECK-DAG: 1) eq + // CHECK-DAG: 1) not eq +} diff --git a/test/regression/2023-27-10-SimpleComparison.c b/test/regression/2023-27-10-SimpleComparison.c new file mode 100644 index 0000000000..def7647d8c --- /dev/null +++ b/test/regression/2023-27-10-SimpleComparison.c @@ -0,0 +1,21 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --debug-assignment-validating-solver=false --use-fast-cex-solver=false --use-cex-cache=false --use-branch-cache=false --use-alpha-equivalence=true --use-independent-solver=false --use-concretizing-solver=false --output-dir=%t.klee-out --skip-not-symbolic-objects --use-timestamps=false --use-guided-search=none %t.bc + +#include + +struct Node { + int *x; +}; + +int main() { + struct Node *nodeA; + struct Node *nodeB; + klee_make_symbolic(&nodeA, sizeof(nodeA), "nodeA"); + klee_make_symbolic(&nodeB, sizeof(nodeB), "nodeB"); + + if (nodeA && nodeB && nodeA == nodeB && (*nodeA->x * 2) != (*nodeA->x + *nodeB->x)) { + assert(0); + } + return 0; +} diff --git a/tools/kleaver/main.cpp b/tools/kleaver/main.cpp index 441e7ffacf..2deedb3c0b 100644 --- a/tools/kleaver/main.cpp +++ b/tools/kleaver/main.cpp @@ -9,6 +9,7 @@ #include "klee/ADT/SparseStorage.h" #include "klee/Config/Version.h" +#include "klee/Expr/ArrayCache.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprBuilder.h" @@ -212,7 +213,8 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, std::move(coreSolver), getQueryLogPath(ALL_QUERIES_SMT2_FILE_NAME), getQueryLogPath(SOLVER_QUERIES_SMT2_FILE_NAME), getQueryLogPath(ALL_QUERIES_KQUERY_FILE_NAME), - getQueryLogPath(SOLVER_QUERIES_KQUERY_FILE_NAME), nullptr); + getQueryLogPath(SOLVER_QUERIES_KQUERY_FILE_NAME), nullptr, + P->getArrayCache()); unsigned Index = 0; for (std::vector::iterator it = Decls.begin(), ie = Decls.end(); @@ -224,13 +226,9 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, assert("FIXME: Support counterexample query commands!"); if (QC->Values.empty() && QC->Objects.empty()) { bool result; - constraints_ty constraints; - for (auto i : QC->Constraints) { - constraints.insert(i); - } - if (S->mustBeTrue( - Query(ConstraintSet(constraints, {}, {true}), QC->Query), - result)) { + constraints_ty constraints(QC->Constraints.begin(), + QC->Constraints.end()); + if (S->mustBeTrue(Query(constraints, QC->Query), result)) { llvm::outs() << (result ? "VALID" : "INVALID"); } else { llvm::outs() << "FAIL (reason: " @@ -246,13 +244,9 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, assert(QC->Query->isFalse() && "FIXME: Support counterexamples with non-trivial query!"); ref result; - constraints_ty constraints; - for (auto i : QC->Constraints) { - constraints.insert(i); - } - if (S->getValue( - Query(ConstraintSet(constraints, {}, {true}), QC->Values[0]), - result)) { + constraints_ty constraints(QC->Constraints.begin(), + QC->Constraints.end()); + if (S->getValue(Query(constraints, QC->Values[0]), result)) { llvm::outs() << "INVALID\n"; llvm::outs() << "\tExpr 0:\t" << result; } else { @@ -264,14 +258,11 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, } else { std::vector> result; - constraints_ty constraints; - for (auto i : QC->Constraints) { - constraints.insert(i); - } + constraints_ty constraints(QC->Constraints.begin(), + QC->Constraints.end()); - if (S->getInitialValues( - Query(ConstraintSet(constraints, {}, {true}), QC->Query), - QC->Objects, result)) { + if (S->getInitialValues(Query(constraints, QC->Query), QC->Objects, + result)) { llvm::outs() << "INVALID\n"; Assignment solutionAssugnment(QC->Objects, result); for (unsigned i = 0, e = result.size(); i != e; ++i) { @@ -378,13 +369,9 @@ static bool printInputAsSMTLIBv2(const char *Filename, * constraint in the constraint set is set to NULL and * will later cause a NULL pointer dereference. */ - constraints_ty constraints; - for (auto i : QC->Constraints) { - constraints.insert(i); - } - - ConstraintSet constraintM(constraints, {}, {true}); - Query query(constraintM, QC->Query); + constraints_ty constraints(QC->Constraints.begin(), + QC->Constraints.end()); + Query query(constraints, QC->Query); printer.setQuery(query); if (!QC->Objects.empty()) diff --git a/tools/klee/CMakeLists.txt b/tools/klee/CMakeLists.txt index cabdfdfcbd..5d63f93901 100644 --- a/tools/klee/CMakeLists.txt +++ b/tools/klee/CMakeLists.txt @@ -20,6 +20,9 @@ target_compile_options(klee PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) target_compile_definitions(klee PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) +# Copy run script +configure_file(${CMAKE_SOURCE_DIR}/scripts/kleef ${CMAKE_BINARY_DIR}/bin/kleef COPYONLY) + install(TARGETS klee RUNTIME DESTINATION bin) # The KLEE binary depends on the runtimes diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 1099b9da14..e0ec4b2092 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -15,7 +15,7 @@ #include "klee/Core/Context.h" #include "klee/Core/Interpreter.h" #include "klee/Core/TargetedExecutionReporter.h" -#include "klee/Expr/Expr.h" +#include "klee/Module/LocationInfo.h" #include "klee/Module/SarifReport.h" #include "klee/Module/TargetForest.h" #include "klee/Solver/SolverCmdLine.h" @@ -34,9 +34,8 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" @@ -52,8 +51,8 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/TargetSelect.h" DISABLE_WARNING_POP +#include #include -#include #include #include #include @@ -89,6 +88,11 @@ cl::opt cl::desc("Do not generate any test files (default=false)"), cl::cat(TestCaseCat)); +cl::opt WriteKTests( + "write-ktests", cl::init(true), + cl::desc("Write .ktest files for each test case (default=true)"), + cl::cat(TestCaseCat)); + cl::opt WriteCVCs("write-cvcs", cl::desc("Write .cvc files for each test case (default=false)"), @@ -341,10 +345,31 @@ cl::opt Libcxx( "libcxx", cl::desc("Link the llvm libc++ library into the bitcode (default=false)"), cl::init(false), cl::cat(LinkCat)); + +cl::OptionCategory + TestCompCat("Options specific to Test-Comp", + "These are options specific to the Test-Comp competition."); + +cl::opt WriteXMLTests("write-xml-tests", + cl::desc("Write XML-formated tests"), + cl::init(false), cl::cat(TestCompCat)); + +cl::opt + XMLMetadataProgramFile("xml-metadata-programfile", + cl::desc("Original file name for xml metadata"), + cl::cat(TestCompCat)); + +cl::opt XMLMetadataProgramHash( + "xml-metadata-programhash", + llvm::cl::desc("Test-Comp hash sum of original file for xml metadata"), + llvm::cl::cat(TestCompCat)); + } // namespace namespace klee { extern cl::opt MaxTime; +extern cl::opt FunctionCallReproduce; +extern cl::opt DumpStatesOnHalt; class ExecutionState; } // namespace klee @@ -384,12 +409,16 @@ class KleeHandler : public InterpreterHandler { void processTestCase(const ExecutionState &state, const char *message, const char *suffix, bool isError = false); + void writeTestCaseXML(bool isError, const KTest &out, unsigned id, + unsigned version = 0); + std::string getOutputFilename(const std::string &filename); std::unique_ptr openOutputFile(const std::string &filename); - std::string getTestFilename(const std::string &suffix, unsigned id); - std::unique_ptr openTestFile(const std::string &suffix, - unsigned id); + std::string getTestFilename(const std::string &suffix, unsigned id, + unsigned version = 0); + std::unique_ptr + openTestFile(const std::string &suffix, unsigned id, unsigned version = 0); // load a .path file static void loadPathFile(std::string name, std::vector &buffer); @@ -530,11 +559,14 @@ KleeHandler::openOutputFile(const std::string &filename) { return f; } -std::string KleeHandler::getTestFilename(const std::string &suffix, - unsigned id) { +std::string KleeHandler::getTestFilename(const std::string &suffix, unsigned id, + unsigned version) { std::stringstream filename; - filename << "test" << std::setfill('0') << std::setw(6) << id << '.' - << suffix; + filename << "test" << std::setfill('0') << std::setw(6) << id; + if (version) { + filename << '_' << version; + } + filename << '.' << suffix; return filename.str(); } @@ -543,8 +575,9 @@ SmallString<128> KleeHandler::getOutputDirectory() const { } std::unique_ptr -KleeHandler::openTestFile(const std::string &suffix, unsigned id) { - return openOutputFile(getTestFilename(suffix, id)); +KleeHandler::openTestFile(const std::string &suffix, unsigned id, + unsigned version) { + return openOutputFile(getTestFilename(suffix, id, version)); } /* Outputs all files (.ktest, .kquery, .cov etc.) describing a test case */ @@ -552,7 +585,12 @@ void KleeHandler::processTestCase(const ExecutionState &state, const char *message, const char *suffix, bool isError) { unsigned id = ++m_numTotalTests; - if (!WriteNone) { + if (!WriteNone && + (FunctionCallReproduce == "" || strcmp(suffix, "assert.err") == 0 || + strcmp(suffix, "reachable.err") == 0 || + (DumpStatesOnHalt == HaltExecution::Reason::UnreachedTarget && + m_interpreter->getHaltExecution() == + HaltExecution::Reason::UnreachedTarget))) { KTest ktest; ktest.numArgs = m_argc; ktest.args = m_argv; @@ -565,27 +603,39 @@ void KleeHandler::processTestCase(const ExecutionState &state, klee_warning("unable to get symbolic solution, losing test case"); const auto start_time = time::getWallTime(); + bool atLeastOneGenerated = false; if (success) { - if (!kTest_toFile( - &ktest, - getOutputFilename(getTestFilename("ktest", id)).c_str())) { - klee_warning("unable to write output test case, losing it"); - } else { - ++m_numGeneratedTests; + if (WriteKTests) { + for (unsigned i = 0; i < ktest.uninitCoeff + 1; ++i) { + if (!kTest_toFile( + &ktest, + getOutputFilename(getTestFilename("ktest", id, i)).c_str())) { + klee_warning("unable to write output test case, losing it"); + } else { + atLeastOneGenerated = true; + } + } + + if (WriteStates) { + auto f = openTestFile("state", id); + m_interpreter->logState(state, id, f); + } } - if (WriteStates) { - auto f = openTestFile("state", id); - m_interpreter->logState(state, id, f); + if (WriteXMLTests) { + for (unsigned i = 0; i < ktest.uninitCoeff + 1; ++i) { + writeTestCaseXML(message != nullptr, ktest, id, i); + atLeastOneGenerated = true; + } } - } - for (unsigned i = 0; i < ktest.numObjects; i++) { - delete[] ktest.objects[i].bytes; - delete[] ktest.objects[i].pointers; + for (unsigned i = 0; i < ktest.numObjects; i++) { + delete[] ktest.objects[i].bytes; + delete[] ktest.objects[i].pointers; + } + delete[] ktest.objects; } - delete[] ktest.objects; if (message) { auto f = openTestFile(suffix, id); @@ -617,6 +667,10 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } + if (atLeastOneGenerated) { + ++m_numGeneratedTests; + } + if (m_numGeneratedTests == MaxTests) m_interpreter->setHaltExecution(HaltExecution::MaxTests); @@ -663,13 +717,13 @@ void KleeHandler::processTestCase(const ExecutionState &state, } if (WriteCov) { - std::map> cov; + std::map> cov; m_interpreter->getCoveredLines(state, cov); auto f = openTestFile("cov", id); if (f) { for (const auto &entry : cov) { for (const auto &line : entry.second) { - *f << *entry.first << ':' << line << '\n'; + *f << entry.first << ':' << line << '\n'; } } } @@ -681,6 +735,66 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } +void KleeHandler::writeTestCaseXML(bool isError, const KTest &assignments, + unsigned id, unsigned version) { + + // TODO: This is super specific to test-comp and assumes that the name is the + // type information + auto file = openTestFile("xml", id, version); + if (!file) + return; + + *file << "\n"; + *file << "\n"; + *file << "\n"; + for (unsigned i = 0; i < assignments.numObjects; i++) { + auto item = assignments.objects[i]; + std::string name(item.name); + + *file << "\t"; + // Ignore the type + auto type_size_bytes = item.numBytes * 8; + llvm::APInt v(type_size_bytes, 0, false); + for (int i = item.numBytes - 1; i >= 0; i--) { + v <<= 8; + v |= item.bytes[i]; + } + // print value + + // Check if this is an unsigned type + if (name.find("u") == 0) { + v.print(*file, false); + } else if (name.rfind("*") != std::string::npos) { + // Pointer types + v.print(*file, false); + } else if (name.find("float") == 0) { + llvm::APFloat(APFloatBase::IEEEhalf(), v).print(*file); + } else if (name.find("double") == 0) { + llvm::APFloat(APFloatBase::IEEEdouble(), v).print(*file); + } else if (name.rfind("_t") != std::string::npos) { + // arbitrary type, e.g. sector_t + v.print(*file, false); + } else if (name.find("_") == 0) { + // _Bool + v.print(*file, false); + } else { + // the rest must be signed + v.print(*file, true); + } + *file << "\n"; + } + *file << "\n"; +} + // load a .path file void KleeHandler::loadPathFile(std::string name, std::vector &buffer) { std::ifstream f(name.c_str(), std::ios::in | std::ios::binary); @@ -1112,22 +1226,6 @@ static void halt_via_gdb(int pid) { perror("system"); } -static void replaceOrRenameFunction(llvm::Module *module, const char *old_name, - const char *new_name) { - Function *new_function, *old_function; - new_function = module->getFunction(new_name); - old_function = module->getFunction(old_name); - if (old_function) { - if (new_function) { - old_function->replaceAllUsesWith(new_function); - old_function->eraseFromParent(); - } else { - old_function->setName(new_name); - assert(old_function->getName() == new_name); - } - } -} - static void createLibCWrapper(std::vector> &userModules, std::vector> &libsModules, @@ -1204,7 +1302,7 @@ createLibCWrapper(std::vector> &userModules, } static void -linkWithUclibc(StringRef libDir, std::string opt_suffix, +linkWithUclibc(StringRef libDir, std::string bit_suffix, std::string opt_suffix, std::vector> &userModules, std::vector> &libsModules) { LLVMContext &ctx = userModules[0]->getContext(); @@ -1221,7 +1319,17 @@ linkWithUclibc(StringRef libDir, std::string opt_suffix, // Ensure that klee-uclibc exists SmallString<128> uclibcBCA(libDir); - llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_NAME); + // Hack to find out bitness of .bc file + + if (bit_suffix == "64") { + llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_64_NAME); + } else if (bit_suffix == "32") { + llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_32_NAME); + } else { + klee_error("Cannot determine bitness of source file from the name %s", + uclibcBCA.c_str()); + } + if (!klee::loadFileAsOneModule(uclibcBCA.c_str(), ctx, libsModules, errorMsg)) klee_error("Cannot find klee-uclibc '%s': %s", uclibcBCA.c_str(), errorMsg.c_str()); @@ -1268,6 +1376,47 @@ static int run_klee_on_function(int pArgc, char **pArgv, char **pEnvp, } auto startTime = std::time(nullptr); + + if (WriteXMLTests) { + // Write metadata.xml + auto meta_file = handler->openOutputFile("metadata.xml"); + if (!meta_file) + klee_error("Could not write metadata.xml"); + + *meta_file + << "\n"; + *meta_file + << "\n"; + *meta_file << "\n"; + *meta_file << "\tC\n"; + *meta_file << "\t" << PACKAGE_STRING << "\n"; + + // Assume with early exit a bug finding mode and otherwise coverage + if (OptExitOnError) + *meta_file << "\tCOVER( init(main()), FQL(COVER " + "EDGES(@CALL(__VERIFIER_error))) )\n"; + else + *meta_file << "\tCOVER( init(main()), FQL(COVER " + "EDGES(@DECISIONEDGE)) )\n"; + + // Assume the input file resembles the original source file; just exchange + // extension + *meta_file << "\t" << XMLMetadataProgramFile + << ".c\n"; + *meta_file << "\t" << XMLMetadataProgramHash + << "\n"; + *meta_file << "\t" << EntryPoint << "\n"; + *meta_file << "\t" + << finalModule->getDataLayout().getPointerSizeInBits() + << "bit\n"; + std::stringstream t; + t << std::put_time(std::localtime(&startTime), "%Y-%m-%dT%H:%M:%SZ"); + *meta_file << "\t" << t.str() << "\n"; + *meta_file << "\n"; + } + { // output clock info and start time std::stringstream startInfo; startInfo << time::getClockInfo() << "Started: " @@ -1543,13 +1692,19 @@ int main(int argc, char **argv, char **envp) { } llvm::Module *mainModule = loadedUserModules.front().get(); - std::unique_ptr origInfos; - std::unique_ptr assemblyFS; + FLCtoOpcode origInstructions; if (UseGuidedSearch == Interpreter::GuidanceKind::ErrorGuidance) { + for (const auto &Func : *mainModule) { + for (const auto &instr : llvm::instructions(Func)) { + auto locationInfo = getLocationInfo(&instr); + origInstructions[locationInfo.file][locationInfo.line] + [locationInfo.column] + .insert(instr.getOpcode()); + } + } + std::vector args; - origInfos = std::make_unique( - *mainModule, std::move(assemblyFS), true); args.push_back(llvm::Type::getInt32Ty(ctx)); // argc args.push_back(llvm::PointerType::get( Type::getInt8PtrTy(ctx), @@ -1568,15 +1723,16 @@ int main(int argc, char **argv, char **envp) { EntryPoint = stubEntryPoint; } - std::unordered_set mainModuleFunctions; + std::set mainModuleFunctions; for (auto &Function : *mainModule) { if (!Function.isDeclaration()) { mainModuleFunctions.insert(Function.getName().str()); } } - std::unordered_set mainModuleGlobals; - for (const auto &gv : mainModule->globals()) + std::set mainModuleGlobals; + for (const auto &gv : mainModule->globals()) { mainModuleGlobals.insert(gv.getName().str()); + } const std::string &module_triple = mainModule->getTargetTriple(); std::string host_triple = llvm::sys::getDefaultTargetTriple(); @@ -1587,16 +1743,16 @@ int main(int argc, char **argv, char **envp) { module_triple.c_str(), host_triple.c_str()); // Detect architecture - std::string opt_suffix = "64"; // Fall back to 64bit + std::string bit_suffix = "64"; // Fall back to 64bit if (module_triple.find("i686") != std::string::npos || module_triple.find("i586") != std::string::npos || module_triple.find("i486") != std::string::npos || module_triple.find("i386") != std::string::npos || module_triple.find("arm") != std::string::npos) - opt_suffix = "32"; + bit_suffix = "32"; // Add additional user-selected suffix - opt_suffix += "_" + RuntimeBuild.getValue(); + std::string opt_suffix = bit_suffix + "_" + RuntimeBuild.getValue(); if (UseGuidedSearch == Interpreter::GuidanceKind::ErrorGuidance) { SimplifyModule = false; @@ -1728,7 +1884,7 @@ int main(int argc, char **argv, char **envp) { break; } case LibcType::UcLibc: - linkWithUclibc(LibraryDir, opt_suffix, loadedUserModules, + linkWithUclibc(LibraryDir, bit_suffix, opt_suffix, loadedUserModules, loadedLibsModules); break; } @@ -1790,6 +1946,10 @@ int main(int argc, char **argv, char **envp) { if (UseGuidedSearch == Interpreter::GuidanceKind::ErrorGuidance) { paths = parseStaticAnalysisInput(); + } else if (FunctionCallReproduce != "") { + klee_warning("Turns on error-guided mode to cover %s function", + FunctionCallReproduce.c_str()); + UseGuidedSearch = Interpreter::GuidanceKind::ErrorGuidance; } Interpreter::InterpreterOptions IOpts(paths); @@ -1810,8 +1970,9 @@ int main(int argc, char **argv, char **envp) { // locale and other data and then calls main. auto finalModule = interpreter->setModule( - loadedUserModules, loadedLibsModules, Opts, mainModuleFunctions, - mainModuleGlobals, std::move(origInfos)); + loadedUserModules, loadedLibsModules, Opts, + std::move(mainModuleFunctions), std::move(mainModuleGlobals), + std::move(origInstructions)); externalsAndGlobalsCheck(finalModule); if (InteractiveMode) { diff --git a/unittests/Assignment/AssignmentTest.cpp b/unittests/Assignment/AssignmentTest.cpp index f7906ef73b..419a4d0956 100644 --- a/unittests/Assignment/AssignmentTest.cpp +++ b/unittests/Assignment/AssignmentTest.cpp @@ -19,7 +19,7 @@ TEST(AssignmentTest, FoldNotOptimized) { SourceBuilder::makeSymbolic("simple_array", 0)); // Create a simple assignment std::vector objects; - SparseStorage value(1); + SparseStorage value(0); std::vector> values; objects.push_back(array); @@ -27,7 +27,7 @@ TEST(AssignmentTest, FoldNotOptimized) { values.push_back(value); // We want to simplify to a constant so allow free values so // if the assignment is incomplete we don't get back a constant. - Assignment assignment(objects, values, /*_allowFreeValues=*/true); + Assignment assignment(objects, values); // Now make an expression that reads from the array at position // zero. diff --git a/unittests/Expr/ArrayExprTest.cpp b/unittests/Expr/ArrayExprTest.cpp index 866e6d3fd7..c2c522007d 100644 --- a/unittests/Expr/ArrayExprTest.cpp +++ b/unittests/Expr/ArrayExprTest.cpp @@ -41,8 +41,8 @@ static ArrayCache ac; TEST(ArrayExprTest, HashCollisions) { klee::OptimizeArray = ALL; - std::vector> constVals(256, - ConstantExpr::create(5, Expr::Int8)); + SparseStorage> constVals( + ConstantExpr::create(5, Expr::Int8)); const Array *array = ac.CreateArray( ConstantExpr::create(256, sizeof(uint64_t) * CHAR_BIT), SourceBuilder::constant(constVals), Expr::Int32, Expr::Int8); @@ -65,8 +65,7 @@ TEST(ArrayExprTest, HashCollisions) { SparseStorage value({6, 0, 0, 0}); std::vector> values = {value}; std::vector assigmentArrays = {symArray}; - auto a = std::make_unique(assigmentArrays, values, - /*_allowFreeValues=*/true); + auto a = std::make_unique(assigmentArrays, values); EXPECT_NE(a->evaluate(updatedRead), a->evaluate(firstRead)); EXPECT_EQ(a->evaluate(updatedRead), getConstant(42, Expr::Int8)); diff --git a/unittests/Expr/ExprTest.cpp b/unittests/Expr/ExprTest.cpp index 2a34463d9f..f6d79683e7 100644 --- a/unittests/Expr/ExprTest.cpp +++ b/unittests/Expr/ExprTest.cpp @@ -128,9 +128,10 @@ TEST(ExprTest, ReadExprFoldingBasic) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -148,7 +149,7 @@ TEST(ExprTest, ReadExprFoldingBasic) { // Read - should be constant folded to Contents[i] // Check that constant folding worked ConstantExpr *c = static_cast(read.get()); - EXPECT_EQ(Contents[i]->getZExtValue(), c->getZExtValue()); + EXPECT_EQ(Contents.load(i)->getZExtValue(), c->getZExtValue()); } } @@ -156,9 +157,10 @@ TEST(ExprTest, ReadExprFoldingIndexOutOfBound) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = ac.CreateArray(ConstantExpr::create(size, sizeof(uint64_t) * CHAR_BIT), @@ -178,9 +180,10 @@ TEST(ExprTest, ReadExprFoldingConstantUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -205,9 +208,10 @@ TEST(ExprTest, ReadExprFoldingConstantMultipleUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -234,9 +238,10 @@ TEST(ExprTest, ReadExprFoldingSymbolicValueUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -263,9 +268,10 @@ TEST(ExprTest, ReadExprFoldingSymbolicIndexUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = diff --git a/unittests/Solver/SolverTest.cpp b/unittests/Solver/SolverTest.cpp index 3206bd1a18..a208376c7d 100644 --- a/unittests/Solver/SolverTest.cpp +++ b/unittests/Solver/SolverTest.cpp @@ -82,9 +82,9 @@ void testOperation(Solver &solver, int value, Expr::Width operandWidth, ref queryExpr = EqExpr::create(fullySymbolicExpr, partiallyConstantExpr); - ConstraintSet constraints; - constraints.addConstraint( - Simplificator::simplifyExpr(ConstraintSet(), expr).simplified, {}); + constraints_ty constraints; + constraints.insert( + Simplificator::simplifyExpr(ConstraintSet(), expr).simplified); bool res; bool success = solver.mustBeTrue(Query(constraints, queryExpr), res); EXPECT_EQ(true, success) << "Constraint solving failed"; diff --git a/unittests/Solver/Z3SolverTest.cpp b/unittests/Solver/Z3SolverTest.cpp index 8c8d84e9be..a9a2581d89 100644 --- a/unittests/Solver/Z3SolverTest.cpp +++ b/unittests/Solver/Z3SolverTest.cpp @@ -14,6 +14,7 @@ #include "gtest/gtest.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Expr/ArrayCache.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" @@ -37,17 +38,16 @@ class Z3SolverTest : public ::testing::Test { }; TEST_F(Z3SolverTest, GetConstraintLog) { - ConstraintSet Constraints; + constraints_ty Constraints; const std::vector ConstantValues{1, 2, 3, 4}; - std::vector> ConstantExpressions; + SparseStorage> ConstantExpressions( + ConstantExpr::create(0, Expr::Int8)); - std::transform( - ConstantValues.begin(), ConstantValues.end(), - std::back_inserter(ConstantExpressions), [](const uint64_t Value) { - ref ConstantExpr(ConstantExpr::alloc(Value, Expr::Int8)); - return ConstantExpr; - }); + for (unsigned i = 0; i < ConstantValues.size(); ++i) { + ConstantExpressions.store( + i, ConstantExpr::alloc(ConstantValues[i], Expr::Int8)); + } const Array *ConstantArray = AC.CreateArray(ConstantExpr::create(4, sizeof(uint64_t) * CHAR_BIT),