Compare commits

...

1 Commits

Author SHA1 Message Date
9bc37e23ae Turns out, this was unnecessary! 2021-02-24 21:46:07 +02:00
11 changed files with 322 additions and 98 deletions

View File

@ -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

View File

@ -0,0 +1,135 @@
//
// Created by erki on 24.02.21.
//
#include "OperationAnalyzer.hpp"
#include <clang/Basic/SourceManager.h>
using namespace clang;
namespace
{
bool IsInMainFile(const SourceManager& source_manager, const SourceLocation& loc)
{
//return source_manager.isWrittenInMainFile(loc);
return true;
}
template<typename TOp>
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<TypedefType>(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());
}
}

View File

@ -0,0 +1,23 @@
//
// Created by erki on 24.02.21.
//
#ifndef C_ANALYZER_OPERATIONANALYZER_HPP
#define C_ANALYZER_OPERATIONANALYZER_HPP
#include <clang/AST/AST.h>
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

View File

@ -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<UnaryOperator>("unary_arithmetic");
const Expr* lhs = result.Nodes.getNodeAs<Expr>("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<TypedefType>(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);
}

View File

@ -8,6 +8,8 @@
#include <clang/ASTMatchers/ASTMatchers.h>
#include <clang/ASTMatchers/ASTMatchFinder.h>
#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

View File

@ -0,0 +1,5 @@
//
// Created by erki on 24.02.21.
//
#include "OperationFinderAction.hpp"

View File

@ -0,0 +1,23 @@
//
// Created by erki on 24.02.21.
//
#ifndef C_ANALYZER_OPERATIONFINDERACTION_HPP
#define C_ANALYZER_OPERATIONFINDERACTION_HPP
#include <clang/AST/RecursiveASTVisitor.h>
class OperationFinderAction
: public clang::RecursiveASTVisitor<OperationFinderAction>
{
public:
bool VisitBinaryOperation(clang::BinaryOperator* bo);
bool VisitUnaryOperation(clang::UnaryOperator* uo);
bool VisitCompoundStatement(clang::CompoundStmt* cmp);
private:
};
#endif //C_ANALYZER_OPERATIONFINDERACTION_HPP

View File

@ -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<clang::ASTConsumer> OperationFinderAction::CreateASTConsumer(
clang::CompilerInstance& compiler, llvm::StringRef in_file)
{
return std::unique_ptr<clang::ASTConsumer>(
new OperationFinderConsumer());
}

View File

@ -0,0 +1,32 @@
//
// Created by erki on 24.02.21.
//
#ifndef C_ANALYZER_OPERATIONFINDERCONSUMER_HPP
#define C_ANALYZER_OPERATIONFINDERCONSUMER_HPP
#include <clang/AST/ASTConsumer.h>
#include <clang/Frontend/FrontendAction.h>
#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<clang::ASTConsumer> CreateASTConsumer(
clang::CompilerInstance& compiler, llvm::StringRef in_file) override;
};
#endif //C_ANALYZER_OPERATIONFINDERCONSUMER_HPP

View File

@ -0,0 +1,62 @@
//
// Created by erki on 24.02.21.
//
#ifndef C_ANALYZER_TESTASTCONSUMER_HPP
#define C_ANALYZER_TESTASTCONSUMER_HPP
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/AST/RecursiveASTVisitor.h>
class DebuggeringASTVisitor
: public clang::RecursiveASTVisitor<DebuggeringASTVisitor>
{
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<clang::ASTConsumer> CreateASTConsumer(
clang::CompilerInstance &Compiler, llvm::StringRef InFile) override
{
return std::unique_ptr<clang::ASTConsumer>(
new DebuggeringASTConsumer(&Compiler.getASTContext()));
}
};
#endif //C_ANALYZER_TESTASTCONSUMER_HPP

View File

@ -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<clang::ASTPrintAction>().get());
Tool.run(newFrontendActionFactory<DebuggeringASTAction>().get());
Tool.run(newFrontendActionFactory<OperationFinderAction>().get());
// return Tool.run(newFrontendActionFactory(&finder).get());
}