170 lines
4.3 KiB
C++
170 lines
4.3 KiB
C++
//
|
|
// Created by erki on 16.02.21.
|
|
//
|
|
|
|
#include "OperationFinder.hpp"
|
|
|
|
#include <iostream>
|
|
|
|
#include "ASTHelpers.hpp"
|
|
|
|
using namespace clang;
|
|
using namespace clang::ast_matchers;
|
|
|
|
namespace
|
|
{
|
|
|
|
std::string ResolveTypeName(const QualType& t)
|
|
{
|
|
if (t->isTypedefNameType())
|
|
{
|
|
const TypedefType* tdt = cast<TypedefType>(t);
|
|
assert(tdt);
|
|
llvm::outs() << "Typedef type: " << t.getAsString()
|
|
<< ", underlying: " << tdt->desugar().getAsString()
|
|
<< ".";
|
|
|
|
return tdt->desugar().getAsString();
|
|
}
|
|
else if (t->isBuiltinType())
|
|
{
|
|
llvm::outs() << "Builtin type: " << t.getAsString() << ".";
|
|
return t.getAsString();
|
|
}
|
|
else
|
|
{
|
|
llvm::outs() << "Other type: " << t.getAsString() << ".";
|
|
return t.getAsString();
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
OperationFinder::OperationFinder(IOperationOutput* storage)
|
|
: _storage(storage)
|
|
{
|
|
assert(storage);
|
|
}
|
|
|
|
void OperationFinder::processArithmetic(const clang::BinaryOperator* op, const clang::SourceManager& source_manager)
|
|
{
|
|
const auto [file_name, line_number, column_number] = resolveLocations(op, source_manager);
|
|
|
|
llvm::outs() << file_name << ":"
|
|
<< line_number << ":"
|
|
<< column_number << ":"
|
|
<< "Binary arithmetic: Type: " << getOpcode(op) << " LHS: ";
|
|
|
|
OperationLog log;
|
|
log.line = line_number;
|
|
log.entry_type = OperationLog::BasicOperation::TYPE_NAME;
|
|
log.entry = _createBasicOperationLogEntry(op, op->getLHS(), op->getRHS());
|
|
log.current_for_loops = _for_loop_stack;
|
|
log.is_fallthrough = _in_fallthrough;
|
|
|
|
_storage->pushOperation(file_name, std::move(log));
|
|
|
|
llvm::outs() << "\n";
|
|
}
|
|
|
|
void OperationFinder::processUnaryArithmetic(const clang::UnaryOperator* op, const clang::SourceManager& source_manager)
|
|
{
|
|
const Expr* lhs = op->getExprStmt();
|
|
|
|
assert(op);
|
|
assert(lhs);
|
|
|
|
const auto [file_name, line_number, column_number] = resolveLocations(op, source_manager);
|
|
|
|
llvm::outs() << file_name << ":"
|
|
<< line_number << ":"
|
|
<< column_number << ":"
|
|
<< "Unary arithmetic: Type: " << getOpcode(op) << " LHS: ";
|
|
|
|
OperationLog log;
|
|
log.line = line_number;
|
|
log.entry_type = OperationLog::BasicOperation::TYPE_NAME;
|
|
log.entry = _createBasicOperationLogEntry(op, lhs, nullptr);
|
|
log.current_for_loops = _for_loop_stack;
|
|
log.is_fallthrough = _in_fallthrough;
|
|
|
|
_storage->pushOperation(file_name, std::move(log));
|
|
|
|
llvm::outs() << "\n";
|
|
}
|
|
|
|
void OperationFinder::processFunctionCall(const clang::CallExpr* call, const SourceManager& source_manager)
|
|
{
|
|
const FunctionDecl* func = call->getDirectCallee();
|
|
|
|
assert(func);
|
|
|
|
const auto [file_name, line_number, column_number] = resolveLocations(call, source_manager);
|
|
|
|
const std::string res_type = ResolveTypeName(func->getType());
|
|
const std::string func_name = func->getNameAsString();
|
|
|
|
llvm::outs() << file_name << ":"
|
|
<< line_number << ":"
|
|
<< column_number << ":"
|
|
<< "Function call: name: " << func_name << " Restype: "
|
|
<< res_type << "\n";
|
|
|
|
auto func_call = std::make_unique<OperationLog::FunctionCall>();
|
|
func_call->function_name = func_name;
|
|
func_call->call_result_type = res_type;
|
|
|
|
OperationLog log;
|
|
log.line = line_number;
|
|
log.entry_type = OperationLog::FunctionCall::TYPE_NAME;
|
|
log.entry = std::move(func_call);
|
|
log.current_for_loops = _for_loop_stack;
|
|
log.is_fallthrough = _in_fallthrough;
|
|
|
|
_storage->pushOperation(file_name, std::move(log));
|
|
}
|
|
|
|
void OperationFinder::fallthroughBranchEntered()
|
|
{
|
|
_in_fallthrough = true;
|
|
}
|
|
|
|
void OperationFinder::fallthroughBranchExited()
|
|
{
|
|
_in_fallthrough = false;
|
|
}
|
|
|
|
void OperationFinder::forLoopEntered()
|
|
{
|
|
_for_loop_stack.push_back(_next_for_loop_id);
|
|
|
|
_next_for_loop_id++;
|
|
}
|
|
|
|
void OperationFinder::forLoopExited()
|
|
{
|
|
_for_loop_stack.pop_back();
|
|
}
|
|
|
|
std::unique_ptr<OperationLog::BasicOperation>
|
|
OperationFinder::_createBasicOperationLogEntry(const Expr* source, const Expr* op1, const Expr* op2)
|
|
{
|
|
auto log = std::make_unique<OperationLog::BasicOperation>();
|
|
|
|
llvm::outs() << "Expression types:\n\tExpression eval type: ";
|
|
log->type_result = ResolveTypeName(source->getType());
|
|
|
|
if (op1)
|
|
{
|
|
llvm::outs() << "\n\tLHS eval type: ";
|
|
log->type_lhs = ResolveTypeName(op1->getType());
|
|
}
|
|
if (op2)
|
|
{
|
|
llvm::outs() << "\n\tRHS eval type: ";
|
|
log->type_rhs = ResolveTypeName(op2->getType());
|
|
}
|
|
|
|
return log;
|
|
}
|