diff --git a/op-finder/CMakeLists.txt b/op-finder/CMakeLists.txt index 183ddea..84c1c17 100644 --- a/op-finder/CMakeLists.txt +++ b/op-finder/CMakeLists.txt @@ -20,6 +20,9 @@ llvm_map_components_to_libnames(llvm_libs support option core) add_executable(op-finder main.cpp OperationFinder.cpp + OperationFinderConsumer.cpp + OperationFinderAction.cpp + OperationAnalyzer.cpp ) target_include_directories(op-finder diff --git a/op-finder/OperationAnalyzer.cpp b/op-finder/OperationAnalyzer.cpp new file mode 100644 index 0000000..b7e8199 --- /dev/null +++ b/op-finder/OperationAnalyzer.cpp @@ -0,0 +1,135 @@ +// +// Created by erki on 24.02.21. +// + +#include "OperationAnalyzer.hpp" + +#include + +using namespace clang; + +namespace +{ + +bool IsInMainFile(const SourceManager& source_manager, const SourceLocation& loc) +{ + //return source_manager.isWrittenInMainFile(loc); + return true; +} + +template +StringRef getOpcode(const TOp *op) +{ + return op->getOpcodeStr(op->getOpcode()); +} + +} + +void OperationAnalyzer::processAssignment(const BinaryOperator* op, const SourceManager& source_manager) +{ + if (!IsInMainFile(source_manager, op->getBeginLoc())) + return; + + const auto& loc = op->getBeginLoc(); + + + llvm::outs() << source_manager.getFilename(loc) << ":" + << source_manager.getSpellingLineNumber(loc) << ":" + << source_manager.getSpellingColumnNumber(loc) << ":" + << "Assignment: Assigned to: "; + + _processExpressionTypes(op, op->getLHS(), op->getRHS()); + + llvm::outs() << "\n"; +} + +void OperationAnalyzer::processBinaryArithmetic(const BinaryOperator* op, const SourceManager& source_manager) +{ + if (!IsInMainFile(source_manager, op->getBeginLoc())) + return; + + const auto& loc = op->getBeginLoc(); + + llvm::outs() << source_manager.getFilename(loc) << ":" + << source_manager.getSpellingLineNumber(loc) << ":" + << source_manager.getSpellingColumnNumber(loc) << ":" + << "Arithmetic: Type: " << getOpcode(op) << " LHS: "; + + _processExpressionTypes(op, op->getLHS(), op->getRHS()); + + llvm::outs() << "\n"; +} + +void OperationAnalyzer::processCompoundAssignment(const clang::CompoundAssignOperator* op, const SourceManager& source_manager) +{ + if (!IsInMainFile(source_manager, op->getBeginLoc())) + return; + + const auto& loc = op->getBeginLoc(); + + llvm::outs() << source_manager.getFilename(loc) << ":" + << source_manager.getSpellingLineNumber(loc) << ":" + << source_manager.getSpellingColumnNumber(loc) << ":" + << "Compound assignment: Op code: " << getOpcode(op) << " "; + + _processExpressionTypes(op, op->getLHS(), op->getRHS()); + + llvm::outs() << "\n"; +} + +void OperationAnalyzer::processUnaryArithmetic(const UnaryOperator* op, const SourceManager& source_manager) +{ + const Expr* lhs = op->getExprStmt(); + + if (!IsInMainFile(source_manager, lhs->getBeginLoc())) + return; + + const auto& loc = lhs->getBeginLoc(); + + llvm::outs() << source_manager.getFilename(loc) << ":" + << source_manager.getSpellingLineNumber(loc) << ":" + << source_manager.getSpellingColumnNumber(loc) << ":" + << "Unary arithmetic: Type: " << getOpcode(op) << " LHS: "; + + _processExpressionTypes(op, lhs, nullptr); + + llvm::outs() << "\n"; +} + +void OperationAnalyzer::_processExpressionTypes(const Expr* source, const Expr* lhs, + const Expr* rhs) +{ + auto printTypeName = [](const QualType& t) -> void + { + if (t->isTypedefNameType()) + { + const TypedefType* tdt = cast(t); + assert(tdt); + llvm::outs() << "Typedef type: " << t.getAsString() + << ", underlying: " << tdt->desugar().getAsString() + << "."; + } + else if (t->isBuiltinType()) + { + llvm::outs() << "Builtin type: " << t.getAsString() << "."; + } + else + { + llvm::outs() << "Other type: " << t.getAsString() << "."; + } + }; + + llvm::outs() << "Expression types:\n\tExpression eval type: "; + printTypeName(source->getType()); + + if (lhs) + { + llvm::outs() << "\n\tLHS eval type: "; + printTypeName(lhs->getType()); + } + if (rhs) + { + llvm::outs() << "\n\tRHS eval type: "; + printTypeName(rhs->getType()); + } +} diff --git a/op-finder/OperationAnalyzer.hpp b/op-finder/OperationAnalyzer.hpp new file mode 100644 index 0000000..de5c5f8 --- /dev/null +++ b/op-finder/OperationAnalyzer.hpp @@ -0,0 +1,23 @@ +// +// Created by erki on 24.02.21. +// + +#ifndef C_ANALYZER_OPERATIONANALYZER_HPP +#define C_ANALYZER_OPERATIONANALYZER_HPP + +#include + +class OperationAnalyzer +{ +public: + void processAssignment(const clang::BinaryOperator* op, const clang::SourceManager& source_manager); + void processBinaryArithmetic(const clang::BinaryOperator* op, const clang::SourceManager& source_manager); + void processCompoundAssignment(const clang::CompoundAssignOperator* op, const clang::SourceManager& source_manager); + void processUnaryArithmetic(const clang::UnaryOperator* op, const clang::SourceManager& source_manager); + +private: + void _processExpressionTypes(const clang::Expr* source, const clang::Expr* lhs, const clang::Expr* rhs); +}; + + +#endif //C_ANALYZER_OPERATIONANALYZER_HPP diff --git a/op-finder/OperationFinder.cpp b/op-finder/OperationFinder.cpp index 1c04481..3e7639d 100644 --- a/op-finder/OperationFinder.cpp +++ b/op-finder/OperationFinder.cpp @@ -78,21 +78,7 @@ void OperationFinder::_processAssignment(const clang::ast_matchers::MatchFinder: assert(op); - if (!isInMainFile(result, op->getBeginLoc())) - return; - - const auto& loc = op->getBeginLoc(); - const auto& source_manager = *result.SourceManager; - - - llvm::outs() << source_manager.getFilename(loc) << ":" - << source_manager.getSpellingLineNumber(loc) << ":" - << source_manager.getSpellingColumnNumber(loc) << ":" - << "Assignment: Assigned to: "; - - _processExpressionTypes(op, op->getLHS(), op->getRHS()); - - llvm::outs() << "\n"; + _operation_analyzer.processAssignment(op, *result.SourceManager); } void OperationFinder::_processArithmetic(const MatchFinder::MatchResult& result) @@ -101,20 +87,7 @@ void OperationFinder::_processArithmetic(const MatchFinder::MatchResult& result) assert(op); - if (!isInMainFile(result, op->getBeginLoc())) - return; - - const auto& loc = op->getBeginLoc(); - const auto& source_manager = *result.SourceManager; - - llvm::outs() << source_manager.getFilename(loc) << ":" - << source_manager.getSpellingLineNumber(loc) << ":" - << source_manager.getSpellingColumnNumber(loc) << ":" - << "Arithmetic: Type: " << getOpcode(op) << " LHS: "; - - _processExpressionTypes(op, op->getLHS(), op->getRHS()); - - llvm::outs() << "\n"; + _operation_analyzer.processBinaryArithmetic(op, *result.SourceManager); } void OperationFinder::_processCompoundStmt(const clang::ast_matchers::MatchFinder::MatchResult& result) @@ -128,79 +101,14 @@ void OperationFinder::_processCompoundStmt(const clang::ast_matchers::MatchFinde if (!op || !op->isCompoundAssignmentOp()) return; - if (!isInMainFile(result, op->getBeginLoc())) - return; - - const auto& loc = op->getBeginLoc(); - const auto& source_manager = *result.SourceManager; - - llvm::outs() << source_manager.getFilename(loc) << ":" - << source_manager.getSpellingLineNumber(loc) << ":" - << source_manager.getSpellingColumnNumber(loc) << ":" - << "Compound assignment: Op code: " << getOpcode(op) << " "; - - _processExpressionTypes(op, op->getLHS(), op->getRHS()); - - llvm::outs() << "\n"; + _operation_analyzer.processCompoundAssignment(op, *result.SourceManager); } void OperationFinder::_processUnaryArithmetic(const MatchFinder::MatchResult &result) { const UnaryOperator* op = result.Nodes.getNodeAs("unary_arithmetic"); - const Expr* lhs = result.Nodes.getNodeAs("lhs"); assert(op); - assert(lhs); - if (!isInMainFile(result, lhs->getBeginLoc())) - return; - - const auto& loc = lhs->getBeginLoc(); - const auto& source_manager = *result.SourceManager; - - llvm::outs() << source_manager.getFilename(loc) << ":" - << source_manager.getSpellingLineNumber(loc) << ":" - << source_manager.getSpellingColumnNumber(loc) << ":" - << "Unary arithmetic: Type: " << getOpcode(op) << " LHS: "; - - _processExpressionTypes(op, lhs, nullptr); - - llvm::outs() << "\n"; -} - -void OperationFinder::_processExpressionTypes(const Expr* source, const Expr* op1, const Expr* op2) -{ - auto printTypeName = [](const QualType& t) -> void - { - if (t->isTypedefNameType()) - { - const TypedefType* tdt = cast(t); - assert(tdt); - llvm::outs() << "Typedef type: " << t.getAsString() - << ", underlying: " << tdt->desugar().getAsString() - << "."; - } - else if (t->isBuiltinType()) - { - llvm::outs() << "Builtin type: " << t.getAsString() << "."; - } - else - { - llvm::outs() << "Other type: " << t.getAsString() << "."; - } - }; - - llvm::outs() << "Expression types:\n\tExpression eval type: "; - printTypeName(source->getType()); - - if (op1) - { - llvm::outs() << "\n\tLHS eval type: "; - printTypeName(op1->getType()); - } - if (op2) - { - llvm::outs() << "\n\tRHS eval type: "; - printTypeName(op2->getType()); - } + _operation_analyzer.processUnaryArithmetic(op, *result.SourceManager); } diff --git a/op-finder/OperationFinder.hpp b/op-finder/OperationFinder.hpp index 4242c00..ef48ba0 100644 --- a/op-finder/OperationFinder.hpp +++ b/op-finder/OperationFinder.hpp @@ -8,6 +8,8 @@ #include #include +#include "OperationAnalyzer.hpp" + class OperationFinder : public clang::ast_matchers::MatchFinder::MatchCallback { public: @@ -20,7 +22,7 @@ private: void _processCompoundStmt(const clang::ast_matchers::MatchFinder::MatchResult& result); void _processUnaryArithmetic(const clang::ast_matchers::MatchFinder::MatchResult& result); - void _processExpressionTypes(const clang::Expr* source, const clang::Expr* op1, const clang::Expr* op2); + OperationAnalyzer _operation_analyzer; }; #endif //LLVM_PROTO_OPERATIONFINDER_HPP diff --git a/op-finder/OperationFinderAction.cpp b/op-finder/OperationFinderAction.cpp new file mode 100644 index 0000000..25c27c8 --- /dev/null +++ b/op-finder/OperationFinderAction.cpp @@ -0,0 +1,5 @@ +// +// Created by erki on 24.02.21. +// + +#include "OperationFinderAction.hpp" diff --git a/op-finder/OperationFinderAction.hpp b/op-finder/OperationFinderAction.hpp new file mode 100644 index 0000000..868cb2a --- /dev/null +++ b/op-finder/OperationFinderAction.hpp @@ -0,0 +1,23 @@ +// +// Created by erki on 24.02.21. +// + +#ifndef C_ANALYZER_OPERATIONFINDERACTION_HPP +#define C_ANALYZER_OPERATIONFINDERACTION_HPP + +#include + +class OperationFinderAction + : public clang::RecursiveASTVisitor +{ +public: + bool VisitBinaryOperation(clang::BinaryOperator* bo); + bool VisitUnaryOperation(clang::UnaryOperator* uo); + bool VisitCompoundStatement(clang::CompoundStmt* cmp); + +private: + +}; + + +#endif //C_ANALYZER_OPERATIONFINDERACTION_HPP diff --git a/op-finder/OperationFinderConsumer.cpp b/op-finder/OperationFinderConsumer.cpp new file mode 100644 index 0000000..f559412 --- /dev/null +++ b/op-finder/OperationFinderConsumer.cpp @@ -0,0 +1,25 @@ +// +// Created by erki on 24.02.21. +// + +#include "OperationFinderConsumer.hpp" + +OperationFinderConsumer::OperationFinderConsumer() +{ + _op_finder.addMatcher(_ast_finder); +} + +void OperationFinderConsumer::HandleTranslationUnit(clang::ASTContext& context) +{ + //_ast_finder.matchAST(context); + auto consumer = _ast_finder.newASTConsumer(); + + consumer->HandleTranslationUnit(context); +} + +std::unique_ptr OperationFinderAction::CreateASTConsumer( + clang::CompilerInstance& compiler, llvm::StringRef in_file) +{ + return std::unique_ptr( + new OperationFinderConsumer()); +} diff --git a/op-finder/OperationFinderConsumer.hpp b/op-finder/OperationFinderConsumer.hpp new file mode 100644 index 0000000..2fd98ec --- /dev/null +++ b/op-finder/OperationFinderConsumer.hpp @@ -0,0 +1,32 @@ +// +// Created by erki on 24.02.21. +// + +#ifndef C_ANALYZER_OPERATIONFINDERCONSUMER_HPP +#define C_ANALYZER_OPERATIONFINDERCONSUMER_HPP + +#include +#include + +#include "OperationFinder.hpp" + +class OperationFinderConsumer : public clang::ASTConsumer +{ +public: + OperationFinderConsumer(); + + void HandleTranslationUnit(clang::ASTContext& context) override; + +private: + OperationFinder _op_finder; + clang::ast_matchers::MatchFinder _ast_finder; +}; + +class OperationFinderAction : public clang::ASTFrontendAction +{ +public: + std::unique_ptr CreateASTConsumer( + clang::CompilerInstance& compiler, llvm::StringRef in_file) override; +}; + +#endif //C_ANALYZER_OPERATIONFINDERCONSUMER_HPP diff --git a/op-finder/TestASTConsumer.hpp b/op-finder/TestASTConsumer.hpp new file mode 100644 index 0000000..7bca6f1 --- /dev/null +++ b/op-finder/TestASTConsumer.hpp @@ -0,0 +1,62 @@ +// +// Created by erki on 24.02.21. +// + +#ifndef C_ANALYZER_TESTASTCONSUMER_HPP +#define C_ANALYZER_TESTASTCONSUMER_HPP + +#include +#include +#include + +class DebuggeringASTVisitor + : public clang::RecursiveASTVisitor +{ +public: + explicit DebuggeringASTVisitor(clang::ASTContext* context) + : _context(context) + { } + + bool VisitBinaryOperator(clang::BinaryOperator* bo) + { + llvm::outs() << "OKAY FUCK YOU\n"; + bo->dump(); + + return true; + } + +private: + clang::ASTContext* _context; +}; + +class DebuggeringASTConsumer : public clang::ASTConsumer +{ +public: + explicit DebuggeringASTConsumer(clang::ASTContext* context) + : _visitor(context) + { + + } + + void HandleTranslationUnit(clang::ASTContext& context) override + { + _visitor.TraverseAST(context); + } +private: + DebuggeringASTVisitor _visitor; +}; + +class DebuggeringASTAction : public clang::ASTFrontendAction +{ +public: + std::unique_ptr CreateASTConsumer( + clang::CompilerInstance &Compiler, llvm::StringRef InFile) override + { + return std::unique_ptr( + new DebuggeringASTConsumer(&Compiler.getASTContext())); + } +}; + + + +#endif //C_ANALYZER_TESTASTCONSUMER_HPP diff --git a/op-finder/main.cpp b/op-finder/main.cpp index 8aa6d3c..7f90038 100644 --- a/op-finder/main.cpp +++ b/op-finder/main.cpp @@ -6,6 +6,8 @@ #include "llvm/Support/CommandLine.h" #include "OperationFinder.hpp" +#include "TestASTConsumer.hpp" +#include "OperationFinderConsumer.hpp" using namespace clang::tooling; using namespace clang::ast_matchers; @@ -42,5 +44,9 @@ int main(int argc, const char** argv) op_finder.addMatcher(finder); - return Tool.run(newFrontendActionFactory(&finder).get()); + // Tool.run(newFrontendActionFactory().get()); + Tool.run(newFrontendActionFactory().get()); + Tool.run(newFrontendActionFactory().get()); + + // return Tool.run(newFrontendActionFactory(&finder).get()); } \ No newline at end of file