diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e812a7cb4c03a6cb43d45b66689b17c6379149b..5452eeeec3fbe38b94ff18b364624e162c6317cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,6 @@ target_include_directories(CTUApex PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>) target_link_libraries(CTUApex metacg) -target_link_libraries(CTUApex minicpr) +#target_link_libraries(CTUApex minicpr) target_link_libraries(CTUApex clangTooling) target_compile_options(CTUApex PUBLIC -fno-rtti) \ No newline at end of file diff --git a/include/ExtractionMetadata.h b/include/ExtractionMetadata.h index ad733425316c25fe8bd765b65598c3a2a7143fa4..8a63634b28a537867b316cdc5e7823e50e3afd26 100644 --- a/include/ExtractionMetadata.h +++ b/include/ExtractionMetadata.h @@ -5,7 +5,7 @@ #ifndef CTUAPEX_EXTRACTIONMETADATA_H #define CTUAPEX_EXTRACTIONMETADATA_H -#include <MetaData.h> +#include <metadata/MetaData.h> class ExtractionMetadata : public metacg::MetaData::Registrar<ExtractionMetadata> { public: diff --git a/src/CTUApexConsumer.cpp b/src/CTUApexConsumer.cpp index 6c979368cb07b5db4525943b9aec5c19719972c5..8da27a9630632d787c19df31c6bce02737f736da 100644 --- a/src/CTUApexConsumer.cpp +++ b/src/CTUApexConsumer.cpp @@ -147,10 +147,14 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) { outFile << getNextExtractionBlock().contents << "\n"; } - outFile.close(); 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()){ + //we have no main function and need to create or own + outFile<<"\nint main(){return 0;}\n"; + } + // Outline the code we want //SPDLOG_DEBUG("Generating outline"); //assert(output.empty()); @@ -164,6 +168,8 @@ void CTUApexConsumer::HandleTranslationUnit(clang::ASTContext &Context) { // output = extracted_source; //} + outFile.close(); + SPDLOG_INFO("Clean CG for next run"); for (const auto &node: call_graph->getNodes()) { if (node.second->has<ExtractionMetadata>()) { diff --git a/src/main.cpp b/src/main.cpp index 9c40d69553d250867ccfc1060eea2a5b207a69da..cef1d5d257d2d010b88ab87da97e009280985537 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,97 +13,12 @@ #include "CTUApexAction.h" #include "CTUApexConsumer.h" -#include "MCGReader.h" -#include "MCGWriter.h" +#include "io/VersionTwoMCGReader.h" +#include "io/VersionThreeMCGReader.h" #include "Util.h" #include "ExtractionMetadata.h" -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); - return; - } - - std::string fileOrigin = j["origin"].get<std::string>(); - bool isFromSystemInclude = j["systemInclude"].get<bool>(); - origin = fileOrigin; - fromSystemInclude = isFromSystemInclude; - } - - nlohmann::json to_json() const final { - nlohmann::json j; - j["origin"] = origin; - j["systemInclude"] = fromSystemInclude; - return j; - }; - - virtual const char *getKey() const final { return key; } - - std::string origin; - 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()) { - metacg::MCGLogger::instance().getConsole()->trace("Could not retrieve meta data for {}", key); - return; - } - auto jsonNumStmts = j.get<long long int>(); - metacg::MCGLogger::instance().getConsole()->debug("Read {} stmts from file", jsonNumStmts); - setNumberOfStatements(jsonNumStmts); - } - - nlohmann::json to_json() const final { - nlohmann::json j; - j["numStatements"] = getNumberOfStatements(); - return j; - }; - - 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: - bool wasInPreviousProfile{false}; - bool dominantRuntime{false}; - bool hasBody{false}; - int numStmts{0}; -}; - -inline void to_json(nlohmann::json &j, const PiraOneData &data) { - j = nlohmann::json{{"numStatements", data.getNumberOfStatements()}}; -} //Das sind convenience definitionen, dass wir nicht so viel tippen müssen using namespace llvm; @@ -120,6 +35,16 @@ static cl::opt<std::string> cg_file("cg-file", cl::desc("MetaCG file containing enum class LogLevel { Trace, Debug, Info, Warning, Error, /* Critical,*/ Off }; + +//static cl::opt<std::string> extractionStart("extract", +// cl::desc("Qualified name of the function to start the extraction from"), +// cl::value_desc("functionname"), cl::Optional, cl::cat(CTUApex)); + +static cl::list<std::string> extractionPoints("extract", + cl::desc("Qualified names of the function to start the extraction from"), + cl::value_desc("Comma separated list of function names"), cl::Optional, + cl::cat(CTUApex)); + static cl::opt<LogLevel> LoggingLevel("log-level", cl::desc("Select log level"), cl::values(clEnumValN(LogLevel::Trace, "trace", "Enable Trace and higher logs"), clEnumValN(LogLevel::Debug, "debug", "Enable Debug and higher logs"), @@ -129,31 +54,31 @@ static cl::opt<LogLevel> LoggingLevel("log-level", cl::desc("Select log level"), clEnumValN(LogLevel::Error, "error", "Enable only Error logs"), clEnumValN(LogLevel::Off, "off", "Disable all logging")), cl::init(LogLevel::Info), cl::cat(CTUApex)); + 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)); +class CTUApexFactory : clang::ASTFrontendAction { +public: + CTUApexFactory(metacg::Callgraph &cg) : cg(&cg) {} -template<typename T, class... Args> -std::unique_ptr<clang::tooling::FrontendActionFactory> argumentParsingFrontendActionFactory(Args... args) { - - class SimpleFrontendActionFactory : public clang::tooling::FrontendActionFactory { - public: - explicit SimpleFrontendActionFactory(Args... constructorArgs) { - fn1 = [=]() { return std::make_unique<T>(constructorArgs...); }; - } - - std::unique_ptr<clang::FrontendAction> create() override { - return fn1(); - } + std::unique_ptr<clang::ASTConsumer> newASTConsumer() { + return std::unique_ptr<clang::ASTConsumer>(new CTUApexConsumer(cg, includes, macros, pragmas)); + } - private: - std::function<std::unique_ptr<T>()> fn1; // function - }; + std::unique_ptr<clang::ASTConsumer> CreateASTConsumer([[maybe_unused]] clang::CompilerInstance &compiler, + [[maybe_unused]] llvm::StringRef sr) { + return std::unique_ptr<clang::ASTConsumer>(new CTUApexConsumer(cg, includes, macros, pragmas)); + } - return std::unique_ptr<FrontendActionFactory>(new SimpleFrontendActionFactory(args...)); -} +private: + std::vector<ExtractionBlock> includes; + std::vector<ExtractionBlock> macros; + std::vector<ExtractionBlock> pragmas; + metacg::Callgraph *cg; +}; void markCalleesToExtract(const size_t nodeID, const metacg::Callgraph &cg) { @@ -162,6 +87,7 @@ void markCalleesToExtract(const size_t nodeID, const metacg::Callgraph &cg) { markCalleesToExtract(call->getId(), cg); } } + void markFunctionsAlongCallpaths(metacg::Callgraph &cg) { SPDLOG_INFO("Compute set of functions to be extracted"); for (const auto &node: cg.getNodes()) { @@ -204,18 +130,40 @@ int main(int argc, const char **argv) { } CommonOptionsParser &OptionsParser = ExpectedParser.get(); - ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList()); - std::string error = "error"; - auto fcd = FixedCompilationDatabase::loadFromDirectory("", error); + + ClangTool tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList()); + metacg::io::FileSource fs(cg_file.getValue()); - metacg::io::VersionTwoMetaCGReader mcgReader(fs); + + std::unique_ptr<metacg::io::MetaCGReader> mcgReader; + + if (fs.get().at("_MetaCG").at("version") == "3.0") { + mcgReader = std::make_unique<metacg::io::VersionThreeMetaCGReader>(fs); + } else if (fs.get().at("_MetaCG").at("version") == "2.0") { + mcgReader = std::make_unique<metacg::io::VersionTwoMetaCGReader>(fs); + } else { + assert(false && "File corrupt or format not specified"); + } + auto &mcgManager = metacg::graph::MCGManager::get(); mcgManager.addToManagedGraphs("emptyGraph", std::make_unique<metacg::Callgraph>()); - mcgReader.read(mcgManager); + mcgReader->read(mcgManager); + auto &cg = *mcgManager.getCallgraph(); + //Add extraction point gotten via the CLI + for(const auto& extractionFunc : extractionPoints){ + if (cg.hasNode(extractionFunc)) { + auto *md = new ExtractionMetadata(); + md->setMarkedToExtract(true); + cg.getNode(extractionFunc)->addMetaData(md); + }else{ + SPDLOG_ERROR("The given function: "+ extractionFunc + " does not exist in the given callgraph"); + } + } - markFunctionsAlongCallpaths(*mcgManager.getCallgraph()); + markFunctionsAlongCallpaths(cg); - Tool.run(argumentParsingFrontendActionFactory<CTUApexAction>(mcgManager.getCallgraph()).get()); + tool.run(clang::tooling::newFrontendActionFactory<CTUApexFactory>( + new CTUApexFactory(*mcgManager.getCallgraph())).get()); return 0; }