commit 76c7d38139569615270925380ff8a805cfd7aecc
parent 766b1869141bb3450fa8bb47a2badf46956c9cf1
Author: Kyle Milz <kyle@0x30.net>
Date: Sun, 7 Aug 2016 18:11:35 -0600
src: improve logging from ast visitor
- also nuke inst_sites from the runtime node, it's not necessary
Diffstat:
7 files changed, 122 insertions(+), 31 deletions(-)
diff --git a/lib/runtime.c b/lib/runtime.c
@@ -158,7 +158,6 @@ xwrite(int d, const void *buf, size_t bytes_total)
* - length of source file name
* - source file name
* - size of the execution counters
- * - number of instrumentation sites.
*/
static void
send_static(int fd)
@@ -203,7 +202,6 @@ send_static(int fd)
xwrite(fd, &sz, sizeof(sz));
xwrite(fd, node.file_name, sz);
xwrite(fd, &node.size, sizeof(node.size));
- xwrite(fd, &node.inst_sites, sizeof(node.size));
}
assert(i == nodes_total);
assert(w == NULL);
diff --git a/lib/runtime.h b/lib/runtime.h
@@ -4,7 +4,6 @@ static uint8_t citrun_minor = 0;
struct citrun_node {
uint64_t *lines_ptr;
uint32_t size;
- uint32_t inst_sites;
const char *file_name;
struct citrun_node *next;
uint64_t *old_lines;
diff --git a/src/inst_action.cc b/src/inst_action.cc
@@ -39,17 +39,16 @@ InstrumentAction::EndSourceFileAction()
{
clang::SourceManager &sm = m_TheRewriter.getSourceMgr();
const clang::FileID main_fid = sm.getMainFileID();
- std::stringstream ss;
clang::SourceLocation start = sm.getLocForStartOfFile(main_fid);
clang::SourceLocation end = sm.getLocForEndOfFile(main_fid);
unsigned int num_lines = sm.getPresumedLineNumber(end);
- int rw_count = m_InstrumentASTConsumer->get_visitor().GetRewriteCount();
std::string const file_name = getCurrentFile();
// Write instrumentation preamble. Includes runtime header, per tu
// citrun_node and static constructor for runtime initialization.
+ std::stringstream ss;
ss << "#ifdef __cplusplus" << std::endl
<< "extern \"C\" {" << std::endl
<< "#endif" << std::endl;
@@ -58,7 +57,6 @@ InstrumentAction::EndSourceFileAction()
ss << "static struct citrun_node _citrun_node = {" << std::endl
<< " _citrun_lines," << std::endl
<< " " << num_lines << "," << std::endl
- << " " << rw_count << "," << std::endl
<< " \"" << file_name << "\"," << std::endl;
ss << "};" << std::endl;
ss << "__attribute__((constructor))" << std::endl
@@ -68,16 +66,40 @@ InstrumentAction::EndSourceFileAction()
ss << "#ifdef __cplusplus" << std::endl
<< "}" << std::endl
<< "#endif" << std::endl;
- m_TheRewriter.InsertTextAfter(start, ss.str());
+
+ std::string header = ss.str();
+ unsigned header_sz = std::count(header.begin(), header.end(), '\n');
+
+ if (m_TheRewriter.InsertTextAfter(start, header)) {
+ *m_log << m_pfx << "Failed inserting " << header_sz
+ << " lines of instrumentation preabmle.";
+ return;
+ }
+
+ RewriteASTVisitor v = m_InstrumentASTConsumer->get_visitor();
+ *m_log << m_pfx << "Instrumentation of '" << file_name << "' finished:\n";
+ *m_log << m_pfx << " " << num_lines << " Lines of source code\n";
+ *m_log << m_pfx << " " << header_sz << " Lines of instrumentation header\n";
+ *m_log << m_pfx << " " << v.m_mainfunc << " Functions called 'main'\n";
+ *m_log << m_pfx << " " << v.m_funcdecl << " Function declarations\n";
+ *m_log << m_pfx << " " << v.m_ifstmt << " If statements\n";
+ *m_log << m_pfx << " " << v.m_forstmt << " For statements\n";
+ *m_log << m_pfx << " " << v.m_whilestmt << " While statements\n";
+ *m_log << m_pfx << " " << v.m_switchstmt << " Switch statements\n";
+ *m_log << m_pfx << " " << v.m_returnstmt << " Return statement values\n";
+ *m_log << m_pfx << " " << v.m_callexpr << " Call expressions\n";
+ *m_log << m_pfx << " " << v.m_totalstmt << " Total statements in source\n";
std::error_code ec;
llvm::raw_fd_ostream output(file_name, ec, llvm::sys::fs::F_None);
-
if (ec.value()) {
+ *m_log << m_pfx << "Error writing modified source: "
+ << ec.message() << "\n";
warnx("'%s': %s", file_name.c_str(), ec.message().c_str());
return;
}
// Write the instrumented source file
m_TheRewriter.getEditBuffer(main_fid).write(output);
+ *m_log << m_pfx << "Modified source written successfully.\n";
}
diff --git a/src/inst_action.h b/src/inst_action.h
@@ -1,6 +1,7 @@
#include <clang/AST/ASTConsumer.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Rewrite/Core/Rewriter.h>
+#include <clang/Tooling/Tooling.h>
#include "inst_ast_visitor.h"
@@ -27,7 +28,11 @@ private:
// For each source file provided to the tool, a new FrontendAction is created.
class InstrumentAction : public clang::ASTFrontendAction {
public:
- InstrumentAction() {};
+ InstrumentAction(llvm::raw_fd_ostream *log, std::string const &pfx, bool citruninst) :
+ m_log(log),
+ m_pfx(pfx),
+ m_is_citruninst(citruninst)
+ {};
void EndSourceFileAction() override;
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &, clang::StringRef) override;
@@ -35,4 +40,25 @@ public:
private:
clang::Rewriter m_TheRewriter;
RewriteASTConsumer *m_InstrumentASTConsumer;
+ llvm::raw_fd_ostream *m_log;
+ std::string m_pfx;
+ bool m_is_citruninst;
+};
+
+class InstrumentActionFactory : public clang::tooling::FrontendActionFactory {
+public:
+ InstrumentActionFactory(llvm::raw_fd_ostream *log, std::string const &pfx, bool citruninst) :
+ m_log(log),
+ m_pfx(pfx),
+ m_is_citruninst(citruninst)
+ {};
+
+ clang::ASTFrontendAction *create() {
+ return new InstrumentAction(m_log, m_pfx, m_is_citruninst);
+ }
+
+private:
+ llvm::raw_fd_ostream *m_log;
+ std::string m_pfx;
+ bool m_is_citruninst;
};
diff --git a/src/inst_ast_visitor.cc b/src/inst_ast_visitor.cc
@@ -29,47 +29,68 @@ RewriteASTVisitor::VisitVarDecl(clang::VarDecl *d)
bool
RewriteASTVisitor::VisitStmt(clang::Stmt *s)
{
- clang::Stmt *stmt_to_inst = NULL;
+ m_totalstmt++;
if (clang::isa<clang::IfStmt>(s)) {
- stmt_to_inst = clang::cast<clang::IfStmt>(s)->getCond();
+ s = clang::cast<clang::IfStmt>(s)->getCond();
+ if (modify_stmt(s) == false)
+ return true;
+ m_ifstmt++;
}
else if (clang::isa<clang::ForStmt>(s)) {
- stmt_to_inst = clang::cast<clang::ForStmt>(s)->getCond();
+ s = clang::cast<clang::ForStmt>(s)->getCond();
+ if (modify_stmt(s) == false)
+ return true;
+ m_forstmt++;
}
else if (clang::isa<clang::WhileStmt>(s)) {
- stmt_to_inst = clang::cast<clang::WhileStmt>(s)->getCond();
+ s = clang::cast<clang::WhileStmt>(s)->getCond();
+ if (modify_stmt(s) == false)
+ return true;
+ m_whilestmt++;
}
else if (clang::isa<clang::SwitchStmt>(s)) {
- stmt_to_inst = clang::cast<clang::SwitchStmt>(s)->getCond();
+ s = clang::cast<clang::SwitchStmt>(s)->getCond();
+ if (modify_stmt(s) == false)
+ return true;
+ m_switchstmt++;
}
else if (clang::isa<clang::ReturnStmt>(s)) {
- stmt_to_inst = clang::cast<clang::ReturnStmt>(s)->getRetValue();
+ s = clang::cast<clang::ReturnStmt>(s)->getRetValue();
+ if (modify_stmt(s) == false)
+ return true;
+ m_returnstmt++;
}
/*
else if (isa<BreakStmt>(s) || isa<ContinueStmt>(s) ||
|| isa<SwitchCase>(s)) {
}
- */
else if (clang::isa<clang::DeclStmt>(s)) {
}
+ */
else if (clang::isa<clang::CallExpr>(s)) {
- stmt_to_inst = s;
+ if (modify_stmt(s) == false)
+ return true;
+ m_callexpr++;
}
- if (stmt_to_inst == NULL)
- return true;
+ return true;
+}
+
+bool
+RewriteASTVisitor::modify_stmt(clang::Stmt *s)
+{
+ if (s == NULL)
+ return false;
std::stringstream ss;
ss << "(++_citrun_lines["
<< m_SM.getPresumedLineNumber(s->getLocStart())
<< "], ";
- if (m_TheRewriter.InsertTextBefore(stmt_to_inst->getLocStart(), ss.str()))
+ if (m_TheRewriter.InsertTextBefore(s->getLocStart(), ss.str()))
// writing failed, don't attempt to add ")"
- return true;
-
- m_TheRewriter.InsertTextAfter(real_loc_end(stmt_to_inst), ")");
- ++m_rewrite_count;
+ return false;
+ m_TheRewriter.InsertTextAfter(real_loc_end(s), ")");
return true;
}
@@ -85,8 +106,10 @@ RewriteASTVisitor::VisitFunctionDecl(clang::FunctionDecl *f)
// main() is a special case because it must start the runtime thread.
clang::DeclarationName DeclName = f->getNameInfo().getName();
- if (DeclName.getAsString() == "main")
+ if (DeclName.getAsString() == "main") {
+ m_mainfunc++;
rewrite_text << "citrun_start();";
+ }
clang::Stmt *FuncBody = f->getBody();
clang::SourceLocation curly_brace(FuncBody->getLocStart().getLocWithOffset(1));
@@ -100,6 +123,7 @@ RewriteASTVisitor::VisitFunctionDecl(clang::FunctionDecl *f)
// Rewrite the function source right after the beginning curly brace.
m_TheRewriter.InsertTextBefore(curly_brace, rewrite_text.str());
+ m_funcdecl++;
return true;
}
diff --git a/src/inst_ast_visitor.h b/src/inst_ast_visitor.h
@@ -4,19 +4,39 @@
class RewriteASTVisitor : public clang::RecursiveASTVisitor<RewriteASTVisitor> {
public:
RewriteASTVisitor(clang::Rewriter &R) :
+ m_totalstmt(0),
+ m_funcdecl(0),
+ m_ifstmt(0),
+ m_forstmt(0),
+ m_whilestmt(0),
+ m_switchstmt(0),
+ m_returnstmt(0),
+ m_callexpr(0),
+ m_mainfunc(0),
m_TheRewriter(R),
- m_SM(R.getSourceMgr()),
- m_rewrite_count(0) {}
+ m_SM(R.getSourceMgr())
+ {}
bool VisitVarDecl(clang::VarDecl *d);
bool VisitStmt(clang::Stmt *s);
bool VisitFunctionDecl(clang::FunctionDecl *f);
- unsigned int GetRewriteCount() { return m_rewrite_count; };
+
+ unsigned int m_totalstmt;
+ unsigned int m_funcdecl;
+ unsigned int m_ifstmt;
+ unsigned int m_forstmt;
+ unsigned int m_whilestmt;
+ unsigned int m_switchstmt;
+ unsigned int m_returnstmt;
+ unsigned int m_callexpr;
+ unsigned int m_mainfunc;
+
private:
+ bool modify_stmt(clang::Stmt *);
+ clang::SourceLocation real_loc_end(clang::Stmt *);
+
clang::Rewriter &m_TheRewriter;
clang::SourceManager &m_SM;
clang::LangOptions m_lopt;
- unsigned int m_rewrite_count;
- clang::SourceLocation real_loc_end(clang::Stmt *s);
};
diff --git a/src/inst_main.cc b/src/inst_main.cc
@@ -300,7 +300,9 @@ CitrunInst::instrument()
log->setPrefix(std::to_string(m_pid));
Tool.setDiagnosticConsumer(log);
- if (Tool.run(clang::tooling::newFrontendActionFactory<InstrumentAction>().get())) {
+ std::unique_ptr<InstrumentActionFactory> f =
+ llvm::make_unique<InstrumentActionFactory>(&m_log, m_pfx, false);
+ if (Tool.run(f.get())) {
m_log << m_pfx << "Instrumentation failed.\n";
return try_unmodified_compile();
}