Skip to content
Snippets Groups Projects
Commit f7b6db1d authored by Heldmann, Tim's avatar Heldmann, Tim
Browse files

Make output less verbose, fix bug in global extraction

parent a1c3b425
Branches main
No related tags found
No related merge requests found
......@@ -10,7 +10,11 @@ struct ExtractionBlock {
ExtractionBlock(clang::SourceLocation b, clang::SourceLocation e, std::string c) {
begin = b;
end = e;
contents = c;
contents = std::move(c);
}
bool operator==(const ExtractionBlock& other) const{
return this->begin==other.begin&&this->end==other.end&&this->contents==other.contents;
}
clang::SourceLocation begin;
......
......@@ -54,7 +54,7 @@ private:
clang::SourceManager &sourceManager;
clang::LangOptions languageOption;
void MacroDefined(const clang::Token &MacroNameTok, const clang::MacroDirective *MD);
void MacroDefined(const clang::Token &MacroNameTok, const clang::MacroDirective *MD) override;
};
#endif //CTUAPEX_PREPROCESSOREXTRACT_H
......@@ -8,6 +8,8 @@
#include "llvm/Demangle/Demangle.h"
#include "FunctionFinderVisitor.h"
static bool generatedMain = false;
void CTUApexConsumer::outlineFunctions() {
for (const auto &node: call_graph->getNodes()) {
//check for each node in the graph, whether we found a corresponding node in the current ast
......@@ -43,7 +45,7 @@ void CTUApexConsumer::outlineFunctions() {
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;
std::vector<ExtractionBlock> returnBlocks;
for (const auto &node: call_graph->getNodes()) {
......@@ -53,19 +55,21 @@ void CTUApexConsumer::outlineGlobals() {
GlobalsMarker gMarker;
auto globalsSet = gMarker.get_nodes_to_outline(
clang::cast<clang::FunctionDecl>(md.second->get_decl_node()));
for (const auto &func: globalsSet) {
for (const auto &decl: 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(),
eb.begin = decl->getBeginLoc();
eb.end = decl->getEndLoc();
clang::CharSourceRange charSourceRange({eb.begin, eb.end}, true);
eb.contents = clang::Lexer::getSourceText(charSourceRange, decl->getASTContext().getSourceManager(),
clang::LangOptions(),
nullptr).str();
globals.push_back(eb);
}
}
}
//as we find globals in the order they are used, but want them in the order they are declared we need to sort the globals
std::sort(globals.begin(), globals.end(),
[](const ExtractionBlock &a, const ExtractionBlock &b) { return a.begin < b.begin; });
}
void CTUApexConsumer::filterExtrationBlocks() {
......@@ -92,70 +96,56 @@ ExtractionBlock CTUApexConsumer::getNextExtractionBlock() {
//as we will erase parts of the vectors later, potentially invalidating pointers in the process
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();
}
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();
}
//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());
}
const auto &pred = [&min](const auto &elem) { return min.end >= elem.end; };
includes.erase(std::remove_if(includes.begin(), includes.end(), pred), includes.end());
funcs.erase(std::remove_if(funcs.begin(), funcs.end(), pred), funcs.end());
globals.erase(std::remove_if(globals.begin(), globals.end(), pred), globals.end());
macros.erase(std::remove_if(macros.begin(), macros.end(), pred), macros.end());
pragmas.erase(std::remove_if(pragmas.begin(), pragmas.end(), pred), pragmas.end());
return min;
}
void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) {
//Whole path with line and column
std::string path = Context.getSourceManager().getLocForEndOfFile(
Context.getSourceManager().getMainFileID()).printToString(Context.getSourceManager());
//Only file name with line and column
path = path.substr(path.find_last_of('/') + 1);
//Only file name
path = path.substr(0, path.find_first_of(':'));
SPDLOG_INFO("Extracting from file: {}", path);
const auto &translation_unit = Context.getTranslationUnitDecl();
SPDLOG_INFO("Mapping functions to the call graph");
FunctionFinderVisitor functionFinderVisitor(call_graph);
functionFinderVisitor.TraverseTranslationUnitDecl(translation_unit);
......@@ -184,9 +174,11 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) {
SPDLOG_CRITICAL("WRAPPER CALLS CAN NOT YET BE IMPLEMENTED");
if (auto md = call_graph->getMain()->checkAndGet<ExtractionMetadata>(); md.first &&
!md.second->isMarkedToExtract()) {
!md.second->isMarkedToExtract() &&
!generatedMain) {
//we have no main function and need to create or own
outFile << "\nint main(){return 0;}\n";
generatedMain = true;
}
......
......@@ -34,8 +34,6 @@ bool FunctionFinderVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDec
for (const auto &s: D->specializations()) {
for (const auto &name: getMangledName(s)) {
assert(callgraph->hasNode(name));
// 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);
......@@ -71,8 +69,6 @@ bool FunctionFinderVisitor::VisitFunctionDecl(clang::FunctionDecl *functionDecl)
for (const auto &name: possibleNames) {
assert(callgraph->hasNode(name));
// 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);
......
......@@ -76,7 +76,6 @@ inline void PreprocessorExtract::PragmaDirective(clang::SourceLocation Loc,
// or enounter a \ followed by a newline, which means the pragma goes on in the next line
for (int i = 0; !text.endswith("\n") || text.endswith("\\\n"); i++) {
//only reset the assumed end of the sourcerange to keep object intact
llvm::outs() << text << "\n";
charSourceRange.setEnd(Loc.getLocWithOffset(i));
text = clang::Lexer::getSourceText(charSourceRange, sourceManager, languageOption);
assert(i < 5000);//This is for debugging
......
......@@ -5,7 +5,6 @@
//Wir machen Tooling
#include "clang/Tooling/Tooling.h"
//Wir benutzen die Visitor strategy
#include <clang/AST/RecursiveASTVisitor.h>
//Wir müssen mit dem compiler interagieren können.
#include <clang/Frontend/CompilerInstance.h>
#include <spdlog/spdlog.h>
......@@ -146,21 +145,25 @@ std::vector<std::string> clangResourceDirBasedAdjuster(const CommandLineArgument
void printMarkedFunctions(const metacg::Callgraph &cg) {
std::cout << "Extracting:\n";
size_t size=500;
char* a = static_cast<char *>(malloc(size * sizeof(char)));
int status;
size_t count=0;
for (const auto &[_, node]: cg.getNodes()) {
if (node->has<ExtractionMetadata>()) {
size_t size=500;
char* a = static_cast<char *>(malloc(size * sizeof(char)));
int status;
count++;
if(llvm::itaniumDemangle(node->getFunctionName().c_str(),a,&size,&status);status==llvm::demangle_success){
if(llvm::StringRef b =a;!b.startswith("std::")){
std::cout << "Node: " << demangle(node->getFunctionName()) << "\n";
//std::cout << "Node: " << demangle(node->getFunctionName()) << "\n";
}
}
free(a);
}
}
free(a);
std::cout<<"Marked: "<<count<<" functions\n";
}
int main(int argc, const char **argv) {
auto ExpectedParser = CommonOptionsParser::create(argc, argv, CTUApex);
......@@ -212,9 +215,9 @@ int main(int argc, const char **argv) {
auto &mcgManager = metacg::graph::MCGManager::get();
//As the mcgReader spits out a warning for every occurance of a missing metadata,
//As the mcgReader spits out a warning for every occurrence of a missing metadata,
//we silence all warnings for the duration of the read
const auto &lv = spdlog::get_level();
const auto lv = spdlog::get_level();
spdlog::set_level(spdlog::level::off);
mcgManager.addToManagedGraphs("activeGraph", mcgReader->read());
spdlog::set_level(lv);
......@@ -232,8 +235,12 @@ int main(int argc, const char **argv) {
}
}
markFunctionsAlongCallpaths(cg);
//printMarkedFunctions(cg);
tool.run(argumentParsingFrontendActionFactory<CTUApexAction>(mcgManager.getCallgraph()).get()) ;
return 0;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment