commit 91a7e82ed3918f533341acbfc66442d203de1a04
Author: kyle <kyle@getaddrinfo.net>
Date: Sat, 24 Oct 2015 16:08:04 -0600
initial commit
Diffstat:
A | Makefile | | | 19 | +++++++++++++++++++ |
A | instrument.cpp | | | 167 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 186 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,19 @@
+CXXFLAGS += -I/usr/local/include
+CXXFLAGS += -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS
+CXXFLAGS += -std=c++1y -fno-rtti
+CXX = eg++
+
+LDLIBS += \
+ -lclangFrontendTool -lclangFrontend -lclangDriver \
+ -lclangSerialization -lclangCodeGen -lclangParse \
+ -lclangSema -lclangStaticAnalyzerFrontend \
+ -lclangStaticAnalyzerCheckers -lclangStaticAnalyzerCore \
+ -lclangAnalysis -lclangARCMigrate -lclangRewriteCore -lclangRewriteFrontend \
+ -lclangEdit -lclangAST -lclangLex -lclangBasic \
+ -lLLVMObjCARCOpts -lLLVMLinker -lLLVMipo -lLLVMVectorize -lLLVMBitWriter -lLLVMIRReader -lLLVMAsmParser -lLLVMXCoreDisassembler -lLLVMXCoreCodeGen -lLLVMXCoreDesc -lLLVMXCoreInfo -lLLVMXCoreAsmPrinter -lLLVMSystemZDisassembler -lLLVMSystemZCodeGen -lLLVMSystemZAsmParser -lLLVMSystemZDesc -lLLVMSystemZInfo -lLLVMSystemZAsmPrinter -lLLVMSparcDisassembler -lLLVMSparcCodeGen -lLLVMSparcAsmParser -lLLVMSparcDesc -lLLVMSparcInfo -lLLVMSparcAsmPrinter -lLLVMR600CodeGen -lLLVMR600Desc -lLLVMR600Info -lLLVMR600AsmPrinter -lLLVMPowerPCDisassembler -lLLVMPowerPCCodeGen -lLLVMPowerPCAsmParser -lLLVMPowerPCDesc -lLLVMPowerPCInfo -lLLVMPowerPCAsmPrinter -lLLVMNVPTXCodeGen -lLLVMNVPTXDesc -lLLVMNVPTXInfo -lLLVMNVPTXAsmPrinter -lLLVMMSP430CodeGen -lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMSP430AsmPrinter -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMMipsAsmPrinter -lLLVMHexagonCodeGen -lLLVMHexagonAsmPrinter -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMCppBackendCodeGen -lLLVMCppBackendInfo -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMAsmPrinter -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter -lLLVMAArch64Utils -lLLVMTableGen -lLLVMDebugInfo -lLLVMOption -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMMCParser -lLLVMX86Desc -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMJIT -lLLVMLineEditor -lLLVMMCDisassembler -lLLVMInstrumentation -lLLVMInterpreter -lLLVMCodeGen -lLLVMScalarOpts -lLLVMInstCombine -lLLVMTransformUtils -lLLVMipa -lLLVMAnalysis -lLLVMMCJIT -lLLVMTarget -lLLVMRuntimeDyld -lLLVMExecutionEngine -lLLVMMC -lLLVMObject -lLLVMBitReader -lLLVMCore -lLLVMSupport \
+ -lpthread -lz
+
+instrument: instrument.cpp
+
+clean:
+ rm instrument.o
diff --git a/instrument.cpp b/instrument.cpp
@@ -0,0 +1,167 @@
+#include <cstdio>
+#include <string>
+#include <sstream>
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Rewrite/Frontend/Rewriters.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace std;
+
+
+// By implementing RecursiveASTVisitor, we can specify which AST nodes
+// we're interested in by overriding relevant methods.
+class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
+{
+public:
+ MyASTVisitor(Rewriter &R)
+ : TheRewriter(R)
+ {}
+
+ bool VisitStmt(Stmt *s) {
+ // Only care about If statements.
+ if (isa<IfStmt>(s)) {
+ IfStmt *IfStatement = cast<IfStmt>(s);
+ Stmt *Then = IfStatement->getThen();
+
+ TheRewriter.InsertText(Then->getLocStart(),
+ "// the 'if' part\n",
+ true, true);
+
+ Stmt *Else = IfStatement->getElse();
+ if (Else)
+ TheRewriter.InsertText(Else->getLocStart(),
+ "// the 'else' part\n",
+ true, true);
+ }
+
+ return true;
+ }
+
+ bool VisitFunctionDecl(FunctionDecl *f) {
+ // Only function definitions (with bodies), not declarations.
+ if (f->hasBody()) {
+ Stmt *FuncBody = f->getBody();
+
+ // Type name as string
+ QualType QT = f->getReturnType();
+ string TypeStr = QT.getAsString();
+
+ // Function name
+ DeclarationName DeclName = f->getNameInfo().getName();
+ string FuncName = DeclName.getAsString();
+
+ // Add comment before
+ stringstream SSBefore;
+ SSBefore << "// Begin function " << FuncName << " returning "
+ << TypeStr << "\n";
+ SourceLocation ST = f->getSourceRange().getBegin();
+ TheRewriter.InsertText(ST, SSBefore.str(), true, true);
+
+ // And after
+ stringstream SSAfter;
+ SSAfter << "\n// End function " << FuncName << "\n";
+ ST = FuncBody->getLocEnd().getLocWithOffset(1);
+ TheRewriter.InsertText(ST, SSAfter.str(), true, true);
+ }
+
+ return true;
+ }
+
+private:
+ void AddBraces(Stmt *s);
+
+ Rewriter &TheRewriter;
+};
+
+
+// Implementation of the ASTConsumer interface for reading an AST produced
+// by the Clang parser.
+class MyASTConsumer : public ASTConsumer
+{
+public:
+ MyASTConsumer(Rewriter &R)
+ : Visitor(R)
+ {}
+
+ // Override the method that gets called for each parsed top-level
+ // declaration.
+ virtual bool HandleTopLevelDecl(DeclGroupRef DR) {
+ for (DeclGroupRef::iterator b = DR.begin(), e = DR.end();
+ b != e; ++b)
+ // Traverse the declaration using our AST visitor.
+ Visitor.TraverseDecl(*b);
+ return true;
+ }
+
+private:
+ MyASTVisitor Visitor;
+};
+
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2) {
+ llvm::errs() << "Usage: rewritersample <filename>\n";
+ return 1;
+ }
+
+ // CompilerInstance will hold the instance of the Clang compiler for us,
+ // managing the various objects needed to run the compiler.
+ CompilerInstance TheCompInst;
+ TheCompInst.createDiagnostics(NULL, false);
+
+ // Initialize target info with the default triple for our platform.
+ TargetOptions TO;
+ TO.Triple = llvm::sys::getDefaultTargetTriple();
+ std::shared_ptr<TargetOptions> TO_shared (&TO);
+ TargetInfo *TI = TargetInfo::CreateTargetInfo(
+ TheCompInst.getDiagnostics(), &TO);
+ TheCompInst.setTarget(TI);
+
+ TheCompInst.createFileManager();
+ FileManager &FileMgr = TheCompInst.getFileManager();
+ TheCompInst.createSourceManager(FileMgr);
+ SourceManager &SourceMgr = TheCompInst.getSourceManager();
+ TheCompInst.createPreprocessor();
+ TheCompInst.createASTContext();
+
+ // A Rewriter helps us manage the code rewriting task.
+ Rewriter TheRewriter;
+ TheRewriter.setSourceMgr(SourceMgr, TheCompInst.getLangOpts());
+
+ // Set the main file handled by the source manager to the input file.
+ const FileEntry *FileIn = FileMgr.getFile(argv[1]);
+ SourceMgr.createMainFileID(FileIn);
+ TheCompInst.getDiagnosticClient().BeginSourceFile(
+ TheCompInst.getLangOpts(),
+ &TheCompInst.getPreprocessor());
+
+ // Create an AST consumer instance which is going to get called by
+ // ParseAST.
+ MyASTConsumer TheConsumer(TheRewriter);
+
+ // Parse the file to AST, registering our consumer as the AST consumer.
+ ParseAST(TheCompInst.getPreprocessor(), &TheConsumer,
+ TheCompInst.getASTContext());
+
+ // At this point the rewriter's buffer should be full with the rewritten
+ // file contents.
+ const RewriteBuffer *RewriteBuf =
+ TheRewriter.getRewriteBufferFor(SourceMgr.getMainFileID());
+ llvm::outs() << string(RewriteBuf->begin(), RewriteBuf->end());
+
+ return 0;
+}