More work on edge properties. Use Edge classes instead of strings in CompilationGraph.

llvm-svn: 50726
This commit is contained in:
Mikhail Glushenkov 2008-05-06 16:36:50 +00:00
parent 459df48de7
commit 251280ce0b
6 changed files with 69 additions and 48 deletions

View File

@ -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

View File

@ -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");
} }

View File

@ -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

View File

@ -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>
]>; ]>;

View File

@ -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.

View File

@ -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";