From: Mikhail Glushenkov Date: Fri, 23 Jul 2010 03:42:55 +0000 (+0000) Subject: Get rid of exceptions in llvmc. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b374d4fd82ec01f8549a69a25f4938584c136111;p=oota-llvm.git Get rid of exceptions in llvmc. llvmc can be now compiled with llvm-gcc on Windows. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@109215 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Makefile.rules b/Makefile.rules index a3a4937b792..44b8328f422 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -203,7 +203,6 @@ ifdef LLVMC_PLUGIN LIBRARYNAME := $(patsubst %,plugin_llvmc_%,$(LLVMC_PLUGIN)) CPP.Flags += -DLLVMC_PLUGIN_NAME=$(LLVMC_PLUGIN) -REQUIRES_EH := 1 ifeq ($(ENABLE_LLVMC_DYNAMIC),1) LD.Flags += -lCompilerDriver @@ -226,8 +225,6 @@ ifdef LLVMC_BASED_DRIVER TOOLNAME = $(LLVMC_BASED_DRIVER) -REQUIRES_EH := 1 - ifeq ($(ENABLE_LLVMC_DYNAMIC),1) LD.Flags += -lCompilerDriver else diff --git a/include/llvm/CompilerDriver/Action.h b/include/llvm/CompilerDriver/Action.h index 70141393ce1..4ff6fd9c02e 100644 --- a/include/llvm/CompilerDriver/Action.h +++ b/include/llvm/CompilerDriver/Action.h @@ -34,10 +34,14 @@ namespace llvmc { std::string OutFile_; public: - Action (const std::string& C, const StrVector& A, - bool S, const std::string& O) - : Command_(C), Args_(A), StopCompilation_(S), OutFile_(O) - {} + void Construct (const std::string& C, const StrVector& A, + bool S, const std::string& O) { + Command_ = C; + Args_ = A; + StopCompilation_ = S; + OutFile_ = O; + } + bool IsConstructed () { return (Command_.size() != 0);} /// Execute - Executes the represented action. int Execute () const; diff --git a/include/llvm/CompilerDriver/CompilationGraph.h b/include/llvm/CompilerDriver/CompilationGraph.h index ba6ff4714ce..9f2e50e3041 100644 --- a/include/llvm/CompilerDriver/CompilationGraph.h +++ b/include/llvm/CompilerDriver/CompilationGraph.h @@ -36,7 +36,7 @@ namespace llvmc { public: /// GetLanguage - Find the language name corresponding to a given file. - const std::string& GetLanguage(const llvm::sys::Path&) const; + const std::string* GetLanguage(const llvm::sys::Path&) const; }; /// Edge - Represents an edge of the compilation graph. @@ -133,7 +133,7 @@ namespace llvmc { /// insertEdge - Insert a new edge into the graph. Takes ownership /// of the Edge object. - void insertEdge(const std::string& A, Edge* E); + int insertEdge(const std::string& A, Edge* E); /// Build - Build target(s) from the input file set. Command-line /// options are passed implicitly as global variables. @@ -146,8 +146,8 @@ namespace llvmc { /// getNode - 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; + 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 @@ -157,7 +157,7 @@ namespace llvmc { void viewGraph(); /// writeGraph - Write Graphviz .dot source file to the current direcotry. - void writeGraph(const std::string& OutputFilename); + int writeGraph(const std::string& OutputFilename); // GraphTraits support. friend NodesIterator GraphBegin(CompilationGraph*); @@ -169,14 +169,14 @@ namespace llvmc { /// getToolsVector - 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; + const tools_vector_type* getToolsVector(const std::string& LangName) const; /// PassThroughGraph - Pass the input file through the toolchain /// starting at StartNode. - void PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode, - const InputLanguagesSet& InLangs, - const llvm::sys::Path& TempDir, - const LanguageMap& LangMap) const; + int PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode, + const InputLanguagesSet& InLangs, + const llvm::sys::Path& TempDir, + const LanguageMap& LangMap) const; /// FindToolChain - Find head of the toolchain corresponding to /// the given file. @@ -186,15 +186,15 @@ namespace llvmc { const LanguageMap& LangMap) const; /// BuildInitial - Traverse the initial parts of the toolchains. - void BuildInitial(InputLanguagesSet& InLangs, - const llvm::sys::Path& TempDir, - const LanguageMap& LangMap); + int BuildInitial(InputLanguagesSet& InLangs, + const llvm::sys::Path& TempDir, + const LanguageMap& LangMap); /// TopologicalSort - Sort the nodes in topological order. - void TopologicalSort(std::vector& Out); + int TopologicalSort(std::vector& Out); /// TopologicalSortFilterJoinNodes - Call TopologicalSort and /// filter the resulting list to include only Join nodes. - void TopologicalSortFilterJoinNodes(std::vector& Out); + int TopologicalSortFilterJoinNodes(std::vector& Out); // Functions used to implement Check(). @@ -270,7 +270,7 @@ namespace llvmc { } inline pointer operator*() const { - return &OwningGraph->getNode((*EdgeIter)->ToolName()); + return OwningGraph->getNode((*EdgeIter)->ToolName()); } inline pointer operator->() const { return this->operator*(); @@ -301,7 +301,7 @@ namespace llvm { typedef llvmc::NodeChildIterator ChildIteratorType; static NodeType* getEntryNode(GraphType* G) { - return &G->getNode("root"); + return G->getNode("root"); } static ChildIteratorType child_begin(NodeType* N) { diff --git a/include/llvm/CompilerDriver/Error.h b/include/llvm/CompilerDriver/Error.h index fa678cfbfb9..02339296162 100644 --- a/include/llvm/CompilerDriver/Error.h +++ b/include/llvm/CompilerDriver/Error.h @@ -7,29 +7,27 @@ // //===----------------------------------------------------------------------===// // -// Exception classes for llvmc. +// Error handling. // //===----------------------------------------------------------------------===// #ifndef LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H #define LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H -#include +#include "llvm/Support/raw_ostream.h" -namespace llvmc { +#include - /// error_code - This gets thrown during the compilation process if a tool - /// invocation returns a non-zero exit code. - class error_code: public std::runtime_error { - int Code_; - public: - error_code (int c) - : std::runtime_error("Tool returned error code"), Code_(c) - {} +namespace llvmc { - int code() const { return Code_; } - }; + inline void PrintError(const char* Err) { + extern const char* ProgramName; + llvm::errs() << ProgramName << ": " << Err << '\n'; + } + inline void PrintError(const std::string& Err) { + PrintError(Err.c_str()); + } } #endif // LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H diff --git a/include/llvm/CompilerDriver/Plugin.h b/include/llvm/CompilerDriver/Plugin.h index e9a20488a08..75fd9162dfe 100644 --- a/include/llvm/CompilerDriver/Plugin.h +++ b/include/llvm/CompilerDriver/Plugin.h @@ -32,15 +32,15 @@ namespace llvmc { /// PreprocessOptions - The auto-generated function that performs various /// consistency checks on options (like ensuring that -O2 and -O3 are not /// used together). - virtual void PreprocessOptions() const = 0; + virtual int PreprocessOptions() const = 0; /// PopulateLanguageMap - The auto-generated function that fills in /// the language map (map from file extensions to language names). - virtual void PopulateLanguageMap(LanguageMap&) const = 0; + virtual int PopulateLanguageMap(LanguageMap&) const = 0; /// PopulateCompilationGraph - The auto-generated function that /// populates the compilation graph with nodes and edges. - virtual void PopulateCompilationGraph(CompilationGraph&) const = 0; + virtual int PopulateCompilationGraph(CompilationGraph&) const = 0; /// Needed to avoid a compiler warning. virtual ~BasePlugin() {} @@ -68,7 +68,7 @@ namespace llvmc { /// RunInitialization - Calls PreprocessOptions, PopulateLanguageMap and /// PopulateCompilationGraph methods of all plugins. This populates the /// global language map and the compilation graph. - void RunInitialization(LanguageMap& langMap, CompilationGraph& graph) const; + int RunInitialization(LanguageMap& langMap, CompilationGraph& graph) const; private: // noncopyable diff --git a/include/llvm/CompilerDriver/Tool.h b/include/llvm/CompilerDriver/Tool.h index 85d1690bcfe..d064a03eebc 100644 --- a/include/llvm/CompilerDriver/Tool.h +++ b/include/llvm/CompilerDriver/Tool.h @@ -38,17 +38,19 @@ namespace llvmc { virtual ~Tool() {} - virtual Action GenerateAction (const PathVector& inFiles, - bool HasChildren, - const llvm::sys::Path& TempDir, - const InputLanguagesSet& InLangs, - const LanguageMap& LangMap) const = 0; - - virtual Action GenerateAction (const llvm::sys::Path& inFile, - bool HasChildren, - const llvm::sys::Path& TempDir, - const InputLanguagesSet& InLangs, - const LanguageMap& LangMap) const = 0; + virtual int GenerateAction (Action& Out, + const PathVector& inFiles, + const bool HasChildren, + const llvm::sys::Path& TempDir, + const InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const = 0; + + virtual int GenerateAction (Action& Out, + const llvm::sys::Path& inFile, + const bool HasChildren, + const llvm::sys::Path& TempDir, + const InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const = 0; virtual const char* Name() const = 0; virtual const char** InputLanguages() const = 0; @@ -74,11 +76,13 @@ namespace llvmc { void ClearJoinList() { JoinList_.clear(); } bool JoinListEmpty() const { return JoinList_.empty(); } - Action GenerateAction(bool HasChildren, - const llvm::sys::Path& TempDir, - const InputLanguagesSet& InLangs, - const LanguageMap& LangMap) const { - return GenerateAction(JoinList_, HasChildren, TempDir, InLangs, LangMap); + int GenerateAction(Action& Out, + const bool HasChildren, + const llvm::sys::Path& TempDir, + const InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const { + return GenerateAction(Out, JoinList_, HasChildren, TempDir, InLangs, + LangMap); } // We shouldn't shadow base class's version of GenerateAction. using Tool::GenerateAction; diff --git a/lib/CompilerDriver/Action.cpp b/lib/CompilerDriver/Action.cpp index 5f30dce5855..0be80496a3c 100644 --- a/lib/CompilerDriver/Action.cpp +++ b/lib/CompilerDriver/Action.cpp @@ -13,6 +13,7 @@ #include "llvm/CompilerDriver/Action.h" #include "llvm/CompilerDriver/BuiltinOptions.h" +#include "llvm/CompilerDriver/Error.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/SystemUtils.h" @@ -58,11 +59,15 @@ namespace { if (prog.isEmpty()) { prog = FindExecutable(name, ProgramName, (void *)(intptr_t)&Main); - if (prog.isEmpty()) - throw std::runtime_error("Can't find program '" + name + "'"); + if (prog.isEmpty()) { + PrintError("Can't find program '" + name + "'"); + return -1; + } + } + if (!prog.canExecute()) { + PrintError("Program '" + name + "' is not executable."); + return -1; } - if (!prog.canExecute()) - throw std::runtime_error("Program '" + name + "' is not executable."); // Build the command line vector and the redirects array. const sys::Path* redirects[3] = {0,0,0}; diff --git a/lib/CompilerDriver/CompilationGraph.cpp b/lib/CompilerDriver/CompilationGraph.cpp index 7d1c7fe4a62..4e953cbe110 100644 --- a/lib/CompilerDriver/CompilationGraph.cpp +++ b/lib/CompilerDriver/CompilationGraph.cpp @@ -25,21 +25,22 @@ #include #include #include -#include using namespace llvm; using namespace llvmc; namespace llvmc { - const std::string& LanguageMap::GetLanguage(const sys::Path& File) const { + const std::string* LanguageMap::GetLanguage(const sys::Path& File) const { StringRef suf = File.getSuffix(); LanguageMap::const_iterator Lang = this->find(suf.empty() ? "*empty*" : suf); - if (Lang == this->end()) - throw std::runtime_error("File '" + File.str() + - "' has unknown suffix '" + suf.str() + '\''); - return Lang->second; + if (Lang == this->end()) { + PrintError("File '" + File.str() + "' has unknown suffix '" + + suf.str() + '\''); + return 0; + } + return &Lang->second; } } @@ -67,14 +68,16 @@ namespace { } } - if (!SingleMax) - throw std::runtime_error("Node " + NodeName + - ": multiple maximal outward edges found!" - " Most probably a specification error."); - if (!MaxEdge) - throw std::runtime_error("Node " + NodeName + - ": no maximal outward edge found!" - " Most probably a specification error."); + if (!SingleMax) { + PrintError("Node " + NodeName + ": multiple maximal outward edges found!" + " Most probably a specification error."); + return 0; + } + if (!MaxEdge) { + PrintError("Node " + NodeName + ": no maximal outward edge found!" + " Most probably a specification error."); + return 0; + } return MaxEdge; } @@ -98,29 +101,34 @@ CompilationGraph::CompilationGraph() { NodesMap["root"] = Node(this); } -Node& CompilationGraph::getNode(const std::string& ToolName) { +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 the graph"); - return I->second; + if (I == NodesMap.end()) { + PrintError("Node " + ToolName + " is not in the graph"); + return 0; + } + 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); - if (I == NodesMap.end()) - throw std::runtime_error("Node " + ToolName + " is not in the graph!"); - return I->second; + if (I == NodesMap.end()) { + PrintError("Node " + ToolName + " is not in the graph!"); + return 0; + } + return &I->second; } // Find the tools list corresponding to the given language name. -const CompilationGraph::tools_vector_type& +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 tool corresponding to the language " - + LangName + " found"); - return I->second; + if (I == ToolsMap.end()) { + PrintError("No tool corresponding to the language " + LangName + " found"); + return 0; + } + return &I->second; } void CompilationGraph::insertNode(Tool* V) { @@ -128,29 +136,37 @@ void CompilationGraph::insertNode(Tool* V) { NodesMap[V->Name()] = Node(this, V); } -void CompilationGraph::insertEdge(const std::string& A, Edge* Edg) { - Node& B = getNode(Edg->ToolName()); +int CompilationGraph::insertEdge(const std::string& A, Edge* Edg) { + Node* B = getNode(Edg->ToolName()); + if (B == 0) + return -1; + if (A == "root") { - const char** InLangs = B.ToolPtr->InputLanguages(); + const char** InLangs = B->ToolPtr->InputLanguages(); for (;*InLangs; ++InLangs) ToolsMap[*InLangs].push_back(IntrusiveRefCntPtr(Edg)); NodesMap["root"].AddEdge(Edg); } else { - Node& N = getNode(A); - N.AddEdge(Edg); + Node* N = getNode(A); + if (N == 0) + return -1; + + N->AddEdge(Edg); } // Increase the inward edge counter. - B.IncrInEdges(); + B->IncrInEdges(); + + return 0; } // Pass input file through the chain until we bump into a Join node or // a node that says that it is the last. -void CompilationGraph::PassThroughGraph (const sys::Path& InFile, - const Node* StartNode, - const InputLanguagesSet& InLangs, - const sys::Path& TempDir, - const LanguageMap& LangMap) const { +int CompilationGraph::PassThroughGraph (const sys::Path& InFile, + const Node* StartNode, + const InputLanguagesSet& InLangs, + const sys::Path& TempDir, + const LanguageMap& LangMap) const { sys::Path In = InFile; const Node* CurNode = StartNode; @@ -158,25 +174,35 @@ void CompilationGraph::PassThroughGraph (const sys::Path& InFile, Tool* CurTool = CurNode->ToolPtr.getPtr(); if (CurTool->IsJoin()) { - JoinTool& JT = dynamic_cast(*CurTool); + JoinTool& JT = static_cast(*CurTool); JT.AddToJoinList(In); break; } - Action CurAction = CurTool->GenerateAction(In, CurNode->HasChildren(), - TempDir, InLangs, LangMap); + Action CurAction; + if (int ret = CurTool->GenerateAction(CurAction, In, CurNode->HasChildren(), + TempDir, InLangs, LangMap)) { + return ret; + } if (int ret = CurAction.Execute()) - throw error_code(ret); + return ret; if (CurAction.StopCompilation()) - return; + return 0; + + const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name()); + if (Edg == 0) + return -1; + + CurNode = getNode(Edg->ToolName()); + if (CurNode == 0) + return -1; - CurNode = &getNode(ChooseEdge(CurNode->OutEdges, - InLangs, - CurNode->Name())->ToolName()); In = CurAction.OutFile(); } + + return 0; } // Find the head of the toolchain corresponding to the given file. @@ -186,26 +212,39 @@ FindToolChain(const sys::Path& In, const std::string* ForceLanguage, InputLanguagesSet& InLangs, const LanguageMap& LangMap) const { // Determine the input language. - const std::string& InLanguage = - ForceLanguage ? *ForceLanguage : LangMap.GetLanguage(In); + const std::string* InLang = LangMap.GetLanguage(In); + if (InLang == 0) + return 0; + const std::string& InLanguage = (ForceLanguage ? *ForceLanguage : *InLang); // Add the current input language to the input language set. InLangs.insert(InLanguage); // Find the toolchain for the input language. - const tools_vector_type& TV = getToolsVector(InLanguage); - if (TV.empty()) - throw std::runtime_error("No toolchain corresponding to language " - + InLanguage + " found"); - return &getNode(ChooseEdge(TV, InLangs)->ToolName()); + const tools_vector_type* pTV = getToolsVector(InLanguage); + if (pTV == 0) + return 0; + + const tools_vector_type& TV = *pTV; + if (TV.empty()) { + PrintError("No toolchain corresponding to language " + + InLanguage + " found"); + return 0; + } + + const Edge* Edg = ChooseEdge(TV, InLangs); + if (Edg == 0) + return 0; + + return getNode(Edg->ToolName()); } // Helper function used by Build(). // Traverses initial portions of the toolchains (up to the first Join node). // This function is also responsible for handling the -x option. -void CompilationGraph::BuildInitial (InputLanguagesSet& InLangs, - const sys::Path& TempDir, - const LanguageMap& LangMap) { +int CompilationGraph::BuildInitial (InputLanguagesSet& InLangs, + const sys::Path& TempDir, + const LanguageMap& LangMap) { // This is related to -x option handling. cl::list::const_iterator xIter = Languages.begin(), xBegin = xIter, xEnd = Languages.end(); @@ -255,15 +294,25 @@ void CompilationGraph::BuildInitial (InputLanguagesSet& InLangs, // Find the toolchain corresponding to this file. const Node* N = FindToolChain(In, xLanguage, InLangs, LangMap); + if (N == 0) + return -1; // Pass file through the chain starting at head. - PassThroughGraph(In, N, InLangs, TempDir, LangMap); + if (int ret = PassThroughGraph(In, N, InLangs, TempDir, LangMap)) + return ret; } + + return 0; } // Sort the nodes in topological order. -void CompilationGraph::TopologicalSort(std::vector& Out) { +int CompilationGraph::TopologicalSort(std::vector& Out) { std::queue Q; - Q.push(&getNode("root")); + + Node* Root = getNode("root"); + if (Root == 0) + return -1; + + Q.push(Root); while (!Q.empty()) { const Node* A = Q.front(); @@ -271,12 +320,17 @@ void CompilationGraph::TopologicalSort(std::vector& Out) { Out.push_back(A); for (Node::const_iterator EB = A->EdgesBegin(), EE = A->EdgesEnd(); EB != EE; ++EB) { - Node* B = &getNode((*EB)->ToolName()); + Node* B = getNode((*EB)->ToolName()); + if (B == 0) + return -1; + B->DecrInEdges(); if (B->HasNoInEdges()) Q.push(B); } } + + return 0; } namespace { @@ -287,49 +341,64 @@ namespace { // Call TopologicalSort and filter the resulting list to include // only Join nodes. -void CompilationGraph:: +int CompilationGraph:: TopologicalSortFilterJoinNodes(std::vector& Out) { std::vector TopSorted; - TopologicalSort(TopSorted); + if (int ret = TopologicalSort(TopSorted)) + return ret; std::remove_copy_if(TopSorted.begin(), TopSorted.end(), std::back_inserter(Out), NotJoinNode); + + return 0; } int CompilationGraph::Build (const sys::Path& TempDir, const LanguageMap& LangMap) { - InputLanguagesSet InLangs; // Traverse initial parts of the toolchains and fill in InLangs. - BuildInitial(InLangs, TempDir, LangMap); + if (int ret = BuildInitial(InLangs, TempDir, LangMap)) + return ret; std::vector JTV; - TopologicalSortFilterJoinNodes(JTV); + if (int ret = TopologicalSortFilterJoinNodes(JTV)) + return ret; // For all join nodes in topological order: for (std::vector::iterator B = JTV.begin(), E = JTV.end(); B != E; ++B) { const Node* CurNode = *B; - JoinTool* JT = &dynamic_cast(*CurNode->ToolPtr.getPtr()); + JoinTool* JT = &static_cast(*CurNode->ToolPtr.getPtr()); // Are there any files in the join list? if (JT->JoinListEmpty() && !(JT->WorksOnEmpty() && InputFilenames.empty())) continue; - Action CurAction = JT->GenerateAction(CurNode->HasChildren(), - TempDir, InLangs, LangMap); + Action CurAction; + if (int ret = JT->GenerateAction(CurAction, CurNode->HasChildren(), + TempDir, InLangs, LangMap)) { + return ret; + } if (int ret = CurAction.Execute()) - throw error_code(ret); + return ret; if (CurAction.StopCompilation()) return 0; - const Node* NextNode = &getNode(ChooseEdge(CurNode->OutEdges, InLangs, - CurNode->Name())->ToolName()); - PassThroughGraph(sys::Path(CurAction.OutFile()), NextNode, - InLangs, TempDir, LangMap); + const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name()); + if (Edg == 0) + return -1; + + const Node* NextNode = getNode(Edg->ToolName()); + if (NextNode == 0) + return -1; + + if (int ret = PassThroughGraph(sys::Path(CurAction.OutFile()), NextNode, + InLangs, TempDir, LangMap)) { + return ret; + } } return 0; @@ -337,6 +406,7 @@ int CompilationGraph::Build (const sys::Path& TempDir, int CompilationGraph::CheckLanguageNames() const { int ret = 0; + // Check that names for output and input languages on all edges do match. for (const_nodes_iterator B = this->NodesMap.begin(), E = this->NodesMap.end(); B != E; ++B) { @@ -345,9 +415,11 @@ int CompilationGraph::CheckLanguageNames() const { if (N1.ToolPtr) { for (Node::const_iterator EB = N1.EdgesBegin(), EE = N1.EdgesEnd(); EB != EE; ++EB) { - const Node& N2 = this->getNode((*EB)->ToolName()); + const Node* N2 = this->getNode((*EB)->ToolName()); + if (N2 == 0) + return -1; - if (!N2.ToolPtr) { + if (!N2->ToolPtr) { ++ret; errs() << "Error: there is an edge from '" << N1.ToolPtr->Name() << "' back to the root!\n\n"; @@ -355,7 +427,7 @@ int CompilationGraph::CheckLanguageNames() const { } const char* OutLang = N1.ToolPtr->OutputLanguage(); - const char** InLangs = N2.ToolPtr->InputLanguages(); + const char** InLangs = N2->ToolPtr->InputLanguages(); bool eq = false; for (;*InLangs; ++InLangs) { if (std::strcmp(OutLang, *InLangs) == 0) { @@ -367,11 +439,11 @@ int CompilationGraph::CheckLanguageNames() const { if (!eq) { ++ret; errs() << "Error: Output->input language mismatch in the edge '" - << N1.ToolPtr->Name() << "' -> '" << N2.ToolPtr->Name() + << N1.ToolPtr->Name() << "' -> '" << N2->ToolPtr->Name() << "'!\n" << "Expected one of { "; - InLangs = N2.ToolPtr->InputLanguages(); + InLangs = N2->ToolPtr->InputLanguages(); for (;*InLangs; ++InLangs) { errs() << '\'' << *InLangs << (*(InLangs+1) ? "', " : "'"); } @@ -422,7 +494,12 @@ int CompilationGraph::CheckMultipleDefaultEdges() const { int CompilationGraph::CheckCycles() { unsigned deleted = 0; std::queue Q; - Q.push(&getNode("root")); + + Node* Root = getNode("root"); + if (Root == 0) + return -1; + + Q.push(Root); // Try to delete all nodes that have no ingoing edges, starting from the // root. If there are any nodes left after this operation, then we have a @@ -434,7 +511,10 @@ int CompilationGraph::CheckCycles() { for (Node::iterator EB = A->EdgesBegin(), EE = A->EdgesEnd(); EB != EE; ++EB) { - Node* B = &getNode((*EB)->ToolName()); + Node* B = getNode((*EB)->ToolName()); + if (B == 0) + return -1; + B->DecrInEdges(); if (B->HasNoInEdges()) Q.push(B); @@ -453,18 +533,28 @@ int CompilationGraph::CheckCycles() { int CompilationGraph::Check () { // We try to catch as many errors as we can in one go. + int errs = 0; int ret = 0; // Check that output/input language names match. - ret += this->CheckLanguageNames(); + ret = this->CheckLanguageNames(); + if (ret < 0) + return -1; + errs += ret; // Check for multiple default edges. - ret += this->CheckMultipleDefaultEdges(); + ret = this->CheckMultipleDefaultEdges(); + if (ret < 0) + return -1; + errs += ret; // Check for cycles. - ret += this->CheckCycles(); + ret = this->CheckCycles(); + if (ret < 0) + return -1; + errs += ret; - return ret; + return errs; } // Code related to graph visualization. @@ -516,7 +606,7 @@ namespace llvm { } -void CompilationGraph::writeGraph(const std::string& OutputFilename) { +int CompilationGraph::writeGraph(const std::string& OutputFilename) { std::string ErrorInfo; raw_fd_ostream O(OutputFilename.c_str(), ErrorInfo); @@ -526,9 +616,11 @@ void CompilationGraph::writeGraph(const std::string& OutputFilename) { errs() << "done.\n"; } else { - throw std::runtime_error("Error opening file '" + OutputFilename - + "' for writing!"); + PrintError("Error opening file '" + OutputFilename + "' for writing!"); + return -1; } + + return 0; } void CompilationGraph::viewGraph() { diff --git a/lib/CompilerDriver/Main.cpp b/lib/CompilerDriver/Main.cpp index b5e507dfc3a..28b2737f38b 100644 --- a/lib/CompilerDriver/Main.cpp +++ b/lib/CompilerDriver/Main.cpp @@ -20,7 +20,6 @@ #include "llvm/System/Path.h" #include -#include #include namespace cl = llvm::cl; @@ -31,9 +30,7 @@ namespace { std::stringstream* GlobalTimeLog; - sys::Path getTempDir() { - sys::Path tempDir; - + int getTempDir(sys::Path& tempDir) { // The --temp-dir option. if (!TempDirname.empty()) { tempDir = TempDirname; @@ -41,7 +38,7 @@ namespace { // GCC 4.5-style -save-temps handling. else if (SaveTemps == SaveTempsEnum::Unset) { tempDir = sys::Path::GetTemporaryDirectory(); - return tempDir; + return 0; } else if (SaveTemps == SaveTempsEnum::Obj && !OutputFilename.empty()) { tempDir = OutputFilename; @@ -49,35 +46,34 @@ namespace { } else { // SaveTemps == Cwd --> use current dir (leave tempDir empty). - return tempDir; + return 0; } if (!tempDir.exists()) { std::string ErrMsg; - if (tempDir.createDirectoryOnDisk(true, &ErrMsg)) - throw std::runtime_error(ErrMsg); + if (tempDir.createDirectoryOnDisk(true, &ErrMsg)) { + PrintError(ErrMsg); + return -1; + } } - return tempDir; + return 0; } /// BuildTargets - A small wrapper for CompilationGraph::Build. int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) { int ret; - const sys::Path& tempDir = getTempDir(); + sys::Path tempDir; bool toDelete = (SaveTemps == SaveTempsEnum::Unset); - try { - ret = graph.Build(tempDir, langMap); - } - catch(...) { - if (toDelete) - tempDir.eraseFromDisk(true); - throw; - } + if (int ret = getTempDir(tempDir)) + return ret; + + ret = graph.Build(tempDir, langMap); if (toDelete) tempDir.eraseFromDisk(true); + return ret; } } @@ -93,64 +89,54 @@ void AppendToGlobalTimeLog(const std::string& cmd, double time) { const char* ProgramName; int Main(int argc, char** argv) { - try { - LanguageMap langMap; - CompilationGraph graph; - - ProgramName = argv[0]; + int ret = 0; + LanguageMap langMap; + CompilationGraph graph; - cl::ParseCommandLineOptions - (argc, argv, "LLVM Compiler Driver (Work In Progress)", - /* ReadResponseFiles = */ false); + ProgramName = argv[0]; - PluginLoader Plugins; - Plugins.RunInitialization(langMap, graph); + cl::ParseCommandLineOptions + (argc, argv, "LLVM Compiler Driver (Work In Progress)", + /* ReadResponseFiles = */ false); - if (CheckGraph) { - int ret = graph.Check(); - if (!ret) - llvm::errs() << "check-graph: no errors found.\n"; + PluginLoader Plugins; + if (int ret = Plugins.RunInitialization(langMap, graph)) + return ret; - return ret; - } + if (CheckGraph) { + ret = graph.Check(); + if (!ret) + llvm::errs() << "check-graph: no errors found.\n"; - if (ViewGraph) { - graph.viewGraph(); - if (!WriteGraph) - return 0; - } + return ret; + } - if (WriteGraph) { - graph.writeGraph(OutputFilename.empty() - ? std::string("compilation-graph.dot") - : OutputFilename); + if (ViewGraph) { + graph.viewGraph(); + if (!WriteGraph) return 0; - } + } - if (Time) { - GlobalTimeLog = new std::stringstream; - GlobalTimeLog->precision(2); - } + if (WriteGraph) { + const std::string& Out = (OutputFilename.empty() + ? std::string("compilation-graph.dot") + : OutputFilename); + return graph.writeGraph(Out); + } - int ret = BuildTargets(graph, langMap); + if (Time) { + GlobalTimeLog = new std::stringstream; + GlobalTimeLog->precision(2); + } - if (Time) { - llvm::errs() << GlobalTimeLog->str(); - delete GlobalTimeLog; - } + ret = BuildTargets(graph, langMap); - return ret; - } - catch(llvmc::error_code& ec) { - return ec.code(); + if (Time) { + llvm::errs() << GlobalTimeLog->str(); + delete GlobalTimeLog; } - catch(const std::exception& ex) { - llvm::errs() << argv[0] << ": " << ex.what() << '\n'; - } - catch(...) { - llvm::errs() << argv[0] << ": unknown error!\n"; - } - return 1; + + return ret; } } // end namespace llvmc diff --git a/lib/CompilerDriver/Makefile b/lib/CompilerDriver/Makefile index 66c6d11552f..b829f5261c4 100644 --- a/lib/CompilerDriver/Makefile +++ b/lib/CompilerDriver/Makefile @@ -21,9 +21,6 @@ else LINK_COMPONENTS = support system endif -REQUIRES_EH := 1 -REQUIRES_RTTI := 1 - include $(LEVEL)/Makefile.common ifeq ($(ENABLE_LLVMC_DYNAMIC_PLUGINS), 1) diff --git a/lib/CompilerDriver/Plugin.cpp b/lib/CompilerDriver/Plugin.cpp index 0fdfef4c6a2..c06bda3eff6 100644 --- a/lib/CompilerDriver/Plugin.cpp +++ b/lib/CompilerDriver/Plugin.cpp @@ -62,17 +62,22 @@ namespace llvmc { pluginListInitialized = false; } - void PluginLoader::RunInitialization(LanguageMap& langMap, + int PluginLoader::RunInitialization(LanguageMap& langMap, CompilationGraph& graph) const { llvm::sys::SmartScopedLock Lock(*PluginMutex); for (PluginList::iterator B = Plugins.begin(), E = Plugins.end(); B != E; ++B) { const BasePlugin* BP = *B; - BP->PreprocessOptions(); - BP->PopulateLanguageMap(langMap); - BP->PopulateCompilationGraph(graph); + if (int ret = BP->PreprocessOptions()) + return ret; + if (int ret = BP->PopulateLanguageMap(langMap)) + return ret; + if (int ret = BP->PopulateCompilationGraph(graph)) + return ret; } + + return 0; } } diff --git a/tools/llvmc/Makefile b/tools/llvmc/Makefile index 8f995265d2c..df91728ea36 100644 --- a/tools/llvmc/Makefile +++ b/tools/llvmc/Makefile @@ -11,7 +11,6 @@ LEVEL = ../.. export LLVMC_BASED_DRIVER_NAME = llvmc export LLVMC_BUILTIN_PLUGINS = Base Clang -REQUIRES_RTTI = 1 DIRS = plugins driver diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index 4a16930effe..be6e398bd8c 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -1957,10 +1957,10 @@ struct ActionHandlingCallbackBase unsigned IndentLevel, raw_ostream& O) const { O.indent(IndentLevel) - << "throw std::runtime_error(\"" << - (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0)) - : "Unknown error!") + << "PrintError(\"" + << (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0)) : "Unknown error!") << "\");\n"; + O.indent(IndentLevel) << "return -1;\n"; } void onWarningDag(const DagInit& d, @@ -2154,25 +2154,32 @@ class EmitActionHandlersCallback : }; void EmitGenerateActionMethodHeader(const ToolDescription& D, - bool IsJoin, raw_ostream& O) + bool IsJoin, bool Naked, + raw_ostream& O) { + O.indent(Indent1) << "int GenerateAction(Action& Out,\n"; + if (IsJoin) - O.indent(Indent1) << "Action GenerateAction(const PathVector& inFiles,\n"; + O.indent(Indent2) << "const PathVector& inFiles,\n"; else - O.indent(Indent1) << "Action GenerateAction(const sys::Path& inFile,\n"; + O.indent(Indent2) << "const sys::Path& inFile,\n"; - O.indent(Indent2) << "bool HasChildren,\n"; + O.indent(Indent2) << "const bool HasChildren,\n"; O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n"; O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n"; O.indent(Indent2) << "const LanguageMap& LangMap) const\n"; O.indent(Indent1) << "{\n"; - O.indent(Indent2) << "std::string cmd;\n"; - O.indent(Indent2) << "std::string out_file;\n"; - O.indent(Indent2) << "std::vector > vec;\n"; - O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n"; - O.indent(Indent2) << "bool no_out_file = false;\n"; - O.indent(Indent2) << "const char* output_suffix = \"" - << D.OutputSuffix << "\";\n"; + + if (!Naked) { + O.indent(Indent2) << "std::string cmd;\n"; + O.indent(Indent2) << "std::string out_file;\n"; + O.indent(Indent2) + << "std::vector > vec;\n"; + O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n"; + O.indent(Indent2) << "bool no_out_file = false;\n"; + O.indent(Indent2) << "const char* output_suffix = \"" + << D.OutputSuffix << "\";\n"; + } } // EmitGenerateActionMethod - Emit either a normal or a "join" version of the @@ -2181,7 +2188,7 @@ void EmitGenerateActionMethod (const ToolDescription& D, const OptionDescriptions& OptDescs, bool IsJoin, raw_ostream& O) { - EmitGenerateActionMethodHeader(D, IsJoin, O); + EmitGenerateActionMethodHeader(D, IsJoin, /* Naked = */ false, O); if (!D.CmdLine) throw "Tool " + D.Name + " has no cmd_line property!"; @@ -2245,8 +2252,9 @@ void EmitGenerateActionMethod (const ToolDescription& D, O.indent(Indent2) << "}\n"; } - O.indent(Indent2) << "return Action(cmd, this->SortArgs(vec), " + O.indent(Indent2) << "Out.Construct(cmd, this->SortArgs(vec), " << "stop_compilation, out_file);\n"; + O.indent(Indent2) << "return 0;\n"; O.indent(Indent1) << "}\n\n"; } @@ -2256,14 +2264,11 @@ void EmitGenerateActionMethods (const ToolDescription& ToolDesc, const OptionDescriptions& OptDescs, raw_ostream& O) { if (!ToolDesc.isJoin()) { - O.indent(Indent1) << "Action GenerateAction(const PathVector& inFiles,\n"; - O.indent(Indent2) << "bool HasChildren,\n"; - O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n"; - O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n"; - O.indent(Indent2) << "const LanguageMap& LangMap) const\n"; - O.indent(Indent1) << "{\n"; - O.indent(Indent2) << "throw std::runtime_error(\"" << ToolDesc.Name + EmitGenerateActionMethodHeader(ToolDesc, /* IsJoin = */ true, + /* Naked = */ true, O); + O.indent(Indent2) << "PrintError(\"" << ToolDesc.Name << " is not a Join tool!\");\n"; + O.indent(Indent2) << "return -1;\n"; O.indent(Indent1) << "}\n\n"; } else { @@ -2627,7 +2632,7 @@ public: void EmitPreprocessOptions (const RecordKeeper& Records, const OptionDescriptions& OptDecs, raw_ostream& O) { - O << "void PreprocessOptionsLocal() {\n"; + O << "int PreprocessOptionsLocal() {\n"; const RecordVector& OptionPreprocessors = Records.getAllDerivedDefinitions("OptionPreprocessor"); @@ -2640,13 +2645,15 @@ void EmitPreprocessOptions (const RecordKeeper& Records, false, OptDecs, O); } + O << '\n'; + O.indent(Indent1) << "return 0;\n"; O << "}\n\n"; } /// EmitPopulateLanguageMap - Emit the PopulateLanguageMapLocal() function. void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O) { - O << "void PopulateLanguageMapLocal(LanguageMap& langMap) {\n"; + O << "int PopulateLanguageMapLocal(LanguageMap& langMap) {\n"; // Get the relevant field out of RecordKeeper const Record* LangMapRecord = Records.getDef("LanguageMap"); @@ -2671,6 +2678,8 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O) } } + O << '\n'; + O.indent(Indent1) << "return 0;\n"; O << "}\n\n"; } @@ -2688,10 +2697,12 @@ void IncDecWeight (const Init* i, unsigned IndentLevel, O.indent(IndentLevel) << "ret -= "; } else if (OpName == "error") { + // TODO: fix this CheckNumberOfArguments(d, 1); - O.indent(IndentLevel) << "throw std::runtime_error(\"" + O.indent(IndentLevel) << "PrintError(\"" << InitPtrToString(d.getArg(0)) << "\");\n"; + O.indent(IndentLevel) << "return -1;\n"; return; } else { @@ -2752,7 +2763,7 @@ void EmitPopulateCompilationGraph (const RecordVector& EdgeVector, const ToolDescriptions& ToolDescs, raw_ostream& O) { - O << "void PopulateCompilationGraphLocal(CompilationGraph& G) {\n"; + O << "int PopulateCompilationGraphLocal(CompilationGraph& G) {\n"; for (ToolDescriptions::const_iterator B = ToolDescs.begin(), E = ToolDescs.end(); B != E; ++B) @@ -2770,17 +2781,21 @@ void EmitPopulateCompilationGraph (const RecordVector& EdgeVector, const std::string& NodeB = Edge->getValueAsString("b"); DagInit& Weight = *Edge->getValueAsDag("weight"); - O.indent(Indent1) << "G.insertEdge(\"" << NodeA << "\", "; + O.indent(Indent1) << "if (int ret = G.insertEdge(\"" << NodeA << "\", "; if (IsDagEmpty(Weight)) O << "new SimpleEdge(\"" << NodeB << "\")"; else O << "new Edge" << i << "()"; - O << ");\n"; + O << "))\n"; + O.indent(Indent2) << "return ret;\n"; + ++i; } + O << '\n'; + O.indent(Indent1) << "return 0;\n"; O << "}\n\n"; } @@ -2963,13 +2978,13 @@ void EmitRegisterPlugin(int Priority, raw_ostream& O) { O << "struct Plugin : public llvmc::BasePlugin {\n\n"; O.indent(Indent1) << "int Priority() const { return " << Priority << "; }\n\n"; - O.indent(Indent1) << "void PreprocessOptions() const\n"; - O.indent(Indent1) << "{ PreprocessOptionsLocal(); }\n\n"; - O.indent(Indent1) << "void PopulateLanguageMap(LanguageMap& langMap) const\n"; - O.indent(Indent1) << "{ PopulateLanguageMapLocal(langMap); }\n\n"; + O.indent(Indent1) << "int PreprocessOptions() const\n"; + O.indent(Indent1) << "{ return PreprocessOptionsLocal(); }\n\n"; + O.indent(Indent1) << "int PopulateLanguageMap(LanguageMap& langMap) const\n"; + O.indent(Indent1) << "{ return PopulateLanguageMapLocal(langMap); }\n\n"; O.indent(Indent1) - << "void PopulateCompilationGraph(CompilationGraph& graph) const\n"; - O.indent(Indent1) << "{ PopulateCompilationGraphLocal(graph); }\n" + << "int PopulateCompilationGraph(CompilationGraph& graph) const\n"; + O.indent(Indent1) << "{ return PopulateCompilationGraphLocal(graph); }\n" << "};\n\n" << "static llvmc::RegisterPlugin RP;\n\n"; } @@ -2979,6 +2994,7 @@ void EmitRegisterPlugin(int Priority, raw_ostream& O) { void EmitIncludes(raw_ostream& O) { O << "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n" << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n" + << "#include \"llvm/CompilerDriver/Error.h\"\n" << "#include \"llvm/CompilerDriver/ForceLinkageMacros.h\"\n" << "#include \"llvm/CompilerDriver/Plugin.h\"\n" << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"