Files
revng-revng/lib/ValueMaterializer/ControlFlowEdgesGraph.cpp
Ivan Krysak 7d235f4fd0 Enforce licence header consistency
Also do some basic cleanup: capitalize first letters, add `.`
at the end of the sentences, and so on.
2023-07-03 15:23:10 +00:00

136 lines
3.3 KiB
C++

/// \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<BasicBlock *>;
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<Instruction *>;
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 << "</FONT>";
}
if (Interesting.contains(I)) {
Open = true;
Stream << "<FONT COLOR=\"RED\">";
}
}
void finish(raw_ostream &Stream) {
if (Open) {
Open = false;
Stream << "</FONT>";
}
}
};
using CFEG = ControlFlowEdgesGraph;
/// Put Source and Destination BasicBlocks in the node label
std::string DOTGraphTraits<const CFEG *>::getNodeLabel(const CFEG::Node *Node,
const CFEG *Graph) {
std::string Result;
Result += "<FONT FACE=\"monospace\">";
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 += "</FONT>";
return Result;
}
std::string
DOTGraphTraits<const CFEG *>::getNodeAttributes(const CFEG::Node *Node,
const CFEG *Graph) {
std::string Result;
if (Node->Destination != nullptr)
Result += "style=dashed";
return Result;
}