mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Convert internal representation to use DAG. This gives us more flexibility and enables future improvements.
llvm-svn: 50724
This commit is contained in:
parent
cc7550a68c
commit
72590c9cc7
@ -15,6 +15,10 @@ class Tool<list<dag> l> {
|
||||
list<dag> properties = l;
|
||||
}
|
||||
|
||||
// Special Tool instance - root of all toolchains
|
||||
|
||||
def root : Tool<[]>;
|
||||
|
||||
// Possible Tool properties
|
||||
|
||||
def in_language;
|
||||
@ -52,12 +56,13 @@ class LanguageMap<list<LangToSuffixes> lst> {
|
||||
list<LangToSuffixes> map = lst;
|
||||
}
|
||||
|
||||
// Toolchain classes
|
||||
// Compilation graph
|
||||
|
||||
class ToolChain <list<Tool> lst> {
|
||||
list <Tool> tools = lst;
|
||||
class Edge<Tool t1, Tool t2> {
|
||||
Tool a = t1;
|
||||
Tool b = t2;
|
||||
}
|
||||
|
||||
class ToolChains <list<ToolChain> lst> {
|
||||
list<ToolChain> chains = lst;
|
||||
class CompilationGraph<list<Edge> lst> {
|
||||
list<Edge> edges = lst;
|
||||
}
|
||||
|
@ -14,46 +14,120 @@
|
||||
#include "CompilationGraph.h"
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/DOTGraphTraits.h"
|
||||
#include "llvm/Support/GraphWriter.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvmcc;
|
||||
|
||||
extern cl::list<std::string> InputFilenames;
|
||||
extern cl::opt<std::string> OutputFilename;
|
||||
|
||||
int llvmcc::CompilationGraph::Build (const sys::Path& tempDir) const {
|
||||
sys::Path In(InputFilenames.at(0)), Out;
|
||||
CompilationGraph::CompilationGraph() {
|
||||
NodesMap["root"] = Node(this);
|
||||
}
|
||||
|
||||
// Find out which language corresponds to the suffix of the first input file
|
||||
LanguageMap::const_iterator Lang = ExtsToLangs.find(In.getSuffix());
|
||||
Node& CompilationGraph::getNode(const std::string& ToolName) {
|
||||
nodes_map_type::iterator I = NodesMap.find(ToolName);
|
||||
if (I == NodesMap.end())
|
||||
throw std::runtime_error("Node " + ToolName + " is not in graph");
|
||||
return I->second;
|
||||
}
|
||||
|
||||
const Node& CompilationGraph::getNode(const std::string& ToolName) const {
|
||||
nodes_map_type::const_iterator I = NodesMap.find(ToolName);
|
||||
if (I == NodesMap.end())
|
||||
throw std::runtime_error("Node " + ToolName + " is not in graph!");
|
||||
return I->second;
|
||||
}
|
||||
|
||||
const std::string& CompilationGraph::getLanguage(const sys::Path& File) const {
|
||||
LanguageMap::const_iterator Lang = ExtsToLangs.find(File.getSuffix());
|
||||
if (Lang == ExtsToLangs.end())
|
||||
throw std::runtime_error("Unknown suffix!");
|
||||
throw std::runtime_error("Unknown suffix: " + File.getSuffix() + '!');
|
||||
return Lang->second;
|
||||
}
|
||||
|
||||
// Find the toolchain corresponding to this language
|
||||
ToolChainMap::const_iterator ToolsIt = ToolChains.find(Lang->second);
|
||||
if (ToolsIt == ToolChains.end())
|
||||
throw std::runtime_error("Unknown language!");
|
||||
ToolChain Tools = ToolsIt->second;
|
||||
const CompilationGraph::tools_vector_type&
|
||||
CompilationGraph::getToolsVector(const std::string& LangName) const
|
||||
{
|
||||
tools_map_type::const_iterator I = ToolsMap.find(LangName);
|
||||
if (I == ToolsMap.end())
|
||||
throw std::runtime_error("No tools corresponding to " + LangName
|
||||
+ " found!");
|
||||
return I->second;
|
||||
}
|
||||
|
||||
void CompilationGraph::insertVertex(const IntrusiveRefCntPtr<Tool> V) {
|
||||
if (!NodesMap.count(V->Name())) {
|
||||
Node N;
|
||||
N.OwningGraph = this;
|
||||
N.ToolPtr = V;
|
||||
NodesMap[V->Name()] = N;
|
||||
}
|
||||
}
|
||||
|
||||
void CompilationGraph::insertEdge(const std::string& A,
|
||||
const std::string& B) {
|
||||
// TOTHINK: check this at compile-time?
|
||||
if (B == "root")
|
||||
throw std::runtime_error("Edges back to the root are not allowed!"
|
||||
"Compilation graph should be acyclic!");
|
||||
|
||||
if (A == "root") {
|
||||
const Node& N = getNode(B);
|
||||
const std::string& InputLanguage = N.ToolPtr->InputLanguage();
|
||||
ToolsMap[InputLanguage].push_back(B);
|
||||
|
||||
// Needed to support iteration via GraphTraits.
|
||||
NodesMap["root"].Children.push_back(B);
|
||||
}
|
||||
else {
|
||||
Node& NA = getNode(A);
|
||||
// Check that there is a node at B.
|
||||
getNode(B);
|
||||
NA.Children.push_back(B);
|
||||
}
|
||||
}
|
||||
|
||||
// TOFIX: extend, add an ability to choose between different
|
||||
// toolchains, support more interesting graph topologies.
|
||||
int CompilationGraph::Build (const sys::Path& tempDir) const {
|
||||
PathVector JoinList;
|
||||
const Tool* JoinTool = 0;
|
||||
sys::Path In, Out;
|
||||
|
||||
// For each input file
|
||||
for (cl::list<std::string>::const_iterator B = InputFilenames.begin(),
|
||||
E = InputFilenames.end(); B != E; ++B) {
|
||||
In = sys::Path(*B);
|
||||
|
||||
// Pass input file through the toolchain
|
||||
for (ToolChain::const_iterator B = Tools.begin(), E = Tools.end();
|
||||
B != E; ++B) {
|
||||
// Get to the head of the toolchain.
|
||||
const tools_vector_type& TV = getToolsVector(getLanguage(In));
|
||||
if(TV.empty())
|
||||
throw std::runtime_error("Tool names vector is empty!");
|
||||
const Node* N = &getNode(*TV.begin());
|
||||
|
||||
const Tool* CurTool = B->getPtr();
|
||||
// Pass it through the chain until we bump into a Join node or a
|
||||
// node that says that it is the last.
|
||||
bool Last = false;
|
||||
while(!Last) {
|
||||
const Tool* CurTool = N->ToolPtr.getPtr();
|
||||
|
||||
// Is this the last step in the chain?
|
||||
if (llvm::next(B) == E || CurTool->IsLast()) {
|
||||
if(CurTool->IsJoin()) {
|
||||
JoinList.push_back(In);
|
||||
JoinTool = CurTool;
|
||||
break;
|
||||
}
|
||||
|
||||
// Is this the last tool?
|
||||
if (N->Children.empty() || CurTool->IsLast()) {
|
||||
Out.appendComponent(In.getBasename());
|
||||
Out.appendSuffix(CurTool->OutputSuffix());
|
||||
Last = true;
|
||||
}
|
||||
else {
|
||||
Out = tempDir;
|
||||
Out.appendComponent(In.getBasename());
|
||||
@ -65,24 +139,57 @@ int llvmcc::CompilationGraph::Build (const sys::Path& tempDir) const {
|
||||
if (CurTool->GenerateAction(In, Out).Execute() != 0)
|
||||
throw std::runtime_error("Tool returned error code!");
|
||||
|
||||
N = &getNode(*N->Children.begin());
|
||||
In = Out; Out.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Pass .o files to linker
|
||||
const Tool* JoinNode = (--Tools.end())->getPtr();
|
||||
if(JoinTool) {
|
||||
// If the final output name is empty, set it to "a.out"
|
||||
if (!OutputFilename.empty()) {
|
||||
Out = sys::Path(OutputFilename);
|
||||
}
|
||||
else {
|
||||
Out = sys::Path("a");
|
||||
Out.appendSuffix(JoinTool->OutputSuffix());
|
||||
}
|
||||
|
||||
// If the final output name is empty, set it to "a.out"
|
||||
if (!OutputFilename.empty()) {
|
||||
Out = sys::Path(OutputFilename);
|
||||
if (JoinTool->GenerateAction(JoinList, Out).Execute() != 0)
|
||||
throw std::runtime_error("Tool returned error code!");
|
||||
}
|
||||
else {
|
||||
Out = sys::Path("a");
|
||||
Out.appendSuffix(JoinNode->OutputSuffix());
|
||||
}
|
||||
|
||||
if (JoinNode->GenerateAction(JoinList, Out).Execute() != 0)
|
||||
throw std::runtime_error("Tool returned error code!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
template <>
|
||||
struct DOTGraphTraits<llvmcc::CompilationGraph*>
|
||||
: public DefaultDOTGraphTraits
|
||||
{
|
||||
|
||||
template<typename GraphType>
|
||||
static std::string getNodeLabel(const Node* N, const GraphType&) {
|
||||
if (N->ToolPtr)
|
||||
return N->ToolPtr->Name();
|
||||
else
|
||||
return "root";
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
void CompilationGraph::writeGraph() {
|
||||
std::ofstream O("CompilationGraph.dot");
|
||||
|
||||
if(O.good()) {
|
||||
llvm::WriteGraph(this, "CompilationGraph");
|
||||
O.close();
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("");
|
||||
}
|
||||
}
|
||||
|
||||
void CompilationGraph::viewGraph() {
|
||||
llvm::ViewGraph(this, "CompilationGraph");
|
||||
}
|
||||
|
@ -17,20 +17,196 @@
|
||||
#include "AutoGenerated.h"
|
||||
#include "Tool.h"
|
||||
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/iterator"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/System/Path.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace llvmcc {
|
||||
|
||||
typedef std::vector<llvm::IntrusiveRefCntPtr<Tool> > ToolChain;
|
||||
typedef llvm::StringMap<ToolChain> ToolChainMap;
|
||||
class CompilationGraph;
|
||||
|
||||
struct CompilationGraph {
|
||||
ToolChainMap ToolChains;
|
||||
struct Node {
|
||||
typedef llvm::SmallVector<std::string, 3> sequence_type;
|
||||
|
||||
Node() {}
|
||||
Node(CompilationGraph* G) : OwningGraph(G) {}
|
||||
Node(CompilationGraph* G, Tool* T) : OwningGraph(G), ToolPtr(T) {}
|
||||
|
||||
// Needed to implement NodeChildIterator/GraphTraits
|
||||
CompilationGraph* OwningGraph;
|
||||
// The corresponding Tool.
|
||||
llvm::IntrusiveRefCntPtr<Tool> ToolPtr;
|
||||
// Links to children.
|
||||
sequence_type Children;
|
||||
};
|
||||
|
||||
// This can be generalised to something like value_iterator for maps
|
||||
class NodesIterator : public llvm::StringMap<Node>::iterator {
|
||||
typedef llvm::StringMap<Node>::iterator super;
|
||||
typedef NodesIterator ThisType;
|
||||
typedef Node* pointer;
|
||||
typedef Node& reference;
|
||||
|
||||
public:
|
||||
NodesIterator(super I) : super(I) {}
|
||||
|
||||
inline reference operator*() const {
|
||||
return super::operator->()->second;
|
||||
}
|
||||
inline pointer operator->() const {
|
||||
return &super::operator->()->second;
|
||||
}
|
||||
};
|
||||
|
||||
class CompilationGraph {
|
||||
typedef llvm::StringMap<Node> nodes_map_type;
|
||||
typedef llvm::SmallVector<std::string, 3> tools_vector_type;
|
||||
typedef llvm::StringMap<tools_vector_type> tools_map_type;
|
||||
|
||||
// Map from file extensions to language names.
|
||||
LanguageMap ExtsToLangs;
|
||||
// Map from language names to lists of tool names.
|
||||
tools_map_type ToolsMap;
|
||||
// Map from tool names to Tool objects.
|
||||
nodes_map_type NodesMap;
|
||||
|
||||
public:
|
||||
|
||||
CompilationGraph();
|
||||
|
||||
// insertVertex - insert a new node into the graph.
|
||||
void insertVertex(const llvm::IntrusiveRefCntPtr<Tool> T);
|
||||
|
||||
// insertEdge - Insert a new edge into the graph. This function
|
||||
// assumes that both A and B have been already inserted.
|
||||
void insertEdge(const std::string& A, const std::string& B);
|
||||
|
||||
// Build - Build the target(s) from the set of the input
|
||||
// files. Command-line options are passed implicitly as global
|
||||
// variables.
|
||||
int Build(llvm::sys::Path const& tempDir) const;
|
||||
|
||||
/// viewGraph - This function is meant for use from the debugger.
|
||||
/// You can just say 'call G->viewGraph()' and a ghostview window
|
||||
/// should pop up from the program, displaying the compilation
|
||||
/// graph. This depends on there being a 'dot' and 'gv' program
|
||||
/// in your path.
|
||||
void viewGraph();
|
||||
|
||||
/// Write a CompilationGraph.dot file.
|
||||
void writeGraph();
|
||||
|
||||
// GraphTraits support
|
||||
|
||||
typedef NodesIterator nodes_iterator;
|
||||
|
||||
nodes_iterator nodes_begin() {
|
||||
return NodesIterator(NodesMap.begin());
|
||||
}
|
||||
|
||||
nodes_iterator nodes_end() {
|
||||
return NodesIterator(NodesMap.end());
|
||||
}
|
||||
|
||||
// Return a reference to the node correponding to the given tool
|
||||
// name. Throws std::runtime_error in case of error.
|
||||
Node& getNode(const std::string& ToolName);
|
||||
const Node& getNode(const std::string& ToolName) const;
|
||||
|
||||
// Auto-generated function.
|
||||
friend void PopulateCompilationGraph(CompilationGraph&);
|
||||
|
||||
private:
|
||||
// Helper function - find out which language corresponds to the
|
||||
// suffix of this file
|
||||
const std::string& getLanguage(const llvm::sys::Path& File) const;
|
||||
|
||||
// Return a reference to the tool names list correponding to the
|
||||
// given language name. Throws std::runtime_error in case of
|
||||
// error.
|
||||
const tools_vector_type& getToolsVector(const std::string& LangName) const;
|
||||
};
|
||||
|
||||
// Auxiliary class needed to implement GraphTraits support.
|
||||
class NodeChildIterator : public bidirectional_iterator<Node, ptrdiff_t> {
|
||||
typedef NodeChildIterator ThisType;
|
||||
typedef Node::sequence_type::iterator iterator;
|
||||
|
||||
CompilationGraph* OwningGraph;
|
||||
iterator KeyIter;
|
||||
public:
|
||||
typedef Node* pointer;
|
||||
typedef Node& reference;
|
||||
|
||||
NodeChildIterator(Node* N, iterator I) :
|
||||
OwningGraph(N->OwningGraph), KeyIter(I) {}
|
||||
|
||||
const ThisType& operator=(const ThisType& I) {
|
||||
assert(OwningGraph == I.OwningGraph);
|
||||
KeyIter = I.KeyIter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator==(const ThisType& I) const
|
||||
{ return KeyIter == I.KeyIter; }
|
||||
inline bool operator!=(const ThisType& I) const
|
||||
{ return KeyIter != I.KeyIter; }
|
||||
|
||||
inline pointer operator*() const {
|
||||
return &OwningGraph->getNode(*KeyIter);
|
||||
}
|
||||
inline pointer operator->() const {
|
||||
return &OwningGraph->getNode(*KeyIter);
|
||||
}
|
||||
|
||||
ThisType& operator++() { ++KeyIter; return *this; } // Preincrement
|
||||
ThisType operator++(int) { // Postincrement
|
||||
ThisType tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline ThisType& operator--() { --KeyIter; return *this; } // Predecrement
|
||||
inline ThisType operator--(int) { // Postdecrement
|
||||
ThisType tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
template <>
|
||||
struct GraphTraits<llvmcc::CompilationGraph*> {
|
||||
typedef llvmcc::CompilationGraph GraphType;
|
||||
typedef llvmcc::Node NodeType;
|
||||
typedef llvmcc::NodeChildIterator ChildIteratorType;
|
||||
|
||||
static NodeType* getEntryNode(GraphType* G) {
|
||||
return &G->getNode("root");
|
||||
}
|
||||
|
||||
static ChildIteratorType child_begin(NodeType* N) {
|
||||
return ChildIteratorType(N, N->Children.begin());
|
||||
}
|
||||
static ChildIteratorType child_end(NodeType* N) {
|
||||
return ChildIteratorType(N, N->Children.end());
|
||||
}
|
||||
|
||||
typedef GraphType::nodes_iterator nodes_iterator;
|
||||
static nodes_iterator nodes_begin(GraphType *G) {
|
||||
return G->nodes_begin();
|
||||
}
|
||||
static nodes_iterator nodes_end(GraphType *G) {
|
||||
return G->nodes_end();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LLVM_TOOLS_LLVMC2_COMPILATION_GRAPH_H
|
||||
|
@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains toolchain descriptions used by llvmcc.
|
||||
// This file contains compilation graph description used by llvmcc.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -16,9 +16,14 @@ include "Tools.td"
|
||||
|
||||
// Toolchains
|
||||
|
||||
def ToolChains : ToolChains<[
|
||||
ToolChain<[llvm_gcc_c, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
||||
ToolChain<[llvm_gcc_cpp, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
||||
ToolChain<[llvm_as, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
||||
ToolChain<[llvm_gcc_assembler, llvm_gcc_linker]>
|
||||
def CompilationGraph : CompilationGraph<[
|
||||
Edge<root, llvm_gcc_c>,
|
||||
Edge<root, llvm_gcc_assembler>,
|
||||
Edge<root, llvm_gcc_cpp>,
|
||||
Edge<root, llvm_as>,
|
||||
Edge<llvm_gcc_c, llc>,
|
||||
Edge<llvm_gcc_cpp, llc>,
|
||||
Edge<llvm_as, llc>,
|
||||
Edge<llc, llvm_gcc_assembler>,
|
||||
Edge<llvm_gcc_assembler, llvm_gcc_linker>
|
||||
]>;
|
||||
|
@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains toolchain descriptions used by llvmcc.
|
||||
// This file contains compilation graph description used by llvmcc.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -16,9 +16,15 @@ include "Tools.td"
|
||||
|
||||
// Toolchains
|
||||
|
||||
def ToolChains : ToolChains<[
|
||||
ToolChain<[llvm_gcc_c, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
||||
ToolChain<[llvm_gcc_cpp, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
||||
ToolChain<[llvm_as, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
||||
ToolChain<[llvm_gcc_assembler, llvm_gcc_linker]>
|
||||
def CompilationGraph : CompilationGraph<[
|
||||
Edge<root, llvm_gcc_c>,
|
||||
Edge<root, llvm_gcc_assembler>,
|
||||
Edge<root, llvm_gcc_cpp>,
|
||||
Edge<root, llvm_as>,
|
||||
Edge<llvm_gcc_c, opt>,
|
||||
Edge<llvm_gcc_cpp, opt>,
|
||||
Edge<llvm_as, opt>,
|
||||
Edge<opt, llc>,
|
||||
Edge<llc, llvm_gcc_assembler>,
|
||||
Edge<llvm_gcc_assembler, llvm_gcc_linker>
|
||||
]>;
|
||||
|
@ -28,13 +28,21 @@ namespace cl = llvm::cl;
|
||||
namespace sys = llvm::sys;
|
||||
using namespace llvmcc;
|
||||
|
||||
// Built-in command-line options.
|
||||
// External linkage here is intentional.
|
||||
cl::list<std::string> InputFilenames(cl::Positional,
|
||||
cl::desc("<input file>"), cl::OneOrMore);
|
||||
|
||||
cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input file>"),
|
||||
cl::OneOrMore);
|
||||
cl::opt<std::string> OutputFilename("o", cl::desc("Output file name"),
|
||||
cl::value_desc("file"));
|
||||
cl::opt<bool> VerboseMode("v", cl::desc("Enable verbose mode"));
|
||||
|
||||
cl::opt<bool> VerboseMode("v",
|
||||
cl::desc("Enable verbose mode"));
|
||||
cl::opt<bool> WriteGraph("write-graph",
|
||||
cl::desc("Write CompilationGraph.dot file"),
|
||||
cl::Hidden);
|
||||
cl::opt<bool> ViewGraph("view-graph",
|
||||
cl::desc("Show compilation graph in GhostView"),
|
||||
cl::Hidden);
|
||||
|
||||
namespace {
|
||||
int BuildTargets(const CompilationGraph& graph) {
|
||||
@ -61,6 +69,12 @@ int main(int argc, char** argv) {
|
||||
cl::ParseCommandLineOptions(argc, argv,
|
||||
"LLVM Compiler Driver(Work In Progress)");
|
||||
PopulateCompilationGraph(graph);
|
||||
|
||||
if(WriteGraph)
|
||||
graph.writeGraph();
|
||||
if(ViewGraph)
|
||||
graph.viewGraph();
|
||||
|
||||
return BuildTargets(graph);
|
||||
}
|
||||
catch(const std::exception& ex) {
|
||||
|
@ -380,7 +380,7 @@ private:
|
||||
checkNumberOfArguments(d, 1);
|
||||
SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
|
||||
if (toolProps_.CmdLine.empty())
|
||||
throw std::string("Tool " + toolProps_.Name + " has empty command line!");
|
||||
throw "Tool " + toolProps_.Name + " has empty command line!";
|
||||
}
|
||||
|
||||
void onInLanguage (DagInit* d) {
|
||||
@ -653,6 +653,9 @@ void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
|
||||
<< Indent2 << "std::vector<std::string> vec;\n";
|
||||
|
||||
// Parse CmdLine tool property
|
||||
if(P.CmdLine.empty())
|
||||
throw "Tool " + P.Name + " has empty command line!";
|
||||
|
||||
StrVector::const_iterator I = P.CmdLine.begin();
|
||||
++I;
|
||||
for (StrVector::const_iterator E = P.CmdLine.end(); I != E; ++I) {
|
||||
@ -766,6 +769,10 @@ void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
|
||||
|
||||
// Emit a Tool class definition
|
||||
void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
|
||||
|
||||
if(P.Name == "root")
|
||||
return;
|
||||
|
||||
// Header
|
||||
O << "class " << P.Name << " : public Tool {\n"
|
||||
<< "public:\n";
|
||||
@ -851,35 +858,40 @@ void EmitPopulateCompilationGraph (const RecordKeeper& Records,
|
||||
std::ostream& O)
|
||||
{
|
||||
// Get the relevant field out of RecordKeeper
|
||||
Record* ToolChains = Records.getDef("ToolChains");
|
||||
if (!ToolChains)
|
||||
throw std::string("No ToolChains specification found!");
|
||||
ListInit* chains = ToolChains->getValueAsListInit("chains");
|
||||
if (!chains)
|
||||
throw std::string("Error in toolchain list definition!");
|
||||
Record* CompilationGraph = Records.getDef("CompilationGraph");
|
||||
if (!CompilationGraph)
|
||||
throw std::string("No CompilationGraph specification found!");
|
||||
ListInit* edges = CompilationGraph->getValueAsListInit("edges");
|
||||
if (!edges)
|
||||
throw std::string("Error in compilation graph definition!");
|
||||
|
||||
// Generate code
|
||||
O << "void llvmcc::PopulateCompilationGraph(CompilationGraph& G) {\n"
|
||||
<< Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n"
|
||||
<< Indent1 << "std::vector<IntrusiveRefCntPtr<Tool> > vec;\n\n";
|
||||
<< Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n\n";
|
||||
|
||||
for (unsigned i = 0; i < chains->size(); ++i) {
|
||||
Record* ToolChain = chains->getElementAsRecord(i);
|
||||
ListInit* Tools = ToolChain->getValueAsListInit("tools");
|
||||
// Insert vertices
|
||||
|
||||
// Get name of the first tool in the list
|
||||
const std::string& firstTool =
|
||||
dynamic_cast<DefInit&>(**Tools->begin()).getDef()->getName();
|
||||
RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
|
||||
if (Tools.empty())
|
||||
throw std::string("No tool definitions found!");
|
||||
|
||||
for (ListInit::iterator B = Tools->begin(),
|
||||
E = Tools->end(); B != E; ++B) {
|
||||
Record* val = dynamic_cast<DefInit&>(**B).getDef();
|
||||
O << Indent1 << "vec.push_back(IntrusiveRefCntPtr<Tool>(new "
|
||||
<< val->getName() << "()));\n";
|
||||
}
|
||||
O << Indent1 << "G.ToolChains[\"" << ToolToLang[firstTool]
|
||||
<< "\"] = vec;\n";
|
||||
O << Indent1 << "vec.clear();\n\n";
|
||||
for (RecordVector::iterator B = Tools.begin(), E = Tools.end(); B != E; ++B) {
|
||||
const std::string& Name = (*B)->getName();
|
||||
if(Name != "root")
|
||||
O << Indent1 << "G.insertVertex(IntrusiveRefCntPtr<Tool>(new "
|
||||
<< Name << "()));\n";
|
||||
}
|
||||
|
||||
O << '\n';
|
||||
|
||||
// Insert edges
|
||||
|
||||
for (unsigned i = 0; i < edges->size(); ++i) {
|
||||
Record* Edge = edges->getElementAsRecord(i);
|
||||
Record* A = Edge->getValueAsDef("a");
|
||||
Record* B = Edge->getValueAsDef("b");
|
||||
O << Indent1 << "G.insertEdge(\"" << A->getName() << "\", \""
|
||||
<< B->getName() << "\");\n";
|
||||
}
|
||||
|
||||
O << "}\n\n";
|
||||
|
Loading…
Reference in New Issue
Block a user