/// \file ScopeGraphAlgorithms.cpp /// Helpers for the `ScopeGraph` building /// // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "llvm/ADT/SetVector.h" #include "llvm/IR/BasicBlock.h" #include "revng/ADT/ReversePostOrderTraversal.h" #include "revng/RestructureCFG/ScopeGraphAlgorithms.h" #include "revng/RestructureCFG/ScopeGraphGraphTraits.h" using namespace llvm; SmallSetVector getScopeGraphSuccessors(BasicBlock *N) { // We employ a `SetVector` so that we do not take into account // multiplicity for edges out of a conditional SmallSetVector ConditionalSuccessors; for (BasicBlock *Successor : children>(N)) { ConditionalSuccessors.insert(Successor); } return ConditionalSuccessors; } SmallSetVector getScopeGraphPredecessors(BasicBlock *N) { // It is important that we use a `SetVector` here in order to // deduplicate the successors outputted by the `llvm::children` range // iterator SmallSetVector Predecessors; for (auto *Predecessor : children>>(N)) { Predecessors.insert(Predecessor); } return Predecessors; } SmallVector getNodesInScope(BasicBlock *ScopeEntryBlock, BasicBlock *PostDominator) { // We exploit the `Visited` set, by passing it to // `ReversePostOrderTraversalExt`, in order to stop the visit at the // `PostDominator` std::set Visited; Visited.insert(PostDominator); // We collect all the nodes between the `Conditional` and its // immediate postdominator, by using the `ReversePostOrderTraversalExt` SmallVector NodesToProcess; for (BasicBlock *RPONode : ReversePostOrderTraversalExt>(ScopeEntryBlock, Visited)) { NodesToProcess.push_back(RPONode); } // From the collected nodes, we need to remove the first node, which // corresponds to the `Conditional`, which should not be processed in this // round revng_assert(NodesToProcess.front() == ScopeEntryBlock); NodesToProcess.erase(NodesToProcess.begin()); return NodesToProcess; }