27#include "llvm/ADT/StringExtras.h"
28#include "llvm/Support/CommandLine.h"
29#include "llvm/Support/ManagedStatic.h"
30#include "llvm/Support/MemoryBuffer.h"
31#include "llvm/Support/raw_ostream.h"
37#include "llvm/Support/Signals.h"
44llvm::cl::opt<std::string> InputFile(llvm::cl::desc(
"<input query log>"),
45 llvm::cl::Positional, llvm::cl::init(
"-"),
48enum ToolActions { PrintTokens, PrintAST, PrintSMTLIBv2, Evaluate };
50static llvm::cl::opt<ToolActions> ToolAction(
51 llvm::cl::desc(
"Tool actions:"), llvm::cl::init(Evaluate),
52 llvm::cl::values(clEnumValN(PrintTokens,
"print-tokens",
53 "Print tokens from the input file."),
54 clEnumValN(PrintSMTLIBv2,
"print-smtlib",
55 "Print parsed input file as SMT-LIBv2 query."),
56 clEnumValN(PrintAST,
"print-ast",
57 "Print parsed AST nodes from the input file."),
58 clEnumValN(Evaluate,
"evaluate",
59 "Evaluate parsed AST nodes from the input file.")),
64 ConstantFoldingBuilder,
68static llvm::cl::opt<BuilderKinds> BuilderKind(
69 "builder", llvm::cl::desc(
"Expression builder:"),
70 llvm::cl::init(DefaultBuilder),
71 llvm::cl::values(clEnumValN(DefaultBuilder,
"default",
72 "Default expression construction."),
73 clEnumValN(ConstantFoldingBuilder,
"constant-folding",
74 "Fold constant expressions."),
75 clEnumValN(SimplifyingBuilder,
"simplify",
76 "Fold constants and simplify expressions.")),
79llvm::cl::opt<std::string> DirectoryToWriteQueryLogs(
82 "The folder to write query logs to (default=current directory)"),
85llvm::cl::opt<bool> ClearArrayAfterQuery(
86 "clear-array-decls-after-query",
87 llvm::cl::desc(
"Discard the previous array declarations after a query "
88 "is performed (default=false)"),
96 if( !(stat(DirectoryToWriteQueryLogs.c_str(),&s) == 0 && S_ISDIR(s.st_mode)) )
98 llvm::errs() <<
"Directory to log queries \""
99 << DirectoryToWriteQueryLogs <<
"\" does not exist!"
105 if( !( (s.st_mode & S_IWUSR) && getuid() == s.st_uid) &&
106 !( (s.st_mode & S_IWGRP) && getgid() == s.st_gid) &&
107 !( s.st_mode & S_IWOTH)
110 llvm::errs() <<
"Directory to log queries \""
111 << DirectoryToWriteQueryLogs <<
"\" is not writable!"
116 std::string path = DirectoryToWriteQueryLogs;
124 llvm::raw_string_ostream s(Str);
125 for (
unsigned i=0; i<length; ++i) {
129 }
else if (c ==
'\n') {
133 << hexdigit(((
unsigned char) c >> 4) & 0xF)
134 << hexdigit((
unsigned char) c & 0xF);
145 llvm::outs() <<
"(Token \"" << T.
getKindName() <<
"\" "
148 }
while (T.
kind != Token::EndOfFile);
152 const MemoryBuffer *MB,
154 std::vector<Decl*> Decls;
155 Parser *P = Parser::Create(Filename, MB, Builder, ClearArrayAfterQuery);
158 unsigned NumQueries = 0;
161 if (isa<QueryCommand>(D))
162 llvm::outs() <<
"# Query " << ++NumQueries <<
"\n";
171 llvm::errs() << Filename <<
": parse failure: " << N <<
" errors.\n";
175 for (std::vector<Decl*>::iterator it = Decls.begin(),
176 ie = Decls.end(); it != ie; ++it)
185 const MemoryBuffer *MB,
187 std::vector<Decl*> Decls;
188 Parser *P = Parser::Create(Filename, MB, Builder, ClearArrayAfterQuery);
196 llvm::errs() << Filename <<
": parse failure: " << N <<
" errors.\n";
207 if (maxCoreSolverTime) {
219 for (std::vector<Decl*>::iterator it = Decls.begin(),
220 ie = Decls.end(); it != ie; ++it) {
223 llvm::outs() <<
"Query " << Index <<
":\t";
225 assert(
"FIXME: Support counterexample query commands!");
226 if (QC->Values.empty() && QC->Objects.empty()) {
230 llvm::outs() << (result ?
"VALID" :
"INVALID");
232 llvm::outs() <<
"FAIL (reason: "
236 }
else if (!QC->Values.empty()) {
237 assert(QC->Objects.empty() &&
238 "FIXME: Support counterexamples for values and objects!");
239 assert(QC->Values.size() == 1 &&
240 "FIXME: Support counterexamples for multiple values!");
241 assert(QC->Query->isFalse() &&
242 "FIXME: Support counterexamples with non-trivial query!");
246 llvm::outs() <<
"INVALID\n";
247 llvm::outs() <<
"\tExpr 0:\t" << result;
249 llvm::outs() <<
"FAIL (reason: "
254 std::vector< std::vector<unsigned char> > result;
259 llvm::outs() <<
"INVALID\n";
261 for (
unsigned i = 0, e = result.size(); i != e; ++i) {
262 llvm::outs() <<
"\tArray " << i <<
":\t"
263 << QC->Objects[i]->name
265 for (
unsigned j = 0; j != QC->Objects[i]->size; ++j) {
266 llvm::outs() << (unsigned) result[i][j];
267 if (j + 1 != QC->Objects[i]->size)
268 llvm::outs() <<
", ";
272 llvm::outs() <<
"\n";
276 if (SolverImpl::SOLVER_RUN_STATUS_TIMEOUT == retCode) {
277 llvm::outs() <<
" FAIL (reason: "
278 << SolverImpl::getOperationStatusString(retCode)
282 llvm::outs() <<
"VALID (counterexample request ignored)";
287 llvm::outs() <<
"\n";
292 for (std::vector<Decl*>::iterator it = Decls.begin(),
293 ie = Decls.end(); it != ie; ++it)
302 <<
"total queries = " <<
queries <<
'\n'
303 <<
"total query constructs = "
305 <<
"valid queries = "
307 <<
"invalid queries = "
317 const MemoryBuffer *MB,
321 std::vector<Decl*> Decls;
322 Parser *P = Parser::Create(Filename, MB, Builder, ClearArrayAfterQuery);
332 llvm::errs() << Filename <<
": parse failure: "
333 << N <<
" errors.\n";
343 unsigned int queryNumber = 0;
345 for (std::vector<Decl*>::iterator it = Decls.begin(), ie = Decls.end(); it != ie; ++it)
351 if(queryNumber!=0) llvm::outs() <<
"\n";
354 llvm::outs() <<
";SMTLIBv2 Query " << queryNumber <<
"\n";
365 Query query(constraintM, QC->Query);
368 if(!QC->Objects.empty())
379 for (std::vector<Decl*>::iterator it = Decls.begin(),
380 ie = Decls.end(); it != ie; ++it)
387int main(
int argc,
char **argv) {
388#if LLVM_VERSION_CODE >= LLVM_VERSION(13, 0)
389 KCommandLine::HideOptions(llvm::cl::getGeneralCategory());
391 KCommandLine::HideOptions(llvm::cl::GeneralCategory);
396 llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
398 llvm::cl::ParseCommandLineOptions(argc, argv);
400 std::string ErrorStr;
402 auto MBResult = MemoryBuffer::getFileOrSTDIN(InputFile.c_str());
404 llvm::errs() << argv[0] <<
": error: " << MBResult.getError().message()
408 std::unique_ptr<MemoryBuffer> &MB = *MBResult;
411 switch (BuilderKind) {
415 case ConstantFoldingBuilder:
419 case SimplifyingBuilder:
426 switch (ToolAction) {
431 success =
PrintInputAST(InputFile==
"-" ?
"<stdin>" : InputFile.c_str(), MB.get(),
439 success =
printInputAsSMTLIBv2(InputFile==
"-"?
"<stdin>" : InputFile.c_str(), MB.get(),Builder);
442 llvm::errs() << argv[0] <<
": error: Unknown program action!\n";
446 llvm::llvm_shutdown();
447 return success ? 0 : 1;
ExprBuilder - Base expression builder class.
void setQuery(const Query &q)
void setOutput(llvm::raw_ostream &output)
void setArrayValuesToGet(const std::vector< const Array * > &a)
virtual SolverRunStatus getOperationStatusCode()=0
getOperationStatusCode - get the status of the last solver operation
bool mustBeTrue(const Query &, bool &result)
bool getValue(const Query &, ref< ConstantExpr > &result)
bool getInitialValues(const Query &, const std::vector< const Array * > &objects, std::vector< std::vector< unsigned char > > &result)
virtual void setCoreSolverTimeout(time::Span timeout)
Statistic * getStatisticByName(const std::string &name) const
Decl - Base class for top level declarations.
Lexer - Interface for lexing tokens from a .kquery language file.
Token & Lex(Token &Result)
Parser - Public interface for parsing a .kquery language file.
virtual unsigned GetNumErrors() const =0
GetNumErrors - Return the number of encountered errors.
virtual void SetMaxErrors(unsigned N)=0
SetMaxErrors - Suppress anything beyond the first N errors.
virtual Decl * ParseTopLevelDecl()=0
static bool printInputAsSMTLIBv2(const char *Filename, const MemoryBuffer *MB, ExprBuilder *Builder)
static bool EvaluateInputAST(const char *Filename, const MemoryBuffer *MB, ExprBuilder *Builder)
int main(int argc, char **argv)
static std::string getQueryLogPath(const char filename[])
static std::string escapedString(const char *start, unsigned length)
static void PrintInputTokens(const MemoryBuffer *MB)
static bool PrintInputAST(const char *Filename, const MemoryBuffer *MB, ExprBuilder *Builder)
ExprBuilder * createDefaultExprBuilder()
llvm::cl::opt< CoreSolverType > CoreSolverToUse
ExprBuilder * createConstantFoldingExprBuilder(ExprBuilder *Base)
Solver * constructSolverChain(Solver *coreSolver, std::string querySMT2LogPath, std::string baseSolverQuerySMT2LogPath, std::string queryKQueryLogPath, std::string baseSolverQueryKQueryLogPath)
llvm::cl::opt< std::string > MaxCoreSolverTime
const char ALL_QUERIES_KQUERY_FILE_NAME[]
const char SOLVER_QUERIES_SMT2_FILE_NAME[]
const char ALL_QUERIES_SMT2_FILE_NAME[]
Solver * createCoreSolver(CoreSolverType cst)
llvm::cl::OptionCategory SolvingCat
ExprBuilder * createSimplifyingExprBuilder(ExprBuilder *Base)
llvm::cl::OptionCategory ExprCat
void printVersion(llvm::raw_ostream &OS)
const char SOLVER_QUERIES_KQUERY_FILE_NAME[]
StatisticManager * theStatisticManager
const char * start
The token kind.
unsigned column
The line number of the start of this token.
unsigned line
The length of the token.
const char * getKindName() const
getKindName - The name of this token's kind.
unsigned length
The beginning of the token string.