about summary refs log tree commit diff homepage
path: root/lib/Solver/STPSolver.cpp
diff options
context:
space:
mode:
authorFrank Busse <bb0xfb@gmail.com>2019-01-23 00:29:08 +0000
committerCristian Cadar <c.cadar@imperial.ac.uk>2019-03-20 19:15:35 +0000
commit8234aca4486e03b887ee9bec9bf192339cb4b2ff (patch)
tree7e5505849ef22e0380c5e2090af49fd7bb60feb9 /lib/Solver/STPSolver.cpp
parente4cfe53809f4bd06a7fa91b9936e454b921c0b9d (diff)
downloadklee-8234aca4486e03b887ee9bec9bf192339cb4b2ff.tar.gz
STPSolver: C++11, add missing free, refactoring
Diffstat (limited to 'lib/Solver/STPSolver.cpp')
-rw-r--r--lib/Solver/STPSolver.cpp182
1 files changed, 85 insertions, 97 deletions
diff --git a/lib/Solver/STPSolver.cpp b/lib/Solver/STPSolver.cpp
index b058a9cb..e8b9222f 100644
--- a/lib/Solver/STPSolver.cpp
+++ b/lib/Solver/STPSolver.cpp
@@ -7,27 +7,25 @@
 //
 //===----------------------------------------------------------------------===//
 #include "klee/Config/config.h"
+
 #ifdef ENABLE_STP
-#include "STPSolver.h"
 #include "STPBuilder.h"
-#include "klee/Solver.h"
-#include "klee/SolverImpl.h"
+#include "STPSolver.h"
 #include "klee/Constraints.h"
-#include "klee/Internal/Support/ErrorHandling.h"
 #include "klee/OptionCategories.h"
+#include "klee/SolverImpl.h"
+#include "klee/Internal/Support/ErrorHandling.h"
 #include "klee/util/Assignment.h"
 #include "klee/util/ExprUtil.h"
 
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Errno.h"
-#include "llvm/Support/ErrorHandling.h"
 
-#include <errno.h>
+#include <csignal>
 #include <unistd.h>
-#include <signal.h>
-#include <sys/wait.h>
 #include <sys/ipc.h>
 #include <sys/shm.h>
+#include <sys/wait.h>
 
 namespace {
 
@@ -44,7 +42,7 @@ llvm::cl::opt<bool> IgnoreSolverFailures(
 
 #define vc_bvBoolExtract IAMTHESPAWNOFSATAN
 
-static unsigned char *shared_memory_ptr;
+static unsigned char *shared_memory_ptr = nullptr;
 static int shared_memory_id = 0;
 // Darwin by default has a very small limit on the maximum amount of shared
 // memory, which will quickly be exhausted by KLEE running its tests in
@@ -73,25 +71,25 @@ private:
   SolverRunStatus runStatusCode;
 
 public:
-  STPSolverImpl(bool _useForkedSTP, bool _optimizeDivides = true);
-  ~STPSolverImpl();
+  explicit STPSolverImpl(bool useForkedSTP, bool optimizeDivides = true);
+  ~STPSolverImpl() override;
 
-  char *getConstraintLog(const Query &);
-  void setCoreSolverTimeout(time::Span timeout) { this->timeout = timeout; }
+  char *getConstraintLog(const Query &) override;
+  void setCoreSolverTimeout(time::Span timeout) override { this->timeout = timeout; }
 
-  bool computeTruth(const Query &, bool &isValid);
-  bool computeValue(const Query &, ref<Expr> &result);
+  bool computeTruth(const Query &, bool &isValid) override;
+  bool computeValue(const Query &, ref<Expr> &result) override;
   bool computeInitialValues(const Query &,
                             const std::vector<const Array *> &objects,
-                            std::vector<std::vector<unsigned char> > &values,
-                            bool &hasSolution);
-  SolverRunStatus getOperationStatusCode();
+                            std::vector<std::vector<unsigned char>> &values,
+                            bool &hasSolution) override;
+  SolverRunStatus getOperationStatusCode() override;
 };
 
-STPSolverImpl::STPSolverImpl(bool _useForkedSTP, bool _optimizeDivides)
+STPSolverImpl::STPSolverImpl(bool useForkedSTP, bool optimizeDivides)
     : vc(vc_createValidityChecker()),
-      builder(new STPBuilder(vc, _optimizeDivides)),
-      useForkedSTP(_useForkedSTP), runStatusCode(SOLVER_RUN_STATUS_FAILURE) {
+      builder(new STPBuilder(vc, optimizeDivides)),
+      useForkedSTP(useForkedSTP), runStatusCode(SOLVER_RUN_STATUS_FAILURE) {
   assert(vc && "unable to create validity checker");
   assert(builder && "unable to create STPBuilder");
 
@@ -113,17 +111,17 @@ STPSolverImpl::STPSolverImpl(bool _useForkedSTP, bool _optimizeDivides)
         shmget(IPC_PRIVATE, shared_memory_size, IPC_CREAT | 0700);
     if (shared_memory_id < 0)
       llvm::report_fatal_error("unable to allocate shared memory region");
-    shared_memory_ptr = (unsigned char *)shmat(shared_memory_id, NULL, 0);
+    shared_memory_ptr = (unsigned char *)shmat(shared_memory_id, nullptr, 0);
     if (shared_memory_ptr == (void *)-1)
       llvm::report_fatal_error("unable to attach shared memory region");
-    shmctl(shared_memory_id, IPC_RMID, NULL);
+    shmctl(shared_memory_id, IPC_RMID, nullptr);
   }
 }
 
 STPSolverImpl::~STPSolverImpl() {
   // Detach the memory region.
   shmdt(shared_memory_ptr);
-  shared_memory_ptr = 0;
+  shared_memory_ptr = nullptr;
   shared_memory_id = 0;
 
   delete builder;
@@ -135,10 +133,9 @@ STPSolverImpl::~STPSolverImpl() {
 
 char *STPSolverImpl::getConstraintLog(const Query &query) {
   vc_push(vc);
-  for (std::vector<ref<Expr> >::const_iterator it = query.constraints.begin(),
-                                               ie = query.constraints.end();
-       it != ie; ++it)
-    vc_assertFormula(vc, builder->construct(*it));
+
+  for (const auto &constraint : query.constraints)
+    vc_assertFormula(vc, builder->construct(constraint));
   assert(query.expr == ConstantExpr::alloc(0, Expr::Bool) &&
          "Unexpected expression in query!");
 
@@ -152,7 +149,7 @@ char *STPSolverImpl::getConstraintLog(const Query &query) {
 
 bool STPSolverImpl::computeTruth(const Query &query, bool &isValid) {
   std::vector<const Array *> objects;
-  std::vector<std::vector<unsigned char> > values;
+  std::vector<std::vector<unsigned char>> values;
   bool hasSolution;
 
   if (!computeInitialValues(query, objects, values, hasSolution))
@@ -164,7 +161,7 @@ bool STPSolverImpl::computeTruth(const Query &query, bool &isValid) {
 
 bool STPSolverImpl::computeValue(const Query &query, ref<Expr> &result) {
   std::vector<const Array *> objects;
-  std::vector<std::vector<unsigned char> > values;
+  std::vector<std::vector<unsigned char>> values;
   bool hasSolution;
 
   // Find the object used in the expression, and compute an assignment
@@ -184,36 +181,28 @@ bool STPSolverImpl::computeValue(const Query &query, ref<Expr> &result) {
 static SolverImpl::SolverRunStatus
 runAndGetCex(::VC vc, STPBuilder *builder, ::VCExpr q,
              const std::vector<const Array *> &objects,
-             std::vector<std::vector<unsigned char> > &values,
+             std::vector<std::vector<unsigned char>> &values,
              bool &hasSolution) {
   // XXX I want to be able to timeout here, safely
   hasSolution = !vc_query(vc, q);
 
-  if (hasSolution) {
-    values.reserve(objects.size());
-    for (std::vector<const Array *>::const_iterator it = objects.begin(),
-                                                    ie = objects.end();
-         it != ie; ++it) {
-      const Array *array = *it;
-      std::vector<unsigned char> data;
-
-      data.reserve(array->size);
-      for (unsigned offset = 0; offset < array->size; offset++) {
-        ExprHandle counter =
-            vc_getCounterExample(vc, builder->getInitialRead(array, offset));
-        unsigned char val = getBVUnsigned(counter);
-        data.push_back(val);
-      }
+  if (!hasSolution)
+    return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE;
+
+  values.reserve(objects.size());
+  unsigned i = 0; // FIXME C++17: use reference from emplace_back()
+  for (const auto object : objects) {
+    values.emplace_back(object->size);
 
-      values.push_back(data);
+    for (unsigned offset = 0; offset < object->size; offset++) {
+      ExprHandle counter =
+          vc_getCounterExample(vc, builder->getInitialRead(object, offset));
+      values[i][offset] = static_cast<unsigned char>(getBVUnsigned(counter));
     }
+    ++i;
   }
 
-  if (true == hasSolution) {
-    return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE;
-  } else {
-    return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE;
-  }
+  return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE;
 }
 
 static void stpTimeoutHandler(int x) { _exit(52); }
@@ -221,47 +210,46 @@ static void stpTimeoutHandler(int x) { _exit(52); }
 static SolverImpl::SolverRunStatus
 runAndGetCexForked(::VC vc, STPBuilder *builder, ::VCExpr q,
                    const std::vector<const Array *> &objects,
-                   std::vector<std::vector<unsigned char> > &values,
+                   std::vector<std::vector<unsigned char>> &values,
                    bool &hasSolution, time::Span timeout) {
   unsigned char *pos = shared_memory_ptr;
   unsigned sum = 0;
-  for (std::vector<const Array *>::const_iterator it = objects.begin(),
-                                                  ie = objects.end();
-       it != ie; ++it)
-    sum += (*it)->size;
+  for (const auto object : objects)
+    sum += object->size;
   if (sum >= shared_memory_size)
     llvm::report_fatal_error("not enough shared memory for counterexample");
 
   fflush(stdout);
   fflush(stderr);
+
+  // fork solver
   int pid = fork();
+  // - error
   if (pid == -1) {
     klee_warning("fork failed (for STP) - %s", llvm::sys::StrError(errno).c_str());
     if (!IgnoreSolverFailures)
       exit(1);
     return SolverImpl::SOLVER_RUN_STATUS_FORK_FAILED;
   }
-
+  // - child (solver)
   if (pid == 0) {
     if (timeout) {
       ::alarm(0); /* Turn off alarm so we can safely set signal handler */
       ::signal(SIGALRM, stpTimeoutHandler);
       ::alarm(std::max(1u, static_cast<unsigned>(timeout.toSeconds())));
     }
-    unsigned res = vc_query(vc, q);
+    int res = vc_query(vc, q);
     if (!res) {
-      for (std::vector<const Array *>::const_iterator it = objects.begin(),
-                                                      ie = objects.end();
-           it != ie; ++it) {
-        const Array *array = *it;
-        for (unsigned offset = 0; offset < array->size; offset++) {
+      for (const auto object : objects) {
+        for (unsigned offset = 0; offset < object->size; offset++) {
           ExprHandle counter =
-              vc_getCounterExample(vc, builder->getInitialRead(array, offset));
-          *pos++ = getBVUnsigned(counter);
+              vc_getCounterExample(vc, builder->getInitialRead(object, offset));
+          *pos++ = static_cast<unsigned char>(getBVUnsigned(counter));
         }
       }
     }
     _exit(res);
+  // - parent
   } else {
     int status;
     pid_t res;
@@ -290,53 +278,51 @@ runAndGetCexForked(::VC vc, STPBuilder *builder, ::VCExpr q,
     }
 
     int exitcode = WEXITSTATUS(status);
+
+    // solvable
     if (exitcode == 0) {
       hasSolution = true;
-    } else if (exitcode == 1) {
-      hasSolution = false;
-    } else if (exitcode == 52) {
-      klee_warning("STP timed out");
-      // mark that a timeout occurred
-      return SolverImpl::SOLVER_RUN_STATUS_TIMEOUT;
-    } else {
-      klee_warning("STP did not return a recognized code");
-      if (!IgnoreSolverFailures)
-        exit(1);
-      return SolverImpl::SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE;
-    }
 
-    if (hasSolution) {
-      values = std::vector<std::vector<unsigned char> >(objects.size());
-      unsigned i = 0;
-      for (std::vector<const Array *>::const_iterator it = objects.begin(),
-                                                      ie = objects.end();
-           it != ie; ++it) {
-        const Array *array = *it;
-        std::vector<unsigned char> &data = values[i++];
-        data.insert(data.begin(), pos, pos + array->size);
-        pos += array->size;
+      values.reserve(objects.size());
+      for (const auto object : objects) {
+        values.emplace_back(pos, pos + object->size);
+        pos += object->size;
       }
-    }
 
-    if (true == hasSolution) {
       return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE;
-    } else {
+    }
+
+    // unsolvable
+    if (exitcode == 1) {
+      hasSolution = false;
       return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE;
     }
+
+    // timeout
+    if (exitcode == 52) {
+      klee_warning("STP timed out");
+      // mark that a timeout occurred
+      return SolverImpl::SOLVER_RUN_STATUS_TIMEOUT;
+    }
+
+    // unknown return code
+    klee_warning("STP did not return a recognized code");
+    if (!IgnoreSolverFailures)
+      exit(1);
+    return SolverImpl::SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE;
   }
 }
+
 bool STPSolverImpl::computeInitialValues(
     const Query &query, const std::vector<const Array *> &objects,
-    std::vector<std::vector<unsigned char> > &values, bool &hasSolution) {
+    std::vector<std::vector<unsigned char>> &values, bool &hasSolution) {
   runStatusCode = SOLVER_RUN_STATUS_FAILURE;
   TimerStatIncrementer t(stats::queryTime);
 
   vc_push(vc);
 
-  for (ConstraintManager::const_iterator it = query.constraints.begin(),
-                                         ie = query.constraints.end();
-       it != ie; ++it)
-    vc_assertFormula(vc, builder->construct(*it));
+  for (const auto &constraint : query.constraints)
+    vc_assertFormula(vc, builder->construct(constraint));
 
   ++stats::queries;
   ++stats::queryCounterexamples;
@@ -348,6 +334,7 @@ bool STPSolverImpl::computeInitialValues(
     unsigned long len;
     vc_printQueryStateToBuffer(vc, stp_e, &buf, &len, false);
     klee_warning("STP query:\n%.*s\n", (unsigned)len, buf);
+    free(buf);
   }
 
   bool success;
@@ -388,5 +375,6 @@ char *STPSolver::getConstraintLog(const Query &query) {
 void STPSolver::setCoreSolverTimeout(time::Span timeout) {
   impl->setCoreSolverTimeout(timeout);
 }
-}
+
+} // klee
 #endif // ENABLE_STP