diff --git a/llvm/tools/llvmc2/Common.td b/llvm/tools/llvmc2/Common.td index ea211e1e1ef3..44358573764a 100644 --- a/llvm/tools/llvmc2/Common.td +++ b/llvm/tools/llvmc2/Common.td @@ -15,7 +15,7 @@ class Tool l> { list properties = l; } -// Special Tool instance - root of all toolchains +// Special Tool instance - graph root. def root : Tool<[]>; @@ -45,6 +45,17 @@ def unpack_values; def help; def required; +// Possible edge properties + +def switch_on; +def parameter_equals; +def element_in_list; + +// Property combinators +// TOFIX: implement +def and; +def or; + // Map from suffixes to language names class LangToSuffixes lst> { @@ -58,11 +69,20 @@ class LanguageMap lst> { // Compilation graph -class Edge { +class EdgeBase lst> { Tool a = t1; Tool b = t2; + list props = lst; } -class CompilationGraph lst> { - list edges = lst; +class Edge : EdgeBase; + +// Edge and DefaultEdge are synonyms. +class DefaultEdge : EdgeBase; + +// Optionally enabled edge. +class OptionalEdge lst> : EdgeBase; + +class CompilationGraph lst> { + list edges = lst; } diff --git a/llvm/tools/llvmc2/CompilationGraph.cpp b/llvm/tools/llvmc2/CompilationGraph.cpp index bff1aa5627d3..07b09e7390b7 100644 --- a/llvm/tools/llvmc2/CompilationGraph.cpp +++ b/llvm/tools/llvmc2/CompilationGraph.cpp @@ -60,7 +60,7 @@ CompilationGraph::getToolsVector(const std::string& LangName) const return I->second; } -void CompilationGraph::insertVertex(const IntrusiveRefCntPtr V) { +void CompilationGraph::insertNode(Tool* V) { if (!NodesMap.count(V->Name())) { Node N; N.OwningGraph = this; @@ -82,13 +82,13 @@ void CompilationGraph::insertEdge(const std::string& A, ToolsMap[InputLanguage].push_back(B); // Needed to support iteration via GraphTraits. - NodesMap["root"].Children.push_back(B); + NodesMap["root"].AddEdge(new DefaultEdge(B)); } else { - Node& NA = getNode(A); + Node& N = getNode(A); // Check that there is a node at B. getNode(B); - NA.Children.push_back(B); + N.AddEdge(new DefaultEdge(B)); } } @@ -123,7 +123,7 @@ int CompilationGraph::Build (const sys::Path& tempDir) const { } // Is this the last tool? - if (N->Children.empty() || CurTool->IsLast()) { + if (!N->HasChildren() || CurTool->IsLast()) { Out.appendComponent(In.getBasename()); Out.appendSuffix(CurTool->OutputSuffix()); Last = true; @@ -139,7 +139,7 @@ int 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()); + N = &getNode((*N->EdgesBegin())->ToolName()); In = Out; Out.clear(); } } diff --git a/llvm/tools/llvmc2/CompilationGraph.h b/llvm/tools/llvmc2/CompilationGraph.h index f46b287bd5d6..85210dc499c3 100644 --- a/llvm/tools/llvmc2/CompilationGraph.h +++ b/llvm/tools/llvmc2/CompilationGraph.h @@ -18,6 +18,7 @@ #include "Tool.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/iterator" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" @@ -27,24 +28,119 @@ namespace llvmcc { - class CompilationGraph; + class Edge : public llvm::RefCountedBaseVPTR { + public: + Edge(const std::string& T) : ToolName_(T) {} + virtual ~Edge() {}; + + const std::string& ToolName() const { return ToolName_; } + virtual bool isEnabled() const = 0; + virtual bool isDefault() const = 0; + private: + std::string ToolName_; + }; + + class DefaultEdge : public Edge { + public: + DefaultEdge(const std::string& T) : Edge(T) {} + bool isEnabled() const { return true;} + bool isDefault() const { return true;} + }; struct Node { - typedef llvm::SmallVector sequence_type; + typedef llvm::SmallVector, 3> container_type; + typedef container_type::iterator iterator; + typedef container_type::const_iterator const_iterator; Node() {} Node(CompilationGraph* G) : OwningGraph(G) {} Node(CompilationGraph* G, Tool* T) : OwningGraph(G), ToolPtr(T) {} + bool HasChildren() const { return OutEdges.empty(); } + + iterator EdgesBegin() { return OutEdges.begin(); } + const_iterator EdgesBegin() const { return OutEdges.begin(); } + iterator EdgesEnd() { return OutEdges.end(); } + const_iterator EdgesEnd() const { return OutEdges.end(); } + + // E is a new-allocated pointer. + void AddEdge(Edge* E) + { OutEdges.push_back(llvm::IntrusiveRefCntPtr(E)); } + // Needed to implement NodeChildIterator/GraphTraits CompilationGraph* OwningGraph; // The corresponding Tool. llvm::IntrusiveRefCntPtr ToolPtr; // Links to children. - sequence_type Children; + container_type OutEdges; }; - // This can be generalised to something like value_iterator for maps + class NodesIterator; + + class CompilationGraph { + typedef llvm::SmallVector tools_vector_type; + typedef llvm::StringMap tools_map_type; + typedef llvm::StringMap nodes_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 insertNode(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; + + // Return a reference to the node correponding to the given tool + // name. Throws std::runtime_error. + Node& getNode(const std::string& ToolName); + const Node& getNode(const std::string& ToolName) 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 + friend NodesIterator GraphBegin(CompilationGraph*); + friend NodesIterator GraphEnd(CompilationGraph*); + friend void PopulateCompilationGraph(CompilationGraph&); + + private: + // Helper functions. + + // 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 list of tool names corresponding to + // the given language name. Throws std::runtime_error. + const tools_vector_type& getToolsVector(const std::string& LangName) const; + }; + + /// GraphTraits support code. + + // Auxiliary class needed to implement GraphTraits support. Can be + // generalised to something like value_iterator for map-like + // containers. class NodesIterator : public llvm::StringMap::iterator { typedef llvm::StringMap::iterator super; typedef NodesIterator ThisType; @@ -62,115 +158,55 @@ namespace llvmcc { } }; - class CompilationGraph { - typedef llvm::StringMap nodes_map_type; - typedef llvm::SmallVector tools_vector_type; - typedef llvm::StringMap tools_map_type; + inline NodesIterator GraphBegin(CompilationGraph* G) { + return NodesIterator(G->NodesMap.begin()); + } - // 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; + inline NodesIterator GraphEnd(CompilationGraph* G) { + return NodesIterator(G->NodesMap.end()); + } - public: - CompilationGraph(); - - // insertVertex - insert a new node into the graph. - void insertVertex(const llvm::IntrusiveRefCntPtr 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. + // Another auxiliary class needed by GraphTraits. class NodeChildIterator : public bidirectional_iterator { typedef NodeChildIterator ThisType; - typedef Node::sequence_type::iterator iterator; + typedef Node::container_type::iterator iterator; CompilationGraph* OwningGraph; - iterator KeyIter; + iterator EdgeIter; public: typedef Node* pointer; typedef Node& reference; NodeChildIterator(Node* N, iterator I) : - OwningGraph(N->OwningGraph), KeyIter(I) {} + OwningGraph(N->OwningGraph), EdgeIter(I) {} const ThisType& operator=(const ThisType& I) { assert(OwningGraph == I.OwningGraph); - KeyIter = I.KeyIter; + EdgeIter = I.EdgeIter; return *this; } inline bool operator==(const ThisType& I) const - { return KeyIter == I.KeyIter; } + { return EdgeIter == I.EdgeIter; } inline bool operator!=(const ThisType& I) const - { return KeyIter != I.KeyIter; } + { return EdgeIter != I.EdgeIter; } inline pointer operator*() const { - return &OwningGraph->getNode(*KeyIter); + return &OwningGraph->getNode((*EdgeIter)->ToolName()); } inline pointer operator->() const { - return &OwningGraph->getNode(*KeyIter); + return &OwningGraph->getNode((*EdgeIter)->ToolName()); } - ThisType& operator++() { ++KeyIter; return *this; } // Preincrement + ThisType& operator++() { ++EdgeIter; return *this; } // Preincrement ThisType operator++(int) { // Postincrement ThisType tmp = *this; ++*this; return tmp; } - inline ThisType& operator--() { --KeyIter; return *this; } // Predecrement + inline ThisType& operator--() { --EdgeIter; return *this; } // Predecrement inline ThisType operator--(int) { // Postdecrement ThisType tmp = *this; --*this; @@ -192,18 +228,18 @@ namespace llvm { } static ChildIteratorType child_begin(NodeType* N) { - return ChildIteratorType(N, N->Children.begin()); + return ChildIteratorType(N, N->OutEdges.begin()); } static ChildIteratorType child_end(NodeType* N) { - return ChildIteratorType(N, N->Children.end()); + return ChildIteratorType(N, N->OutEdges.end()); } - typedef GraphType::nodes_iterator nodes_iterator; + typedef llvmcc::NodesIterator nodes_iterator; static nodes_iterator nodes_begin(GraphType *G) { - return G->nodes_begin(); + return GraphBegin(G); } static nodes_iterator nodes_end(GraphType *G) { - return G->nodes_end(); + return GraphEnd(G); } }; diff --git a/llvm/tools/llvmc2/Tools.td b/llvm/tools/llvmc2/Tools.td index f69c290dff5e..4b84aef38557 100644 --- a/llvm/tools/llvmc2/Tools.td +++ b/llvm/tools/llvmc2/Tools.td @@ -21,7 +21,7 @@ def llvm_gcc_c : Tool< [(in_language "c"), - (out_language "llvm-assembler"), + (out_language "llvm-bitcode"), (output_suffix "bc"), (cmd_line "llvm-gcc -c $INFILE -o $OUTFILE -emit-llvm"), (sink) @@ -29,7 +29,7 @@ def llvm_gcc_c : Tool< def llvm_gcc_cpp : Tool< [(in_language "c++"), - (out_language "llvm-assembler"), + (out_language "llvm-bitcode"), (output_suffix "bc"), (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"), (sink) diff --git a/llvm/utils/TableGen/LLVMCCConfigurationEmitter.cpp b/llvm/utils/TableGen/LLVMCCConfigurationEmitter.cpp index 5db3d03869c2..92e2df188508 100644 --- a/llvm/utils/TableGen/LLVMCCConfigurationEmitter.cpp +++ b/llvm/utils/TableGen/LLVMCCConfigurationEmitter.cpp @@ -27,7 +27,7 @@ using namespace llvm; -namespace { +//namespace { //===----------------------------------------------------------------------===// /// Typedefs @@ -144,6 +144,7 @@ struct GlobalOptionDescription : public OptionDescription { std::string Help; unsigned Flags; + // We need t provide a default constructor since // StringMap can only store DefaultConstructible objects GlobalOptionDescription() : OptionDescription(), Flags(0) {} @@ -539,8 +540,6 @@ void CollectToolProperties (RecordVector::const_iterator B, for (;B!=E;++B) { RecordVector::value_type T = *B; ListInit* PropList = T->getValueAsListInit("properties"); - if (!PropList) - throw std::string("Tool has no property list!"); IntrusiveRefCntPtr ToolProps(new ToolProperties(T->getName())); @@ -853,17 +852,66 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O) O << "}\n\n"; } -void EmitPopulateCompilationGraph (const RecordKeeper& Records, - StringMap& ToolToLang, +// Fills in two tables that map tool names to (input, output) languages. +// Used by the typechecker. +void FillInToolToLang (const ToolPropertiesList& TPList, + StringMap& ToolToInLang, + StringMap& ToolToOutLang) { + for (ToolPropertiesList::const_iterator B = TPList.begin(), E = TPList.end(); + B != E; ++B) { + const ToolProperties& P = *(*B); + ToolToInLang[P.Name] = P.InLanguage; + ToolToOutLang[P.Name] = P.OutLanguage; + } +} + +// Check that all output and input language names match. +void TypecheckGraph (Record* CompilationGraph, + const ToolPropertiesList& TPList) { + StringMap ToolToInLang; + StringMap ToolToOutLang; + + FillInToolToLang(TPList, ToolToInLang, ToolToOutLang); + ListInit* edges = CompilationGraph->getValueAsListInit("edges"); + StringMap::iterator IAE = ToolToInLang.end(); + StringMap::iterator IBE = ToolToOutLang.end(); + + for (unsigned i = 0; i < edges->size(); ++i) { + Record* Edge = edges->getElementAsRecord(i); + Record* A = Edge->getValueAsDef("a"); + Record* B = Edge->getValueAsDef("b"); + StringMap::iterator IA = ToolToOutLang.find(A->getName()); + StringMap::iterator IB = ToolToInLang.find(B->getName()); + if(IA == IAE) + throw A->getName() + ": no such tool!"; + if(IB == IBE) + throw B->getName() + ": no such tool!"; + if(A->getName() != "root" && IA->second != IB->second) + throw "Edge " + A->getName() + "->" + B->getName() + + ": output->input language mismatch"; + } +} + +// Emit Edge* classes used for. +void EmitEdgeClasses (Record* CompilationGraph, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { + ListInit* edges = CompilationGraph->getValueAsListInit("edges"); + + for (unsigned i = 0; i < edges->size(); ++i) { + //Record* Edge = edges->getElementAsRecord(i); + //Record* A = Edge->getValueAsDef("a"); + //Record* B = Edge->getValueAsDef("b"); + //ListInit* Props = Edge->getValueAsListInit("props"); + + O << "class Edge" << i << " {};\n\n"; + } +} + +void EmitPopulateCompilationGraph (Record* CompilationGraph, std::ostream& O) { - // Get the relevant field out of RecordKeeper - 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" @@ -878,14 +926,13 @@ void EmitPopulateCompilationGraph (const RecordKeeper& Records, 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(new " - << Name << "()));\n"; + O << Indent1 << "G.insertNode(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"); @@ -897,17 +944,9 @@ void EmitPopulateCompilationGraph (const RecordKeeper& Records, O << "}\n\n"; } -void FillInToolToLang (const ToolPropertiesList& T, - StringMap& M) { - for (ToolPropertiesList::const_iterator B = T.begin(), E = T.end(); - B != E; ++B) { - const ToolProperties& P = *(*B); - M[P.Name] = P.InLanguage; - } -} // End of anonymous namespace -} +//} // Back-end entry point void LLVMCCConfigurationEmitter::run (std::ostream &O) { @@ -936,12 +975,18 @@ void LLVMCCConfigurationEmitter::run (std::ostream &O) { E = tool_props.end(); B!=E; ++B) EmitToolClassDefinition(*(*B), O); - // Fill in table that maps tool names to languages - StringMap ToolToLang; - FillInToolToLang(tool_props, ToolToLang); + Record* CompilationGraphRecord = Records.getDef("CompilationGraph"); + if (!CompilationGraphRecord) + throw std::string("Compilation graph description not found!"); + + // Typecheck the compilation graph. + TypecheckGraph(CompilationGraphRecord, tool_props); + + // Emit Edge* classes. + EmitEdgeClasses(CompilationGraphRecord, opt_descs, O); // Emit PopulateCompilationGraph function - EmitPopulateCompilationGraph(Records, ToolToLang, O); + EmitPopulateCompilationGraph(CompilationGraphRecord, O); // EOF }