diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index d98c03e..e51bf9c 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -1,218 +1,210 @@ cmake_minimum_required(VERSION 2.8.11) project(xreate) cmake_policy(SET CMP0022 NEW) +message("MODULES" ${CMAKE_MODULE_PATH}) + # LLVM #====================== -#FIND_PACKAGE (LLVM REQUIRED CONFIG PATHS PATH-TO-CMAKE-DIR NO_DEFAULT_PATH) FIND_PACKAGE (LLVM REQUIRED) -set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-tools") -#include(PCH_GCC4_v2) - set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}) -message ("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS}) - -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) -message ("MPATH:" ${CMAKE_MODULE_PATH}) - message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS}) message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") -message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}") + INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS}) -message("LLVM defs: " ${LLVM_DEFINITIONS}) +message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}") + add_definitions(${LLVM_DEFINITIONS}) -llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support) -message("LLVM libs: " ${LLVM_LIBS}) +message("LLVM DEFS: " ${LLVM_DEFINITIONS}) + +llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support option) +message("LLVM LIBS: " ${LLVM_LIBS}) # CLANG #====================== set(CLANG_LIBS - ${LLVM_LIBRARY_DIRS}/libclangCodeGen.so - ${LLVM_LIBRARY_DIRS}/libclangASTMatchers.so - ${LLVM_LIBRARY_DIRS}/libclangQuery.so - ${LLVM_LIBRARY_DIRS}/libclangTooling.so - ${LLVM_LIBRARY_DIRS}/libclangFrontend.so - ${LLVM_LIBRARY_DIRS}/libclangSerialization.so - ${LLVM_LIBRARY_DIRS}/libclangDriver.so - ${LLVM_LIBRARY_DIRS}/libclangParse.so - ${LLVM_LIBRARY_DIRS}/libclangSema.so - ${LLVM_LIBRARY_DIRS}/libclangAnalysis.so - ${LLVM_LIBRARY_DIRS}/libclangAST.so - ${LLVM_LIBRARY_DIRS}/libclangEdit.so - ${LLVM_LIBRARY_DIRS}/libclangLex.so - ${LLVM_LIBRARY_DIRS}/libclangBasic.so + clangCodeGen + clangASTMatchers + clangQuery + clangTooling + clangFrontend + clangSerialization + clangDriver + clangParse + clangSema + clangAnalysis + clangAST + clangEdit + clangLex + clangBasic ) -#find_package(Clang REQUIRED clangTooling libClang) -message(STATUS "CLANG LIBS: " ${CLANG_LIBS}) # POTASSCO #====================== set(POTASSCO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources") set(POTASSCO_INCLUDE_PATH ${POTASSCO_PATH}/libgringo ${POTASSCO_PATH}/libclasp ${POTASSCO_PATH}/libclingo ${POTASSCO_PATH}/libprogram_opts ${POTASSCO_PATH}/liblp ) - INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH}) - -set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug) - set(LIBCLASP_LIBS clingo clasp gringo program_opts reify lp ) -message(STATUS "CLASP LIBS: " ${LIBCLASP_LIBS}) -link_directories(${LIBCLASP_PATH}) +message("CLASP LIBS: " ${LIBCLASP_LIBS}) # OTHER DEPENDENCIES #=========================== set(JEAYESON_INCLUDE_PATH ${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/ ) INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH}) # COCO #=========================== set(COCO_EXECUTABLE "" CACHE PATH "Path to coco executable") set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../coco/) set(COCO_SOURCE_FILES ${COCO_GRAMMAR_PATH}/Parser.cpp ${COCO_GRAMMAR_PATH}/Scanner.cpp) INCLUDE_DIRECTORIES(${COCO_GRAMMAR_PATH}) add_custom_command(OUTPUT ${COCO_SOURCE_FILES} COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar ${COCO_EXECUTABLE} WORKING_DIRECTORY ${COCO_GRAMMAR_PATH} MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/xreate.ATG ) message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT}) # XREATE #====================== set(SOURCE_FILES - pass/compilepass.cpp - pass/interpretationpass.cpp - compilation/targetinterpretation.cpp - + pass/compilepass.cpp ast.cpp ExternLayer.cpp attachments.cpp analysis/cfagraph.cpp analysis/dfagraph.cpp analysis/aux.cpp compilation/containers.cpp compilation/advanced.cpp compilation/transformations.cpp - analysis/DominatorsTreeAnalysisProvider.cpp clasplayer.cpp compilation/latecontextcompiler2.cpp query/context.cpp #compilation/latecontextcompiler.cpp - serialization/expressionserializer.cpp serialization/expressionserializer2.cpp llvmlayer.cpp utils.cpp passmanager.cpp pass/abstractpass.cpp pass/dfapass.cpp pass/cfapass.cpp - pass/loggerpass.cpp pass/adhocpass.cpp - query/containers.cpp contextrule.cpp + query/containers.cpp + pass/loggerpass.cpp + pass/interpretationpass.cpp + serialization/expressionserializer.cpp + compilation/targetinterpretation.cpp + analysis/DominatorsTreeAnalysisProvider.cpp #query/ptrvalid.cpp #pass/rulespass.cpp # ) set(XREATE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/ ) INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS}) set(XREATE_PRIVATE_INCLUDE_DIRS ${XREATE_INCLUDE_DIRS} ${COCO_GRAMMAR_PATH} ${JEAYESON_INCLUDE_PATH} ${LLVM_INCLUDE_DIRS} ${POTASSCO_INCLUDE_PATH} ) add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${COCO_SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} ${LIBCLASP_LIBS}) +target_link_libraries(${PROJECT_NAME}) target_include_directories(${PROJECT_NAME} INTERFACE ${XREATE_INCLUDE_DIRS} ${COCO_GRAMMAR_PATH} ${JEAYESON_INCLUDE_PATH} ${LLVM_INCLUDE_DIRS} ${POTASSCO_INCLUDE_PATH} ) get_directory_property(DEFINITIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS) message("definitions all: " ${DEFINITIONS_ALL}) target_compile_definitions(${PROJECT_NAME} INTERFACE ${DEFINITIONS_ALL}) get_directory_property(COMPILATION_OPTIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS) message("compilations all: " ${COMPILATION_OPTIONS_ALL}) target_compile_options(${PROJECT_NAME} INTERFACE ${COMPILATION_OPTIONS_ALL}) SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY - INTERFACE_LINK_LIBRARIES ${LLVM_LIBS} ${CLANG_LIBS} tbb + INTERFACE_LINK_LIBRARIES ${LIBCLASP_LIBS} ${CLANG_LIBS} ${LLVM_LIBS} tbb ) +#${CLANG_LIBS} + + #set (LINK_INTERFACE_LIBRARIES "") # FUNCTION(PREPEND var prefix) # SET(listVar "") # FOREACH(f ${ARGN}) # LIST(APPEND listVar "${prefix}/${f}") # ENDFOREACH(f) # SET(${var} "${listVar}" PARENT_SCOPE) # ENDFUNCTION(PREPEND) #set(COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "-j4") #cotire(xreate) # MACRO (ADD_PCH_RULE _header_filename _src_list) # SET(_gch_filename "${_header_filename}.gch") # LIST(APPEND ${_src_list} ${_gch_filename}) # SET (_args ${CMAKE_CXX_FLAGS}) # LIST(APPEND _args -c ${_header_filename} -o ${_gch_filename}) # GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES) # foreach (_inc ${DIRINC}) # LIST(APPEND _args "-I" ${_inc}) # endforeach(_inc ${DIRINC}) # SEPARATE_ARGUMENTS(_args) # add_custom_command(OUTPUT ${_gch_filename} # COMMAND rm -f ${_gch_filename} # COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args} # DEPENDS ${_header_filename}) # ENDMACRO(ADD_PCH_RULE _header_filename _src_list) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/ast.h SOURCE_FILES) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/llvmlayer.h SOURCE_FILES) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/clasplayer.h SOURCE_FILES) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/pass/abstractpass.h SOURCE_FILES) diff --git a/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp b/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp index 7d08a2d..9bd280d 100644 --- a/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp +++ b/cpp/src/analysis/DominatorsTreeAnalysisProvider.cpp @@ -1,233 +1,233 @@ /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ -/* +/* * File: DominatorsTreeAnalysisProvider.cpp * Author: pgess - * + * * Created on May 13, 2016, 11:39 AM */ #include "analysis/cfagraph.h" #include "analysis/DominatorsTreeAnalysisProvider.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/GenericDomTreeConstruction.h" #include "llvm/Support/GenericDomTree.h" #include #include #include using namespace std; using namespace xreate; using namespace boost; using namespace boost::bimaps; struct ControlFlowTree; struct Node { ScopePacked scope; ControlFlowTree* tree; }; /* bool operator !=(const Node& a, const Node& b){ return (a.tree != b.tree) || (a.scope != b.scope); } Node& operator++(Node& a){ ++a.scope; return a; } */ struct ControlFlowTree{ typedef bimap, multiset_of> CHILD_RELATIONS; CHILD_RELATIONS edges; std::vector nodes; Node* entry = nullptr; size_t size; - + ControlFlowTree(const size_t nodesCount): nodes(nodesCount), size(nodesCount){ } - + static ControlFlowTree* build(const ClaspLayer* engine){ ControlFlowTree* tree = new ControlFlowTree(engine->getScopesCount()); - + xreate::analysis::CFAGraph* graph = engine->dataCFA.get(); - + for (const auto& edge: graph->__parentScopeRelations){ tree->edges.insert(CHILD_RELATIONS::value_type(edge.second, edge.first)); } - + for (const auto& edge: graph->__callRelations){ unsigned int calleeFunction = edge.right; ScopePacked caller = edge.left; - + auto range = graph->__parentFunctionRelations.right.equal_range(calleeFunction); for (auto& i=range.first; i!= range.second; ++i){ tree->edges.insert(CHILD_RELATIONS::value_type(caller, i->second)); } } - + for (size_t i=0; isize; ++i){ tree->nodes[i]= Node{(unsigned int) i, tree}; } - + return tree; } - + std::list getRootFunctions() const{ size_t idMax = size; size_t id =0; std::list results; auto i = edges.right.begin(); - + while (id < idMax) { if (i!= edges.right.end() && i->first == id){ i = edges.right.upper_bound(i->first); - + } else { results.push_back(id); } - + ++id; } - + return std::move(results); } }; namespace llvm { template <> struct GraphTraits { typedef Node* nodes_iterator; typedef Node NodeType; typedef std::function Transformer; - typedef typename boost::iterators::transform_iterator ChildIteratorType; - + typedef typename boost::transform_iterator ChildIteratorType; + static ChildIteratorType child_begin(const nodes_iterator& node) { auto range = node->tree->edges.left.equal_range(node->scope); Transformer x = [node](auto edge){return &node->tree->nodes[edge.second];}; - + return boost::make_transform_iterator(range.first, x); } - + static ChildIteratorType child_end(const nodes_iterator& node) { auto range = node->tree->edges.left.equal_range(node->scope); Transformer x = [node](auto edge){return &node->tree->nodes[edge.second];}; - - return boost::make_transform_iterator(range.second, x); + + return boost::make_transform_iterator(range.second, x); } }; - + template <> struct GraphTraits> { typedef Node* nodes_iterator; typedef Node NodeType; typedef std::function Transformer; - typedef typename boost::iterators::transform_iterator ChildIteratorType; - + typedef typename boost::transform_iterator ChildIteratorType; + static ChildIteratorType child_begin(const nodes_iterator& node) { auto range = node->tree->edges.right.equal_range(node->scope); Transformer x = [node](auto edge){return &node->tree->nodes[edge.second];}; - + return boost::make_transform_iterator(range.first, x); } - + static ChildIteratorType child_end(const nodes_iterator& node) { auto range = node->tree->edges.right.equal_range(node->scope); Transformer x = [node](auto edge){return &node->tree->nodes[edge.second];}; - - return boost::make_transform_iterator(range.second, x); + + return boost::make_transform_iterator(range.second, x); } }; - + template <> struct GraphTraits: public GraphTraits { static NodeType* - getEntryNode(ControlFlowTree* F) { + getEntryNode(ControlFlowTree* F) { if (F->entry) return F->entry; - + list&& roots = F->getRootFunctions(); assert(roots.size()==1); - + return F->entry = &F->nodes[roots.front()]; } static nodes_iterator nodes_begin(ControlFlowTree* F) { return &F->nodes[0]; } static nodes_iterator nodes_end(ControlFlowTree* F) { return &F->nodes[F->size]; } static size_t size(ControlFlowTree* F) { return F->size; } }; } class xreate::DominatorTree: public llvm::DominatorTreeBase { public: DominatorsTreeAnalysisProvider::Dominators dominators; - + DominatorTree(bool isPostDom): llvm::DominatorTreeBase(isPostDom) {} - + void run(ControlFlowTree& program){ recalculate(program); - + //extract dominators info for (auto& entry: DomTreeNodes){ if (!entry.getFirst()) continue; - + dominators.emplace(entry.getFirst()->scope, make_pair(entry.getSecond()->getDFSNumIn(), entry.getSecond()->getDFSNumOut())); } } - + void print(std::ostringstream& output, const std::string& atom) const { boost::format formatAtom(atom + "(%1%, range(%2%, %3%))."); for (auto entry: dominators){ output << formatAtom % (entry.first) % (entry.second.first) % (entry.second.second) << endl; } } }; void DominatorsTreeAnalysisProvider::run(const ClaspLayer* engine){ boost::scoped_ptr program(ControlFlowTree::build(engine)); - + treeForwardDominators->run(*program); treePostDominators->run(*program); } void DominatorsTreeAnalysisProvider::print(std::ostringstream& output) const{ treeForwardDominators->print(output, "cfa_forwdom"); treePostDominators->print(output, "cfa_postdom"); } -const DominatorsTreeAnalysisProvider::Dominators& +const DominatorsTreeAnalysisProvider::Dominators& DominatorsTreeAnalysisProvider::getForwardDominators() const{ return treeForwardDominators->dominators; } -const DominatorsTreeAnalysisProvider::Dominators& +const DominatorsTreeAnalysisProvider::Dominators& DominatorsTreeAnalysisProvider::getPostDominators() const{ return treePostDominators->dominators; } DominatorsTreeAnalysisProvider::DominatorsTreeAnalysisProvider() : treeForwardDominators(new DominatorTree(false)) , treePostDominators(new DominatorTree(true)) {} DominatorsTreeAnalysisProvider::~DominatorsTreeAnalysisProvider() {} -//void +//void //CodeScopesTree::print(){ // typedef llvm::GraphTraits Traits; // for (size_t i=0; i" << (*j)->scope << endl; // } // } //} \ No newline at end of file diff --git a/cpp/src/analysis/dfagraph.cpp b/cpp/src/analysis/dfagraph.cpp index 7ccf9e0..00a3006 100644 --- a/cpp/src/analysis/dfagraph.cpp +++ b/cpp/src/analysis/dfagraph.cpp @@ -1,250 +1,250 @@ #include "analysis/dfagraph.h" #include "analysis/aux.h" #include using namespace xreate; using namespace xreate::analysis; using namespace std; namespace xreate { namespace analysis { void DFAGraph::print(std::ostringstream& output) const { std::set symbols; output << endl << "%\t\tStatic analysis: DFA" << endl; std::vector>::const_iterator i1; std::vector::const_iterator i2; boost::format formatDfaConnection("dfa_connection(%1%, %2%, %3%)."); for (i1 = this->__edges.begin(), i2 = this->__data.begin(); i1 != this->__edges.end(); ++i1, ++i2) { string edgeName; switch (*i2) { case DFGConnection::WEAK: edgeName = "weak"; break; case DFGConnection::STRONG: edgeName = "strong"; break; case DFGConnection::PROTOTYPE: edgeName = "proto"; break; } output << formatDfaConnection % formatSymbol(i1->first) % formatSymbol(i1->second) % edgeName << " %" << this->__clasp->getHintForPackedSymbol(i1->first) << " - " << this->__clasp->getHintForPackedSymbol(i1->second) << endl; symbols.insert(i1->first); symbols.insert(i1->second); } boost::format formatDfaDependency("dfa_dependency(%1%, %2%)."); for (auto i = this->__dependencies.begin(); i != this->__dependencies.end(); ++i) { output << formatDfaDependency % formatSymbol(i->first) % formatSymbol(i->second) << " %" << this->__clasp->getHintForPackedSymbol(i->first) << " - " << this->__clasp->getHintForPackedSymbol(i->second) << endl; } boost::format formatBind("bind(%1%, %2%)."); for (const pair& tag : this->__tags) { for (string variant : xreate::analysis::compile(tag.second)) { output << formatBind % formatSymbol(tag.first) % (variant) << "%" << this->__clasp->getHintForPackedSymbol(tag.first) << endl; } symbols.insert(tag.first); } for (const SymbolPacked& s : symbols) { output << "v(" << formatSymbol(s) << ")." << " %" << this->__clasp->getHintForPackedSymbol(s) << endl; } } class VisitorAddTag : public boost::static_visitor<> { public: void operator()(const SymbolPacked& symbol) { __graph->__tags.emplace(symbol, move(__tag)); } void operator()(SymbolTransient& symbol) { symbol.tags.push_back(move(__tag)); } void operator()(const SymbolInvalid& symbol) { assert(false && "Undefined behaviour"); } VisitorAddTag(DFAGraph * const dfagraph, Expression&& tag) : __graph(dfagraph), __tag(tag) { } private: DFAGraph * const __graph; Expression __tag; }; class VisitorAddLink : public boost::static_visitor<> { public: void operator()(const SymbolPacked& nodeFrom) { if (!__graph->isConnected(__nodeTo, nodeFrom)) { __graph->__edges.emplace_back(__nodeTo, nodeFrom); __graph->__data.push_back(__link); DFAGraph::EdgeId eid = __graph->__edges.size() - 1; __graph->__outEdges.emplace(nodeFrom, eid); } } void operator()(const SymbolTransient& symbolFrom) { switch (__link) { case DFGConnection::WEAK: { //virtual symbol to hold transient annotations SymbolPacked symbPivot = __graph->createAnonymousSymbol(symbolFrom.scope); __graph->addConnection(symbPivot, symbolFrom, DFGConnection::STRONG); __graph->addConnection(__nodeTo, symbPivot, DFGConnection::WEAK); break; } case DFGConnection::STRONG: { for (const Expression& tag : symbolFrom.tags) { __graph->__tags.emplace(__nodeTo, tag); } break; } default: assert(false && "Undefined behavior"); } } void operator()(const SymbolInvalid&) { if (__link == DFGConnection::STRONG) return; if (__link == DFGConnection::WEAK) return; assert(false && "Undefined behavior"); } VisitorAddLink(DFAGraph * const dfagraph, const SymbolPacked& nodeTo, DFGConnection link) : __graph(dfagraph), __nodeTo(nodeTo), __link(link) { } private: DFAGraph * const __graph; SymbolPacked __nodeTo; DFGConnection __link; }; class VisitorGetDependencyConnection : public boost::static_visitor> { public: list operator()(const SymbolPacked & nodeFrom) { return { nodeFrom }; } list operator()(const SymbolTransient & nodeFrom) { return nodeFrom.dependencies; } list operator()(const SymbolInvalid&) { assert(false && "Undefined behavior"); } VisitorGetDependencyConnection(DFAGraph * const g) : graph(g) { } DFAGraph * const graph; }; class VisitorSetDependencyConnection : public boost::static_visitor<> { public: void operator()(SymbolPacked& nodeTo) { VisitorGetDependencyConnection visitorGetDepenencies(graph); auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom); for (const SymbolPacked& dep : deps) { graph->__dependencies.emplace(nodeTo, dep); } } void operator()(SymbolTransient& nodeTo) { VisitorGetDependencyConnection visitorGetDepenencies(graph); auto deps = boost::apply_visitor(visitorGetDepenencies, nodeFrom); for (const SymbolPacked& dep : deps) { nodeTo.dependencies.push_back(dep); } } void operator()(SymbolInvalid&) { assert(false && "Undefined behavior"); } VisitorSetDependencyConnection(DFAGraph * const g, SymbolNode s) : graph(g), nodeFrom(s) { } DFAGraph * const graph; SymbolNode nodeFrom; }; bool DFAGraph::isConnected(const SymbolPacked& identifierTo, const SymbolPacked& identifierFrom) { auto range = __outEdges.equal_range(identifierFrom); for (std::multimap::iterator edge = range.first; edge != range.second; ++edge) { if (__edges[edge->second].second == identifierTo) return true; } return false; } void DFAGraph::addConnection(const SymbolPacked& nodeTo, const SymbolNode& nodeFrom, DFGConnection link) { VisitorAddLink visitor(this, nodeTo, link); boost::apply_visitor(visitor, nodeFrom); } void DFAGraph::addDependencyConnection(SymbolNode& identifierTo, SymbolNode& identifierFrom) { VisitorSetDependencyConnection visitor(this, identifierFrom); boost::apply_visitor(visitor, identifierTo); } void DFAGraph::addAnnotation(SymbolNode& node, Expression&& tag) { VisitorAddTag visitor(this, move(tag)); boost::apply_visitor(visitor, node); } SymbolPacked DFAGraph::createAnonymousSymbol(const ScopePacked& scope) { - return SymbolPacked{__countAnonymousSymbols++, scope, true}; + return SymbolPacked(__countAnonymousSymbols++, scope, true); } } } \ No newline at end of file diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp index 76509c6..6434235 100644 --- a/cpp/src/clasplayer.cpp +++ b/cpp/src/clasplayer.cpp @@ -1,279 +1,275 @@ #include "clasplayer.h" #include #include "utils.h" #include #include #include #include "analysis/aux.h" #include "analysis/DominatorsTreeAnalysisProvider.h" #include "analysis/cfagraph.h" #include "analysis/dfagraph.h" using namespace std; //TODO escape identifiers started from upper case symbol namespace xreate { void ClaspLayer::printWarnings(std::ostream& out) { const std::string warningTag = "warning"; auto warningsRange = __model.equal_range(warningTag); for (auto warning=warningsRange.first; warning!= warningsRange.second; ++warning) { unsigned int warningId; Gringo::Symbol params; std::tie(warningId, params) = parse(warning->second); cout << "Warning: " << __warnings.at(warningId) << " "; params.print(out); out< warnings; cout << "Model: " << endl; const string& atomBindVar = Config::get("clasp.bindings.variable"); const string& atomBindFunc = Config::get("clasp.bindings.function"); const string& atomBindScope = Config::get("clasp.bindings.scope"); for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) { atom.print(cout); cout <<" | "<< endl; string atomName(atom.name().c_str()); if (atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope){ string name = std::get<1>(parse(atom)).name().c_str(); __model.emplace(move(name), move(atom)); } __model.emplace(atomName, move(atom)); } return true; } void ClaspLayer::setCFAData(xreate::analysis::CFAGraph* graph) { dataCFA.reset(graph); } void ClaspLayer::setDFAData(xreate::analysis::DFAGraph* graph){ dataDFA.reset(graph); } void ClaspLayer::addRuleWarning(const RuleWarning &rule) { //__partGeneral << rule << endl; list domains; boost::format formatDef("%1%(%2%)"); std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()), [&formatDef](const std::pair &argument) { string domain; switch (argument.second) { case DomainAnnotation::FUNCTION: domain = "function"; break; case DomainAnnotation::VARIABLE: domain = "variable"; break; } return boost::str(formatDef % domain % argument.first); }); list vars; std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()), [](const std::pair &argument) { return argument.first.c_str(); }); list> guardsRaw; std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()), [this](const Expression &guard) { return xreate::analysis::compile(guard); }); const list& guards = xreate::analysis::multiplyLists(std::move(guardsRaw)); list &&branches = xreate::analysis::compileNeg(rule.__condition); boost::format formatWarning("warning(%1%, (%2%)):- %3%, %4%, %5%."); for (const string &guardsJoined: guards) for (const string &branch: branches) { unsigned int hook = registerWarning(string(rule.__message)); __partGeneral << formatWarning %(hook) %(boost::algorithm::join(vars, ", ")) %(branch) %(guardsJoined) %(boost::algorithm::join(domains, ", ")) <__rawImports) { std::ifstream file(fn); if (!file) continue; while(!file.eof()){ string line; std::getline(file, line); out << line << endl; } } } void ClaspLayer::addRawScript(std::string&& script){ __partGeneral << script; } void ClaspLayer::run() { involveImports(); if (this->dataDFA){ this->dataDFA->print(__partGeneral); } if (this->dataCFA){ this->dataCFA->print(__partGeneral); } DominatorsTreeAnalysisProvider providerDominators; providerDominators.run(this); providerDominators.print(__partGeneral); ostringstream program; program << __partTags.str() << __partGeneral.str(); cout << FYEL(program.str()) << endl; std::vector args{"clingo", nullptr}; DefaultGringoModule moduleDefault; Gringo::Scripts scriptsDefault(moduleDefault); ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0); ctl.add("base", {}, program.str()); ctl.ground({{"base", {}}}, nullptr); // solve Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) { this->handleSolution(model); return true; }, {}); if (result.satisfiable() == Gringo::SolveResult::Satisfiable) { cout << FGRN("SUCCESSFULLY") << endl; } else { cout << FRED("UNSUCCESSFULLY") << endl; } // invoke all query plugins to process clasp data for (auto q: __queries) { q.second->init(this); } } ClaspLayer::ClaspLayer() { } ClaspLayer::ModelFragment ClaspLayer::query(const std::string& atom) { if (! __model.count(atom)){ return boost::none; } return ModelFragment(__model.equal_range(atom)); } ScopePacked ClaspLayer::pack(CodeScope* const scope) { auto pos = __indexScopes.emplace(scope, __indexScopes.size()); if (pos.second) __registryScopes.push_back(scope); return pos.first->second; } size_t ClaspLayer::getScopesCount() const{ return __registryScopes.size(); } SymbolPacked ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName) { - SymbolPacked result; - - result.scope = pack(symbol.scope); - result.identifier = symbol.identifier; + SymbolPacked result(symbol.identifier, pack(symbol.scope)); __indexSymbolNameHints.emplace(result, hintSymbolName); return result; } Symbol ClaspLayer::unpack(const SymbolPacked& symbol) { return Symbol{symbol.identifier, __registryScopes[symbol.scope]}; }; std::string ClaspLayer::getHintForPackedSymbol(const SymbolPacked& symbol){ if (!symbol.categoryTransient) { auto result = __indexSymbolNameHints.find(symbol); return (result == __indexSymbolNameHints.end())? "" : result->second; } else { return "anonym(" + to_string(symbol.identifier) + ")"; } } bool operator==(const SymbolPacked& s1, const SymbolPacked& s2) { return s1.identifier == s2.identifier && s1.scope == s2.scope; } bool operator<(const SymbolPacked& s1, const SymbolPacked& s2) { return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier); } IQuery* ClaspLayer::registerQuery(IQuery *query, const QueryId& id) { return __queries.emplace(id, query).first->second; } IQuery* ClaspLayer::getQuery(const QueryId& id){ assert(__queries.count(id) && "Undefined query"); return __queries.at(id); } -} - +} \ No newline at end of file diff --git a/cpp/src/clasplayer.h b/cpp/src/clasplayer.h index ad8da19..6961026 100644 --- a/cpp/src/clasplayer.h +++ b/cpp/src/clasplayer.h @@ -1,227 +1,230 @@ #ifndef CLASPLAYER_H #define CLASPLAYER_H #include "ast.h" #include "contextrule.h" #include #include #include #include #include #include #include #include namespace xreate { typedef unsigned int ScopePacked; struct SymbolPacked { VID identifier; ScopePacked scope; - bool categoryTransient = false; + bool categoryTransient; + + SymbolPacked(): categoryTransient(false){} + SymbolPacked(VID i, ScopePacked s, bool isTransient = false): identifier(i), scope(s), categoryTransient(isTransient){} }; bool operator==(const SymbolPacked& s1, const SymbolPacked& s2); bool operator<(const SymbolPacked& s1, const SymbolPacked& s2); enum class DFGConnection { STRONG, WEAK, PROTOTYPE }; class IAnalysisData { public: void print(std::ostringstream& output) const; virtual ~IAnalysisData(){}; }; class IQuery { public: virtual void init(ClaspLayer* clasp) = 0; virtual ~IQuery() {} }; enum class QueryId { ContainersQuery, ContextQuery, PtrvalidQuery }; namespace analysis{ class DFAGraph; class CFAGraph; } class ClaspLayer { friend class ContextRule; //PROVIDERS: public: boost::scoped_ptr dataDFA; void setDFAData(xreate::analysis::DFAGraph* graph); boost::scoped_ptr dataCFA; void setCFAData(xreate::analysis::CFAGraph* graph); void addRawScript(std::string&& script); private: void involveImports(); //QUERIES public: IQuery* registerQuery(IQuery* query, const QueryId& id); IQuery* getQuery(const QueryId& id); template static std::tuple parse(const Gringo::Symbol& atom); typedef std::multimap::const_iterator ModelIterator; typedef boost::optional> ModelFragment; ModelFragment query(const std::string& atom); size_t getScopesCount() const; SymbolPacked pack(const Symbol& symbol, std::string hintSymbolName = ""); ScopePacked pack(CodeScope * const scope); Symbol unpack(const SymbolPacked& symbol); std::string getHintForPackedSymbol(const SymbolPacked& symbol); private: std::map __queries; std::multimap __model; std::map __indexSymbolNameHints; std::unordered_map __indexScopes; std::vector __registryScopes; //WARNINGS //TODO move to separate provider/query public: void addRuleWarning(const RuleWarning &rule); unsigned int registerWarning(std::string &&message); private: std::map __warnings; void printWarnings(std::ostream& out); //DEFAULT public: AST *ast; ClaspLayer(); void run(); private: std::ostringstream __partTags; std::ostringstream __partGeneral; bool handleSolution(Gringo::Model const &model); }; template struct ParseImplAtom { static typ get(const Gringo::Symbol& atom) { return atom.num(); } }; template<> struct ParseImplAtom { static std::string get(const Gringo::Symbol& atom) { switch (atom.type()) { case Gringo::SymbolType::Str: return atom.string().c_str(); case Gringo::SymbolType::Fun: return atom.name().c_str(); default: break; } assert(false && "Inappropriate symbol type"); } }; template<> struct ParseImplAtom { static SymbolPacked get(const Gringo::Symbol& atom) { auto result = ClaspLayer::parse(atom); - return SymbolPacked{std::get<0>(result), std::get<1>(result)}; + return SymbolPacked(std::get<0>(result), std::get<1>(result)); } }; template<> struct ParseImplAtom { static Gringo::Symbol get(const Gringo::Symbol& atom) { return atom; } }; template<> struct ParseImplAtom { static Expression get(const Gringo::Symbol& atom) { switch (atom.type()) { case Gringo::SymbolType::Num: return Expression(atom.num()); case Gringo::SymbolType::Str: return Expression(std::string(atom.string().c_str())); case Gringo::SymbolType::Fun: { //ID if (!atom.args().size){ return Expression(std::string(atom.name().c_str())); } //FUNC Expression result(Operator::CALL,{Expression(std::string(atom.name().c_str()))}); for (const Gringo::Symbol& arg : atom.args()) { result.addArg(ParseImplAtom::get(arg)); } return result; } default: { assert(false); } } } }; template struct Parse_Impl { static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) { const size_t tupleSize = std::tuple_size::value; typedef typename std::tuple_element < tupleSize - index, Tuple>::type ElType; ElType& el = std::get < tupleSize - index > (tup); Gringo::Symbol atom = *arg; el = ParseImplAtom::get(atom); Parse_Impl ::parse(tup, ++arg); } }; template struct Parse_Impl { static void parse(Tuple& tup, Gringo::SymSpan::iterator arg) { } }; template std::tuple ClaspLayer::parse(const Gringo::Symbol& atom) { typedef std::tuple < Types...> Tuple; Tuple tup; Parse_Impl::value>::parse(tup, atom.args().first); return tup; } } -#endif +#endif \ No newline at end of file diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp index 90c48fb..b50bf13 100644 --- a/cpp/src/compilation/targetinterpretation.cpp +++ b/cpp/src/compilation/targetinterpretation.cpp @@ -1,447 +1,446 @@ /* * File: targetinterpretation.cpp * Author: pgess * * Created on June 29, 2016, 6:45 PM */ #include "compilation/targetinterpretation.h" #include "pass/interpretationpass.h" #include "llvmlayer.h" #include #include using namespace std; namespace xreate{ namespace compilation { const Expression EXPRESSION_FALSE = Expression(Atom(0)); const Expression EXPRESSION_TRUE = Expression(Atom(1)); //Expression //InterpretationScope::compile(const Expression& expression){} CodeScope* InterpretationScope::processOperatorIf(const Expression& expression){ const Expression& exprCondition = process(expression.getOperands()[0]); if (exprCondition == EXPRESSION_TRUE){ return expression.blocks.front(); } return expression.blocks.back(); } CodeScope* InterpretationScope::processOperatorSwitch(const Expression& expression) { const Expression& exprCondition = process(expression.operands[0]); bool flagHasDefault = expression.operands[1].op == Operator::CASE_DEFAULT; //TODO check that one and only one case variant is appropriate for (size_t size = expression.operands.size(), i= flagHasDefault? 2: 1; igetScope(exprCase.blocks.front())->processScope() == exprCondition){ return exprCase.blocks.back(); } } if (flagHasDefault){ const Expression& exprCaseDefault = expression.operands[1]; return exprCaseDefault.blocks.front(); } assert(false && "Switch has no appropriate variant"); return nullptr; } llvm::Value* InterpretationScope::compileHybrid(const InterpretationOperator& op, const Expression& expression, const Context& context){ switch(op){ case IF_INTERPRET_CONDITION: { CodeScope* scopeResult = processOperatorIf(expression); llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile(); return result; } case SWITCH_INTERPRET_CONDITION:{ CodeScope* scopeResult = processOperatorSwitch(expression); llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile(); return result; } case FOLD_INTERPRET_INPUT: { //initialization const Expression& exprInput = process(expression.getOperands()[0]); assert(exprInput.op == Operator::LIST); CodeScope* scopeBody = expression.blocks.front(); const string& nameEl = expression.bindings[0]; const Symbol& symbolEl = scopeBody->findSymbol(nameEl); const std::string& idAccum = expression.bindings[1]; llvm::Value* rawAccum = context.scope->process(expression.getOperands()[1]); compilation::CodeScopeUnit* unitBody = context.function->getScopeUnit(scopeBody); InterpretationScope* intrBody = function->getScope(scopeBody); const std::vector elementsInput= exprInput.getOperands(); for (size_t i=0; ireset(); intrBody->overrideBinding(exprElement, nameEl); unitBody->overrideDeclaration(symbolEl, move(exprElement)); unitBody->bindArg(rawAccum, string(idAccum)); rawAccum = unitBody->compile(); } return rawAccum; } case CALL_INTERPRET_PARTIAL: { const std::string &calleeName = expression.getValueString(); CodeScopeUnit* scopeUnitSelf = context.scope; ManagedFnPtr callee = this->function->man->ast->findFunction(calleeName); const FunctionInterpretationData& calleeData = FunctionInterpretationHelper::getSignature(callee); std::vector argsActual; PIFSignature sig; sig.declaration = callee; for(size_t no=0, size = expression.operands.size(); no < size; ++no){ const Expression& op = expression.operands[no]; if (calleeData.signature.at(no) == INTR_ONLY){ sig.bindings.push_back(process(op)); continue; } argsActual.push_back(scopeUnitSelf->process(op)); } TargetInterpretation* man = dynamic_cast(this->function->man); PIFunction* pifunction = man->getFunction(move(sig)); llvm::Function* raw = pifunction->compile(); boost::scoped_ptr statement(new CallStatementRaw(raw, man->pass->man->llvm)); return (*statement)(move(argsActual)); } default: break; } assert(false&& "Unknown hybrid operator"); return nullptr; } llvm::Value* InterpretationScope::compile(const Expression& expression, const Context& context){ const InterpretationData& data = Attachments::get(expression); if (data.op != InterpretationOperator::NONE){ return compileHybrid(data.op, expression, context); } Expression result = process(expression); return context.scope->processLowlevel(result); } Expression InterpretationScope::process(const Expression& expression){ switch (expression.__state){ case Expression::VARIANT: case Expression::INVALID: assert(false); case Expression::NUMBER: case Expression::STRING: return expression; case Expression::IDENT:{ const std::string &ident = expression.getValueString(); Symbol s = scope->findSymbol(ident); return Parent::processSymbol(s); } case Expression::COMPOUND: break; default: assert(false); } switch (expression.op) { case Operator::EQU: { const Expression& left = process(expression.operands[0]); const Expression& right = process(expression.operands[1]); if (left == right) return EXPRESSION_TRUE; return EXPRESSION_FALSE; } case Operator::NE: { const Expression& left = process(expression.operands[0]); const Expression& right = process(expression.operands[1]); if (left == right) return EXPRESSION_FALSE; return EXPRESSION_TRUE; } case Operator::LOGIC_AND: { assert(expression.operands.size() == 1); return process (expression.operands[0]); } // case Operator::LOGIC_OR: case Operator::CALL: { const std::string &fnName = expression.getValueString(); ManagedFnPtr fnAst = this->function->man->ast->findFunction(fnName); - InterpretatonFunction* fnUnit = this->function->man->getFunction(fnAst); + InterpretationFunction* fnUnit = this->function->man->getFunction(fnAst); vector args; args.reserve(expression.getOperands().size()); for(size_t i=0, size = expression.getOperands().size(); iprocess(args); } case Operator::IF:{ CodeScope* scopeResult = processOperatorIf(expression); return function->getScope(scopeResult)->processScope(); } case Operator::SWITCH: { CodeScope* scopeResult = processOperatorSwitch(expression); return function->getScope(scopeResult)->processScope(); } case Operator::INDEX: { const Expression& exprKey = process(expression.operands[0]); const Expression& exprData = processSymbol(scope->findSymbol(expression.getValueString())); if (exprKey.__state == Expression::STRING){ const string& key = exprKey.getValueString(); assert(exprData.__indexBindings.count(key)); return exprData.operands[exprData.__indexBindings.at(key)]; } if (exprKey.__state == Expression::NUMBER){ int key = exprKey.getValueDouble(); return exprData.operands[key]; } assert(false); } case Operator::FOLD: { const Expression& exprInput = process(expression.getOperands()[0]); const Expression& exprInit = process(expression.getOperands()[1]); const std::string& argEl = expression.bindings[0]; const std::string& argAccum = expression.bindings[1]; InterpretationScope* body = function->getScope(expression.blocks.front()); Expression accum = exprInit; for(size_t size=exprInput.getOperands().size(), i=0; ioverrideBinding(exprInput.getOperands()[i], argEl); body->overrideBinding(accum, argAccum); accum = body->processScope(); } return accum; } // case Operator::MAP: { // break; // } default: break; } return expression; } -InterpretatonFunction* +InterpretationFunction* TargetInterpretation::getFunction(FunctionUnit* unit){ if (__dictFunctionsByUnit.count(unit)) { return __dictFunctionsByUnit.at(unit); } - InterpretatonFunction* f = new InterpretatonFunction(unit->function, this); + InterpretationFunction* f = new InterpretationFunction(unit->function, this); __dictFunctionsByUnit.emplace(unit, f); assert(__functions.emplace(unit->function.id(), f).second); return f; } PIFunction* TargetInterpretation::getFunction(PIFSignature&& sig){ - auto f = __pifunctions.find(sig); + auto f = __pifunctions.find(sig); if (f != __pifunctions.end()){ - return *f; + return f->second; } - PIFunction* result = new PIFunction(move(sig), __pifunctions.size(), this); - __pifunctions.insert(result); + PIFunction* result = new PIFunction(PIFSignature(sig), __pifunctions.size(), this); + __pifunctions.emplace(move(sig), result); assert(__dictFunctionsByUnit.emplace(result->functionUnit, result).second); return result; } InterpretationScope* TargetInterpretation::transformContext(const Context& c){ return this->getFunction(c.function)->getScope(c.scope->scope); } llvm::Value* TargetInterpretation::transform(const Expression& expression, llvm::Value* raw, const Context& ctx){ return raw; } Expression TargetInterpretation::transform(const Expression& expression, const Context& ctx){ return transformContext(ctx)->process(expression); } llvm::Value* TargetInterpretation::compile(const Expression& expression, const Context& ctx){ return transformContext(ctx)->compile(expression, ctx); } bool TargetInterpretation::isAcceptable(const Expression& expression){ const InterpretationData& data = Attachments::get(expression, {ANY, NONE}); return (data.resolution == INTR_ONLY || data.op != InterpretationOperator::NONE); } -InterpretatonFunction::InterpretatonFunction(const ManagedFnPtr& function, Target* target) +InterpretationFunction::InterpretationFunction(const ManagedFnPtr& function, Target* target) : Function(function, target) {} Expression -InterpretatonFunction::process(const std::vector& args){ +InterpretationFunction::process(const std::vector& args){ InterpretationScope* body = getScope(__function->__entry); for(size_t i=0, size = args.size(); ioverrideBinding(args.at(i), string(body->scope->__bindings.at(i))); } return body->processScope(); } // Partial function interpretation typedef BasicFunctionDecorator PIFunctionUnitParent; class PIFunctionUnit: public PIFunctionUnitParent{ public: PIFunctionUnit(ManagedFnPtr f, std::set&& arguments, size_t id, CompilePass* p) : PIFunctionUnitParent(f, p), argumentsActual(move(arguments)), __id(id) {} protected: std::vector prepareArguments(){ LLVMLayer* llvm = PIFunctionUnitParent::pass->man->llvm; AST* ast = PIFunctionUnitParent::pass->man->root; CodeScope* entry = PIFunctionUnitParent::function->__entry; std::vector signature; for(size_t no: argumentsActual){ Symbol arg = entry->findSymbol(entry->__bindings[no]); signature.push_back(llvm->toLLVMType(ast->expandType(entry->__declarations[arg.identifier].type))); } return signature; } llvm::Function::arg_iterator prepareBindings(){ CodeScope* entry = PIFunctionUnitParent::function->__entry; CodeScopeUnit* entryCompilation = PIFunctionUnitParent::getScopeUnit(entry); llvm::Function::arg_iterator fargsI = PIFunctionUnitParent::raw->arg_begin(); for(size_t no: argumentsActual){ Symbol arg = entry->findSymbol(entry->__bindings[no]); entryCompilation->__rawVars[arg.identifier] = &*fargsI; fargsI->setName(entry->__bindings[no]); ++fargsI; } return fargsI; } virtual std::string prepareName(){ return PIFunctionUnitParent::prepareName() + "_" + std::to_string(__id); } private: std::set argumentsActual; size_t __id; }; PIFunction::PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target) - : InterpretatonFunction(sig.declaration, target), signatureInstance(move(sig)) + : InterpretationFunction(sig.declaration, target), signatureInstance(move(sig)) { const FunctionInterpretationData& functionData = FunctionInterpretationHelper::getSignature(signatureInstance.declaration); std::set argumentsActual; for (size_t no=0, size=functionData.signature.size(); no < size; ++no){ if (functionData.signature.at(no) != INTR_ONLY){ argumentsActual.insert(no); } } functionUnit = new PIFunctionUnit(signatureInstance.declaration, move(argumentsActual), id, target->pass); CodeScope* entry = signatureInstance.declaration->__entry; CodeScopeUnit* entryUnit = functionUnit->getEntry(); - InterpretationScope* entryIntrp = InterpretatonFunction::getScope(entry); + InterpretationScope* entryIntrp = InterpretationFunction::getScope(entry); for(size_t no=0, sigNo=0, size = entry->__bindings.size(); no < size; ++no){ if (functionData.signature.at(no) == INTR_ONLY){ entryIntrp->overrideBinding(signatureInstance.bindings[sigNo], entry->__bindings[no]); entryUnit->overrideDeclaration(entry->findSymbol(entry->__bindings[no]), Expression(signatureInstance.bindings[sigNo])); ++sigNo; } } } llvm::Function* PIFunction::compile(){ llvm::Function* raw = functionUnit->compile(); return raw; } bool operator<(const PIFSignature& lhs, const PIFSignature& rhs){ if (lhs.declaration.id() != rhs.declaration.id()) { return lhs.declaration.id() < rhs.declaration.id(); } return lhs.bindings < rhs.bindings; } bool operator<(const PIFSignature& lhs, PIFunction* const rhs){ return lhs < rhs->signatureInstance; } bool operator<(PIFunction* const lhs, const PIFSignature& rhs){ return lhs->signatureInstance < rhs; } -}} - +}} \ No newline at end of file diff --git a/cpp/src/compilation/targetinterpretation.h b/cpp/src/compilation/targetinterpretation.h index 2d7444e..0ef32e7 100644 --- a/cpp/src/compilation/targetinterpretation.h +++ b/cpp/src/compilation/targetinterpretation.h @@ -1,117 +1,116 @@ /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ /* * File: targetstatic.h * Author: pgess * * Created on July 2, 2016, 1:25 PM */ #ifndef TARGETSTATIC_H #define TARGETSTATIC_H #include "ast.h" #include "compilation/targets.h" #include "transformations.h" #include "pass/interpretationpass.h" namespace xreate{ namespace compilation { class TargetInterpretation; class InterpretationScope; -class InterpretatonFunction; +class InterpretationFunction; template <> struct TargetInfo { typedef Expression Result; typedef InterpretationScope Scope; - typedef InterpretatonFunction Function; + typedef InterpretationFunction Function; }; template<> struct TransformerInfo { static const int id = 1; }; class InterpretationScope: public Scope{ typedef Scope Parent; public: InterpretationScope(CodeScope* scope, Function* f): Parent(scope, f) {} Expression process(const Expression& expression) override; llvm::Value* compile(const Expression& expression, const Context& context); private: llvm::Value* compileHybrid(const InterpretationOperator& op, const Expression& expression, const Context& context); //llvm::Value* compilePartialFnCall(const Expression& expression, const Context& context); CodeScope* processOperatorIf(const Expression& expression); CodeScope* processOperatorSwitch(const Expression& expression); }; -class InterpretatonFunction: public Function{ +class InterpretationFunction: public Function{ public: - InterpretatonFunction(const ManagedFnPtr& function, Target* target); + InterpretationFunction(const ManagedFnPtr& function, Target* target); Expression process(const std::vector& args); }; /* * Partially interpreted function signature */ struct PIFSignature{ ManagedFnPtr declaration; std::vector bindings; }; class PIFunctionUnit; -class PIFunction: public InterpretatonFunction{ +class PIFunction: public InterpretationFunction{ public: PIFunctionUnit* functionUnit; PIFSignature signatureInstance; PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target); llvm::Function* compile(); }; bool operator<(const PIFSignature& lhs, PIFunction* const rhs); bool operator<(PIFunction* const lhs, const PIFSignature& rhs); class TargetInterpretation: public Target, public Transformer{ public: TargetInterpretation(AST* root, CompilePass* passCompilation): Target(root), pass(passCompilation){} //transformer: public: virtual llvm::Value* transform(const Expression& expression, llvm::Value* raw, const Context& ctx) override; virtual Expression transform(const Expression& expression, const Context& ctx) override; virtual bool isAcceptable(const Expression& expression) override; //target: public: - InterpretatonFunction* getFunction(FunctionUnit* unit); + InterpretationFunction* getFunction(FunctionUnit* unit); PIFunction* getFunction(PIFSignature&& sig); private: - std::set> __pifunctions; - std::map __dictFunctionsByUnit; + std::map __pifunctions; + std::map __dictFunctionsByUnit; //self: public: CompilePass* pass; llvm::Value* compile(const Expression& expression, const Context& ctx); private: InterpretationScope* transformContext(const Context& c); }; }} -#endif /* TARGETSTATIC_H */ - +#endif /* TARGETSTATIC_H */ \ No newline at end of file diff --git a/cpp/src/compilation/targets.h b/cpp/src/compilation/targets.h index b1821e3..f6b47bb 100644 --- a/cpp/src/compilation/targets.h +++ b/cpp/src/compilation/targets.h @@ -1,156 +1,161 @@ /* * File: targetabstract.h * Author: pgess * * Created on July 2, 2016, 1:25 PM */ #ifndef TARGETABSTRACT_H #define TARGETABSTRACT_H #include "ast.h" #include #include namespace xreate{ namespace compilation { template struct TargetInfo{ //typedef Result //typedef Function //typedef Scope }; template class Function; template class Target; template class Scope{ public: CodeScope* scope; typename TargetInfo::Result processSymbol(const Symbol& s){ CodeScope* scope = s.scope; typename TargetInfo::Scope* self = function->getScope(scope); if (self->__bindings.count(s.identifier)) { return self->__bindings[s.identifier]; } const Expression& declaration = CodeScope::findDeclaration(s); if (!declaration.isDefined()){ assert(false); //for bindings there should be result already } return self->__bindings[s.identifier] = self->process(declaration); } typename TargetInfo::Result processScope() { if (raw) return *raw; raw = process(scope->getBody()); return *raw; } // typename TargetInfo::Result // processFunction(typename TargetInfo::Function* fnRemote, const std::vector::Result>& args){ // Scope scopeRemote = fnRemote->getScope(fnRemote->__function->__entry); // // if (scopeRemote->raw){ // return scopeRemote->raw; // } // // return fnRemote->process(args); // } virtual typename TargetInfo::Result process(const Expression& expression)=0; Scope(CodeScope* codeScope, Function* f) : scope(codeScope), function(f) {} virtual ~Scope(){} void overrideBinding(typename TargetInfo::Result arg, const std::string& name){ assert(scope->__identifiers.count(name)); VID id = scope->__identifiers.at(name); __bindings[id] = arg; //reset the result if any: raw.reset(); } protected: Function* function=0; std::map::Result> __bindings; typename boost::optional::Result> raw; //ResultType findFunction(const std::string& callee); }; template class Function{ typedef typename TargetInfo::Result Result; public: Function(const ManagedFnPtr& function, Target* target) : man(target), __function(function) {} + virtual ~Function(){}; + typename TargetInfo::Scope* getScope(CodeScope* scope){ if (!__scopes.count(scope)){ typename TargetInfo::Scope* unit = new typename TargetInfo::Scope(scope, this); __scopes.emplace(scope, std::unique_ptr::Scope>(unit)); } return __scopes.at(scope).get(); } virtual Result process(const std::vector& args)=0; Target* man=0; ManagedFnPtr __function; protected: std::map::Scope>> __scopes; }; template class Target { typedef typename TargetInfo::Function ConcreteFunction; public: Target(AST* root): ast(root){} ConcreteFunction* getFunction(const ManagedFnPtr& function){ unsigned int id = function.id(); if (!__functions.count(id)){ ConcreteFunction* unit = new ConcreteFunction(function, this); - __functions.emplace(id, std::unique_ptr(unit)); + __functions.emplace(id, unit); return unit; } - return __functions.at(id).get(); + return __functions.at(id); } AST* ast; - virtual ~Target(){} + virtual ~Target(){ + for (const auto& entry: __functions){ + delete entry.second; + } + } protected: - std::map> __functions; + std::map __functions; }; }} -#endif /* TARGETABSTRACT_H */ - +#endif /* TARGETABSTRACT_H */ \ No newline at end of file diff --git a/cpp/src/serialization/expressionserializer.cpp b/cpp/src/serialization/expressionserializer.cpp index 42b5a15..53d6ee5 100644 --- a/cpp/src/serialization/expressionserializer.cpp +++ b/cpp/src/serialization/expressionserializer.cpp @@ -1,303 +1,316 @@ /* * expressionserializer.cpp * * Created on: Jan 4, 2016 * Author: pgess */ #include "serialization/expressionserializer.h" +#include #include using namespace std; //using namespace boost::bimaps; namespace xreate { struct Index { string name; size_t degree; //count of parameters unsigned char level; //level in expression tree (depth of tree layer) bool operator< (const Index other) const{ if (name != other.name) return name < other.name; if (degree != other.degree) return degree < other.degree; if (name != other.name) return level < other.level; return false; } }; class ExpressionSerializerPrivate { //boost::bimap> __registry; struct { map left; } __registry; map __range; public: void pack(const Expression& e, unsigned char level, OptionalPackedExpression& target){ if (!target) return; switch (e.op){ case Operator::NONE: { switch (e.__state) { case Expression::NUMBER: case Expression::STRING: case Expression::IDENT : { - + Index index; if ((e.__state == Expression::NUMBER)) index = {std::to_string(e.getValueDouble()), 0, level}; else index = {e.getValueString(), 0, level}; - + if (!__registry.left.count(index)){ target = boost::none; return; } size_t id = __registry.left.at(index); size_t range = __range[level]; (*target) << make_pair(id, range); return; } default: break; } break; } case Operator::CALL: { Index index{e.getValueString(), e.operands.size(), level}; if(!__registry.left.count(index)){ target = boost::none; return; } size_t id = __registry.left.at(index); size_t range = __range[level]; (*target) << make_pair(id, range); for (const Expression& operand: e.operands){ pack(operand, level+1, target); } return; } default: break; } assert(false && "Expression too complicate for serialization"); } void registerExpression(const Expression&e, unsigned char level){ switch (e.op){ case Operator::CALL: { Index index{e.getValueString(), e.operands.size(), level}; if (__registry.left.insert(make_pair(index, __range[level])).second){ __range[level]++; } for (const Expression& operand: e.operands){ registerExpression(operand, level+1); } return; } case Operator::NONE: { Index index; - + switch (e.__state) { case Expression::STRING: case Expression::IDENT: { index = {e.getValueString(), 0, level}; if (__registry.left.insert(make_pair(index, __range[level])).second){ __range[level]++; } return; } - + case Expression::NUMBER: { index = {std::to_string(e.getValueDouble()), 0, level}; if (__registry.left.insert(make_pair(index, __range[level])).second){ __range[level]++; } return; } - + default: break; } break; } default: break; } assert(false && "Expression too complicate for serialization"); } }; ExpressionSerializer::ExpressionSerializer() : strategy(new ExpressionSerializerPrivate()){ } ExpressionSerializer::~ExpressionSerializer() { delete strategy; } void ExpressionSerializer::registerExpression(const Expression&e){ if (e.isValid()) strategy->registerExpression(e, 0); } PackedExpression ExpressionSerializer::getId(const Expression& e){ - OptionalPackedExpression result(move(PackedExpression())); + OptionalPackedExpression result(boost::in_place()); + //move(PackedExpression()) + strategy->pack(e, 0, result); assert(result); return move(*result); } OptionalPackedExpression ExpressionSerializer::getIdOptional(const Expression& e) const{ - OptionalPackedExpression result(move(PackedExpression())); + OptionalPackedExpression result(boost::in_place()); + //move(PackedExpression()) + strategy->pack(e, 0, result); return result; } ExpressionSerializerIntegral::ExpressionSerializerIntegral():serializer(*this){} ExpressionSerializerIntegral::ExpressionSerializerIntegral(const std::vector&& expressions) : std::vector(move(expressions)), serializer(*this){ size_t id =0; for (const Expression& e: expressions){ __registry.emplace(serializer.getId(e), id++); } } size_t ExpressionSerializerIntegral::size() const{ return PARENT::size(); } size_t ExpressionSerializerIntegral::count(const Expression& e) const { return (getIdOptional(e)? 1: 0); } ExpressionSerializerIntegral::const_iterator ExpressionSerializerIntegral::begin() const { return PARENT::begin(); } ExpressionSerializerIntegral::const_iterator ExpressionSerializerIntegral::end() const { return PARENT::end(); } size_t ExpressionSerializerIntegral::getId(const Expression& e) const{ - const auto& exprPacked = serializer.getIdOptional(e); + const OptionalPackedExpression exprPacked = serializer.getIdOptional(e); assert(exprPacked); return __registry.at(*exprPacked); } boost::optional ExpressionSerializerIntegral::getIdOptional(const Expression& e) const{ - const auto& exprPacked = serializer.getIdOptional(e); + const OptionalPackedExpression exprPacked = serializer.getIdOptional(e); if (!exprPacked){ return boost::none; } return __registry.at(*exprPacked); } const Expression& ExpressionSerializerIntegral::get(size_t id) const{ return at(id); } void PackedExpression::operator<< (const std::pair& value){ static const size_t sizeSizeT = sizeof(size_t); const size_t& id = value.first; const size_t& range = value.second; int countSufficientBits = range <=1? 0 : ceil(log2(range)); if (0 < countRemainedBits && countRemainedBits < countSufficientBits) { size_t* tail = reinterpret_cast(__storage + size- sizeSizeT); (*tail) += id >> (countSufficientBits - countRemainedBits); countSufficientBits-=countRemainedBits; countRemainedBits = 0; } if (countRemainedBits == 0) { if (countSufficientBits == 0) return; char* __storageNew = new char[size+sizeSizeT]; std::memcpy (__storageNew, __storage, size); std::memset(__storageNew + size, 0, sizeSizeT); delete[] __storage; __storage = __storageNew; size += sizeSizeT; countRemainedBits = 8 * sizeSizeT; } if (countRemainedBits >= countSufficientBits) { size_t* tail = reinterpret_cast(__storage + size- sizeSizeT); (*tail) += id << (countRemainedBits - countSufficientBits); countRemainedBits -= countSufficientBits; return; } assert("Unreachable block"); } + #if BOOST_VERSION <= 105500 +PackedExpression::PackedExpression(const PackedExpression& other){ + __storage = other.__storage; + size = other.size; + countRemainedBits = other.countRemainedBits; +} + #endif + PackedExpression::PackedExpression(PackedExpression&& other){ __storage = other.__storage; size = other.size; countRemainedBits = other.countRemainedBits; other.__storage = nullptr; } bool PackedExpression::operator==(const PackedExpression& other) const{ if (size == other.size && countRemainedBits == other.countRemainedBits){ return std::memcmp(__storage, other.__storage, size) == 0 ; } return false; } bool PackedExpression::operator<(const PackedExpression& other) const{ if (size < other.size) { return true; } if (countRemainedBits < other.countRemainedBits) return true; if (size == other.size && countRemainedBits == other.countRemainedBits){ return std::memcmp(__storage, other.__storage, size) < 0 ; } return false; } bool PackedExpression::operator!=(const PackedExpression& other) const{ return ! ((*this) == other); } PackedExpression::~PackedExpression() { delete[] __storage; } //PackedExpression::PackedExpression (const PackedExpression& other) // : size(other.size), countRemainedBits(other.countRemainedBits) //{ // __storage = new char[size]; // std::memcpy (__storage, other.__storage, size); //} -} /* namespace xreate */ +} /* namespace xreate */ \ No newline at end of file diff --git a/cpp/src/serialization/expressionserializer.h b/cpp/src/serialization/expressionserializer.h index 9acf8c4..52daba8 100644 --- a/cpp/src/serialization/expressionserializer.h +++ b/cpp/src/serialization/expressionserializer.h @@ -1,103 +1,111 @@ /* * expressionserializer.h * * Created on: Jan 4, 2016 * Author: pgess */ #ifndef SRC_EXPRESSIONSERIALIZER_H_ #define SRC_EXPRESSIONSERIALIZER_H_ #include "ast.h" #include #include +#include namespace xreate { struct PackedExpression{ PackedExpression(){}; PackedExpression(PackedExpression&& other); + + #if BOOST_VERSION <= 105500 + PackedExpression (const PackedExpression&); + + #else + PackedExpression (const PackedExpression&)=delete; + #endif + ~PackedExpression(); void operator<< (const std::pair& value); char* operator*(){return __storage;} bool operator==(const PackedExpression& other) const; bool operator!=(const PackedExpression& other) const; bool operator<(const PackedExpression& other) const; private: - PackedExpression (const PackedExpression&)=delete; PackedExpression& operator=(const PackedExpression&)=delete; PackedExpression& operator=(PackedExpression&&)=delete; char* __storage = nullptr; size_t size =0; unsigned char countRemainedBits =0; }; typedef boost::optional OptionalPackedExpression; class ExpressionSerializerPrivate; class ExpressionSerializer { public: template ExpressionSerializer(const Container& source): ExpressionSerializer(){ for (const Expression& e: source) { registerExpression(e); } } template ExpressionSerializer(const Container& source, Transformer op): ExpressionSerializer(){ for (const typename Container::value_type& e: source) { registerExpression(op(e)); } } ExpressionSerializer(ExpressionSerializer&& other) : strategy(other.strategy) {other.strategy = 0; } virtual ~ExpressionSerializer(); PackedExpression getId(const Expression& e); OptionalPackedExpression getIdOptional(const Expression& e) const; private: ExpressionSerializerPrivate* strategy; void registerExpression(const Expression&e); ExpressionSerializer(); }; class ExpressionSerializerIntegral: private std::vector{ typedef std::vector PARENT; public: ExpressionSerializerIntegral(); ExpressionSerializerIntegral(const std::vector&& expressions); template ExpressionSerializerIntegral(Iterator first, Iterator last) : ExpressionSerializerIntegral(std::vector(first, last)){} ExpressionSerializerIntegral(ExpressionSerializerIntegral&& other) : PARENT(std::move(other)), __registry(std::move(other.__registry)), serializer(std::move(other.serializer)){} size_t getId(const Expression& e) const; boost::optional getIdOptional(const Expression& e) const; const Expression& get(size_t id) const; size_t size() const; size_t count(const Expression& e) const; ExpressionSerializerIntegral::const_iterator begin() const; ExpressionSerializerIntegral::const_iterator end() const; private: ExpressionSerializerIntegral(const ExpressionSerializerIntegral&)=delete; std::map __registry; ExpressionSerializer serializer; }; } /* namespace xreate */ -#endif /* SRC_EXPRESSIONSERIALIZER_H_ */ +#endif /* SRC_EXPRESSIONSERIALIZER_H_ */ \ No newline at end of file diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index e980a74..25f9a64 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -1,18 +1,25 @@ cmake_minimum_required(VERSION 2.8.11) project(xreate-tests) find_package(GTest REQUIRED) INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS}) INCLUDE_DIRECTORIES("/usr/include/libxml2") INCLUDE_DIRECTORIES($) # TESTS #========================= +FIND_PACKAGE (LLVM REQUIRED) +message("LLVM_LIBRARY_DIRS: " ${LLVM_LIBRARY_DIRS}) +link_directories(${LLVM_LIBRARY_DIRS}) + +set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug) +link_directories(${LIBCLASP_PATH}) + aux_source_directory(. TEST_FILES) add_executable(${PROJECT_NAME} ${TEST_FILES}) target_link_libraries(${PROJECT_NAME} xreate ${GTEST_LIBRARIES} pthread xml2 gcov) add_custom_target (coverage COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh WORKING_DIRECTORY ${CMAKE_BINARY_DIR})