about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--lib/Core/Executor.cpp2
-rw-r--r--lib/Core/StatsTracker.cpp74
2 files changed, 54 insertions, 22 deletions
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index 49b022f8..f23fb3c0 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -364,7 +364,7 @@ const Module *Executor::setModule(llvm::Module *module,
   kmodule->prepare(opts, interpreterHandler);
   specialFunctionHandler->bind();
 
-  if (StatsTracker::useStatistics()) {
+  if (StatsTracker::useStatistics() || userSearcherRequiresMD2U()) {
     statsTracker = 
       new StatsTracker(*this,
                        interpreterHandler->getOutputFilename("assembly.ll"),
diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp
index 5e77172e..26890e50 100644
--- a/lib/Core/StatsTracker.cpp
+++ b/lib/Core/StatsTracker.cpp
@@ -86,17 +86,20 @@ namespace {
                      cl::init(1.),
 		     cl::desc("Approximate number of seconds between stats writes (default=1.0s)"));
 
+  cl::opt<unsigned> StatsWriteAfterInstructions(
+      "stats-write-after-instructions", cl::init(0),
+      cl::desc("Write statistics after each n instructions, 0 to disable "
+               "(default=0)"));
+
   cl::opt<double>
   IStatsWriteInterval("istats-write-interval",
 		      cl::init(10.),
                       cl::desc("Approximate number of seconds between istats writes (default: 10.0s)"));
 
-  /*
-  cl::opt<double>
-  BranchCovCountsWriteInterval("branch-cov-counts-write-interval",
-                     cl::desc("Approximate number of seconds between run.branches writes (default: 5.0s)"),
-                     cl::init(5.));
-  */
+  cl::opt<unsigned> IStatsWriteAfterInstructions(
+      "istats-write-after-instructions", cl::init(0),
+      cl::desc("Write istats after each n instructions, 0 to disable "
+               "(default=0)"));
 
   // XXX I really would like to have dynamic rate control for something like this.
   cl::opt<double>
@@ -185,6 +188,18 @@ StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename,
     fullBranches(0),
     partialBranches(0),
     updateMinDistToUncovered(_updateMinDistToUncovered) {
+
+  if (StatsWriteAfterInstructions > 0 && StatsWriteInterval > 0)
+    klee_error("Both options --stats-write-interval and "
+               "--stats-write-after-instructions cannot be enabled at the same "
+               "time.");
+
+  if (IStatsWriteAfterInstructions > 0 && IStatsWriteInterval > 0)
+    klee_error(
+        "Both options --istats-write-interval and "
+        "--istats-write-after-instructions cannot be enabled at the same "
+        "time.");
+
   KModule *km = executor.kmodule;
 
   if (!sys::path::is_absolute(objectFilename)) {
@@ -235,19 +250,22 @@ StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename,
     writeStatsHeader();
     writeStatsLine();
 
-    executor.addTimer(new WriteStatsTimer(this), StatsWriteInterval);
+    if (StatsWriteInterval > 0)
+      executor.addTimer(new WriteStatsTimer(this), StatsWriteInterval);
+  }
 
-    if (updateMinDistToUncovered) {
-      computeReachableUncovered();
-      executor.addTimer(new UpdateReachableTimer(this), UncoveredUpdateInterval);
-    }
+  // Add timer to calculate uncovered instructions if needed by the solver
+  if (updateMinDistToUncovered) {
+    computeReachableUncovered();
+    executor.addTimer(new UpdateReachableTimer(this), UncoveredUpdateInterval);
   }
 
   if (OutputIStats) {
     istatsFile = executor.interpreterHandler->openOutputFile("run.istats");
     assert(istatsFile && "unable to open istats file");
 
-    executor.addTimer(new WriteIStatsTimer(this), IStatsWriteInterval);
+    if (IStatsWriteInterval > 0)
+      executor.addTimer(new WriteIStatsTimer(this), IStatsWriteInterval);
   }
 }
 
@@ -261,8 +279,12 @@ StatsTracker::~StatsTracker() {
 void StatsTracker::done() {
   if (statsFile)
     writeStatsLine();
-  if (OutputIStats)
+
+  if (OutputIStats) {
+    if (updateMinDistToUncovered)
+      computeReachableUncovered();
     writeIStats();
+  }
 }
 
 void StatsTracker::stepInstruction(ExecutionState &es) {
@@ -310,6 +332,14 @@ void StatsTracker::stepInstruction(ExecutionState &es) {
       }
     }
   }
+
+  if (statsFile && StatsWriteAfterInstructions &&
+      stats::instructions % StatsWriteAfterInstructions.getValue() == 0)
+    writeStatsLine();
+
+  if (istatsFile && IStatsWriteAfterInstructions &&
+      stats::instructions % IStatsWriteAfterInstructions.getValue() == 0)
+    writeIStats();
 }
 
 ///
@@ -327,15 +357,17 @@ void StatsTracker::framePushed(ExecutionState &es, StackFrame *parentFrame) {
       sf.callPathNode = cp;
       cp->count++;
     }
+  }
 
-    if (updateMinDistToUncovered) {
-      uint64_t minDistAtRA = 0;
-      if (parentFrame)
-        minDistAtRA = parentFrame->minDistToUncoveredOnReturn;
-      
-      sf.minDistToUncoveredOnReturn = sf.caller ?
-        computeMinDistToUncovered(sf.caller, minDistAtRA) : 0;
-    }
+  if (updateMinDistToUncovered) {
+    StackFrame &sf = es.stack.back();
+
+    uint64_t minDistAtRA = 0;
+    if (parentFrame)
+      minDistAtRA = parentFrame->minDistToUncoveredOnReturn;
+
+    sf.minDistToUncoveredOnReturn =
+        sf.caller ? computeMinDistToUncovered(sf.caller, minDistAtRA) : 0;
   }
 }