Skip to content
Snippets Groups Projects
Commit 8d61b5ee authored by Regfare's avatar Regfare
Browse files

Now handles decleration order of function, macros, pragmas and includes

parent b00e61e7
No related branches found
No related tags found
No related merge requests found
......@@ -16,14 +16,13 @@ add_compile_definitions(
RUNTIME_LOG_LEVEL=spdlog::level::${LOG_LEVEL_LOWER}
)
add_executable(CTUApex
src/main.cpp
src/CTUApexAction.cpp
src/CTUApexConsumer.cpp
src/CTUApexVisitor.cpp
src/Util.cpp
src/IncludeFinder.cpp
src/PreprocessorExtract.cpp
src/GlobalsMarker.cpp
)
......
......@@ -7,6 +7,7 @@
#include <clang/Frontend/FrontendAction.h>
#include <Callgraph.h>
#include "PreprocessorExtract.h"
class CTUApexAction : public clang::ASTFrontendAction {
public:
......@@ -18,6 +19,9 @@ public:
CreateASTConsumer(clang::CompilerInstance &Compiler, llvm::StringRef InFile);
private:
std::vector<ExtractionBlock> includes;
std::vector<ExtractionBlock> macros;
std::vector<ExtractionBlock> pragmas;
metacg::Callgraph *call_graph;
std::string output_text;
};
......
......@@ -13,24 +13,39 @@
#include "clang/Lex/Lexer.h"
#include "GlobalsMarker.h"
#include "CTUApexAction.h"
#include "IncludeFinder.h"
#include "ExtractionBlock.h"
class CTUApexConsumer : public clang::ASTConsumer {
public:
explicit CTUApexConsumer(IncludeFinder* includes,metacg::Callgraph *call_graph)
: completedIncludeFinder(includes), call_graph(call_graph) {}
explicit CTUApexConsumer(metacg::Callgraph *call_graph, std::vector<ExtractionBlock> &includes,
std::vector<ExtractionBlock> &macros, std::vector<ExtractionBlock>& pragmas)
: call_graph(call_graph), includes(includes), macros(macros), pragmas(pragmas) {
}
void outlineFunctions();
void outlineGlobals();
std::string outline(metacg::Callgraph &cg);
std::string mergeSorted();
virtual void HandleTranslationUnit(clang::ASTContext &Context);
private:
void addCalleesToSet(std::unordered_set<clang::Decl *> &set, size_t nodeID, const metacg::Callgraph &cg);
std::unordered_set<clang::Decl *> getCutout(metacg::Callgraph &cg);
std::vector<ExtractionBlock> funcs;
std::vector<ExtractionBlock> globals;
IncludeFinder* completedIncludeFinder; //not owned
std::vector<clang::CallExpr *> calls;
metacg::Callgraph *call_graph; // not owned
// not owned
metacg::Callgraph *call_graph;
std::vector<ExtractionBlock>& includes;
std::vector<ExtractionBlock>& macros;
std::vector<ExtractionBlock>& pragmas;
ExtractionBlock getNextExtractionBlock();
void getAvailableFunctions(metacg::Callgraph callgraph);
};
#endif //CTUAPEX_CTUAPEXCONSUMER_H
//
// Created by tim on 02.01.24.
//
#ifndef CTUAPEX_EXTRACTIONBLOCK_H
#define CTUAPEX_EXTRACTIONBLOCK_H
struct ExtractionBlock {
ExtractionBlock()=default;
ExtractionBlock(clang::SourceLocation b, clang::SourceLocation e, std::string c) {
begin = b;
end = e;
contents = c;
}
clang::SourceLocation begin;
clang::SourceLocation end;
std::string contents;
};
#endif //CTUAPEX_EXTRACTIONBLOCK_H
......@@ -32,6 +32,7 @@ public:
clang::FunctionDecl *get_decl_node() const {return mappedDecl;};
bool isMarkedToExtract(){return extract;};
void setMarkedToExtract(bool shouldExtract){extract=shouldExtract;}
private:
clang::FunctionDecl* mappedDecl= nullptr;
bool extract=false;
......
......@@ -2,21 +2,24 @@
// Created by tim on 21.12.23.
//
#ifndef CTUAPEX_INCLUDEFINDER_H
#define CTUAPEX_INCLUDEFINDER_H
#ifndef CTUAPEX_PREPROCESSOREXTRACT_H
#define CTUAPEX_PREPROCESSOREXTRACT_H
#include <clang/Lex/PPCallbacks.h>
#include <clang/Lex/Lexer.h>
#include <spdlog/spdlog.h>
class IncludeFinder : public clang::PPCallbacks {
public:
IncludeFinder(clang::SourceManager &sm) : sourceManager(sm) {}
#include <utility>
#include "iostream"
inline std::unique_ptr<clang::PPCallbacks> createPreprocessorCallbacks() {
SPDLOG_INFO("Collecting include statements");
return std::make_unique<IncludeFinder>(*this);
}
#include "ExtractionBlock.h"
class PreprocessorExtract : public clang::PPCallbacks {
public:
PreprocessorExtract(clang::SourceManager &sm, std::vector<ExtractionBlock> &includes,
std::vector<ExtractionBlock> &macros, std::vector<ExtractionBlock> &pragmas) : sourceManager(
sm), includes(includes), macros(macros), pragmas(pragmas) {}
inline void InclusionDirective(clang::SourceLocation HashLoc, const clang::Token &IncludeTok,
clang::StringRef FileName, bool IsAngled,
......@@ -24,32 +27,30 @@ public:
clang::Optional<clang::FileEntryRef> File,
clang::StringRef SearchPath, clang::StringRef RelativePath,
const clang::Module *Imported,
clang::SrcMgr::CharacteristicKind FileType) override {
//Note: we currently exclude headers only by name, we could also compare them according to their sourcerange
if (sourceManager.isInMainFile(HashLoc)) {
includes.emplace_back(HashLoc, FilenameRange.getEnd(), FileName.str());
}
};
clang::SrcMgr::CharacteristicKind FileType) override;
void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
ConditionValueKind ConditionValue) override;
void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
const clang::MacroDefinition &MD) override;
void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
const clang::MacroDefinition &MD) override;
void Endif(clang::SourceLocation Loc, clang::SourceLocation IfLoc) override;
inline void PragmaDirective(clang::SourceLocation Loc,
clang::PragmaIntroducerKind Introducer) override;
struct PreprocessorExtract {
PreprocessorExtract(clang::SourceLocation b, clang::SourceLocation e, std::string c) : begin(b), end(e),
contents(std::move(c)) {}
clang::SourceLocation begin;
clang::SourceLocation end;
std::string contents;
};
std::string name;
std::vector<PreprocessorExtract> includes;
std::vector<PreprocessorExtract> macros;
private:
std::vector<ExtractionBlock> &includes;
std::vector<ExtractionBlock> &macros;
std::vector<ExtractionBlock> &pragmas;
//FixMe: make macroBeginStack with beginSourceLoc to save space
std::stack<ExtractionBlock> macroNestingStack;
clang::SourceManager &sourceManager;
};
#endif //CTUAPEX_INCLUDEFINDER_H
#endif //CTUAPEX_PREPROCESSOREXTRACT_H
......@@ -44,6 +44,7 @@ inline bool contains(const C &c, const T &val) {
return std::find(c.begin(), c.end(), val) != c.end();
}
/*
template <typename T>
std::string col2str(const T &col, const std::string &prefix = "", const std::string &split = ",",
const std::string &suffix = ""){
......@@ -56,28 +57,21 @@ std::string col2str(const T &col, const std::string &prefix = "", const std::str
ret += suffix;
return ret;
}
*/
template<typename T>
std::string col2str(const T &col, const std::string &prefix = "", const std::string &split = ",",
const std::string &suffix = "", std::string (*transformer)(
typename std::remove_reference<decltype(*std::declval<T>().begin())>::type) = [](
typename std::remove_reference<decltype(*std::declval<T>().begin())>::type t) -> std::string { return t; }) {
std::string ret = prefix;
template <typename T>
std::string col2str(const T &col, std::string (*transformer)(typename std::remove_reference< decltype( *std::declval<T>().begin() ) >::type), const std::string &prefix = "", const std::string &split = ",",
const std::string &suffix = ""){
std::cout<<__LINE__<<"\n";
std::string ret=prefix;
auto begin=col.begin();
std::cout<<__LINE__<<"\n";
auto end=std::prev(col.end());
std::cout<<__LINE__<<"\n";
for (; begin != end; begin++) {
std::cout<<__LINE__<<"\n";
for (auto begin = col.begin(), end = std::prev(col.end()); begin != end; begin++) {
ret += transformer(*begin);
std::cout<<__LINE__<<"\n";
ret += split;
std::cout<<__LINE__<<"\n";
}
std::cout<<__LINE__<<"\n";
ret += transformer(*col.end());
std::cout<<__LINE__<<"\n";
ret += transformer(col.back());
ret += suffix;
std::cout<<__LINE__<<"\n";
return ret;
}
......
......@@ -4,11 +4,10 @@
#include "CTUApexConsumer.h"
#include <clang/Frontend/CompilerInstance.h>
#include "IncludeFinder.h"
std::unique_ptr<clang::ASTConsumer>
CTUApexAction::CreateASTConsumer(clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
IncludeFinder includeFinder(Compiler.getSourceManager());
Compiler.getPreprocessor().addPPCallbacks(includeFinder.createPreprocessorCallbacks());
return std::make_unique<CTUApexConsumer>(&includeFinder, call_graph);
std::unique_ptr<PreprocessorExtract> includeFinder = std::make_unique<PreprocessorExtract>(Compiler.getSourceManager(), includes, macros, pragmas);
Compiler.getPreprocessor().addPPCallbacks(std::move(includeFinder));
return std::make_unique<CTUApexConsumer>(call_graph,includes,macros,pragmas);
}
\ No newline at end of file
......@@ -8,122 +8,148 @@
#include "llvm/Demangle/Demangle.h"
#include "FunctionFinderVisitor.h"
std::unordered_set<clang::Decl *> CTUApexConsumer::getCutout(metacg::Callgraph &cg) {
std::unordered_set<clang::Decl *> retSet;
std::unordered_set<size_t> entryNodes;
for (const auto &node: cg.getNodes()) {
if (node.second->has<ExtractionMetadata>() && node.second->get<ExtractionMetadata>()->isMarkedToExtract())
entryNodes.insert(node.first);
}
for (auto id: entryNodes) {
addCalleesToSet(retSet, id, cg);
}
std::cout << "Cutout for this TU is:\n";
for (auto &elem: retSet) {
std::cout << clang::cast<clang::FunctionDecl>(elem)->getNameAsString() << "\n";
}
std::cout << std::flush;
return retSet;
}
std::string CTUApexConsumer::outline(metacg::Callgraph &cg) {
//TODO: Move this so its only computed once for each run, not once for each file
SPDLOG_INFO("Compute set of functions to be extracted");
std::unordered_set<clang::Decl *> availableFunctionDecls;
for (const auto &node: cg.getNodes()) {
if (node.second->has<ExtractionMetadata>() && node.second->get<ExtractionMetadata>()->isMarkedToExtract()) {
if (node.second->get<ExtractionMetadata>()->get_decl_node() == nullptr) {
std::cout << "node " << node.second->getFunctionName()
<< " was marked to extract but is not part of this TU\n";
} else {
auto functionDecl = node.second->get<ExtractionMetadata>()->get_decl_node();
availableFunctionDecls.insert(functionDecl);
void CTUApexConsumer::outlineFunctions() {
for (const auto &node: call_graph->getNodes()) {
if (auto md = node.second->checkAndGet<ExtractionMetadata>(); md.first && md.second->get_decl_node()) {
ExtractionBlock eb;
clang::SourceRange sourceRange = md.second->get_decl_node()->getSourceRange();
eb.begin = sourceRange.getBegin();
eb.end = sourceRange.getEnd();
if(md.second->isMarkedToExtract()){
//std::cout<<"Need to extract: "<<md.second->get_decl_node()->getNameAsString()<<"\n";
eb.contents = clang::Lexer::getSourceText(clang::CharSourceRange::getTokenRange(sourceRange),
md.second->get_decl_node()->getASTContext().getSourceManager(),
clang::LangOptions(),
nullptr).str();
}else{
//std::cout<<"Not extracting: "<<md.second->get_decl_node()->getNameAsString()<<"\n";
eb.contents="";
}
addCalleesToSet(availableFunctionDecls, node.first, cg);
funcs.push_back(eb);
}
}
std::cout << "Function marked to be extracted from this TU:\n";
for (auto &elem: availableFunctionDecls) {
std::cout << clang::cast<clang::FunctionDecl>(elem)->getNameAsString() << "\n";
}
//the callgraph nodes are unsorted, we need to sort the extraction blocks afterward
std::sort(funcs.begin(),funcs.end(),[](const ExtractionBlock& a, const ExtractionBlock& b){return a.begin<b.begin;});
}
void CTUApexConsumer::outlineGlobals() {
//Fixme: does this need to extract cross TU as well?
SPDLOG_INFO("Compute set of used globals");
std::unordered_set<clang::Decl *> availableGlobals;
for (const auto &node: availableFunctionDecls) {
assert(clang::isa<clang::FunctionDecl>(node) &&
"Extractionset should only contain function decls at this point");
GlobalsMarker gMarker;
auto func_set = gMarker.get_nodes_to_outline(clang::cast<clang::FunctionDecl>(node));
availableGlobals.insert(func_set.begin(), func_set.end());
std::vector<ExtractionBlock> returnBlocks;
for (const auto &node: call_graph->getNodes()) {
if (auto md = node.second->checkAndGet<ExtractionMetadata>(); md.first && md.second->get_decl_node()) {
assert(clang::isa<clang::FunctionDecl>(md.second->get_decl_node()) &&
"Extractionset should only contain function decls at this point");
GlobalsMarker gMarker;
auto globalsSet = gMarker.get_nodes_to_outline(clang::cast<clang::FunctionDecl>(md.second->get_decl_node()));
for (const auto &func: globalsSet) {
ExtractionBlock eb;
eb.begin = func->getBeginLoc();
eb.end = func->getEndLoc();
clang::SourceRange range(eb.begin, eb.end);
clang::CharSourceRange charSourceRange(range, true);
eb.contents = clang::Lexer::getSourceText(charSourceRange, func->getASTContext().getSourceManager(),
clang::LangOptions(),
nullptr).str();
globals.push_back(eb);
}
}
}
}
std::string returnString;
for (const auto &decl: availableGlobals) {
clang::SourceRange sourceRange = decl->getSourceRange();
returnString += clang::Lexer::getSourceText(clang::CharSourceRange::getTokenRange(sourceRange),
decl->getASTContext().getSourceManager(), clang::LangOptions(),
nullptr).str();
returnString += "\n";
ExtractionBlock CTUApexConsumer::getNextExtractionBlock() {
//find the earliest block by starting source location
ExtractionBlock min;
if (!includes.empty()) {
SPDLOG_TRACE("Setting include as assumed min");
min = includes.front();
} else if (!funcs.empty()) {
SPDLOG_TRACE("Setting funcs as assumed min");
min = funcs.front();
} else if (!globals.empty()) {
SPDLOG_TRACE("Setting globals as assumed min");
min = globals.front();
} else if (!macros.empty()) {
SPDLOG_TRACE("Setting macros as assumed min");
min = macros.front();
} else if (!pragmas.empty()) {
SPDLOG_TRACE("Setting pragmas as assumed min");
min = pragmas.front();
}
std::vector<clang::Decl *> sortedFunctionDecls = {};
sortedFunctionDecls.reserve(availableFunctionDecls.size());
for (const auto &decl: availableFunctionDecls) {
sortedFunctionDecls.push_back(decl);
while (!funcs.empty() && min.begin > funcs.front().begin) {
SPDLOG_TRACE("Overwriting with funcs as min");
min = funcs.front();
}
while (!globals.empty() && min.begin > globals.front().begin) {
SPDLOG_TRACE("Overwriting with globals as min");
min = globals.front();
}
while (!macros.empty() && min.begin > macros.front().begin) {
SPDLOG_TRACE("Overwriting with macros as min");
min = macros.front();
}
while (!pragmas.empty() && min.begin > pragmas.front().begin) {
SPDLOG_TRACE("Overwriting with pragmas as min");
min = pragmas.front();
}
std::sort(sortedFunctionDecls.begin(),sortedFunctionDecls.end(),[](clang::Decl* a, clang::Decl* b){return a->getBeginLoc()<b->getLocation();});
for (const auto &decl: sortedFunctionDecls) {
clang::SourceRange sourceRange = decl->getSourceRange();
returnString += clang::Lexer::getSourceText(clang::CharSourceRange::getTokenRange(sourceRange),
decl->getASTContext().getSourceManager(), clang::LangOptions(),
nullptr).str();
returnString += "\n";
//if the earliest blocks end is after another block, we fully contain the other block
//we don't need to merge that block anymore
while (!includes.empty() && min.end >= includes.front().end) {
SPDLOG_TRACE("Erasing include entry");
includes.erase(includes.begin());
}
while (!funcs.empty() && min.end >= funcs.front().end) {
SPDLOG_TRACE("Erasing funcs entry");
funcs.erase(funcs.begin());
}
while (!globals.empty() && min.end >= globals.front().end) {
SPDLOG_TRACE("Erasing globals entry");
globals.erase(globals.begin());
}
while (!macros.empty() && min.end >= macros.front().end) {
SPDLOG_TRACE("Erasing macros entry");
macros.erase(macros.begin());
}
while (!pragmas.empty() && min.end >= pragmas.front().end) {
SPDLOG_TRACE("Erasing pragmas entry");
pragmas.erase(pragmas.begin());
}
return returnString;
return min;
}
void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) {
const auto &translation_unit = Context.getTranslationUnitDecl();
SPDLOG_INFO("Mapping functions to the call graph");
FunctionFinderVisitor functionFinderVisitor(call_graph);
functionFinderVisitor.TraverseTranslationUnitDecl(translation_unit);
for (auto &node: call_graph->getNodes()) {
if (node.second->has<ExtractionMetadata>() &&
node.second->get<ExtractionMetadata>()->get_decl_node() != nullptr) {
std::cout << "Found " << node.second->getFunctionName() << " in TU\n";
}
}
SPDLOG_INFO("Generate code skeleton");
SPDLOG_INFO("Outlining Functions");
outlineFunctions();
auto t = outline(*call_graph);
SPDLOG_INFO("Outlining Globals");
outlineGlobals();
SPDLOG_INFO("Generate code skeleton");
const auto &sm = Context.getSourceManager();
std::string filename = sm.getFileEntryForID(sm.getMainFileID())->getName().str();
filename.insert(filename.find_last_of('.') + 1, "mini.");
std::ofstream outFile;
outFile.open(filename);
assert(outFile.is_open());
outFile /*<< col2str(completedIncludeFinder.includes, "#include \"", "\"\n#include \"", "\"\n") */<< t << "\n";
outFile.close();
while (!(includes.empty() && funcs.empty() && globals.empty() && macros.empty() && pragmas.empty())) {
outFile << getNextExtractionBlock().contents << "\n";
}
outFile.close();
SPDLOG_INFO("Generate wrapper calls");
SPDLOG_CRITICAL("WRAPPER CALLS CAN NOT YET BE IMPLEMENTED");
// Outline the code we want
//SPDLOG_DEBUG("Generating outline");
......@@ -147,15 +173,4 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) {
}
void CTUApexConsumer::addCalleesToSet(std::unordered_set<clang::Decl *> &set, const size_t nodeID, const metacg::Callgraph &cg) {
for (const auto &call: cg.getCallees(nodeID)) {
if (call->has<ExtractionMetadata>() && call->get<ExtractionMetadata>()->get_decl_node() != nullptr) {
set.insert(call->get<ExtractionMetadata>()->get_decl_node());
SPDLOG_DEBUG("{} attached AST node",call->getFunctionName());
} else {
//SPDLOG_DEBUG("{} has no attached AST node",call->getFunctionName());
}
addCalleesToSet(set, call->getId(), cg);
}
}
......@@ -27,8 +27,13 @@ std::vector<std::string> getMangledName(clang::NamedDecl const *const nd) {
}
bool FunctionFinderVisitor::VisitFunctionDecl(clang::FunctionDecl *functionDecl) {
//If the function is not from main file (e.g a header defined function, don't mark
if(!functionDecl->getASTContext().getSourceManager().isInMainFile(functionDecl->getSourceRange().getBegin())){
return true;
}
if(functionDecl->isDependentContext()){
//SPDLOG_TRACE("Function {} is context dependend\n",functionDecl->getNameAsString());
SPDLOG_DEBUG("Function {} is context dependent",functionDecl->getNameAsString());
return true;
}
......@@ -37,20 +42,13 @@ bool FunctionFinderVisitor::VisitFunctionDecl(clang::FunctionDecl *functionDecl)
//std::cout<<functionDecl->getNameAsString()<<col2str(possibleNames," All possible manglings are:(",",",")")<<"\n";
for(const auto& name : possibleNames){
// We should only override if we have a body or if it is null
if(functionDecl->getASTContext().getSourceManager().isInMainFile(functionDecl->getSourceRange().getBegin())){
//SPDLOG_DEBUG("Function is part of main file\n");
}else{
//SPDLOG_DEBUG("Function is from header\n");
// we should find every node in the whole program callgraph
if(!callgraph->hasNode(name)){
SPDLOG_WARN("Node {} is not in the call-graph. Graph might be wrong or incomplete!",name);
continue;
}
if(!callgraph->hasNode(name)){ // if we do not have the node, it is not used in the program and can be ignored
//std::cout<<"Node "<<name <<" is not in the graph\n";
continue;
}
//SPDLOG_TRACE("Attaching AST node: {}, to the call graph",possibleNames.at(0));
// We should only override if we have a body or if it is null
if (functionDecl->hasBody() || callgraph->getNode(name)->getOrCreateMD<ExtractionMetadata>()->get_decl_node()==
nullptr) {
callgraph->getNode(name)->getOrCreateMD<ExtractionMetadata>()->set_decl_node(functionDecl);
......
......@@ -11,7 +11,7 @@ bool GlobalsMarker::VisitDeclRefExpr(clang::DeclRefExpr *decl_ref){
auto *decl = decl_ref->getDecl();
if(!decl_ref->getDecl()->getASTContext().getSourceManager().isInMainFile(decl_ref->getDecl()->getSourceRange().getBegin())){
std::cout<<"We reference a declaration that is part of a header, we dont need to extract it\n";
//std::cout<<"We reference a declaration that is part of a header, we don't need to extract it\n";
return true;
}
......
//
// Created by tim on 21.12.23.
//
#include "IncludeFinder.h"
#include <iostream>
void IncludeFinder::Endif(clang::SourceLocation Loc, clang::SourceLocation IfLoc) {
clang::LangOptions langOptions;
std::cout << "Preprocessor found #if #endif: \n" << clang::Lexer::getSourceText(
clang::Lexer::getAsCharRange(clang::SourceRange(IfLoc, Loc), sourceManager, clang::LangOptions()),
sourceManager, clang::LangOptions()).str() << "\n";
std::cout << "------------------------------------\n";
}
inline void IncludeFinder::PragmaDirective(clang::SourceLocation Loc,
clang::PragmaIntroducerKind Introducer) {
if (!sourceManager.isInMainFile(Loc)) {
return;
}
std::cout << "Preprocessor found pragma: " << Loc.printToString(sourceManager) << "\n";
Loc.dump(sourceManager);
}
\ No newline at end of file
//
// Created by tim on 21.12.23.
//
#include "PreprocessorExtract.h"
void PreprocessorExtract::If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
ConditionValueKind ConditionValue) {
if (!sourceManager.isInMainFile(Loc)) {
return;
}
assert(Loc.isValid());
macroNestingStack.emplace(Loc, Loc, "");
}
void PreprocessorExtract::Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
const clang::MacroDefinition &MD) {
if (!sourceManager.isInMainFile(Loc)) {
return;
}
assert(Loc.isValid());
macroNestingStack.emplace(Loc, Loc, "");
}
void PreprocessorExtract::Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
const clang::MacroDefinition &MD) { Ifdef(Loc, MacroNameTok, MD); };
void PreprocessorExtract::Endif(clang::SourceLocation Loc, clang::SourceLocation IfLoc) {
if (!sourceManager.isInMainFile(Loc)) {
return;
}
assert(macroNestingStack.top().begin.isValid());
assert(macroNestingStack.top().end.isValid());
assert(IfLoc.isValid());
assert("If these are not equal, we overwrote the last found macro end location allready" &&
macroNestingStack.top().begin == macroNestingStack.top().end);
assert("The last found macros start should be the if loc we found" && macroNestingStack.top().begin == IfLoc);
ExtractionBlock macro = macroNestingStack.top();
macroNestingStack.pop();
macro.end = Loc;
clang::SourceRange sourceRange(macro.begin,macro.end);
clang::CharSourceRange charSourceRange(sourceRange,true);
macro.contents = "#"+clang::Lexer::getSourceText(charSourceRange,sourceManager,clang::LangOptions()).str();
macros.push_back(macro);
}
inline void PreprocessorExtract::PragmaDirective(clang::SourceLocation Loc,
clang::PragmaIntroducerKind Introducer) {
if (!sourceManager.isInMainFile(Loc)) {
return;
}
clang::SourceRange sourceRange(Loc,Loc);
clang::CharSourceRange charSourceRange(sourceRange,true);
ExtractionBlock res;
res.begin=Loc;
res.end=charSourceRange.getEnd();
res.contents=clang::Lexer::getSourceText(charSourceRange,sourceManager,clang::LangOptions());
std::cout<<res.contents;
pragmas.push_back(res);
}
void PreprocessorExtract::InclusionDirective(clang::SourceLocation HashLoc, const clang::Token &IncludeTok,
clang::StringRef FileName, bool IsAngled,
clang::CharSourceRange FilenameRange,
clang::Optional<clang::FileEntryRef> File,
clang::StringRef SearchPath, clang::StringRef RelativePath,
const clang::Module *Imported,
clang::SrcMgr::CharacteristicKind FileType) {
//Note: we currently exclude headers only by name, we could also compare them according to their sourcerange
if (sourceManager.isInMainFile(HashLoc)) {
includes.emplace_back(HashLoc, FilenameRange.getEnd(), "#include \""+FileName.str()+"\"");
}
}
......@@ -22,7 +22,9 @@
class FilePropertiesMetaData : public metacg::MetaData::Registrar<FilePropertiesMetaData> {
public:
static constexpr const char *key = "fileProperties";
FilePropertiesMetaData() : origin("INVALID"), fromSystemInclude(false), lineNumber(0) {}
explicit FilePropertiesMetaData(const nlohmann::json &j) {
if (j.is_null()) {
metacg::MCGLogger::instance().getConsole()->trace("Could not retrieve meta data for {}", key);
......@@ -48,10 +50,13 @@ public:
bool fromSystemInclude;
int lineNumber;
};
class PiraOneData : public metacg::MetaData::Registrar<PiraOneData> {
public:
static constexpr const char *key = "numStatements";
PiraOneData() = default;
explicit PiraOneData(const nlohmann::json &j) {
metacg::MCGLogger::instance().getConsole()->trace("Running PiraOneMetaDataRetriever::read from json");
if (j.is_null()) {
......@@ -72,13 +77,21 @@ public:
virtual const char *getKey() const final { return key; }
void setNumberOfStatements(int numStmts) { this->numStmts = numStmts; }
int getNumberOfStatements() const { return this->numStmts; }
void setHasBody(bool hasBody = true) { this->hasBody = hasBody; }
bool getHasBody() const { return this->hasBody; }
void setDominantRuntime(bool dominantRuntime = true) { this->dominantRuntime = dominantRuntime; }
bool isDominantRuntime() const { return this->dominantRuntime; }
void setComesFromCube(bool fromCube = true) { this->wasInPreviousProfile = fromCube; }
bool comesFromCube() const { return this->wasInPreviousProfile; }
bool inPreviousProfile() const { return wasInPreviousProfile; }
private:
......@@ -122,7 +135,6 @@ static cl::opt<bool> DumpAnalysisResult("dump-analysis-result",
cl::desc("Dump the dependence analysis result to stdout"), cl::cat(CTUApex));
template<typename T, class... Args>
std::unique_ptr<clang::tooling::FrontendActionFactory> argumentParsingFrontendActionFactory(Args... args) {
......@@ -143,10 +155,24 @@ std::unique_ptr<clang::tooling::FrontendActionFactory> argumentParsingFrontendAc
return std::unique_ptr<FrontendActionFactory>(new SimpleFrontendActionFactory(args...));
}
//Der einsprungspunt in das programm
void markCalleesToExtract(const size_t nodeID, const metacg::Callgraph &cg) {
for (const auto &call: cg.getCallees(nodeID)) {
call->getOrCreateMD<ExtractionMetadata>()->setMarkedToExtract(true);
markCalleesToExtract(call->getId(), cg);
}
}
void markFunctionsAlongCallpaths(metacg::Callgraph &cg) {
SPDLOG_INFO("Compute set of functions to be extracted");
for (const auto &node: cg.getNodes()) {
if (auto md = node.second->checkAndGet<ExtractionMetadata>();
md.first && md.second->isMarkedToExtract()) {
markCalleesToExtract(node.first, cg);
}
}
}
int main(int argc, const char **argv) {
//Wir wollen commandozeilen parameter verarbeiten können, also nehmen wir einen option parser
//Da beim parsen etwas schief gehen kann, machen wir den extra schritt mit expectation
auto ExpectedParser = CommonOptionsParser::create(argc, argv, CTUApex);
......@@ -156,7 +182,6 @@ int main(int argc, const char **argv) {
return 1;
}
switch (LoggingLevel) {
case LogLevel::Trace:
spdlog::set_level(spdlog::level::trace);
......@@ -178,19 +203,18 @@ int main(int argc, const char **argv) {
break;
}
//Das ist der eigentliche option parser
CommonOptionsParser &OptionsParser = ExpectedParser.get();
//Wir erstellen ein clang tool objekt
ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
std::string error="error";
auto fcd = FixedCompilationDatabase::loadFromDirectory("",error);
std::string error = "error";
auto fcd = FixedCompilationDatabase::loadFromDirectory("", error);
metacg::io::FileSource fs(cg_file.getValue());
metacg::io::VersionTwoMetaCGReader mcgReader(fs);
auto& mcgManager=metacg::graph::MCGManager::get();
mcgManager.addToManagedGraphs("emptyGraph",std::make_unique<metacg::Callgraph>());
auto &mcgManager = metacg::graph::MCGManager::get();
mcgManager.addToManagedGraphs("emptyGraph", std::make_unique<metacg::Callgraph>());
mcgReader.read(mcgManager);
//Wir führen die frontend action mit unserem tool aus
markFunctionsAlongCallpaths(*mcgManager.getCallgraph());
Tool.run(argumentParsingFrontendActionFactory<CTUApexAction>(mcgManager.getCallgraph()).get());
return 0;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment