forked from OSchip/llvm-project
More work on edge properties. Use Edge classes instead of strings in CompilationGraph.
llvm-svn: 50726
This commit is contained in:
parent
459df48de7
commit
251280ce0b
|
@ -50,10 +50,6 @@ def required;
|
||||||
def switch_on;
|
def switch_on;
|
||||||
def parameter_equals;
|
def parameter_equals;
|
||||||
def element_in_list;
|
def element_in_list;
|
||||||
|
|
||||||
// Property combinators
|
|
||||||
// TOFIX: implement
|
|
||||||
def and;
|
|
||||||
def or;
|
def or;
|
||||||
|
|
||||||
// Map from suffixes to language names
|
// Map from suffixes to language names
|
||||||
|
|
|
@ -32,14 +32,14 @@ CompilationGraph::CompilationGraph() {
|
||||||
Node& CompilationGraph::getNode(const std::string& ToolName) {
|
Node& CompilationGraph::getNode(const std::string& ToolName) {
|
||||||
nodes_map_type::iterator I = NodesMap.find(ToolName);
|
nodes_map_type::iterator I = NodesMap.find(ToolName);
|
||||||
if (I == NodesMap.end())
|
if (I == NodesMap.end())
|
||||||
throw std::runtime_error("Node " + ToolName + " is not in graph");
|
throw std::runtime_error("Node " + ToolName + " is not in the graph");
|
||||||
return I->second;
|
return I->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Node& CompilationGraph::getNode(const std::string& ToolName) const {
|
const Node& CompilationGraph::getNode(const std::string& ToolName) const {
|
||||||
nodes_map_type::const_iterator I = NodesMap.find(ToolName);
|
nodes_map_type::const_iterator I = NodesMap.find(ToolName);
|
||||||
if (I == NodesMap.end())
|
if (I == NodesMap.end())
|
||||||
throw std::runtime_error("Node " + ToolName + " is not in graph!");
|
throw std::runtime_error("Node " + ToolName + " is not in the graph!");
|
||||||
return I->second;
|
return I->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,31 +69,23 @@ void CompilationGraph::insertNode(Tool* V) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilationGraph::insertEdge(const std::string& A,
|
void CompilationGraph::insertEdge(const std::string& A, Edge* E) {
|
||||||
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") {
|
if (A == "root") {
|
||||||
const Node& N = getNode(B);
|
const Node& N = getNode(E->ToolName());
|
||||||
const std::string& InputLanguage = N.ToolPtr->InputLanguage();
|
const std::string& InputLanguage = N.ToolPtr->InputLanguage();
|
||||||
ToolsMap[InputLanguage].push_back(B);
|
ToolsMap[InputLanguage].push_back(E->ToolName());
|
||||||
|
|
||||||
// Needed to support iteration via GraphTraits.
|
// Needed to support iteration via GraphTraits.
|
||||||
NodesMap["root"].AddEdge(new DefaultEdge(B));
|
NodesMap["root"].AddEdge(E);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Node& N = getNode(A);
|
Node& N = getNode(A);
|
||||||
// Check that there is a node at B.
|
N.AddEdge(E);
|
||||||
getNode(B);
|
|
||||||
N.AddEdge(new DefaultEdge(B));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOFIX: extend, add an ability to choose between different
|
// TOFIX: support edge properties.
|
||||||
// toolchains, support more interesting graph topologies.
|
// TOFIX: support more interesting graph topologies.
|
||||||
int CompilationGraph::Build (const sys::Path& tempDir) const {
|
int CompilationGraph::Build (const sys::Path& tempDir) const {
|
||||||
PathVector JoinList;
|
PathVector JoinList;
|
||||||
const Tool* JoinTool = 0;
|
const Tool* JoinTool = 0;
|
||||||
|
@ -124,7 +116,11 @@ int CompilationGraph::Build (const sys::Path& tempDir) const {
|
||||||
|
|
||||||
// Is this the last tool?
|
// Is this the last tool?
|
||||||
if (!N->HasChildren() || CurTool->IsLast()) {
|
if (!N->HasChildren() || CurTool->IsLast()) {
|
||||||
Out.appendComponent(In.getBasename());
|
// Check if the first tool is also the last
|
||||||
|
if(Out.empty())
|
||||||
|
Out.set(In.getBasename());
|
||||||
|
else
|
||||||
|
Out.appendComponent(In.getBasename());
|
||||||
Out.appendSuffix(CurTool->OutputSuffix());
|
Out.appendSuffix(CurTool->OutputSuffix());
|
||||||
Last = true;
|
Last = true;
|
||||||
}
|
}
|
||||||
|
@ -191,5 +187,5 @@ void CompilationGraph::writeGraph() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilationGraph::viewGraph() {
|
void CompilationGraph::viewGraph() {
|
||||||
llvm::ViewGraph(this, "CompilationGraph");
|
llvm::ViewGraph(this, "compilation-graph");
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
namespace llvmcc {
|
namespace llvmcc {
|
||||||
|
|
||||||
|
// An edge in the graph.
|
||||||
class Edge : public llvm::RefCountedBaseVPTR<Edge> {
|
class Edge : public llvm::RefCountedBaseVPTR<Edge> {
|
||||||
public:
|
public:
|
||||||
Edge(const std::string& T) : ToolName_(T) {}
|
Edge(const std::string& T) : ToolName_(T) {}
|
||||||
|
@ -40,13 +41,15 @@ namespace llvmcc {
|
||||||
std::string ToolName_;
|
std::string ToolName_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DefaultEdge : public Edge {
|
// Edges with no properties are instances of this class.
|
||||||
|
class SimpleEdge : public Edge {
|
||||||
public:
|
public:
|
||||||
DefaultEdge(const std::string& T) : Edge(T) {}
|
SimpleEdge(const std::string& T) : Edge(T) {}
|
||||||
bool isEnabled() const { return true;}
|
bool isEnabled() const { return true;}
|
||||||
bool isDefault() const { return true;}
|
bool isDefault() const { return true;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A node in the graph.
|
||||||
struct Node {
|
struct Node {
|
||||||
typedef llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> container_type;
|
typedef llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> container_type;
|
||||||
typedef container_type::iterator iterator;
|
typedef container_type::iterator iterator;
|
||||||
|
@ -56,14 +59,14 @@ namespace llvmcc {
|
||||||
Node(CompilationGraph* G) : OwningGraph(G) {}
|
Node(CompilationGraph* G) : OwningGraph(G) {}
|
||||||
Node(CompilationGraph* G, Tool* T) : OwningGraph(G), ToolPtr(T) {}
|
Node(CompilationGraph* G, Tool* T) : OwningGraph(G), ToolPtr(T) {}
|
||||||
|
|
||||||
bool HasChildren() const { return OutEdges.empty(); }
|
bool HasChildren() const { return !OutEdges.empty(); }
|
||||||
|
|
||||||
iterator EdgesBegin() { return OutEdges.begin(); }
|
iterator EdgesBegin() { return OutEdges.begin(); }
|
||||||
const_iterator EdgesBegin() const { return OutEdges.begin(); }
|
const_iterator EdgesBegin() const { return OutEdges.begin(); }
|
||||||
iterator EdgesEnd() { return OutEdges.end(); }
|
iterator EdgesEnd() { return OutEdges.end(); }
|
||||||
const_iterator EdgesEnd() const { return OutEdges.end(); }
|
const_iterator EdgesEnd() const { return OutEdges.end(); }
|
||||||
|
|
||||||
// E is a new-allocated pointer.
|
// Takes ownership of the object.
|
||||||
void AddEdge(Edge* E)
|
void AddEdge(Edge* E)
|
||||||
{ OutEdges.push_back(llvm::IntrusiveRefCntPtr<Edge>(E)); }
|
{ OutEdges.push_back(llvm::IntrusiveRefCntPtr<Edge>(E)); }
|
||||||
|
|
||||||
|
@ -93,16 +96,16 @@ namespace llvmcc {
|
||||||
|
|
||||||
CompilationGraph();
|
CompilationGraph();
|
||||||
|
|
||||||
// insertVertex - insert a new node into the graph.
|
// insertVertex - insert a new node into the graph. Takes
|
||||||
|
// ownership of the object.
|
||||||
void insertNode(Tool* T);
|
void insertNode(Tool* T);
|
||||||
|
|
||||||
// insertEdge - Insert a new edge into the graph. This function
|
// insertEdge - Insert a new edge into the graph. Takes ownership
|
||||||
// assumes that both A and B have been already inserted.
|
// of the object.
|
||||||
void insertEdge(const std::string& A, const std::string& B);
|
void insertEdge(const std::string& A, Edge* E);
|
||||||
|
|
||||||
// Build - Build the target(s) from the set of the input
|
// Build - Build target(s) from the input file set. Command-line
|
||||||
// files. Command-line options are passed implicitly as global
|
// options are passed implicitly as global variables.
|
||||||
// variables.
|
|
||||||
int Build(llvm::sys::Path const& tempDir) const;
|
int Build(llvm::sys::Path const& tempDir) const;
|
||||||
|
|
||||||
// Return a reference to the node correponding to the given tool
|
// Return a reference to the node correponding to the given tool
|
||||||
|
|
|
@ -21,9 +21,16 @@ def CompilationGraph : CompilationGraph<[
|
||||||
Edge<root, llvm_gcc_assembler>,
|
Edge<root, llvm_gcc_assembler>,
|
||||||
Edge<root, llvm_gcc_cpp>,
|
Edge<root, llvm_gcc_cpp>,
|
||||||
Edge<root, llvm_as>,
|
Edge<root, llvm_as>,
|
||||||
|
|
||||||
Edge<llvm_gcc_c, llc>,
|
Edge<llvm_gcc_c, llc>,
|
||||||
Edge<llvm_gcc_cpp, llc>,
|
Edge<llvm_gcc_cpp, llc>,
|
||||||
Edge<llvm_as, llc>,
|
Edge<llvm_as, llc>,
|
||||||
|
|
||||||
|
OptionalEdge<llvm_gcc_c, opt, [(switch_on "opt")]>,
|
||||||
|
OptionalEdge<llvm_gcc_cpp, opt, [(switch_on "opt")]>,
|
||||||
|
OptionalEdge<llvm_as, opt, [(switch_on "opt")]>,
|
||||||
|
OptionalEdge<opt, llc, [(switch_on "opt")]>,
|
||||||
|
|
||||||
Edge<llc, llvm_gcc_assembler>,
|
Edge<llc, llvm_gcc_assembler>,
|
||||||
Edge<llvm_gcc_assembler, llvm_gcc_linker>
|
Edge<llvm_gcc_assembler, llvm_gcc_linker>
|
||||||
]>;
|
]>;
|
||||||
|
|
|
@ -14,12 +14,7 @@ REQUIRES_EH := 1
|
||||||
|
|
||||||
include $(LEVEL)/Makefile.common
|
include $(LEVEL)/Makefile.common
|
||||||
|
|
||||||
TOOLS_TARGET=default
|
TOOLS_SOURCE=Example.td
|
||||||
ifeq ($(TOOLS_TARGET), default)
|
|
||||||
TOOLS_SOURCE=Example.td
|
|
||||||
else
|
|
||||||
TOOLS_SOURCE=ExampleWithOpt.td
|
|
||||||
endif
|
|
||||||
|
|
||||||
# TOFIX: integrate this part into Makefile.rules?
|
# TOFIX: integrate this part into Makefile.rules?
|
||||||
# The degree of horrorshowness in that file is too much for me atm.
|
# The degree of horrorshowness in that file is too much for me atm.
|
||||||
|
|
|
@ -866,6 +866,8 @@ void FillInToolToLang (const ToolPropertiesList& TPList,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that all output and input language names match.
|
// Check that all output and input language names match.
|
||||||
|
// TOFIX: check for cycles.
|
||||||
|
// TOFIX: check for multiple default edges.
|
||||||
void TypecheckGraph (Record* CompilationGraph,
|
void TypecheckGraph (Record* CompilationGraph,
|
||||||
const ToolPropertiesList& TPList) {
|
const ToolPropertiesList& TPList) {
|
||||||
StringMap<std::string> ToolToInLang;
|
StringMap<std::string> ToolToInLang;
|
||||||
|
@ -889,22 +891,36 @@ void TypecheckGraph (Record* CompilationGraph,
|
||||||
if(A->getName() != "root" && IA->second != IB->second)
|
if(A->getName() != "root" && IA->second != IB->second)
|
||||||
throw "Edge " + A->getName() + "->" + B->getName()
|
throw "Edge " + A->getName() + "->" + B->getName()
|
||||||
+ ": output->input language mismatch";
|
+ ": output->input language mismatch";
|
||||||
|
if(B->getName() == "root")
|
||||||
|
throw std::string("Edges back to the root are not allowed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit Edge* classes used for.
|
// Emit Edge* classes that represent edges in the graph.
|
||||||
|
// TOFIX: add edge properties.
|
||||||
void EmitEdgeClasses (Record* CompilationGraph,
|
void EmitEdgeClasses (Record* CompilationGraph,
|
||||||
const GlobalOptionDescriptions& OptDescs,
|
const GlobalOptionDescriptions& OptDescs,
|
||||||
std::ostream& O) {
|
std::ostream& O) {
|
||||||
ListInit* edges = CompilationGraph->getValueAsListInit("edges");
|
ListInit* edges = CompilationGraph->getValueAsListInit("edges");
|
||||||
|
|
||||||
for (unsigned i = 0; i < edges->size(); ++i) {
|
for (unsigned i = 0; i < edges->size(); ++i) {
|
||||||
//Record* Edge = edges->getElementAsRecord(i);
|
Record* Edge = edges->getElementAsRecord(i);
|
||||||
//Record* A = Edge->getValueAsDef("a");
|
Record* B = Edge->getValueAsDef("b");
|
||||||
//Record* B = Edge->getValueAsDef("b");
|
ListInit* Props = Edge->getValueAsListInit("props");
|
||||||
//ListInit* Props = Edge->getValueAsListInit("props");
|
|
||||||
|
|
||||||
O << "class Edge" << i << " {};\n\n";
|
if (Props->empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
O << "class Edge" << i << ": public Edge {\n"
|
||||||
|
<< "public:\n"
|
||||||
|
<< Indent1 << "Edge" << i << "() : Edge(\"" << B->getName()
|
||||||
|
<< "\") {}\n";
|
||||||
|
|
||||||
|
O << Indent1 << "bool isEnabled() const { return true; }\n";
|
||||||
|
|
||||||
|
O << Indent1 << "bool isDefault() const { return false; }\n";
|
||||||
|
|
||||||
|
O << "};\n\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,8 +953,16 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph,
|
||||||
Record* Edge = edges->getElementAsRecord(i);
|
Record* Edge = edges->getElementAsRecord(i);
|
||||||
Record* A = Edge->getValueAsDef("a");
|
Record* A = Edge->getValueAsDef("a");
|
||||||
Record* B = Edge->getValueAsDef("b");
|
Record* B = Edge->getValueAsDef("b");
|
||||||
O << Indent1 << "G.insertEdge(\"" << A->getName() << "\", \""
|
ListInit* Props = Edge->getValueAsListInit("props");
|
||||||
<< B->getName() << "\");\n";
|
|
||||||
|
O << Indent1 << "G.insertEdge(\"" << A->getName() << "\", ";
|
||||||
|
|
||||||
|
if (Props->empty())
|
||||||
|
O << "new SimpleEdge(\"" << B->getName() << "\")";
|
||||||
|
else
|
||||||
|
O << "new Edge" << i << "()";
|
||||||
|
|
||||||
|
O << ");\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
O << "}\n\n";
|
O << "}\n\n";
|
||||||
|
|
Loading…
Reference in New Issue