/// \file ControlFlowEdgesGraph.cpp // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/GraphWriter.h" #include "revng/Support/DOTGraphTraits.h" #include "revng/Support/IRHelpers.h" #include "revng/ValueMaterializer/ControlFlowEdgesGraph.h" using namespace llvm; std::string ControlFlowEdgesNode::toString() const { revng_assert(Source != nullptr); std::string Result = getName(Source); if (Destination != nullptr) Result += " -> " + getName(Destination); return Result; } void ControlFlowEdgesGraph::dump() const { WriteGraph(this, "cfeg"); } using BlockSet = SmallPtrSetImpl; ControlFlowEdgesGraph ControlFlowEdgesGraph::fromNodeSet(const BlockSet &NodeSet) { using namespace llvm; ControlFlowEdgesGraph Result; auto GetNode = [&Result](BasicBlock *BB) -> Node * { auto It = Result.NodeMap.find(BB); if (It != Result.NodeMap.end()) return It->second; else return Result.NodeMap[BB] = Result.addNode(BB); }; // Create nodes for blocks for (BasicBlock *BB : NodeSet) { // Get/create node for block Node *Source = GetNode(BB); for (BasicBlock *Destination : successors(BB)) { if (NodeSet.contains(Destination)) { // Create node representing the edge on the CFG and connect it Node *EdgeNode = Result.addNode(BB, Destination); Source->addSuccessor(EdgeNode); EdgeNode->addSuccessor(GetNode(Destination)); } } } return Result; } class HighlightInstructions : public AssemblyAnnotationWriter { public: using InstructionSet = SmallPtrSetImpl; private: const InstructionSet &Interesting; bool Open = false; public: HighlightInstructions(const InstructionSet &Interesting) : Interesting(Interesting) {} ~HighlightInstructions() { revng_assert(not Open); } public: void emitInstructionAnnot(const Instruction *I, formatted_raw_ostream &Stream) final { if (Open) { Open = false; Stream << ""; } if (Interesting.contains(I)) { Open = true; Stream << ""; } } void finish(raw_ostream &Stream) { if (Open) { Open = false; Stream << ""; } } }; using CFEG = ControlFlowEdgesGraph; /// Put Source and Destination BasicBlocks in the node label std::string DOTGraphTraits::getNodeLabel(const CFEG::Node *Node, const CFEG *Graph) { std::string Result; Result += ""; if (Node->Destination != nullptr) { Result += "From " + getName(Node->Source) + HTMLNewline; Result += " to " + getName(Node->Destination); } else { { HighlightInstructions Highlighter(Graph->interstingInstructions()); raw_string_ostream Stream(Result); Node->Source->print(Stream, &Highlighter); Highlighter.finish(Stream); } replaceAll(Result, "\n", HTMLNewline); } Result += ""; return Result; } std::string DOTGraphTraits::getNodeAttributes(const CFEG::Node *Node, const CFEG *Graph) { std::string Result; if (Node->Destination != nullptr) Result += "style=dashed"; return Result; }