citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

commit 91a7e82ed3918f533341acbfc66442d203de1a04
Author: kyle <kyle@getaddrinfo.net>
Date:   Sat, 24 Oct 2015 16:08:04 -0600

initial commit

Diffstat:
AMakefile | 19+++++++++++++++++++
Ainstrument.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; +}