diff --git a/lib/Support/GraphWriter.cpp b/lib/Support/GraphWriter.cpp index 152261fbac6..501cc6d89d3 100644 --- a/lib/Support/GraphWriter.cpp +++ b/lib/Support/GraphWriter.cpp @@ -19,6 +19,7 @@ using namespace llvm; void llvm::DisplayGraph(const sys::Path &Filename) { + std::string ErrMsg; #if HAVE_GRAPHVIZ sys::Path Graphviz(LLVM_PATH_GRAPHVIZ); @@ -28,8 +29,8 @@ void llvm::DisplayGraph(const sys::Path &Filename) { args.push_back(0); std::cerr << "Running 'Graphviz' program... " << std::flush; - if (sys::Program::ExecuteAndWait(Graphviz, &args[0])) { - std::cerr << "Error viewing graph: 'Graphviz' not in path?\n"; + if (sys::Program::ExecuteAndWait(Graphviz, &args[0],0,0,0,&ErrMsg)) { + std::cerr << "Error viewing graph: " << ErrMsg << "\n"; } #elif (HAVE_GV && HAVE_DOT) sys::Path PSFilename = Filename; @@ -48,8 +49,8 @@ void llvm::DisplayGraph(const sys::Path &Filename) { args.push_back(0); std::cerr << "Running 'dot' program... " << std::flush; - if (sys::Program::ExecuteAndWait(dot, &args[0])) { - std::cerr << "Error viewing graph: 'dot' not in path?\n"; + if (sys::Program::ExecuteAndWait(dot, &args[0],0,0,0,&ErrMsg)) { + std::cerr << "Error viewing graph: '" << ErrMsg << "\n"; } else { std::cerr << " done. \n"; @@ -59,8 +60,9 @@ void llvm::DisplayGraph(const sys::Path &Filename) { args.push_back(PSFilename.c_str()); args.push_back(0); - if (sys::Program::ExecuteAndWait(gv, &args[0])) { - std::cerr << "Error viewing graph: 'gv' not in path?\n"; + ErrMsg.clear(); + if (sys::Program::ExecuteAndWait(gv, &args[0],0,0,0,&ErrMsg)) { + std::cerr << "Error viewing graph: " << ErrMsg << "\n"; } } PSFilename.eraseFromDisk(); @@ -72,8 +74,8 @@ void llvm::DisplayGraph(const sys::Path &Filename) { args.push_back(0); std::cerr << "Running 'dotty' program... " << std::flush; - if (sys::Program::ExecuteAndWait(dotty, &args[0])) { - std::cerr << "Error viewing graph: 'dotty' not in path?\n"; + if (sys::Program::ExecuteAndWait(dotty, &args[0],0,0,0,&ErrMsg)) { + std::cerr << "Error viewing graph: " << ErrMsg << "\n"; } else { #ifdef __MINGW32__ // Dotty spawns another app and doesn't wait until it returns. return; diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index 0ac514bbefe..4311200cc36 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -179,7 +179,8 @@ bool BugDriver::runPasses(const std::vector &Passes, args[n++] = 0; sys::Path prog(sys::Program::FindProgramByName(ToolName)); - int result = sys::Program::ExecuteAndWait(prog,args,0,0,Timeout); + std::string ErrMsg; + int result = sys::Program::ExecuteAndWait(prog,args,0,0,Timeout,&ErrMsg); // If we are supposed to delete the bytecode file or if the passes crashed, // remove it now. This may fail if the file was never created, but that's ok. @@ -194,10 +195,12 @@ bool BugDriver::runPasses(const std::vector &Passes, std::cout << "Success!\n"; else if (result > 0) std::cout << "Exited with error code '" << result << "'\n"; - else if (result == -9999) - std::cout << "Program not executable\n"; - else if (result < 0) - std::cout << "Crashed with signal #" << abs(result) << "\n"; + else if (result < 0) { + if (result == -1) + std::cout << "Execute failed: " << ErrMsg << "\n"; + else + std::cout << "Crashed with signal #" << abs(result) << "\n"; + } if (result & 0x01000000) std::cout << "Dumped core\n"; } diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 067bf658c73..8712baf353c 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -55,7 +55,7 @@ static void ProcessFailure(sys::Path ProgPath, const char** Args) { sys::Path ErrorFilename("error_messages"); ErrorFilename.makeUnique(); RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, - ErrorFilename); // FIXME: check return code + ErrorFilename); // FIXME: check return code ? // Print out the error messages generated by GCC if possible... std::ifstream ErrorFile(ErrorFilename.c_str()); diff --git a/tools/gccld/GenerateCode.cpp b/tools/gccld/GenerateCode.cpp index 63dda12aa07..285f7ca84cd 100644 --- a/tools/gccld/GenerateCode.cpp +++ b/tools/gccld/GenerateCode.cpp @@ -297,6 +297,7 @@ int llvm::GenerateBytecode(Module *M, int StripLevel, bool Internalize, int llvm::GenerateAssembly(const std::string &OutputFilename, const std::string &InputFilename, const sys::Path &llc, + std::string& ErrMsg, bool Verbose) { // Run LLC to convert the bytecode file into assembly code. std::vector args; @@ -307,13 +308,14 @@ int llvm::GenerateAssembly(const std::string &OutputFilename, args.push_back(InputFilename.c_str()); args.push_back(0); if (Verbose) dumpArgs(&args[0]); - return sys::Program::ExecuteAndWait(llc, &args[0]); + return sys::Program::ExecuteAndWait(llc, &args[0],0,0,0,&ErrMsg); } /// GenerateCFile - generates a C source file from the specified bytecode file. int llvm::GenerateCFile(const std::string &OutputFile, const std::string &InputFile, const sys::Path &llc, + std::string& ErrMsg, bool Verbose) { // Run LLC to convert the bytecode file into C. std::vector args; @@ -325,7 +327,7 @@ int llvm::GenerateCFile(const std::string &OutputFile, args.push_back(InputFile.c_str()); args.push_back(0); if (Verbose) dumpArgs(&args[0]); - return sys::Program::ExecuteAndWait(llc, &args[0]); + return sys::Program::ExecuteAndWait(llc, &args[0],0,0,0,&ErrMsg); } /// GenerateNative - generates a native executable file from the specified @@ -352,6 +354,7 @@ int llvm::GenerateNative(const std::string &OutputFilename, bool ExportAllAsDynamic, const std::vector &RPaths, const std::string &SOName, + std::string& ErrMsg, bool Verbose) { // Remove these environment variables from the environment of the // programs that we will execute. It appears that GCC sets these @@ -436,7 +439,8 @@ int llvm::GenerateNative(const std::string &OutputFilename, // Run the compiler to assembly and link together the program. if (Verbose) dumpArgs(&args[0]); - int Res = sys::Program::ExecuteAndWait(gcc, &args[0],(const char**)clean_env); + int Res = sys::Program::ExecuteAndWait( + gcc, &args[0],(const char**)clean_env,0,0,&ErrMsg); delete [] clean_env; diff --git a/tools/gccld/gccld.cpp b/tools/gccld/gccld.cpp index 22a26ef91a7..a9df06d69c7 100644 --- a/tools/gccld/gccld.cpp +++ b/tools/gccld/gccld.cpp @@ -320,12 +320,19 @@ int main(int argc, char **argv, char **envp ) { // Generate an assembly language file for the bytecode. if (Verbose) std::cout << "Generating Assembly Code\n"; - GenerateAssembly(AssemblyFile.toString(), RealBytecodeOutput, llc, - Verbose); + std::string ErrMsg; + if (0 != GenerateAssembly( + AssemblyFile.toString(), RealBytecodeOutput, llc, ErrMsg, Verbose)) { + std::cerr << argv[0] << ": " << ErrMsg << "\n"; + return 2; + } if (Verbose) std::cout << "Generating Native Code\n"; - GenerateNative(OutputFilename, AssemblyFile.toString(), + if (0 != GenerateNative(OutputFilename, AssemblyFile.toString(), LibPaths, Libraries, gcc, envp, LinkAsLibrary, - NoInternalize, RPath, SOName, Verbose); + NoInternalize, RPath, SOName, ErrMsg, Verbose) ) { + std::cerr << argv[0] << ": " << ErrMsg << "\n"; + return 2; + } if (!SaveTemps) { // Remove the assembly language file. @@ -353,11 +360,19 @@ int main(int argc, char **argv, char **envp ) { // Generate an assembly language file for the bytecode. if (Verbose) std::cout << "Generating C Source Code\n"; - GenerateCFile(CFile.toString(), RealBytecodeOutput, llc, Verbose); + std::string ErrMsg; + if (0 != GenerateCFile( + CFile.toString(), RealBytecodeOutput, llc, ErrMsg, Verbose)) { + std::cerr << argv[0] << ": " << ErrMsg << "\n"; + return 2; + } if (Verbose) std::cout << "Generating Native Code\n"; - GenerateNative(OutputFilename, CFile.toString(), + if (0 != GenerateNative(OutputFilename, CFile.toString(), LibPaths, Libraries, gcc, envp, LinkAsLibrary, - NoInternalize, RPath, SOName, Verbose); + NoInternalize, RPath, SOName, ErrMsg, Verbose)) { + std::cerr << argv[0] << ": " << ErrMsg << "\n"; + return 2; + } if (!SaveTemps) { // Remove the assembly language file. diff --git a/tools/gccld/gccld.h b/tools/gccld/gccld.h index 8dbae884c22..62c058a2df5 100644 --- a/tools/gccld/gccld.h +++ b/tools/gccld/gccld.h @@ -30,12 +30,14 @@ int GenerateAssembly (const std::string &OutputFilename, const std::string &InputFilename, const sys::Path &llc, + std::string& ErrMsg, bool Verbose=false); int GenerateCFile (const std::string &OutputFile, const std::string &InputFile, const sys::Path &llc, + std::string& ErrMsg, bool Verbose=false); int GenerateNative (const std::string &OutputFilename, @@ -48,6 +50,7 @@ GenerateNative (const std::string &OutputFilename, bool ExportAllAsDynamic, const std::vector &RPath, const std::string &SOName, + std::string& ErrMsg, bool Verbose=false); } // End llvm namespace diff --git a/tools/llvm-ld/llvm-ld.cpp b/tools/llvm-ld/llvm-ld.cpp index 9b56bdd1f0e..c8e505c9757 100644 --- a/tools/llvm-ld/llvm-ld.cpp +++ b/tools/llvm-ld/llvm-ld.cpp @@ -227,7 +227,8 @@ void GenerateBytecode(Module* M, const std::string& FileName) { /// static int GenerateAssembly(const std::string &OutputFilename, const std::string &InputFilename, - const sys::Path &llc) { + const sys::Path &llc, + std::string &ErrMsg ) { // Run LLC to convert the bytecode file into assembly code. std::vector args; args.push_back(llc.c_str()); @@ -237,13 +238,14 @@ static int GenerateAssembly(const std::string &OutputFilename, args.push_back(InputFilename.c_str()); args.push_back(0); - return sys::Program::ExecuteAndWait(llc,&args[0]); + return sys::Program::ExecuteAndWait(llc,&args[0],0,0,0,&ErrMsg); } /// GenerateCFile - generates a C source file from the specified bytecode file. static int GenerateCFile(const std::string &OutputFile, const std::string &InputFile, - const sys::Path &llc) { + const sys::Path &llc, + std::string& ErrMsg) { // Run LLC to convert the bytecode file into C. std::vector args; args.push_back(llc.c_str()); @@ -253,7 +255,7 @@ static int GenerateCFile(const std::string &OutputFile, args.push_back(OutputFile.c_str()); args.push_back(InputFile.c_str()); args.push_back(0); - return sys::Program::ExecuteAndWait(llc, &args[0]); + return sys::Program::ExecuteAndWait(llc, &args[0],0,0,0,&ErrMsg); } /// GenerateNative - generates a native object file from the @@ -275,7 +277,8 @@ static int GenerateCFile(const std::string &OutputFile, static int GenerateNative(const std::string &OutputFilename, const std::string &InputFilename, const std::vector &Libraries, - const sys::Path &gcc, char ** const envp) { + const sys::Path &gcc, char ** const envp, + std::string& ErrMsg) { // Remove these environment variables from the environment of the // programs that we will execute. It appears that GCC sets these // environment variables so that the programs it uses can configure @@ -329,7 +332,8 @@ static int GenerateNative(const std::string &OutputFilename, args.push_back(0); // Run the compiler to assembly and link together the program. - int R = sys::Program::ExecuteAndWait(gcc, &args[0], (const char**)clean_env); + int R = sys::Program::ExecuteAndWait( + gcc, &args[0], (const char**)clean_env,0,0,&ErrMsg); delete [] clean_env; return R; } @@ -497,7 +501,8 @@ int main(int argc, char **argv, char **envp) { args[1] = RealBytecodeOutput.c_str(); args[2] = tmp_output.c_str(); args[3] = 0; - if (0 == sys::Program::ExecuteAndWait(prog, args)) { + std::string ErrMsg; + if (0 == sys::Program::ExecuteAndWait(prog, args, 0,0,0, &ErrMsg)) { if (tmp_output.isBytecodeFile()) { sys::Path target(RealBytecodeOutput); target.eraseFromDisk(); @@ -505,6 +510,9 @@ int main(int argc, char **argv, char **envp) { } else return PrintAndReturn( "Post-link optimization output is not bytecode"); + } else { + std::cerr << argv[0] << ": " << ErrMsg << "\n"; + return 2; } } } @@ -533,10 +541,19 @@ int main(int argc, char **argv, char **envp) { // Generate an assembly language file for the bytecode. if (Verbose) std::cout << "Generating Assembly Code\n"; - GenerateAssembly(AssemblyFile.toString(), RealBytecodeOutput, llc); + std::string ErrMsg; + if (0 != GenerateAssembly(AssemblyFile.toString(), RealBytecodeOutput, + llc, ErrMsg)) { + std::cerr << argv[0] << ": " << ErrMsg << "\n"; + return 1; + } + if (Verbose) std::cout << "Generating Native Code\n"; - GenerateNative(OutputFilename, AssemblyFile.toString(), Libraries, - gcc, envp); + if (0 != GenerateNative(OutputFilename, AssemblyFile.toString(), + Libraries,gcc,envp,ErrMsg)) { + std::cerr << argv[0] << ": " << ErrMsg << "\n"; + return 1; + } // Remove the assembly language file. AssemblyFile.eraseFromDisk(); @@ -559,9 +576,19 @@ int main(int argc, char **argv, char **envp) { // Generate an assembly language file for the bytecode. if (Verbose) std::cout << "Generating Assembly Code\n"; - GenerateCFile(CFile.toString(), RealBytecodeOutput, llc); + std::string ErrMsg; + if (0 != GenerateCFile( + CFile.toString(), RealBytecodeOutput, llc, ErrMsg)) { + std::cerr << argv[0] << ": " << ErrMsg << "\n"; + return 1; + } + if (Verbose) std::cout << "Generating Native Code\n"; - GenerateNative(OutputFilename, CFile.toString(), Libraries, gcc, envp); + if (0 != GenerateNative(OutputFilename, CFile.toString(), Libraries, + gcc, envp, ErrMsg)) { + std::cerr << argv[0] << ": " << ErrMsg << "\n"; + return 1; + } // Remove the assembly language file. CFile.eraseFromDisk(); diff --git a/tools/llvmc/CompilerDriver.cpp b/tools/llvmc/CompilerDriver.cpp index 64232f3d2c1..a204964cd84 100644 --- a/tools/llvmc/CompilerDriver.cpp +++ b/tools/llvmc/CompilerDriver.cpp @@ -451,7 +451,7 @@ private: return action; } - bool DoAction(Action*action) { + int DoAction(Action*action, std::string& ErrMsg) { assert(action != 0 && "Invalid Action!"); if (isSet(VERBOSE_FLAG)) WriteAction(action); @@ -477,15 +477,17 @@ private: if (isSet(TIME_ACTIONS_FLAG)) { Timer timer(action->program.toString()); timer.startTimer(); - int resultCode = sys::Program::ExecuteAndWait(action->program, Args); + int resultCode = + sys::Program::ExecuteAndWait(action->program, Args,0,0,0,&ErrMsg); timer.stopTimer(); timer.print(timer,std::cerr); - return resultCode == 0; + return resultCode; } else - return 0 == sys::Program::ExecuteAndWait(action->program, Args); + return + sys::Program::ExecuteAndWait(action->program, Args, 0,0,0, &ErrMsg); } - return true; + return 0; } /// This method tries various variants of a linkage item's file @@ -594,7 +596,7 @@ private: /// @name Methods /// @{ public: - virtual int execute(const InputList& InpList, const sys::Path& Output ) { + virtual int execute(const InputList& InpList, const sys::Path& Output, std::string& ErrMsg ) { try { // Echo the configuration of options if we're running verbose if (isSet(DEBUG_FLAG)) { @@ -851,8 +853,9 @@ public: std::vector::iterator AI = actions.begin(); std::vector::iterator AE = actions.end(); while (AI != AE) { - if (!DoAction(*AI)) - throw std::string("Action failed"); + int ActionResult = DoAction(*AI, ErrMsg); + if (ActionResult != 0) + return ActionResult; AI++; } @@ -932,8 +935,9 @@ public: link->args.push_back(Output.toString()); // Execute the link - if (!DoAction(link)) - throw std::string("Action failed"); + int ActionResult = DoAction(link, ErrMsg); + if (ActionResult != 0) + return ActionResult; } } catch (std::string& msg) { cleanup(); diff --git a/tools/llvmc/CompilerDriver.h b/tools/llvmc/CompilerDriver.h index 41ad2c3bb46..02ec0e9f524 100644 --- a/tools/llvmc/CompilerDriver.h +++ b/tools/llvmc/CompilerDriver.h @@ -150,7 +150,8 @@ namespace llvm { /// @{ public: /// @brief Execute the actions requested for the given input list. - virtual int execute(const InputList& list, const sys::Path& output) = 0; + virtual int execute( + const InputList& list, const sys::Path& output, std::string& ErrMsg) =0; /// @brief Set the final phase at which compilation terminates virtual void setFinalPhase(Phases phase) = 0; diff --git a/tools/llvmc/llvmc.cpp b/tools/llvmc/llvmc.cpp index 496eaa41944..f2e7c1fb37b 100644 --- a/tools/llvmc/llvmc.cpp +++ b/tools/llvmc/llvmc.cpp @@ -355,9 +355,10 @@ int main(int argc, char **argv) { } // Tell the driver to do its thing - int result = CD->execute(InpList, sys::Path(OutputFilename)); + std::string ErrMsg; + int result = CD->execute(InpList, sys::Path(OutputFilename), ErrMsg); if (result != 0) { - throw std::string("Error executing actions. Terminated."); + std::cerr << argv[0] << ": " << ErrMsg << '\n'; return result; }