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

Add experimental support for templated classes

parent b85650fc
No related branches found
No related tags found
No related merge requests found
......@@ -46,6 +46,8 @@ private:
ExtractionBlock getNextExtractionBlock();
void getAvailableFunctions(metacg::Callgraph callgraph);
void filterExtrationBlocks();
};
#endif //CTUAPEX_CTUAPEXCONSUMER_H
......@@ -33,8 +33,5 @@ static cl::opt<LogLevel> LoggingLevel("log-level", cl::desc("Select log level"),
static cl::opt<bool> OnlyWrapper("generate-only-wrapper", cl::desc("Output only the wrapper function"),
cl::cat(CTUApex));
static cl::opt<bool> DumpAnalysisResult("dump-analysis-result",
cl::desc("Dump the dependence analysis result to stdout"), cl::cat(CTUApex));
#endif //CTUAPEX_COMMANDLINEARGS_H
......@@ -10,32 +10,35 @@
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
if (auto md = node.second->checkAndGet<ExtractionMetadata>(); md.first && md.second->get_decl_node()) {
ExtractionBlock eb;
if(md.second->isMarkedToExtract()){
clang::SourceRange sourceRange;
if(md.second->get_decl_node()->isTemplateInstantiation()){
sourceRange =md.second->get_decl_node()->getPrimaryTemplate()->getSourceRange();
}else{
sourceRange= md.second->get_decl_node()->getSourceRange();
}
eb.begin = sourceRange.getBegin();
eb.end = sourceRange.getEnd();
//std::cout<<"Need to extract: "<<md.second->get_decl_node()->getNameAsString()<<"\n";
clang::SourceRange sourceRange;
//The decl will refer to the instantiated template, but we need the contents of the original template specification
if (md.second->get_decl_node()->isTemplateInstantiation()) {
sourceRange = md.second->get_decl_node()->getPrimaryTemplate()->getSourceRange();
} else {
sourceRange = md.second->get_decl_node()->getSourceRange();
}
eb.begin = sourceRange.getBegin();
eb.end = sourceRange.getEnd();
//We only copy the contents if we are interested in them, but we do need an source-range bound extraction block for every function
//To later filter for pragmas and macros
if (md.second->isMarkedToExtract()) {
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="";
} else {
eb.contents = "";
}
funcs.push_back(eb);
}
}
//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;});
std::sort(funcs.begin(), funcs.end(),
[](const ExtractionBlock &a, const ExtractionBlock &b) { return a.begin < b.begin; });
}
void CTUApexConsumer::outlineGlobals() {
......@@ -48,7 +51,8 @@ void CTUApexConsumer::outlineGlobals() {
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()));
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();
......@@ -64,6 +68,24 @@ void CTUApexConsumer::outlineGlobals() {
}
}
void CTUApexConsumer::filterExtrationBlocks() {
//Funcs has source-ranges for every function, but only contents for the relevant ones
//We remove all entries in the includes, macros, and pragmas that are inside ANY function
//We either get the chars by copying the function, then we do not need them
//Or we do not extract the function, then we do not want to copy the includes, macros and pragmas.
//We only want "out of function" includes, macros and pragmas
for (const auto &func: funcs) {
clang::SourceRange s = {func.begin, func.end};
//Cast to void to ignore return-value of remove_if
(void) std::remove_if(includes.begin(), includes.end(),
[&s](const ExtractionBlock &e) { return s.fullyContains({e.begin, e.end}); });
(void) std::remove_if(macros.begin(), macros.end(),
[&s](const ExtractionBlock &e) { return s.fullyContains({e.begin, e.end}); });
(void) std::remove_if(pragmas.begin(), pragmas.end(),
[&s](const ExtractionBlock &e) { return s.fullyContains({e.begin, e.end}); });
}
}
ExtractionBlock CTUApexConsumer::getNextExtractionBlock() {
//find the earliest block by starting source location
//we need to do a potentially expensive copy of the full struct
......@@ -143,6 +165,9 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) {
SPDLOG_INFO("Outlining Globals");
outlineGlobals();
SPDLOG_INFO("Removing duplicate extraction blocks");
filterExtrationBlocks();
SPDLOG_INFO("Generate code skeleton");
const auto &sm = Context.getSourceManager();
std::string filename = sm.getFileEntryForID(sm.getMainFileID())->getName().str();
......@@ -155,16 +180,16 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) {
outFile << getNextExtractionBlock().contents << "\n";
}
SPDLOG_INFO("Generate wrapper calls");
SPDLOG_CRITICAL("WRAPPER CALLS CAN NOT YET BE IMPLEMENTED");
if(auto md=call_graph->getMain()->checkAndGet<ExtractionMetadata>(); md.first && !md.second->isMarkedToExtract()){
if (auto md = call_graph->getMain()->checkAndGet<ExtractionMetadata>(); md.first &&
!md.second->isMarkedToExtract()) {
//we have no main function and need to create or own
outFile<<"\nint main(){return 0;}\n";
outFile << "\nint main(){return 0;}\n";
}
// Outline the code we want
//SPDLOG_DEBUG("Generating outline");
//assert(output.empty());
......@@ -190,3 +215,4 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) {
......@@ -72,8 +72,11 @@ private:
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);
//This check is probably? necessary in case of recursive functions
if(auto [h,v]=call->checkAndGet<ExtractionMetadata>(); !h || !v->isMarkedToExtract()){
call->getOrCreateMD<ExtractionMetadata>()->setMarkedToExtract(true);
markCalleesToExtract(call->getId(), cg);
}
}
}
......@@ -112,14 +115,15 @@ std::vector<std::string> clangIncludeBasedArgumentAdjustor(const CommandLineArgu
std::string::size_type pos;
std::string::size_type prev = 0;
while ((pos = txt.find('\n', prev)) != std::string::npos) {
ret.push_back("-I" + txt.substr(prev, pos - prev));
auto t=std::prev(ret.end(),3);
ret.insert(t,{"-I" + txt.substr(prev, pos - prev)});
prev = pos + 2;
}
return ret;
}
std::vector<std::string> clangResourceDirBasedAdjuster(const CommandLineArguments &cla, StringRef) {
//call the compiler specified in cla[0] with -S and -v like so
//call the compiler specified in cla[0] with the job to print the resource directory for compiler specific includes
std::string command = "clang --print-resource-dir 2>1&";
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(command.c_str(), "r"), pclose);
//then read the output of the command like so:
......@@ -137,7 +141,6 @@ std::vector<std::string> clangResourceDirBasedAdjuster(const CommandLineArgument
//additional search paths need to be inserted before these 3
auto t=std::prev(ret.end(),3);
ret.insert(t,{"-I" + txt + "/include"});
std::cout<<"\n";
return ret;
}
......@@ -193,7 +196,6 @@ int main(int argc, const char **argv) {
ClangTool tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
//tool.clearArgumentsAdjusters();
tool.appendArgumentsAdjuster(clangResourceDirBasedAdjuster);
metacg::io::FileSource fs(cg_file.getValue());
......
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