mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
7d235f4fd0
Also do some basic cleanup: capitalize first letters, add `.` at the end of the sentences, and so on.
136 lines
3.3 KiB
C++
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;
|
|
}
|