#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include #include #include #include "revng/MFP/MFP.h" #include "revng/MFP/SetLattices.h" #include "revng/RestructureCFG/ASTNode.h" #include "revng/RestructureCFG/BasicBlockNodeBB.h" // TODO: move the definition of this object in an unique place, to avoid using // an extern declaration extern Logger<> CombLogger; template using RegionCFGEdge = typename BasicBlockNode::EdgeDescriptor; template inline void moveEdgeTarget(RegionCFGEdge Edge, BasicBlockNode *NewTarget) { auto &SuccEdgeWithLabels = Edge.first->getSuccessorEdge(Edge.second); SuccEdgeWithLabels.first = NewTarget; auto PredEdgeWithLabels = Edge.second->extractPredecessorEdge(Edge.first); NewTarget->addLabeledPredecessor(PredEdgeWithLabels); } template inline void moveEdgeSource(RegionCFGEdge Edge, BasicBlockNode *NewSource) { auto SuccEdgeWithLabels = Edge.first->extractSuccessorEdge(Edge.second); NewSource->addLabeledSuccessor(SuccEdgeWithLabels); auto &PredEdgeWithLabels = Edge.second->getPredecessorEdge(Edge.first); PredEdgeWithLabels.first = NewSource; } template inline void addEdge(std::pair New, const typename BBNodeT::EdgeInfo &EdgeInfos) { New.first->addLabeledSuccessor(std::make_pair(New.second, EdgeInfos)); New.second->addLabeledPredecessor(std::make_pair(New.first, EdgeInfos)); } template inline void addPlainEdge(std::pair New) { addEdge(New, typename BBNodeT::EdgeInfo()); } template inline typename BBNodeT::node_edgeinfo_pair extractLabeledEdge(std::pair Edge) { Edge.second->removePredecessor(Edge.first); return Edge.first->extractSuccessorEdge(Edge.second); } template inline void markEdgeInlined(std::pair Edge) { // TODO: Marking the edge as inlined by temporarily removing it from the graph // and re-inserting it could cause problems in reordering true/false // branches for conditional nodes. Consider adding a primitive for // getting a reference to the `EdgeInfo` struct of an edge without // having to remove it. // Take care of the predecessor edge. auto &EdgePairBack = Edge.second->getPredecessorEdge(Edge.first); EdgePairBack.second.Inlined = true; // Take care of the successor edge. auto &EdgePairForw = Edge.first->getSuccessorEdge(Edge.second); EdgePairForw.second.Inlined = true; // Ensure that the forward and backward edgeinfos carry the same information. // For this to work, we default the spaceship operator for having the equality // between EdgeInfo structs. revng_assert(EdgePairBack.second == EdgePairForw.second); } template inline bool isEdgeInlined(std::pair Edge) { // Take care of the backward edge. auto EdgePairBack = Edge.second->getPredecessorEdge(Edge.first); // Take care of the forward edge. auto EdgePairForw = Edge.first->getSuccessorEdge(Edge.second); bool InlinedForw = EdgePairForw.second.Inlined; // Ensure that the forward and backward edgeinfos carry the same information. revng_assert(EdgePairBack.second == EdgePairForw.second); return InlinedForw; } template inline bool containsSmallVector(llvm::SmallVectorImpl *> &Vec, BasicBlockNode *Node) { for (BasicBlockNode *N : Vec) { if (N == Node) { return true; } } return false; } template using Stack = std::vector *, size_t>>; template inline bool alreadyOnStack(Stack &Stack, BasicBlockNode *Node) { for (auto &StackElem : Stack) { if (StackElem.first == Node) { return true; } } return false; } template using BasicBlockNodeTSet = typename BasicBlockNode::BBNodeSet; template inline bool alreadyOnStackQuick(BasicBlockNodeTSet &StackSet, BasicBlockNode *Node) { return StackSet.contains(Node); } template class CFGDumper { size_t GraphLogCounter; const RegionCFG &Graph; const std::string FunctionName; const std::string RegionName; const std::string FolderName; public: CFGDumper(const RegionCFG &Graph, const std::string &FunctionName, const std::string &RegionName, const std::string &FolderName) : GraphLogCounter(0), Graph(Graph), FunctionName(FunctionName), RegionName(RegionName), FolderName(FolderName) {} void log(const std::string &FilenameSuffix) { if (CombLogger.isEnabled()) { Graph.dumpCFGOnFile(FunctionName, FolderName, "region-" + RegionName + "-step-" + std::to_string(GraphLogCounter++) + FilenameSuffix); } } };