CBMC
smt_solver_process.cpp
Go to the documentation of this file.
1 // Author: Diffblue Ltd.
2 
4 
8 #include <util/exception_utils.h>
9 #include <util/invariant.h>
10 #include <util/string_utils.h>
11 
13  std::string command_line,
14  message_handlert &message_handler,
15  std::unique_ptr<std::ostream> out_stream)
16  : command_line_description{"\"" + command_line + "\""},
17  out_stream(std::move(out_stream)),
18  process{split_string(command_line, ' ', false, true), message_handler},
19  log{message_handler}
20 {
21 }
22 
24 {
26 }
27 
29 {
30  const std::string command_string = smt_to_smt2_string(smt_command);
31  log.debug() << "Sending command to SMT2 solver - " << command_string
32  << messaget::eom;
33 
34  if(out_stream != nullptr)
35  {
36  // Using `std::endl` instead of '\n' to also flush the stream as it is a
37  // debugging functionality, to guarantee a consistent output in case of
38  // hanging after `(check-sat)`
39  *out_stream << command_string << std::endl;
40  }
41 
42  const auto response = process.send(command_string + "\n");
43  switch(response)
44  {
46  return;
48  throw analysis_exceptiont{"Sending to SMT solver sub process failed."};
50  throw analysis_exceptiont{"SMT solver sub process is in error state."};
51  }
53 }
54 
56 static void handle_invalid_smt(
57  const std::vector<std::string> &validation_errors,
58  messaget &log)
59 {
60  for(const std::string &message : validation_errors)
61  {
62  log.error() << message << messaget::eom;
63  }
64  throw analysis_exceptiont{"Invalid SMT response received from solver."};
65 }
66 
68  const std::unordered_map<irep_idt, smt_identifier_termt> &identifier_table)
69 {
70  const auto response_text = process.wait_receive();
71  log.debug() << "Solver response - " << response_text << messaget::eom;
72  response_stream << response_text;
73  const auto parse_tree = smt2irep(response_stream, log.get_message_handler());
74  if(!parse_tree)
75  throw deserialization_exceptiont{"Incomplete SMT response."};
76  const auto validation_result =
77  validate_smt_response(*parse_tree, identifier_table);
78  if(const auto validation_errors = validation_result.get_if_error())
79  handle_invalid_smt(*validation_errors, log);
80  return *validation_result.get_if_valid();
81 }
82 
84  message_handlert &message_handler,
85  std::ostream &out_stream,
86  std::unique_ptr<std::ostream> file_stream)
87  : file_stream(std::move(file_stream)),
88  out_stream(out_stream),
89  log(message_handler)
90 {
91 }
92 
94 {
95  return desc;
96 }
97 
99 {
100  out_stream << smt_to_smt2_string(smt_command) << '\n';
101 }
102 
104  const std::unordered_map<irep_idt, smt_identifier_termt> &identifier_table)
105 {
106  // Using `smt_unsat_responset` as response because the decision-procedure will
107  // terminate anyway (stop-on-fail), it is not reported to the user as for
108  // `unknown`, and does not trigger a subsequent invocation to get the model
109  // (as a `smt_sat_responset` answer will trigger).
111 }
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Thrown when failing to deserialize a value from some low level format, like JSON or raw bytes.
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:154
mstreamt & debug() const
Definition: message.h:421
message_handlert & get_message_handler()
Definition: message.h:183
static eomt eom
Definition: message.h:289
send_responset send(const std::string &message)
Send a string message (command) to the child process.
std::string wait_receive()
Wait until a string is available and read a string from the child process' output.
const std::string & description() override
smt_responset receive_response(const std::unordered_map< irep_idt, smt_identifier_termt > &identifier_table) override
void send(const smt_commandt &smt_command) override
Converts given SMT2 command to SMT2 string and sends it to the solver process.
std::ostream & out_stream
The output stream reference to print the SMT formula to.
smt_incremental_dry_run_solvert(message_handlert &message_handler, std::ostream &out_stream, std::unique_ptr< std::ostream > file_stream)
const std::string desc
Description of the current solver.
messaget log
For debug printing.
std::string command_line_description
The command line used to start the process.
void send(const smt_commandt &smt_command) override
Converts given SMT2 command to SMT2 string and sends it to the solver process.
const std::string & description() override
std::stringstream response_stream
For buffering / combining communications from the solver to cbmc.
smt_piped_solver_processt(std::string command_line, message_handlert &message_handler, std::unique_ptr< std::ostream > out_stream)
smt_responset receive_response(const std::unordered_map< irep_idt, smt_identifier_termt > &identifier_table) override
std::unique_ptr< std::ostream > out_stream
Pointer to the stream to print the SMT formula. nullptr if no output.
piped_processt process
The raw solver sub process.
double log(double x)
Definition: math.c:2776
response_or_errort< smt_responset > validate_smt_response(const irept &parse_tree, const std::unordered_map< irep_idt, smt_identifier_termt > &identifier_table)
static void handle_invalid_smt(const std::vector< std::string > &validation_errors, messaget &log)
Log messages and throw exception.
std::string smt_to_smt2_string(const smt_indext &index)
Streaming SMT data structures to a string based output stream.
std::optional< irept > smt2irep(std::istream &in, message_handlert &message_handler)
returns an irep for an SMT-LIB2 expression read from a given stream returns {} when EOF is encountere...
Definition: smt2irep.cpp:92
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)