about summary refs log tree commit diff homepage
path: root/tools/kleaver/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/kleaver/main.cpp')
-rw-r--r--tools/kleaver/main.cpp86
1 files changed, 86 insertions, 0 deletions
diff --git a/tools/kleaver/main.cpp b/tools/kleaver/main.cpp
index 0c4a78f7..077de3ed 100644
--- a/tools/kleaver/main.cpp
+++ b/tools/kleaver/main.cpp
@@ -12,6 +12,8 @@
 #include "klee/util/ExprPPrinter.h"
 #include "klee/util/ExprVisitor.h"
 
+#include "klee/util/ExprSMTLIBLetPrinter.h"
+
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/CommandLine.h"
@@ -45,6 +47,7 @@ namespace {
   enum ToolActions {
     PrintTokens,
     PrintAST,
+    PrintSMTLIBv2,
     Evaluate
   };
 
@@ -54,12 +57,15 @@ namespace {
              llvm::cl::values(
              clEnumValN(PrintTokens, "print-tokens",
                         "Print tokens from the input file."),
+			clEnumValN(PrintSMTLIBv2, "print-smtlib",
+					   "Print parsed input file as SMT-LIBv2 query."),
              clEnumValN(PrintAST, "print-ast",
                         "Print parsed AST nodes from the input file."),
              clEnumValN(Evaluate, "evaluate",
                         "Print parsed AST nodes from the input file."),
              clEnumValEnd));
 
+
   enum BuilderKinds {
     DefaultBuilder,
     ConstantFoldingBuilder,
@@ -276,6 +282,79 @@ static bool EvaluateInputAST(const char *Filename,
   return success;
 }
 
+static bool printInputAsSMTLIBv2(const char *Filename,
+                             const MemoryBuffer *MB,
+                             ExprBuilder *Builder)
+{
+	//Parse the input file
+	std::vector<Decl*> Decls;
+	Parser *P = Parser::Create(Filename, MB, Builder);
+	P->SetMaxErrors(20);
+	while (Decl *D = P->ParseTopLevelDecl())
+	{
+		Decls.push_back(D);
+	}
+
+	bool success = true;
+	if (unsigned N = P->GetNumErrors())
+	{
+		std::cerr << Filename << ": parse failure: "
+				   << N << " errors.\n";
+		success = false;
+	}
+
+	if (!success)
+	return false;
+
+	ExprSMTLIBPrinter* printer = createSMTLIBPrinter();
+	printer->setOutput(std::cout);
+
+	unsigned int queryNumber = 0;
+	//Loop over the declarations
+	for (std::vector<Decl*>::iterator it = Decls.begin(), ie = Decls.end(); it != ie; ++it)
+	{
+		Decl *D = *it;
+		if (QueryCommand *QC = dyn_cast<QueryCommand>(D))
+		{
+			//print line break to separate from previous query
+			if(queryNumber!=0) 	std::cout << std::endl;
+
+			//Output header for this query as a SMT-LIBv2 comment
+			std::cout << ";SMTLIBv2 Query " << queryNumber << std::endl;
+
+			/* Can't pass ConstraintManager constructor directly
+			 * as argument to Query object. Like...
+			 * query(ConstraintManager(QC->Constraints),QC->Query);
+			 *
+			 * For some reason if constructed this way the first
+			 * constraint in the constraint set is set to NULL and
+			 * will later cause a NULL pointer dereference.
+			 */
+			ConstraintManager constraintM(QC->Constraints);
+			Query query(constraintM,QC->Query);
+			printer->setQuery(query);
+
+			if(!QC->Objects.empty())
+				printer->setArrayValuesToGet(QC->Objects);
+
+			printer->generateOutput();
+
+
+			queryNumber++;
+		}
+	}
+
+	//Clean up
+	for (std::vector<Decl*>::iterator it = Decls.begin(),
+			ie = Decls.end(); it != ie; ++it)
+		delete *it;
+	delete P;
+
+	delete printer;
+
+	return true;
+}
+
 int main(int argc, char **argv) {
   bool success = true;
 
@@ -341,6 +420,13 @@ int main(int argc, char **argv) {
                                MB.get(), Builder);
 #endif
     break;
+  case PrintSMTLIBv2:
+#if LLVM_VERSION_CODE < LLVM_VERSION(2, 9)
+    success = printInputAsSMTLIBv2(InputFile=="-"? "<stdin>" : InputFile.c_str(), MB,Builder);
+#else
+    success = printInputAsSMTLIBv2(InputFile=="-"? "<stdin>" : InputFile.c_str(), MB.get(),Builder);
+#endif
+    break;
   default:
     std::cerr << argv[0] << ": error: Unknown program action!\n";
   }