Index: test/BugPoint/compile-custom.ll =================================================================== --- test/BugPoint/compile-custom.ll +++ test/BugPoint/compile-custom.ll @@ -1,4 +1,4 @@ -; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext --compile-custom --compile-command="%/s.py arg1 arg2" --opt-command opt --output-prefix %t %s | FileCheck %s +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext --compile-custom --compile-command="%/s.py arg1 arg2" --output-prefix %t %s | FileCheck %s ; REQUIRES: loadable_module ; Test that arguments are correctly passed in --compile-command. The output Index: test/BugPoint/crash-narrowfunctiontest.ll =================================================================== --- test/BugPoint/crash-narrowfunctiontest.ll +++ test/BugPoint/crash-narrowfunctiontest.ll @@ -1,6 +1,6 @@ ; Test that bugpoint can narrow down the testcase to the important function ; -; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls --opt-command opt -silence-passes > /dev/null +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls -silence-passes > /dev/null ; REQUIRES: loadable_module define i32 @foo() { ret i32 1 } Index: test/BugPoint/invalid-debuginfo.ll =================================================================== --- test/BugPoint/invalid-debuginfo.ll +++ test/BugPoint/invalid-debuginfo.ll @@ -1,4 +1,4 @@ -; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes --opt-command opt 2>&1 | FileCheck %s +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes 2>&1 | FileCheck %s ; REQUIRES: loadable_module ; CHECK: DICompileUnit not listed in llvm.dbg.cu Index: test/BugPoint/metadata.ll =================================================================== --- test/BugPoint/metadata.ll +++ test/BugPoint/metadata.ll @@ -1,11 +1,11 @@ ; REQUIRES: loadable_module -; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls -silence-passes -disable-namedmd-remove -disable-strip-debuginfo -disable-strip-debug-types --opt-command opt > /dev/null +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls -silence-passes -disable-namedmd-remove -disable-strip-debuginfo -disable-strip-debug-types > /dev/null ; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s ; -; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-nodebug -bugpoint-crashcalls -silence-passes -disable-namedmd-remove --opt-command opt > /dev/null +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-nodebug -bugpoint-crashcalls -silence-passes -disable-namedmd-remove > /dev/null ; RUN: llvm-dis %t-nodebug-reduced-simplified.bc -o - | FileCheck %s --check-prefix=NODEBUG ; -; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-notype -bugpoint-crashcalls -silence-passes -disable-namedmd-remove -disable-strip-debuginfo --opt-command opt > /dev/null +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-notype -bugpoint-crashcalls -silence-passes -disable-namedmd-remove -disable-strip-debuginfo > /dev/null ; RUN: llvm-dis %t-notype-reduced-simplified.bc -o - | FileCheck %s --check-prefix=NOTYPE ; ; Bugpoint should keep the call's metadata attached to the call. Index: test/BugPoint/named-md.ll =================================================================== --- test/BugPoint/named-md.ll +++ test/BugPoint/named-md.ll @@ -1,4 +1,4 @@ -; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes -disable-strip-debuginfo --opt-command opt > /dev/null +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes -disable-strip-debuginfo > /dev/null ; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s ; RUN-DISABLE: bugpoint -disable-namedmd-remove -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes > /dev/null ; RUN-DISABLE: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s Index: test/BugPoint/remove_arguments_test.ll =================================================================== --- test/BugPoint/remove_arguments_test.ll +++ test/BugPoint/remove_arguments_test.ll @@ -1,4 +1,4 @@ -; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls -silence-passes --opt-command opt +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls -silence-passes ; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s ; REQUIRES: loadable_module Index: test/BugPoint/replace-funcs-with-null.ll =================================================================== --- test/BugPoint/replace-funcs-with-null.ll +++ test/BugPoint/replace-funcs-with-null.ll @@ -1,6 +1,6 @@ ; Test that bugpoint can reduce the set of functions by replacing them with null. ; -; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -replace-funcs-with-null -bugpoint-crash-decl-funcs -silence-passes -safe-run-llc --opt-command opt +; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -replace-funcs-with-null -bugpoint-crash-decl-funcs -silence-passes -safe-run-llc ; REQUIRES: loadable_module @foo2 = alias i32 (), i32 ()* @foo Index: tools/bugpoint/ExecutionDriver.cpp =================================================================== --- tools/bugpoint/ExecutionDriver.cpp +++ tools/bugpoint/ExecutionDriver.cpp @@ -148,8 +148,9 @@ std::string Message; if (CCBinary.empty()) { - if (sys::findProgramByName("clang")) - CCBinary = "clang"; + if (ErrorOr ClangPath = + FindProgramByName("clang", getToolName(), &AbsTolerance)) + CCBinary = *ClangPath; else CCBinary = "gcc"; } @@ -193,11 +194,11 @@ break; case CompileCustom: Interpreter = AbstractInterpreter::createCustomCompiler( - Message, CustomCompileCommand); + getToolName(), Message, CustomCompileCommand); break; case Custom: - Interpreter = - AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); + Interpreter = AbstractInterpreter::createCustomExecutor( + getToolName(), Message, CustomExecCommand); break; } if (!Interpreter) @@ -239,8 +240,8 @@ SafeInterpreterSel == RunLLCIA); break; case Custom: - SafeInterpreter = - AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); + SafeInterpreter = AbstractInterpreter::createCustomExecutor( + getToolName(), Message, CustomExecCommand); break; default: Message = "Sorry, this back-end is not supported by bugpoint as the " @@ -252,7 +253,7 @@ exit(1); } - cc = CC::create(Message, CCBinary, &CCToolArgv); + cc = CC::create(getToolName(), Message, CCBinary, &CCToolArgv); if (!cc) { outs() << Message << "\nExiting.\n"; exit(1); Index: tools/bugpoint/OptimizerDriver.cpp =================================================================== --- tools/bugpoint/OptimizerDriver.cpp +++ tools/bugpoint/OptimizerDriver.cpp @@ -16,6 +16,7 @@ //===----------------------------------------------------------------------===// #include "BugDriver.h" +#include "ToolRunner.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Module.h" @@ -166,7 +167,8 @@ std::string tool = OptCmd; if (OptCmd.empty()) { - if (ErrorOr Path = sys::findProgramByName("opt")) + if (ErrorOr Path = + FindProgramByName("opt", getToolName(), &OutputPrefix)) tool = *Path; else errs() << Path.getError().message() << "\n"; Index: tools/bugpoint/ToolRunner.h =================================================================== --- tools/bugpoint/ToolRunner.h +++ tools/bugpoint/ToolRunner.h @@ -49,7 +49,8 @@ public: enum FileType { AsmFile, ObjectFile, CFile }; - static CC *create(std::string &Message, const std::string &CCBinary, + static CC *create(const char *Argv0, std::string &Message, + const std::string &CCBinary, const std::vector *Args); /// ExecuteProgram - Execute the program specified by "ProgramFile" (which is @@ -98,11 +99,11 @@ const std::vector *Args = nullptr); static AbstractInterpreter * - createCustomCompiler(std::string &Message, + createCustomCompiler(const char *Argv0, std::string &Message, const std::string &CompileCommandLine); static AbstractInterpreter * - createCustomExecutor(std::string &Message, + createCustomExecutor(const char *Argv0, std::string &Message, const std::string &ExecCommandLine); virtual ~AbstractInterpreter() {} @@ -178,6 +179,13 @@ unsigned MemoryLimit = 0) override; }; +/// Find the first executable file \ExeName, either in the user's PATH or, +/// failing that, in the same directory as argv[0]. This allows us to find +/// another LLVM tool if it is built in the same directory. If no executable is +/// found, an error is returned. +ErrorOr FindProgramByName(const std::string &ExeName, + const char *Argv0, void *MainAddr); + } // End llvm namespace #endif Index: tools/bugpoint/ToolRunner.cpp =================================================================== --- tools/bugpoint/ToolRunner.cpp +++ tools/bugpoint/ToolRunner.cpp @@ -202,50 +202,33 @@ void AbstractInterpreter::anchor() {} -#if defined(LLVM_ON_UNIX) -const char EXESuffix[] = ""; -#elif defined(_WIN32) -const char EXESuffix[] = "exe"; -#endif - -/// Prepend the path to the program being executed -/// to \p ExeName, given the value of argv[0] and the address of main() -/// itself. This allows us to find another LLVM tool if it is built in the same -/// directory. An empty string is returned on error; note that this function -/// just mainpulates the path and doesn't check for executability. -/// Find a named executable. -static std::string PrependMainExecutablePath(const std::string &ExeName, +ErrorOr llvm::FindProgramByName(const std::string &ExeName, const char *Argv0, void *MainAddr) { + // Check the user PATH. + if (ErrorOr Path = sys::findProgramByName(ExeName)) + return *Path; + // Check the directory that the calling program is in. We can do // this if ProgramPath contains at least one / character, indicating that it // is a relative path to the executable itself. std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr); StringRef Result = sys::path::parent_path(Main); - - if (!Result.empty()) { - SmallString<128> Storage = Result; - sys::path::append(Storage, ExeName); - sys::path::replace_extension(Storage, EXESuffix); - return Storage.str(); - } - - return Result.str(); + return sys::findProgramByName(ExeName, Result); } // LLI create method - Try to find the LLI executable AbstractInterpreter * AbstractInterpreter::createLLI(const char *Argv0, std::string &Message, const std::vector *ToolArgs) { - std::string LLIPath = - PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI); - if (!LLIPath.empty()) { - Message = "Found lli: " + LLIPath + "\n"; - return new LLI(LLIPath, ToolArgs); + if (ErrorOr LLIPath = + FindProgramByName("lli", Argv0, (void *)(intptr_t)&createLLI)) { + Message = "Found lli: " + *LLIPath + "\n"; + return new LLI(*LLIPath, ToolArgs); + } else { + Message = LLIPath.getError().message() + "\n"; + return nullptr; } - - Message = "Cannot find `lli' in executable directory!\n"; - return nullptr; } //===---------------------------------------------------------------------===// @@ -368,8 +351,9 @@ // '\ ' -> ' ' // 'exa\mple' -> 'example' // -static void lexCommand(std::string &Message, const std::string &CommandLine, - std::string &CmdPath, std::vector &Args) { +static void lexCommand(const char *Argv0, std::string &Message, + const std::string &CommandLine, std::string &CmdPath, + std::vector &Args) { std::string Token; std::string Command; @@ -402,7 +386,7 @@ Token.push_back(CommandLine[Pos]); } - auto Path = sys::findProgramByName(Command); + auto Path = FindProgramByName(Command, Argv0, (void *)(intptr_t)&lexCommand); if (!Path) { Message = std::string("Cannot find '") + Command + "' in PATH: " + Path.getError().message() + "\n"; @@ -416,11 +400,12 @@ // Custom execution environment create method, takes the execution command // as arguments AbstractInterpreter *AbstractInterpreter::createCustomCompiler( - std::string &Message, const std::string &CompileCommandLine) { + const char *Argv0, std::string &Message, + const std::string &CompileCommandLine) { std::string CmdPath; std::vector Args; - lexCommand(Message, CompileCommandLine, CmdPath, Args); + lexCommand(Argv0, Message, CompileCommandLine, CmdPath, Args); if (CmdPath.empty()) return nullptr; @@ -430,12 +415,13 @@ // Custom execution environment create method, takes the execution command // as arguments AbstractInterpreter * -AbstractInterpreter::createCustomExecutor(std::string &Message, +AbstractInterpreter::createCustomExecutor(const char *Argv0, + std::string &Message, const std::string &ExecCommandLine) { std::string CmdPath; std::vector Args; - lexCommand(Message, ExecCommandLine, CmdPath, Args); + lexCommand(Argv0, Message, ExecCommandLine, CmdPath, Args); if (CmdPath.empty()) return nullptr; @@ -524,20 +510,20 @@ const std::vector *Args, const std::vector *CCArgs, bool UseIntegratedAssembler) { - std::string LLCPath = - PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC); - if (LLCPath.empty()) { - Message = "Cannot find `llc' in executable directory!\n"; + ErrorOr LLCPath = + FindProgramByName("llc", Argv0, (void *)(intptr_t)&createLLC); + if (!LLCPath) { + Message = LLCPath.getError().message() + "\n"; return nullptr; } - CC *cc = CC::create(Message, CCBinary, CCArgs); + CC *cc = CC::create(Argv0, Message, CCBinary, CCArgs); if (!cc) { errs() << Message << "\n"; exit(1); } - Message = "Found llc: " + LLCPath + "\n"; - return new LLC(LLCPath, cc, Args, UseIntegratedAssembler); + Message = "Found llc: " + *LLCPath + "\n"; + return new LLC(*LLCPath, cc, Args, UseIntegratedAssembler); } //===---------------------------------------------------------------------===// @@ -606,15 +592,14 @@ AbstractInterpreter * AbstractInterpreter::createJIT(const char *Argv0, std::string &Message, const std::vector *Args) { - std::string LLIPath = - PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT); - if (!LLIPath.empty()) { - Message = "Found lli: " + LLIPath + "\n"; - return new JIT(LLIPath, Args); + if (ErrorOr LLIPath = + FindProgramByName("lli", Argv0, (void *)(intptr_t)&createJIT)) { + Message = "Found lli: " + *LLIPath + "\n"; + return new JIT(*LLIPath, Args); + } else { + Message = LLIPath.getError().message() + "\n"; + return nullptr; } - - Message = "Cannot find `lli' in executable directory!\n"; - return nullptr; } //===---------------------------------------------------------------------===// @@ -855,9 +840,10 @@ /// create - Try to find the CC executable /// -CC *CC::create(std::string &Message, const std::string &CCBinary, +CC *CC::create(const char *Argv0, std::string &Message, + const std::string &CCBinary, const std::vector *Args) { - auto CCPath = sys::findProgramByName(CCBinary); + auto CCPath = FindProgramByName(CCBinary, Argv0, (void *)(intptr_t)&create); if (!CCPath) { Message = "Cannot find `" + CCBinary + "' in PATH: " + CCPath.getError().message() + "\n";