mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-19 17:24:57 +00:00
Convert internal representation to use DAG. This gives us more flexibility and enables future improvements.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50724 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -15,6 +15,10 @@ class Tool<list<dag> l> {
|
|||||||
list<dag> properties = l;
|
list<dag> properties = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special Tool instance - root of all toolchains
|
||||||
|
|
||||||
|
def root : Tool<[]>;
|
||||||
|
|
||||||
// Possible Tool properties
|
// Possible Tool properties
|
||||||
|
|
||||||
def in_language;
|
def in_language;
|
||||||
@@ -52,12 +56,13 @@ class LanguageMap<list<LangToSuffixes> lst> {
|
|||||||
list<LangToSuffixes> map = lst;
|
list<LangToSuffixes> map = lst;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toolchain classes
|
// Compilation graph
|
||||||
|
|
||||||
class ToolChain <list<Tool> lst> {
|
class Edge<Tool t1, Tool t2> {
|
||||||
list <Tool> tools = lst;
|
Tool a = t1;
|
||||||
|
Tool b = t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToolChains <list<ToolChain> lst> {
|
class CompilationGraph<list<Edge> lst> {
|
||||||
list<ToolChain> chains = lst;
|
list<Edge> edges = lst;
|
||||||
}
|
}
|
||||||
|
@@ -14,46 +14,120 @@
|
|||||||
#include "CompilationGraph.h"
|
#include "CompilationGraph.h"
|
||||||
|
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/Support/DOTGraphTraits.h"
|
||||||
|
#include "llvm/Support/GraphWriter.h"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace llvmcc;
|
||||||
|
|
||||||
extern cl::list<std::string> InputFilenames;
|
extern cl::list<std::string> InputFilenames;
|
||||||
extern cl::opt<std::string> OutputFilename;
|
extern cl::opt<std::string> OutputFilename;
|
||||||
|
|
||||||
int llvmcc::CompilationGraph::Build (const sys::Path& tempDir) const {
|
CompilationGraph::CompilationGraph() {
|
||||||
sys::Path In(InputFilenames.at(0)), Out;
|
NodesMap["root"] = Node(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Find out which language corresponds to the suffix of the first input file
|
Node& CompilationGraph::getNode(const std::string& ToolName) {
|
||||||
LanguageMap::const_iterator Lang = ExtsToLangs.find(In.getSuffix());
|
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())
|
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
|
const CompilationGraph::tools_vector_type&
|
||||||
ToolChainMap::const_iterator ToolsIt = ToolChains.find(Lang->second);
|
CompilationGraph::getToolsVector(const std::string& LangName) const
|
||||||
if (ToolsIt == ToolChains.end())
|
{
|
||||||
throw std::runtime_error("Unknown language!");
|
tools_map_type::const_iterator I = ToolsMap.find(LangName);
|
||||||
ToolChain Tools = ToolsIt->second;
|
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;
|
PathVector JoinList;
|
||||||
|
const Tool* JoinTool = 0;
|
||||||
|
sys::Path In, Out;
|
||||||
|
|
||||||
|
// For each input file
|
||||||
for (cl::list<std::string>::const_iterator B = InputFilenames.begin(),
|
for (cl::list<std::string>::const_iterator B = InputFilenames.begin(),
|
||||||
E = InputFilenames.end(); B != E; ++B) {
|
E = InputFilenames.end(); B != E; ++B) {
|
||||||
In = sys::Path(*B);
|
In = sys::Path(*B);
|
||||||
|
|
||||||
// Pass input file through the toolchain
|
// Get to the head of the toolchain.
|
||||||
for (ToolChain::const_iterator B = Tools.begin(), E = Tools.end();
|
const tools_vector_type& TV = getToolsVector(getLanguage(In));
|
||||||
B != E; ++B) {
|
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(CurTool->IsJoin()) {
|
||||||
if (llvm::next(B) == E || CurTool->IsLast()) {
|
|
||||||
JoinList.push_back(In);
|
JoinList.push_back(In);
|
||||||
|
JoinTool = CurTool;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is this the last tool?
|
||||||
|
if (N->Children.empty() || CurTool->IsLast()) {
|
||||||
|
Out.appendComponent(In.getBasename());
|
||||||
|
Out.appendSuffix(CurTool->OutputSuffix());
|
||||||
|
Last = true;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
Out = tempDir;
|
Out = tempDir;
|
||||||
Out.appendComponent(In.getBasename());
|
Out.appendComponent(In.getBasename());
|
||||||
@@ -65,24 +139,57 @@ int llvmcc::CompilationGraph::Build (const sys::Path& tempDir) const {
|
|||||||
if (CurTool->GenerateAction(In, Out).Execute() != 0)
|
if (CurTool->GenerateAction(In, Out).Execute() != 0)
|
||||||
throw std::runtime_error("Tool returned error code!");
|
throw std::runtime_error("Tool returned error code!");
|
||||||
|
|
||||||
|
N = &getNode(*N->Children.begin());
|
||||||
In = Out; Out.clear();
|
In = Out; Out.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass .o files to linker
|
if(JoinTool) {
|
||||||
const Tool* JoinNode = (--Tools.end())->getPtr();
|
// 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 (JoinTool->GenerateAction(JoinList, Out).Execute() != 0)
|
||||||
if (!OutputFilename.empty()) {
|
throw std::runtime_error("Tool returned error code!");
|
||||||
Out = sys::Path(OutputFilename);
|
|
||||||
}
|
}
|
||||||
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;
|
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 "AutoGenerated.h"
|
||||||
#include "Tool.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/ADT/StringMap.h"
|
||||||
#include "llvm/System/Path.h"
|
#include "llvm/System/Path.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace llvmcc {
|
namespace llvmcc {
|
||||||
|
|
||||||
typedef std::vector<llvm::IntrusiveRefCntPtr<Tool> > ToolChain;
|
class CompilationGraph;
|
||||||
typedef llvm::StringMap<ToolChain> ToolChainMap;
|
|
||||||
|
|
||||||
struct CompilationGraph {
|
struct Node {
|
||||||
ToolChainMap ToolChains;
|
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;
|
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;
|
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
|
#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
|
// Toolchains
|
||||||
|
|
||||||
def ToolChains : ToolChains<[
|
def CompilationGraph : CompilationGraph<[
|
||||||
ToolChain<[llvm_gcc_c, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
Edge<root, llvm_gcc_c>,
|
||||||
ToolChain<[llvm_gcc_cpp, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
Edge<root, llvm_gcc_assembler>,
|
||||||
ToolChain<[llvm_as, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
Edge<root, llvm_gcc_cpp>,
|
||||||
ToolChain<[llvm_gcc_assembler, llvm_gcc_linker]>
|
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
|
// Toolchains
|
||||||
|
|
||||||
def ToolChains : ToolChains<[
|
def CompilationGraph : CompilationGraph<[
|
||||||
ToolChain<[llvm_gcc_c, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
Edge<root, llvm_gcc_c>,
|
||||||
ToolChain<[llvm_gcc_cpp, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
Edge<root, llvm_gcc_assembler>,
|
||||||
ToolChain<[llvm_as, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
|
Edge<root, llvm_gcc_cpp>,
|
||||||
ToolChain<[llvm_gcc_assembler, llvm_gcc_linker]>
|
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;
|
namespace sys = llvm::sys;
|
||||||
using namespace llvmcc;
|
using namespace llvmcc;
|
||||||
|
|
||||||
|
// Built-in command-line options.
|
||||||
// External linkage here is intentional.
|
// 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::opt<std::string> OutputFilename("o", cl::desc("Output file name"),
|
||||||
cl::value_desc("file"));
|
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 {
|
namespace {
|
||||||
int BuildTargets(const CompilationGraph& graph) {
|
int BuildTargets(const CompilationGraph& graph) {
|
||||||
@@ -61,6 +69,12 @@ int main(int argc, char** argv) {
|
|||||||
cl::ParseCommandLineOptions(argc, argv,
|
cl::ParseCommandLineOptions(argc, argv,
|
||||||
"LLVM Compiler Driver(Work In Progress)");
|
"LLVM Compiler Driver(Work In Progress)");
|
||||||
PopulateCompilationGraph(graph);
|
PopulateCompilationGraph(graph);
|
||||||
|
|
||||||
|
if(WriteGraph)
|
||||||
|
graph.writeGraph();
|
||||||
|
if(ViewGraph)
|
||||||
|
graph.viewGraph();
|
||||||
|
|
||||||
return BuildTargets(graph);
|
return BuildTargets(graph);
|
||||||
}
|
}
|
||||||
catch(const std::exception& ex) {
|
catch(const std::exception& ex) {
|
||||||
|
@@ -380,7 +380,7 @@ private:
|
|||||||
checkNumberOfArguments(d, 1);
|
checkNumberOfArguments(d, 1);
|
||||||
SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
|
SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
|
||||||
if (toolProps_.CmdLine.empty())
|
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) {
|
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";
|
<< Indent2 << "std::vector<std::string> vec;\n";
|
||||||
|
|
||||||
// Parse CmdLine tool property
|
// Parse CmdLine tool property
|
||||||
|
if(P.CmdLine.empty())
|
||||||
|
throw "Tool " + P.Name + " has empty command line!";
|
||||||
|
|
||||||
StrVector::const_iterator I = P.CmdLine.begin();
|
StrVector::const_iterator I = P.CmdLine.begin();
|
||||||
++I;
|
++I;
|
||||||
for (StrVector::const_iterator E = P.CmdLine.end(); I != E; ++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
|
// Emit a Tool class definition
|
||||||
void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
|
void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
|
||||||
|
|
||||||
|
if(P.Name == "root")
|
||||||
|
return;
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
O << "class " << P.Name << " : public Tool {\n"
|
O << "class " << P.Name << " : public Tool {\n"
|
||||||
<< "public:\n";
|
<< "public:\n";
|
||||||
@@ -851,35 +858,40 @@ void EmitPopulateCompilationGraph (const RecordKeeper& Records,
|
|||||||
std::ostream& O)
|
std::ostream& O)
|
||||||
{
|
{
|
||||||
// Get the relevant field out of RecordKeeper
|
// Get the relevant field out of RecordKeeper
|
||||||
Record* ToolChains = Records.getDef("ToolChains");
|
Record* CompilationGraph = Records.getDef("CompilationGraph");
|
||||||
if (!ToolChains)
|
if (!CompilationGraph)
|
||||||
throw std::string("No ToolChains specification found!");
|
throw std::string("No CompilationGraph specification found!");
|
||||||
ListInit* chains = ToolChains->getValueAsListInit("chains");
|
ListInit* edges = CompilationGraph->getValueAsListInit("edges");
|
||||||
if (!chains)
|
if (!edges)
|
||||||
throw std::string("Error in toolchain list definition!");
|
throw std::string("Error in compilation graph definition!");
|
||||||
|
|
||||||
// Generate code
|
// Generate code
|
||||||
O << "void llvmcc::PopulateCompilationGraph(CompilationGraph& G) {\n"
|
O << "void llvmcc::PopulateCompilationGraph(CompilationGraph& G) {\n"
|
||||||
<< Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n"
|
<< Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n\n";
|
||||||
<< Indent1 << "std::vector<IntrusiveRefCntPtr<Tool> > vec;\n\n";
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < chains->size(); ++i) {
|
// Insert vertices
|
||||||
Record* ToolChain = chains->getElementAsRecord(i);
|
|
||||||
ListInit* Tools = ToolChain->getValueAsListInit("tools");
|
|
||||||
|
|
||||||
// Get name of the first tool in the list
|
RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
|
||||||
const std::string& firstTool =
|
if (Tools.empty())
|
||||||
dynamic_cast<DefInit&>(**Tools->begin()).getDef()->getName();
|
throw std::string("No tool definitions found!");
|
||||||
|
|
||||||
for (ListInit::iterator B = Tools->begin(),
|
for (RecordVector::iterator B = Tools.begin(), E = Tools.end(); B != E; ++B) {
|
||||||
E = Tools->end(); B != E; ++B) {
|
const std::string& Name = (*B)->getName();
|
||||||
Record* val = dynamic_cast<DefInit&>(**B).getDef();
|
if(Name != "root")
|
||||||
O << Indent1 << "vec.push_back(IntrusiveRefCntPtr<Tool>(new "
|
O << Indent1 << "G.insertVertex(IntrusiveRefCntPtr<Tool>(new "
|
||||||
<< val->getName() << "()));\n";
|
<< Name << "()));\n";
|
||||||
}
|
}
|
||||||
O << Indent1 << "G.ToolChains[\"" << ToolToLang[firstTool]
|
|
||||||
<< "\"] = vec;\n";
|
O << '\n';
|
||||||
O << Indent1 << "vec.clear();\n\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";
|
O << "}\n\n";
|
||||||
|
Reference in New Issue
Block a user