+ errs() << Path.getError().message() << "\n";
+ }
+ if (tool.empty()) {
+ errs() << "Cannot find `opt' in PATH!\n";
+ return 1;
+ }
+
+ std::string Prog;
+ if (UseValgrind) {
+ if (ErrorOr<std::string> Path = sys::findProgramByName("valgrind"))
+ Prog = *Path;
+ else
+ errs() << Path.getError().message() << "\n";
+ } else
+ Prog = tool;
+ if (Prog.empty()) {
+ errs() << "Cannot find `valgrind' in PATH!\n";
+ return 1;
+ }
+
+ // Ok, everything that could go wrong before running opt is done.
+ InFile.keep();
+
+ // setup the child process' arguments
+ SmallVector<const char*, 8> Args;
+ if (UseValgrind) {
+ Args.push_back("valgrind");
+ Args.push_back("--error-exitcode=1");
+ Args.push_back("-q");
+ Args.push_back(tool.c_str());
+ } else
+ Args.push_back(tool.c_str());
+
+ Args.push_back("-o");
+ Args.push_back(OutputFilename.c_str());
+ for (unsigned i = 0, e = OptArgs.size(); i != e; ++i)
+ Args.push_back(OptArgs[i].c_str());
+ std::vector<std::string> pass_args;
+ for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) {
+ pass_args.push_back( std::string("-load"));
+ pass_args.push_back( PluginLoader::getPlugin(i));
+ }
+ for (std::vector<std::string>::const_iterator I = Passes.begin(),
+ E = Passes.end(); I != E; ++I )
+ pass_args.push_back( std::string("-") + (*I) );
+ for (std::vector<std::string>::const_iterator I = pass_args.begin(),
+ E = pass_args.end(); I != E; ++I )
+ Args.push_back(I->c_str());
+ Args.push_back(InputFilename.c_str());
+ for (unsigned i = 0; i < NumExtraArgs; ++i)
+ Args.push_back(*ExtraArgs);
+ Args.push_back(nullptr);
+
+ DEBUG(errs() << "\nAbout to run:\t";
+ for (unsigned i = 0, e = Args.size()-1; i != e; ++i)
+ errs() << " " << Args[i];
+ errs() << "\n";
+ );
+
+ // Redirect stdout and stderr to nowhere if SilencePasses is given
+ StringRef Nowhere;
+ const StringRef *Redirects[3] = {nullptr, &Nowhere, &Nowhere};
+
+ std::string ErrMsg;
+ int result = sys::ExecuteAndWait(Prog, Args.data(), nullptr,
+ (SilencePasses ? Redirects : nullptr),
+ Timeout, MemoryLimit, &ErrMsg);
+
+ // If we are supposed to delete the bitcode file or if the passes crashed,
+ // remove it now. This may fail if the file was never created, but that's ok.
+ if (DeleteOutput || result != 0)
+ sys::fs::remove(OutputFilename);
+
+ // Remove the temporary input file as well
+ sys::fs::remove(InputFilename.c_str());
+
+ if (!Quiet) {
+ if (result == 0)
+ outs() << "Success!\n";
+ else if (result > 0)
+ outs() << "Exited with error code '" << result << "'\n";
+ else if (result < 0) {
+ if (result == -1)
+ outs() << "Execute failed: " << ErrMsg << "\n";
+ else
+ outs() << "Crashed: " << ErrMsg << "\n";
+ }
+ if (result & 0x01000000)
+ outs() << "Dumped core\n";