mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +00:00
Add viewCFG() and viewCFGOnly() APIs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14679 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cf617ddd98
commit
71bf404e9b
@ -135,6 +135,21 @@ public:
|
|||||||
///
|
///
|
||||||
void print(std::ostream &OS) const;
|
void print(std::ostream &OS) const;
|
||||||
|
|
||||||
|
/// viewCFG - This function is meant for use from the debugger. You can just
|
||||||
|
/// say 'call F->viewCFG()' and a ghostview window should pop up from the
|
||||||
|
/// program, displaying the CFG of the current function with the code for each
|
||||||
|
/// basic block inside. This depends on there being a 'dot' and 'gv' program
|
||||||
|
/// in your path.
|
||||||
|
///
|
||||||
|
void viewCFG() const;
|
||||||
|
|
||||||
|
/// viewCFGOnly - This function is meant for use from the debugger. It works
|
||||||
|
/// just like viewCFG, but it does not include the contents of basic blocks
|
||||||
|
/// into the nodes, just the label. If you are only interested in the CFG
|
||||||
|
/// this can make the graph smaller.
|
||||||
|
///
|
||||||
|
void viewCFGOnly() const;
|
||||||
|
|
||||||
/// dump - Print the current MachineFunction to cerr, useful for debugger use.
|
/// dump - Print the current MachineFunction to cerr, useful for debugger use.
|
||||||
///
|
///
|
||||||
void dump() const;
|
void dump() const;
|
||||||
@ -206,6 +221,57 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//===--------------------------------------------------------------------===//
|
||||||
|
// GraphTraits specializations for function basic block graphs (CFGs)
|
||||||
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Provide specializations of GraphTraits to be able to treat a
|
||||||
|
// machine function as a graph of machine basic blocks... these are
|
||||||
|
// the same as the machine basic block iterators, except that the root
|
||||||
|
// node is implicitly the first node of the function.
|
||||||
|
//
|
||||||
|
template <> struct GraphTraits<MachineFunction*> :
|
||||||
|
public GraphTraits<MachineBasicBlock*> {
|
||||||
|
static NodeType *getEntryNode(MachineFunction *F) {
|
||||||
|
return &F->front();
|
||||||
|
}
|
||||||
|
|
||||||
|
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||||
|
typedef MachineFunction::iterator nodes_iterator;
|
||||||
|
static nodes_iterator nodes_begin(MachineFunction *F) { return F->begin(); }
|
||||||
|
static nodes_iterator nodes_end (MachineFunction *F) { return F->end(); }
|
||||||
|
};
|
||||||
|
template <> struct GraphTraits<const MachineFunction*> :
|
||||||
|
public GraphTraits<const MachineBasicBlock*> {
|
||||||
|
static NodeType *getEntryNode(const MachineFunction *F) {
|
||||||
|
return &F->front();
|
||||||
|
}
|
||||||
|
|
||||||
|
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||||
|
typedef MachineFunction::const_iterator nodes_iterator;
|
||||||
|
static nodes_iterator nodes_begin(const MachineFunction *F) { return F->begin(); }
|
||||||
|
static nodes_iterator nodes_end (const MachineFunction *F) { return F->end(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Provide specializations of GraphTraits to be able to treat a function as a
|
||||||
|
// graph of basic blocks... and to walk it in inverse order. Inverse order for
|
||||||
|
// a function is considered to be when traversing the predecessor edges of a BB
|
||||||
|
// instead of the successor edges.
|
||||||
|
//
|
||||||
|
template <> struct GraphTraits<Inverse<MachineFunction*> > :
|
||||||
|
public GraphTraits<Inverse<MachineBasicBlock*> > {
|
||||||
|
static NodeType *getEntryNode(Inverse<MachineFunction*> G) {
|
||||||
|
return &G.Graph->front();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <> struct GraphTraits<Inverse<const MachineFunction*> > :
|
||||||
|
public GraphTraits<Inverse<const MachineBasicBlock*> > {
|
||||||
|
static NodeType *getEntryNode(Inverse<const MachineFunction *> G) {
|
||||||
|
return &G.Graph->front();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,7 +26,10 @@
|
|||||||
#include "llvm/iOther.h"
|
#include "llvm/iOther.h"
|
||||||
#include "llvm/Type.h"
|
#include "llvm/Type.h"
|
||||||
#include "Support/LeakDetector.h"
|
#include "Support/LeakDetector.h"
|
||||||
|
#include "Support/GraphWriter.h"
|
||||||
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@ -140,6 +143,80 @@ void MachineFunction::print(std::ostream &OS) const {
|
|||||||
OS << "\n# End machine code for " << Fn->getName () << "().\n\n";
|
OS << "\n# End machine code for " << Fn->getName () << "().\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CFGOnly flag - This is used to control whether or not the CFG graph printer
|
||||||
|
/// prints out the contents of basic blocks or not. This is acceptable because
|
||||||
|
/// this code is only really used for debugging purposes.
|
||||||
|
///
|
||||||
|
static bool CFGOnly = false;
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
template<>
|
||||||
|
struct DOTGraphTraits<const MachineFunction*> : public DefaultDOTGraphTraits {
|
||||||
|
static std::string getGraphName(const MachineFunction *F) {
|
||||||
|
return "CFG for '" + F->getFunction()->getName() + "' function";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string getNodeLabel(const MachineBasicBlock *Node,
|
||||||
|
const MachineFunction *Graph) {
|
||||||
|
if (CFGOnly && Node->getBasicBlock() &&
|
||||||
|
!Node->getBasicBlock()->getName().empty())
|
||||||
|
return Node->getBasicBlock()->getName() + ":";
|
||||||
|
|
||||||
|
std::ostringstream Out;
|
||||||
|
if (CFGOnly) {
|
||||||
|
Out << Node->getNumber() << ':';
|
||||||
|
return Out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
Node->print(Out);
|
||||||
|
|
||||||
|
std::string OutStr = Out.str();
|
||||||
|
if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
|
||||||
|
|
||||||
|
// Process string output to make it nicer...
|
||||||
|
for (unsigned i = 0; i != OutStr.length(); ++i)
|
||||||
|
if (OutStr[i] == '\n') { // Left justify
|
||||||
|
OutStr[i] = '\\';
|
||||||
|
OutStr.insert(OutStr.begin()+i+1, 'l');
|
||||||
|
}
|
||||||
|
return OutStr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFunction::viewCFG() const
|
||||||
|
{
|
||||||
|
std::string Filename = "/tmp/cfg." + getFunction()->getName() + ".dot";
|
||||||
|
std::cerr << "Writing '" << Filename << "'... ";
|
||||||
|
std::ofstream F(Filename.c_str());
|
||||||
|
|
||||||
|
if (!F) {
|
||||||
|
std::cerr << " error opening file for writing!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteGraph(F, this);
|
||||||
|
F.close();
|
||||||
|
std::cerr << "\n";
|
||||||
|
|
||||||
|
std::cerr << "Running 'dot' program... " << std::flush;
|
||||||
|
if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename
|
||||||
|
+ " > /tmp/cfg.tempgraph.ps").c_str())) {
|
||||||
|
std::cerr << "Error running dot: 'dot' not in path?\n";
|
||||||
|
} else {
|
||||||
|
std::cerr << "\n";
|
||||||
|
system("gv /tmp/cfg.tempgraph.ps");
|
||||||
|
}
|
||||||
|
system(("rm " + Filename + " /tmp/cfg.tempgraph.ps").c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MachineFunction::viewCFGOnly() const
|
||||||
|
{
|
||||||
|
CFGOnly = true;
|
||||||
|
viewCFG();
|
||||||
|
CFGOnly = false;
|
||||||
|
}
|
||||||
|
|
||||||
// The next two methods are used to construct and to retrieve
|
// The next two methods are used to construct and to retrieve
|
||||||
// the MachineCodeForFunction object for the given function.
|
// the MachineCodeForFunction object for the given function.
|
||||||
// construct() -- Allocates and initializes for a given function and target
|
// construct() -- Allocates and initializes for a given function and target
|
||||||
@ -405,4 +482,3 @@ MachineFunctionInfo::pushTempValue(unsigned size)
|
|||||||
void MachineFunctionInfo::popAllTempValues() {
|
void MachineFunctionInfo::popAllTempValues() {
|
||||||
resetTmpAreaSize(); // clear tmp area to reuse
|
resetTmpAreaSize(); // clear tmp area to reuse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user