#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include #include "revng/Support/IRHelpers.h" namespace llvm { class BasicBlock; } /// Node of a CustomCFG /// /// A simple container for nodes and a set of successors and predecessors. class CustomCFGNode { public: using links_container = std::vector; using links_iterator = typename links_container::iterator; using links_const_iterator = typename links_container::const_iterator; using links_range = llvm::iterator_range; using links_const_range = llvm::iterator_range; private: /// List of successors links_container Successors; /// List of predecessors links_container Predecessors; /// Reference to the corresponding basic block llvm::BasicBlock *BB; public: CustomCFGNode(llvm::BasicBlock *BB) : BB(BB) {} void addSuccessor(CustomCFGNode *Node) { Successors.push_back(Node); } void addPredecessor(CustomCFGNode *Node) { Predecessors.push_back(Node); } bool hasSuccessors() const { return Successors.size() != 0; } size_t successor_size() const { return Successors.size(); } links_const_range successors() const { return llvm::make_range(succ_begin(), succ_end()); } links_range successors() { return llvm::make_range(succ_begin(), succ_end()); } links_const_iterator succ_begin() const { return Successors.begin(); } links_const_iterator succ_end() const { return Successors.end(); } links_iterator succ_begin() { return Successors.begin(); } links_iterator succ_end() { return Successors.end(); } bool hasPredecessors() const { return Predecessors.size() != 0; } size_t predecessor_size() const { return Predecessors.size(); } links_const_range predecessors() const { return llvm::make_range(pred_begin(), pred_end()); } links_const_iterator pred_begin() const { return Predecessors.begin(); } links_const_iterator pred_end() const { return Predecessors.end(); } links_range predecessors() { return llvm::make_range(pred_begin(), pred_end()); } links_iterator pred_begin() { return Predecessors.begin(); } links_iterator pred_end() { return Predecessors.end(); } llvm::BasicBlock *block() const { return BB; } void dump() const debug_function { dump(dbg, ""); } template void dump(T &Output, const char *Prefix) const { Output << Prefix << "Predecessors:\n"; for (CustomCFGNode *Predecessor : predecessors()) Output << Prefix << " " << getName(Predecessor->block()) << "\n"; Output << "\n"; Output << Prefix << "Successors:\n"; for (CustomCFGNode *Successor : successors()) Output << Prefix << " " << getName(Successor->block()) << "\n"; Output << "\n"; } }; /// A CFG representing a custom view on the actual CFG of a function /// /// This class implements `GraphTraits`. class CustomCFG { public: void clear() { Blocks.clear(); } /// Populate the list of predecessors of each node based on the successors void buildBackLinks() { for (auto &P : Blocks) for (CustomCFGNode *Successor : P.second.successors()) Successor->addPredecessor(&P.second); } bool hasNode(const llvm::BasicBlock *BB) const { return Blocks.contains(BB); } CustomCFGNode *getNode(llvm::BasicBlock *BB) { auto It = Blocks.find(BB); if (It != Blocks.end()) return &It->second; else return &Blocks.insert({ BB, CustomCFGNode(BB) }).first->second; } const CustomCFGNode *getNode(const llvm::BasicBlock *BB) const { return &Blocks.at(BB); } void dump() const debug_function { dump(dbg); } template void dump(T &Output) const { for (auto &P : Blocks) { const llvm::BasicBlock *Block = P.first; const CustomCFGNode *Node = &P.second; Output << getName(Block) << ":\n"; Node->dump(Output, " "); } } private: std::map Blocks; }; // Provide graph traits for usage with, e.g., llvm::ReversePostOrderTraversal namespace llvm { template<> struct GraphTraits { using NodeType = CustomCFGNode; using ChildIteratorType = CustomCFGNode::links_iterator; static NodeType *getEntryNode(CustomCFGNode *BB) { return BB; } static inline ChildIteratorType child_begin(CustomCFGNode *N) { return N->successors().begin(); } static inline ChildIteratorType child_end(CustomCFGNode *N) { return N->successors().end(); } }; } // namespace llvm