Skip to content

Commit

Permalink
feat: native interface for PPLite
Browse files Browse the repository at this point in the history
Enable using option -DCRAB_USE_PPLITE_NATIVE=ON

fix(test): HAVE_PPLITE does not imply HAVE_APRON

Before having a native interface for pplite, the pragma HAVE_PPLITE
implied HAVE_APRON because pplite was necessarily using the apron
interface.  However after, that implication does not necessarily
holds. However the decoupled domain (specifically convert_to) expects
both HAVE_APRON and HAVE_PPLITE enabled if template parameter is
instantiated with apron_asc_dsc_pair.
  • Loading branch information
caballa committed Apr 9, 2024
1 parent d257cfc commit 733d448
Show file tree
Hide file tree
Showing 13 changed files with 971 additions and 20 deletions.
31 changes: 25 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
#--------------- Crab Options ---------------------#
option(CRAB_USE_LDD "Enable Ldd library" OFF)
option(CRAB_USE_APRON "Enable Apron library" OFF)
option(CRAB_USE_PPLITE "Enable PPLite library" OFF)
option(CRAB_USE_PPLITE "Enable PPLite domains using Apron interface" OFF)
option(CRAB_USE_PPLITE_NATIVE "Enable PPLite domains using native interface" OFF)
option(CRAB_USE_ELINA "Enable Elina library" OFF)
option(CRAB_BUILD_LIBS_SHARED "Build all Crab libraries dynamically." OFF)
option(CRAB_ENABLE_STATS "Enable stats" ON)
if (CRAB_USE_APRON AND CRAB_USE_ELINA)
message(FATAL_ERROR "Crab: Apron and Elina are not compatible. Choose one")
endif()
if (CRAB_USE_PPLITE_NATIVE)
set(CRAB_USE_PPLITE ON)
endif()

## Only for developers use
option(CRAB_ENABLE_TESTS "Enable tests" OFF)
Expand Down Expand Up @@ -143,7 +147,7 @@ else()
endif()

#---------- MPFR ---------#
if (CRAB_USE_APRON OR CRAB_USE_ELINA)
if (CRAB_USE_APRON OR CRAB_USE_ELINA OR CRAB_USE_PPLITE)
get_filename_component (GMP_SEARCH_PATH ${GMP_INCLUDE_DIR} PATH)
find_package(MPFR REQUIRED)
if (MPFR_FOUND)
Expand All @@ -157,6 +161,7 @@ if (CRAB_USE_PPLITE)
find_package(FLINT REQUIRED)
if (FLINT_FOUND)
get_filename_component (FLINT_SEARCH_PATH ${FLINT_INCLUDES} PATH)
include_directories (${FLINT_INCLUDES})
endif ()
endif ()

Expand All @@ -178,6 +183,7 @@ include(download_apron)
include(download_elina)
include(download_boxes_ldd)
include(download_pplite)
include(download_pplite_domains)

if (CRAB_USE_LDD)
find_package(Ldd)
Expand All @@ -203,6 +209,14 @@ if (CRAB_USE_PPLITE)
include_directories (${PPLITE_INCLUDE_DIR})
set (PPLITE_LIBS ${PPLITE_LIBRARY})
set (HAVE_PPLITE TRUE)
if (CRAB_USE_PPLITE_NATIVE)
if (EXISTS ${CMAKE_SOURCE_DIR}/include/crab/domains/pplite/pplite_native_wrapper.hpp)
set (HAVE_PPLITE_NATIVE TRUE)
else()
message (WARNING "Crab: no pplite/pplite_native_wrapper.hpp found. Run \n\tcmake --build . --target pplite-native && cmake ${CMAKE_SOURCE_DIR}")
return()
endif()
endif()
else()
ExternalProject_Get_Property (pplite INSTALL_DIR)
set (PPLITE_ROOT ${INSTALL_DIR} CACHE FILEPATH "Forced location of pplite" FORCE)
Expand Down Expand Up @@ -265,7 +279,11 @@ endif ()

if (CRAB_USE_PPLITE)
set_target_properties(pplite PROPERTIES EXCLUDE_FROM_ALL ON)
message (STATUS "Crab: PPLite domains will be available")
if (HAVE_PPLITE_NATIVE)
message (STATUS "Crab: PPLite domains using native interface will be available")
else()
message (STATUS "Crab: PPLite domains using Apron interface will be available")
endif()
else ()
message (STATUS "Crab: PPLite domains will NOT be available")
endif ()
Expand Down Expand Up @@ -344,6 +362,7 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES ${_CRAB_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})

install(DIRECTORY include/
DESTINATION crab/include
PATTERN ".git" EXCLUDE
PATTERN "config.h.cmake" EXCLUDE)
install(FILES ${CMAKE_BINARY_DIR}/include/crab/config.h DESTINATION crab/include/crab)

Expand All @@ -359,7 +378,7 @@ endif()

if (CRAB_USE_PPLITE)
ExternalProject_Get_Property (pplite INSTALL_DIR)
install(DIRECTORY ${INSTALL_DIR} DESTINATION .)
install(DIRECTORY ${INSTALL_DIR} DESTINATION .)
endif()

if (CRAB_USE_ELINA)
Expand All @@ -385,9 +404,9 @@ endif ()

# Print cmake command
if (CRAB_ENABLE_TESTS)
message(STATUS "Crab: cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DCRAB_USE_APRON=${CRAB_USE_APRON} -DCRAB_USE_PPLITE=${CRAB_USE_PPLITE} -DCRAB_USE_ELINA=${CRAB_USE_ELINA} -DCRAB_USE_LDD=${CRAB_USE_LDD} -DCRAB_BUILD_LIBS_SHARED=${CRAB_BUILD_LIBS_SHARED} -DCRAB_ENABLE_TESTS=${CRAB_ENABLE_TESTS} -DTEST_DIR=${TEST_DIR}")
message(STATUS "Crab: cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DCRAB_USE_APRON=${CRAB_USE_APRON} -DCRAB_USE_PPLITE=${CRAB_USE_PPLITE} -DCRAB_USE_PPLITE_NATIVE=${CRAB_USE_PPLITE_NATIVE} -DCRAB_USE_ELINA=${CRAB_USE_ELINA} -DCRAB_USE_LDD=${CRAB_USE_LDD} -DCRAB_BUILD_LIBS_SHARED=${CRAB_BUILD_LIBS_SHARED} -DCRAB_ENABLE_TESTS=${CRAB_ENABLE_TESTS} -DTEST_DIR=${TEST_DIR}")
else()
message(STATUS "Crab: cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DCRAB_USE_APRON=${CRAB_USE_APRON} -DCRAB_USE_PPLITE=${CRAB_USE_PPLITE} -DCRAB_USE_ELINA=${CRAB_USE_ELINA} -DCRAB_USE_LDD=${CRAB_USE_LDD} -DCRAB_BUILD_LIBS_SHARED=${CRAB_BUILD_LIBS_SHARED}")
message(STATUS "Crab: cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DCRAB_USE_APRON=${CRAB_USE_APRON} -DCRAB_USE_PPLITE=${CRAB_USE_PPLITE} -DCRAB_USE_PPLITE_NATIVE=${CRAB_USE_PPLITE_NATIVE} -DCRAB_USE_ELINA=${CRAB_USE_ELINA} -DCRAB_USE_LDD=${CRAB_USE_LDD} -DCRAB_BUILD_LIBS_SHARED=${CRAB_BUILD_LIBS_SHARED}")
endif()


9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ requirements are:
- C++11 compiler
- Boost >= 1.65
- GMP
- MPFR (if `-DCRAB_USE_APRON=ON` or `-DCRAB_USE_ELINA=ON`)
- FLINT (only if `-DCRAB_USE_PPLITE=ON`)
- MPFR (if `-DCRAB_USE_APRON=ON` or `-DCRAB_USE_ELINA=ON` or `-DCRAB_USE_PPLITE_NATIVE=ON`)
- FLINT (only if `-DCRAB_USE_PPLITE=ON` or `-DCRAB_USE_PPLITE_NATIVE=ON`)

In linux, you can install requirements typing the commands:

Expand Down Expand Up @@ -135,7 +135,10 @@ installation of the libraries is optional.
`-DCRAB_USE_ELINA=ON` option.

- If you want to use the PPLite library domains then add
`-DCRAB_USE_PPLITE=ON` option.
`-DCRAB_USE_PPLITE=ON` or `-DCRAB_USE_PPLITE_NATIVE=ON` option. The
former calls PPLite using the Apron interface while the latter calls
PPLite natively. The native interface is faster and it will
eventually replace the Apron interface.


**Important:** Apron and Elina are currently not compatible so you
Expand Down
11 changes: 11 additions & 0 deletions cmake/download_pplite_domains.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if (CRAB_USE_PPLITE_NATIVE)
set (PPLITE_DOMAINS_REPO "https://github.com/seahorn/crab-pplite.git"
CACHE STRING "source of wrapper for pplite domains using native interface")
set (PPLITE_SOURCE_DIR "${CMAKE_SOURCE_DIR}/include/crab/domains/pplite")
set (PPLITE_WRAPPER "${PPLITE_SOURCE_DIR}/pplite_native_wrapper.hpp")

if (NOT EXISTS ${PPLITE_WRAPPER})
add_custom_target(pplite-native
${GIT_EXECUTABLE} clone ${PPLITE_DOMAINS_REPO} ${PPLITE_SOURCE_DIR})
endif()
endif()
6 changes: 3 additions & 3 deletions docker/crab.dev.pplite.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Dockerfile for Crab image with pplite library.
# Dockerfile for Crab image with pplite library using Apron interface.
#

# Pull base image.
Expand All @@ -21,9 +21,9 @@ RUN cmake -GNinja \
-DCRAB_USE_APRON=ON -DCRAB_USE_PPLITE=ON \
-DCRAB_ENABLE_TESTS=ON \
../ && \
cmake --build . --target apron && cmake .. && \
cmake --build . --target pplite && cmake .. && \
cmake --build . --target pplite_domains
cmake --build . --target apron && cmake .. && \
cmake --build . --target install

# Run tests
RUN /crab/tests/run_tests.sh /crab/tests/expected_results.pplite.out /crab/build
Expand Down
32 changes: 32 additions & 0 deletions docker/crab.dev.pplite_native.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# Dockerfile for Crab image with pplite library using native interface.
#

# Pull base image.
FROM seahorn/buildpack-deps-crab:jammy

# Assume that docker-build is ran in the top-level Crab directory
COPY . /crab
# Re-create the build directory that might have been present in the source tree
RUN rm -rf /crab/build /crab/debug /crab/release && mkdir /crab/build
WORKDIR /crab/build

ARG BUILD_TYPE
# Build configuration.
RUN cmake -GNinja \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX=run \
-DCMAKE_CXX_COMPILER=g++-12 \
-DCMAKE_EXPORT_COMPILE_COMMANDS=1 \
-DCRAB_USE_PPLITE_NATIVE=ON \
-DCRAB_ENABLE_TESTS=ON \
../ && \
cmake --build . --target pplite && cmake .. && \
cmake --build . --target pplite-native && cmake .. && \
cmake --build . --target install

# Run tests
RUN /crab/tests/run_tests.sh /crab/tests/expected_results.pplite_native.out /crab/build

WORKDIR /crab

15 changes: 14 additions & 1 deletion include/crab/config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,22 @@
/** Define whether apron library is available */
#cmakedefine HAVE_APRON ${HAVE_APRON}

/** Define whether pplite library is available */
/**
* Define whether pplite library is available.
* If HAVE_PPLITE_NATIVE is not enabled then pplite domains are used
* using the apron interface.
**/
#cmakedefine HAVE_PPLITE ${HAVE_PPLITE}

/**
* Define whether pplite native interface is available. There are two ways of
* using pplite domains: via apron interface (both HAVE_APRON and
* HAVE_PPLITE must be enabled) or using a native interface. If
* HAVE_PPLITE and HAVE_PPLITE_NATIVE are enabled then the latter kind of
* interface is also enabled.
**/
#cmakedefine HAVE_PPLITE_NATIVE ${HAVE_PPLITE_NATIVE}

/** Define whether elina library is available */
#cmakedefine HAVE_ELINA ${HAVE_ELINA}

Expand Down
96 changes: 96 additions & 0 deletions include/crab/domains/pplite_domains.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#pragma once

#include <crab/config.h>

#include <crab/domains/abstract_domain.hpp>
#include <crab/domains/abstract_domain_specialized_traits.hpp>
#include <crab/numbers/bignums.hpp>

namespace crab {
namespace domains {

namespace pplite_domains {
/*
The values of this enumeration need to be kept in sync with
enum pplite::dynamic::Abs_Poly::Kind
*/
//enum pplite_domain_id_t : unsigned int;

/*
This enumeration needs to be kept in sync with
enum pplite::dynamic::Abs_Poly::Kind
The listed enum values are up-to-date with PPLite 0.11.
Note: even values are for domains; odd values for _STATS variants.
*/
enum pplite_domain_id_t : unsigned int {
POLY, POLY_STATS,
B_POLY, B_POLY_STATS,
F_POLY, F_POLY_STATS,
U_POLY, U_POLY_STATS,
UF_POLY, UF_POLY_STATS,
P_SET, P_SET_STATS,
FP_SET, FP_SET_STATS
};
} // pplite_domains

template <typename Number> class PPLiteDefaultParams {
public:
// use integers with truncation rounding
enum { use_integers = 1 };
enum { implement_inter_transformers = 0 };
};

template <> class PPLiteDefaultParams<ikos::q_number> {
public:
// use reals
enum { use_integers = 0 };
enum { implement_inter_transformers = 0 };
};

} // namespace domains
} // namespace crab

#if not defined(HAVE_PPLITE) || not defined(HAVE_PPLITE_NATIVE)

/*
* Dummy implementation if PPLite not found
*/

#include <crab/domains/dummy_abstract_domain.hpp>

namespace crab {
namespace domains {

template <typename N, typename V, pplite_domains::pplite_domain_id_t K,
class P = PPLiteDefaultParams<N>>
class pplite_domain final
: public dummy_abstract_domain<pplite_domain<N,V,K,P>> {
public:
std::string not_implemented_msg() const override {
#ifndef HAVE_PPLITE
return "No PPLite. Run cmake with -DCRAB_USE_PPLITE=ON";
#else
return "No PPLite. Make sure that pplite_domains can be found";
#endif
}
};

} // namespace domains
} // namespace crab

#else // defined(HAVE_PPLITE)

#include <crab/domains/pplite/pplite_native_wrapper.hpp>

#endif // HAVE_PPLITE

namespace crab {
namespace domains {
template <typename Number, typename VariableName, pplite_domains::pplite_domain_id_t K,
class Params>
struct abstract_domain_traits<pplite_domain<Number, VariableName, K, Params>> {
using number_t = Number;
using varname_t = VariableName;
};
} // namespace domains
} // namespace crab
12 changes: 11 additions & 1 deletion tests/crab_dom.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <crab/domains/split_oct.hpp>
#include <crab/domains/term_equiv.hpp>
#include <crab/domains/wrapped_interval_domain.hpp>
#include <crab/domains/pplite_domains.hpp>

namespace crab {

Expand Down Expand Up @@ -70,7 +71,13 @@ class ElinaParams {
enum { use_integers = 1 };
enum { implement_inter_transformers = 1 };
};

class PPLiteParams {
public:
// use integers with truncation rounding
enum { use_integers = 1 };
enum { implement_inter_transformers = 1 };
};

using z_dbm_domain_t = sparse_dbm_domain<z_number, varname_t, z_dbm_graph_t, SparseDBMParams>;
using z_sdbm_domain_t = split_dbm_domain<z_number, varname_t, z_dbm_graph_t, SplitDBMParams>;
using z_soct_domain_t = split_oct_domain<z_number, varname_t, z_dbm_graph_t, SplitOctParams>;
Expand All @@ -82,6 +89,9 @@ using z_pk_apron_domain_t = apron_domain<z_number, varname_t, APRON_PK>;
using z_poly_pplite_domain_t = apron_domain<z_number, varname_t, APRON_PPLITE_POLY>;
using z_fpoly_pplite_domain_t = apron_domain<z_number, varname_t, APRON_PPLITE_FPOLY>;
using z_pset_pplite_domain_t = apron_domain<z_number, varname_t, APRON_PPLITE_PSET>;
using z_poly_pplite_native_domain_t = pplite_domain<z_number, varname_t, pplite_domains::POLY, PPLiteParams>;
using z_fpoly_pplite_native_domain_t = pplite_domain<z_number, varname_t, pplite_domains::F_POLY, PPLiteParams>;
using z_pset_pplite_native_domain_t = pplite_domain<z_number, varname_t, pplite_domains::P_SET, PPLiteParams>;
using z_zones_elina_domain_t = elina_domain<z_number, varname_t, ELINA_ZONES>;
using z_oct_elina_domain_t = elina_domain<z_number, varname_t, ELINA_OCT, ElinaParams>;
using z_pk_elina_domain_t = elina_domain<z_number, varname_t, ELINA_PK>;
Expand Down
8 changes: 6 additions & 2 deletions tests/crab_inst.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,17 @@ Z_RUNNER(crab::domain_impl::z_pk_apron_domain_t)
Z_RUNNER(crab::domain_impl::z_poly_pplite_domain_t)
Z_RUNNER(crab::domain_impl::z_fpoly_pplite_domain_t)
Z_RUNNER(crab::domain_impl::z_pset_pplite_domain_t)
Z_RUNNER(crab::domain_impl::z_poly_pplite_native_domain_t)
Z_RUNNER(crab::domain_impl::z_fpoly_pplite_native_domain_t)
Z_RUNNER(crab::domain_impl::z_pset_pplite_native_domain_t)
#ifdef HAVE_APRON
Z_RUNNER(crab::domain_impl::z_dummy_decoupled_box_domain_t)
#endif
#ifdef HAVE_PPLITE
// These domains require HAVE_APRON and HAVE_PPLITE
Z_RUNNER(crab::domain_impl::z_decoupled_box_poly_domain_t)
Z_RUNNER(crab::domain_impl::z_decoupled_box_pset_domain_t)
#endif
#endif
#endif
Z_RUNNER(crab::domain_impl::z_zones_elina_domain_t)
Z_RUNNER(crab::domain_impl::z_oct_elina_domain_t)
Z_RUNNER(crab::domain_impl::z_pk_elina_domain_t)
Expand Down
2 changes: 2 additions & 0 deletions tests/domains/pplite_domains.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,12 @@ int main(int argc, char **argv) {
z_pset_pplite_domain_t init;
run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled);
}
#ifdef HAVE_APRON
{
z_decoupled_box_poly_domain_t init;
run(cfg, cfg->entry(), init, false, 1, 2, 20, stats_enabled);
}
#endif
delete cfg;
}

Expand Down
Loading

0 comments on commit 733d448

Please sign in to comment.