-
Notifications
You must be signed in to change notification settings - Fork 273
First iteration of C++ CBMC API #7274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -215,6 +215,7 @@ cprover_default_properties( | |
cbmc | ||
cbmc-lib | ||
cpp | ||
cprover-api-cpp | ||
cprover | ||
cprover-lib | ||
crangler | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
file(GLOB_RECURSE api_sources "../src/libcprover-cpp/*.cpp" "../src/libcprover-cpp/*.h") | ||
|
||
# This step builds a binary driving the API (to be used for testing) | ||
add_executable(api-binary-driver call_bmc.cpp ${api_sources}) | ||
cprover_default_properties(api-binary-driver) | ||
target_include_directories(api-binary-driver | ||
PUBLIC | ||
${CBMC_BINARY_DIR} | ||
${CBMC_SOURCE_DIR} | ||
# TODO: Should be fixed for the proper include form. | ||
${CMAKE_CURRENT_SOURCE_DIR}/../src/libcprover-cpp/) | ||
Comment on lines
+10
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is this tracked/when will it be fixed? |
||
target_link_libraries(api-binary-driver goto-programs util langapi ansi-c cprover-api-cpp) | ||
|
||
# Enable test running | ||
set(test_pl_path "${CBMC_SOURCE_DIR}/../regression/test.pl") | ||
|
||
macro(add_test_pl_profile name cmdline flag profile) | ||
add_test( | ||
NAME "${name}-${profile}" | ||
COMMAND perl ${test_pl_path} -e -p -c "${cmdline}" ${flag} ${ARGN} | ||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" | ||
) | ||
set_tests_properties("${name}-${profile}" PROPERTIES | ||
LABELS "${profile};CBMC" | ||
) | ||
endmacro(add_test_pl_profile) | ||
Comment on lines
+17
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you need a new one and cannot re-use the existing one? |
||
|
||
macro(add_test_pl_tests cmdline) | ||
get_filename_component(TEST_DIR_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) | ||
message(STATUS "Adding tests in directory: ${TEST_DIR_NAME}") | ||
add_test_pl_profile("${TEST_DIR_NAME}" "${cmdline}" -C CORE ${ARGN}) | ||
add_test_pl_profile("${TEST_DIR_NAME}" "${cmdline}" -T THOROUGH ${ARGN}) | ||
add_test_pl_profile("${TEST_DIR_NAME}" "${cmdline}" -F FUTURE ${ARGN}) | ||
add_test_pl_profile("${TEST_DIR_NAME}" "${cmdline}" -K KNOWNBUG ${ARGN}) | ||
endmacro(add_test_pl_tests) | ||
|
||
# For the best possible utilisation of multiple cores when | ||
# running tests in parallel, it is important that these directories are | ||
# listed with decreasing runtimes (i.e. longest running at the top) | ||
add_subdirectory(model_loading) | ||
Comment on lines
+37
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will we actually get parallelisation within parallel runs here? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Author: Fotis Koutoulakis for Diffblue Ltd. | ||
|
||
// Test file to try loading a GOTO-model into memory and running a sample verification run on it. | ||
#include <util/exception_utils.h> | ||
|
||
#include <libcprover-cpp/api.h> | ||
#include <libcprover-cpp/options.h> | ||
|
||
#include <iostream> | ||
#include <vector> | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
try | ||
{ | ||
std::cout << "Hello from API stub" << std::endl; | ||
|
||
// Convert argv to vector of strings for initialize_goto_model | ||
std::vector<std::string> arguments(argv + 1, argv + argc); | ||
|
||
// Create API options object, to pass to initialiser of API object. | ||
auto api_options = api_optionst::create().simplify(false); | ||
|
||
// Initialise API dependencies and global configuration in one step. | ||
api_sessiont api(api_options); | ||
|
||
// Demonstrate the loading of a goto-model from the command line arguments | ||
api.load_model_from_files(arguments); | ||
|
||
std::cout << "Successfully initialised goto_model" << std::endl; | ||
return 0; | ||
} | ||
catch(const invalid_command_line_argument_exceptiont &e) | ||
{ | ||
std::cout << e.what() << std::endl; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
add_test_pl_tests( | ||
"$<TARGET_FILE:api-binary-driver>" | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#include <assert.h> | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
int a[] = {0, 1, 2, 3, 4}; | ||
assert(a[4] != 4); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
CORE | ||
test.c | ||
|
||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
Successfully initialised goto_model | ||
-- | ||
-- |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
file(GLOB_RECURSE sources "*.cpp" "*.h") | ||
|
||
# This step builds the API in the form of a statically linked library (libcprover-api-cpp.a) | ||
add_library(cprover-api-cpp ${sources}) | ||
generic_includes(cprover-api-cpp) | ||
target_link_libraries(cprover-api-cpp goto-programs util langapi ansi-c) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Author: Fotis Koutoulakis for Diffblue Ltd. | ||
|
||
#include "api.h" | ||
|
||
#include <util/cmdline.h> | ||
#include <util/config.h> | ||
#include <util/message.h> | ||
#include <util/options.h> | ||
|
||
#include <goto-programs/goto_model.h> | ||
#include <goto-programs/initialize_goto_model.h> | ||
|
||
#include <ansi-c/ansi_c_language.h> | ||
#include <langapi/mode.h> | ||
|
||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
extern configt config; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are including |
||
|
||
api_sessiont::api_sessiont() | ||
: message_handler( | ||
util_make_unique<null_message_handlert>(null_message_handlert{})), | ||
options(util_make_unique<optionst>(optionst{})) | ||
{ | ||
// Needed to initialise the language options correctly | ||
cmdlinet cmdline; | ||
// config is global in config.cpp | ||
config.set(cmdline); | ||
// Initialise C language mode | ||
register_language(new_ansi_c_language); | ||
} | ||
|
||
api_sessiont::api_sessiont(const api_optionst &options) | ||
: message_handler( | ||
util_make_unique<null_message_handlert>(null_message_handlert{})), | ||
Comment on lines
+23
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Enforcing a null message handler hardly seems like a good idea. If you absolutely want to avoid exposing the |
||
options(options.to_engine_options()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems the zero-argument constructor should just use this constructor? They do the same, after all. |
||
{ | ||
// Needed to initialise the language options correctly | ||
cmdlinet cmdline; | ||
// config is global in config.cpp | ||
config.set(cmdline); | ||
// Initialise C language mode | ||
register_language(new_ansi_c_language); | ||
} | ||
|
||
api_sessiont::~api_sessiont() = default; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did this need to go in the cpp file? |
||
|
||
void api_sessiont::load_model_from_files(const std::vector<std::string> &files) | ||
{ | ||
model = util_make_unique<goto_modelt>( | ||
initialize_goto_model(files, *message_handler, *options)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Author: Fotis Koutoulakis for Diffblue Ltd. | ||
|
||
#ifndef CPROVER_LIBCPROVER_CPP_API_H | ||
#define CPROVER_LIBCPROVER_CPP_API_H | ||
|
||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
// Forward declaration of API dependencies | ||
class goto_modelt; | ||
class message_handlert; | ||
class optionst; | ||
|
||
#include "options.h" | ||
Comment on lines
+13
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One of these should be removed. |
||
|
||
// An object in the pattern of Session Facade - owning all of the memory | ||
// the API is using and being responsible for the management of that. | ||
struct api_sessiont | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps better use |
||
{ | ||
// Initialising constructor | ||
api_sessiont(); | ||
explicit api_sessiont(const api_optionst &options); | ||
~api_sessiont(); // default constructed in the .cpp file | ||
|
||
/// Load a goto_model from a given vector of filenames. | ||
/// \param files: A vector<string> containing the filenames to be loaded | ||
void load_model_from_files(const std::vector<std::string> &files); | ||
|
||
private: | ||
std::unique_ptr<goto_modelt> model; | ||
std::unique_ptr<message_handlert> message_handler; | ||
std::unique_ptr<optionst> options; | ||
Comment on lines
+30
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest you use PIMPL here: have a single pointer to the actual implementation, and completely hide internals like |
||
}; | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
ansi-c | ||
langapi | ||
goto-programs | ||
util |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Author: Fotis Koutoulakis for Diffblue Ltd. | ||
|
||
#include "options.h" | ||
|
||
#include <util/make_unique.h> | ||
#include <util/options.h> | ||
|
||
api_optionst api_optionst::create() | ||
{ | ||
return api_optionst{}; | ||
} | ||
|
||
api_optionst &api_optionst::simplify(bool on) | ||
{ | ||
simplify_enabled = on; | ||
return *this; | ||
} | ||
|
||
std::unique_ptr<optionst> api_optionst::to_engine_options() const | ||
{ | ||
optionst engine_options; | ||
engine_options.set_option("simplify", simplify_enabled); | ||
return util_make_unique<optionst>(engine_options); | ||
} | ||
Comment on lines
+1
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Couldn't this file please be called api_options.h to avoid confusion? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Author: Fotis Koutoulakis for Diffblue Ltd. | ||
|
||
#ifndef CPROVER_LIBCPROVER_CPP_OPTIONS_H | ||
#define CPROVER_LIBCPROVER_CPP_OPTIONS_H | ||
|
||
#include <memory> | ||
|
||
class optionst; | ||
|
||
class api_optionst | ||
{ | ||
// Options for the verification engine | ||
bool simplify_enabled; | ||
|
||
// Private interface methods | ||
api_optionst() = default; | ||
Comment on lines
+15
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure this comment is helpful? |
||
|
||
public: | ||
static api_optionst create(); | ||
|
||
api_optionst &simplify(bool on); | ||
|
||
std::unique_ptr<optionst> to_engine_options() const; | ||
Comment on lines
+18
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These strictly need comments. This is supposed to be an API to be used, after all. |
||
}; | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# The CPROVER C++ API | ||
|
||
This folder includes the interface and the implementation of a new C++-based | ||
API for the CProver libraries. This allows direct linking to key CProver functionality | ||
via C++ function calls. This (will eventually) allow the use of all aspects of | ||
the CProver verification pipeline via direct function calls and deprecate the | ||
need for invoking separate tools/programs. | ||
|
||
## Implementation | ||
|
||
The major part of the implementation of the API is in [`api.cpp`](src/api.cpp). | ||
To use the API as it stands, you need to include the header [`api.h`](src/api.h) | ||
in your program, and link against the resultant shared-object from the CProver | ||
build process (`libcprover-api.a`). | ||
|
||
## Example | ||
|
||
An example for driving the API in its current form is in the file [`call_bmc.cpp`](regression/call_bmc.cpp), | ||
which we are also using as a binary driver for testing the API. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this not match the directory name?