ToolRunner.cpp revision 327952
1193323Sed//===-- ToolRunner.cpp ----------------------------------------------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file implements the interfaces described in the ToolRunner.h file. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "ToolRunner.h" 15314564Sdim#include "llvm/Config/config.h" 16193323Sed#include "llvm/Support/CommandLine.h" 17193323Sed#include "llvm/Support/Debug.h" 18261991Sdim#include "llvm/Support/FileSystem.h" 19193323Sed#include "llvm/Support/FileUtilities.h" 20249423Sdim#include "llvm/Support/Program.h" 21198090Srdivacky#include "llvm/Support/raw_ostream.h" 22193323Sed#include <fstream> 23193323Sed#include <sstream> 24309124Sdim#include <utility> 25193323Sedusing namespace llvm; 26193323Sed 27276479Sdim#define DEBUG_TYPE "toolrunner" 28276479Sdim 29198090Srdivackynamespace llvm { 30314564Sdimcl::opt<bool> SaveTemps("save-temps", cl::init(false), 31314564Sdim cl::desc("Save temporary files")); 32198090Srdivacky} 33198090Srdivacky 34193323Sednamespace { 35314564Sdimcl::opt<std::string> 36314564Sdim RemoteClient("remote-client", 37314564Sdim cl::desc("Remote execution client (rsh/ssh)")); 38193323Sed 39314564Sdimcl::opt<std::string> RemoteHost("remote-host", 40314564Sdim cl::desc("Remote execution (rsh/ssh) host")); 41193323Sed 42314564Sdimcl::opt<std::string> RemotePort("remote-port", 43314564Sdim cl::desc("Remote execution (rsh/ssh) port")); 44198090Srdivacky 45314564Sdimcl::opt<std::string> RemoteUser("remote-user", 46314564Sdim cl::desc("Remote execution (rsh/ssh) user id")); 47193323Sed 48314564Sdimcl::opt<std::string> 49314564Sdim RemoteExtra("remote-extra-options", 50314564Sdim cl::desc("Remote execution (rsh/ssh) extra options")); 51193323Sed} 52193323Sed 53198090Srdivacky/// RunProgramWithTimeout - This function provides an alternate interface 54198090Srdivacky/// to the sys::Program::ExecuteAndWait interface. 55207618Srdivacky/// @see sys::Program::ExecuteAndWait 56314564Sdimstatic int RunProgramWithTimeout(StringRef ProgramPath, const char **Args, 57314564Sdim StringRef StdInFile, StringRef StdOutFile, 58314564Sdim StringRef StdErrFile, unsigned NumSeconds = 0, 59218885Sdim unsigned MemoryLimit = 0, 60276479Sdim std::string *ErrMsg = nullptr) { 61327952Sdim Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile}; 62314564Sdim return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects, NumSeconds, 63314564Sdim MemoryLimit, ErrMsg); 64193323Sed} 65193323Sed 66198090Srdivacky/// RunProgramRemotelyWithTimeout - This function runs the given program 67198090Srdivacky/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 68198090Srdivacky/// Returns the remote program exit code or reports a remote client error if it 69198090Srdivacky/// fails. Remote client is required to return 255 if it failed or program exit 70198090Srdivacky/// code otherwise. 71207618Srdivacky/// @see sys::Program::ExecuteAndWait 72261991Sdimstatic int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath, 73314564Sdim const char **Args, StringRef StdInFile, 74261991Sdim StringRef StdOutFile, 75261991Sdim StringRef StdErrFile, 76198090Srdivacky unsigned NumSeconds = 0, 77198090Srdivacky unsigned MemoryLimit = 0) { 78327952Sdim Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile}; 79193323Sed 80198090Srdivacky // Run the program remotely with the remote client 81276479Sdim int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, nullptr, 82261991Sdim Redirects, NumSeconds, MemoryLimit); 83198090Srdivacky 84198090Srdivacky // Has the remote client fail? 85198090Srdivacky if (255 == ReturnCode) { 86198090Srdivacky std::ostringstream OS; 87198090Srdivacky OS << "\nError running remote client:\n "; 88198090Srdivacky for (const char **Arg = Args; *Arg; ++Arg) 89198090Srdivacky OS << " " << *Arg; 90198090Srdivacky OS << "\n"; 91198090Srdivacky 92198090Srdivacky // The error message is in the output file, let's print it out from there. 93261991Sdim std::string StdOutFileName = StdOutFile.str(); 94261991Sdim std::ifstream ErrorFile(StdOutFileName.c_str()); 95198090Srdivacky if (ErrorFile) { 96198090Srdivacky std::copy(std::istreambuf_iterator<char>(ErrorFile), 97198090Srdivacky std::istreambuf_iterator<char>(), 98198090Srdivacky std::ostreambuf_iterator<char>(OS)); 99198090Srdivacky ErrorFile.close(); 100198090Srdivacky } 101198090Srdivacky 102236386Sdim errs() << OS.str(); 103198090Srdivacky } 104198090Srdivacky 105198090Srdivacky return ReturnCode; 106198090Srdivacky} 107198090Srdivacky 108314564Sdimstatic Error ProcessFailure(StringRef ProgPath, const char **Args, 109314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) { 110193323Sed std::ostringstream OS; 111193323Sed OS << "\nError running tool:\n "; 112193323Sed for (const char **Arg = Args; *Arg; ++Arg) 113193323Sed OS << " " << *Arg; 114193323Sed OS << "\n"; 115218885Sdim 116193323Sed // Rerun the compiler, capturing any error messages to print them. 117261991Sdim SmallString<128> ErrorFilename; 118276479Sdim std::error_code EC = sys::fs::createTemporaryFile( 119280031Sdim "bugpoint.program_error_messages", "", ErrorFilename); 120261991Sdim if (EC) { 121261991Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 122193323Sed exit(1); 123193323Sed } 124276479Sdim 125261991Sdim RunProgramWithTimeout(ProgPath, Args, "", ErrorFilename.str(), 126261991Sdim ErrorFilename.str(), Timeout, MemoryLimit); 127208599Srdivacky // FIXME: check return code ? 128193323Sed 129296417Sdim // Print out the error messages generated by CC if possible... 130193323Sed std::ifstream ErrorFile(ErrorFilename.c_str()); 131193323Sed if (ErrorFile) { 132193323Sed std::copy(std::istreambuf_iterator<char>(ErrorFile), 133193323Sed std::istreambuf_iterator<char>(), 134193323Sed std::ostreambuf_iterator<char>(OS)); 135193323Sed ErrorFile.close(); 136193323Sed } 137193323Sed 138261991Sdim sys::fs::remove(ErrorFilename.c_str()); 139314564Sdim return make_error<StringError>(OS.str(), inconvertibleErrorCode()); 140193323Sed} 141193323Sed 142193323Sed//===---------------------------------------------------------------------===// 143193323Sed// LLI Implementation of AbstractIntepreter interface 144193323Sed// 145193323Sednamespace { 146314564Sdimclass LLI : public AbstractInterpreter { 147314564Sdim std::string LLIPath; // The path to the LLI executable 148314564Sdim std::vector<std::string> ToolArgs; // Args to pass to LLI 149314564Sdimpublic: 150314564Sdim LLI(const std::string &Path, const std::vector<std::string> *Args) 151193323Sed : LLIPath(Path) { 152314564Sdim ToolArgs.clear(); 153314564Sdim if (Args) { 154314564Sdim ToolArgs = *Args; 155193323Sed } 156314564Sdim } 157193323Sed 158314564Sdim Expected<int> ExecuteProgram( 159314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 160314564Sdim const std::string &InputFile, const std::string &OutputFile, 161314564Sdim const std::vector<std::string> &CCArgs, 162314564Sdim const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 163314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) override; 164314564Sdim}; 165193323Sed} 166193323Sed 167314564SdimExpected<int> LLI::ExecuteProgram(const std::string &Bitcode, 168314564Sdim const std::vector<std::string> &Args, 169314564Sdim const std::string &InputFile, 170314564Sdim const std::string &OutputFile, 171314564Sdim const std::vector<std::string> &CCArgs, 172314564Sdim const std::vector<std::string> &SharedLibs, 173314564Sdim unsigned Timeout, unsigned MemoryLimit) { 174314564Sdim std::vector<const char *> LLIArgs; 175193323Sed LLIArgs.push_back(LLIPath.c_str()); 176193323Sed LLIArgs.push_back("-force-interpreter=true"); 177193323Sed 178218885Sdim for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), 179314564Sdim e = SharedLibs.end(); 180314564Sdim i != e; ++i) { 181199481Srdivacky LLIArgs.push_back("-load"); 182199481Srdivacky LLIArgs.push_back((*i).c_str()); 183199481Srdivacky } 184199481Srdivacky 185193323Sed // Add any extra LLI args. 186193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 187193323Sed LLIArgs.push_back(ToolArgs[i].c_str()); 188193323Sed 189193323Sed LLIArgs.push_back(Bitcode.c_str()); 190193323Sed // Add optional parameters to the running program from Argv 191314564Sdim for (unsigned i = 0, e = Args.size(); i != e; ++i) 192193323Sed LLIArgs.push_back(Args[i].c_str()); 193276479Sdim LLIArgs.push_back(nullptr); 194193323Sed 195314564Sdim outs() << "<lli>"; 196314564Sdim outs().flush(); 197198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 198314564Sdim for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs() 199314564Sdim << " " << LLIArgs[i]; 200314564Sdim errs() << "\n";); 201314564Sdim return RunProgramWithTimeout(LLIPath, &LLIArgs[0], InputFile, OutputFile, 202314564Sdim OutputFile, Timeout, MemoryLimit); 203193323Sed} 204193323Sed 205314564Sdimvoid AbstractInterpreter::anchor() {} 206234353Sdim 207261991Sdim#if defined(LLVM_ON_UNIX) 208261991Sdimconst char EXESuffix[] = ""; 209314564Sdim#elif defined(LLVM_ON_WIN32) 210261991Sdimconst char EXESuffix[] = "exe"; 211261991Sdim#endif 212261991Sdim 213261991Sdim/// Prepend the path to the program being executed 214261991Sdim/// to \p ExeName, given the value of argv[0] and the address of main() 215261991Sdim/// itself. This allows us to find another LLVM tool if it is built in the same 216261991Sdim/// directory. An empty string is returned on error; note that this function 217261991Sdim/// just mainpulates the path and doesn't check for executability. 218261991Sdim/// @brief Find a named executable. 219261991Sdimstatic std::string PrependMainExecutablePath(const std::string &ExeName, 220261991Sdim const char *Argv0, 221261991Sdim void *MainAddr) { 222261991Sdim // Check the directory that the calling program is in. We can do 223261991Sdim // this if ProgramPath contains at least one / character, indicating that it 224261991Sdim // is a relative path to the executable itself. 225261991Sdim std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr); 226261991Sdim StringRef Result = sys::path::parent_path(Main); 227261991Sdim 228261991Sdim if (!Result.empty()) { 229261991Sdim SmallString<128> Storage = Result; 230261991Sdim sys::path::append(Storage, ExeName); 231261991Sdim sys::path::replace_extension(Storage, EXESuffix); 232261991Sdim return Storage.str(); 233261991Sdim } 234261991Sdim 235261991Sdim return Result.str(); 236261991Sdim} 237261991Sdim 238193323Sed// LLI create method - Try to find the LLI executable 239314564SdimAbstractInterpreter * 240314564SdimAbstractInterpreter::createLLI(const char *Argv0, std::string &Message, 241314564Sdim const std::vector<std::string> *ToolArgs) { 242198090Srdivacky std::string LLIPath = 243314564Sdim PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI); 244193323Sed if (!LLIPath.empty()) { 245193323Sed Message = "Found lli: " + LLIPath + "\n"; 246193323Sed return new LLI(LLIPath, ToolArgs); 247193323Sed } 248193323Sed 249218885Sdim Message = "Cannot find `lli' in executable directory!\n"; 250276479Sdim return nullptr; 251193323Sed} 252193323Sed 253193323Sed//===---------------------------------------------------------------------===// 254218885Sdim// Custom compiler command implementation of AbstractIntepreter interface 255218885Sdim// 256218885Sdim// Allows using a custom command for compiling the bitcode, thus allows, for 257218885Sdim// example, to compile a bitcode fragment without linking or executing, then 258218885Sdim// using a custom wrapper script to check for compiler errors. 259218885Sdimnamespace { 260314564Sdimclass CustomCompiler : public AbstractInterpreter { 261314564Sdim std::string CompilerCommand; 262314564Sdim std::vector<std::string> CompilerArgs; 263218885Sdim 264314564Sdimpublic: 265314564Sdim CustomCompiler(const std::string &CompilerCmd, 266314564Sdim std::vector<std::string> CompArgs) 267314564Sdim : CompilerCommand(CompilerCmd), CompilerArgs(std::move(CompArgs)) {} 268218885Sdim 269314564Sdim Error compileProgram(const std::string &Bitcode, unsigned Timeout = 0, 270314564Sdim unsigned MemoryLimit = 0) override; 271314564Sdim 272314564Sdim Expected<int> ExecuteProgram( 273314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 274314564Sdim const std::string &InputFile, const std::string &OutputFile, 275314564Sdim const std::vector<std::string> &CCArgs = std::vector<std::string>(), 276314564Sdim const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 277314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) override { 278314564Sdim return make_error<StringError>( 279314564Sdim "Execution not supported with -compile-custom", 280314564Sdim inconvertibleErrorCode()); 281314564Sdim } 282314564Sdim}; 283218885Sdim} 284218885Sdim 285314564SdimError CustomCompiler::compileProgram(const std::string &Bitcode, 286314564Sdim unsigned Timeout, unsigned MemoryLimit) { 287218885Sdim 288314564Sdim std::vector<const char *> ProgramArgs; 289218885Sdim ProgramArgs.push_back(CompilerCommand.c_str()); 290218885Sdim 291218885Sdim for (std::size_t i = 0; i < CompilerArgs.size(); ++i) 292218885Sdim ProgramArgs.push_back(CompilerArgs.at(i).c_str()); 293218885Sdim ProgramArgs.push_back(Bitcode.c_str()); 294276479Sdim ProgramArgs.push_back(nullptr); 295218885Sdim 296218885Sdim // Add optional parameters to the running program from Argv 297218885Sdim for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) 298218885Sdim ProgramArgs.push_back(CompilerArgs[i].c_str()); 299218885Sdim 300314564Sdim if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0], "", "", "", 301314564Sdim Timeout, MemoryLimit)) 302314564Sdim return ProcessFailure(CompilerCommand, &ProgramArgs[0], Timeout, 303314564Sdim MemoryLimit); 304314564Sdim return Error::success(); 305218885Sdim} 306218885Sdim 307218885Sdim//===---------------------------------------------------------------------===// 308193323Sed// Custom execution command implementation of AbstractIntepreter interface 309193323Sed// 310193323Sed// Allows using a custom command for executing the bitcode, thus allows, 311218885Sdim// for example, to invoke a cross compiler for code generation followed by 312193323Sed// a simulator that executes the generated binary. 313193323Sednamespace { 314314564Sdimclass CustomExecutor : public AbstractInterpreter { 315314564Sdim std::string ExecutionCommand; 316314564Sdim std::vector<std::string> ExecutorArgs; 317193323Sed 318314564Sdimpublic: 319314564Sdim CustomExecutor(const std::string &ExecutionCmd, 320314564Sdim std::vector<std::string> ExecArgs) 321314564Sdim : ExecutionCommand(ExecutionCmd), ExecutorArgs(std::move(ExecArgs)) {} 322314564Sdim 323314564Sdim Expected<int> ExecuteProgram( 324314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 325314564Sdim const std::string &InputFile, const std::string &OutputFile, 326314564Sdim const std::vector<std::string> &CCArgs, 327314564Sdim const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 328314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) override; 329314564Sdim}; 330193323Sed} 331193323Sed 332314564SdimExpected<int> CustomExecutor::ExecuteProgram( 333314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 334314564Sdim const std::string &InputFile, const std::string &OutputFile, 335314564Sdim const std::vector<std::string> &CCArgs, 336314564Sdim const std::vector<std::string> &SharedLibs, unsigned Timeout, 337314564Sdim unsigned MemoryLimit) { 338193323Sed 339314564Sdim std::vector<const char *> ProgramArgs; 340193323Sed ProgramArgs.push_back(ExecutionCommand.c_str()); 341193323Sed 342193323Sed for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 343193323Sed ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); 344193323Sed ProgramArgs.push_back(Bitcode.c_str()); 345276479Sdim ProgramArgs.push_back(nullptr); 346193323Sed 347193323Sed // Add optional parameters to the running program from Argv 348207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 349193323Sed ProgramArgs.push_back(Args[i].c_str()); 350193323Sed 351314564Sdim return RunProgramWithTimeout(ExecutionCommand, &ProgramArgs[0], InputFile, 352314564Sdim OutputFile, OutputFile, Timeout, MemoryLimit); 353193323Sed} 354193323Sed 355218885Sdim// Tokenize the CommandLine to the command and the args to allow 356218885Sdim// defining a full command line as the command instead of just the 357218885Sdim// executed program. We cannot just pass the whole string after the command 358321369Sdim// as a single argument because then the program sees only a single 359218885Sdim// command line argument (with spaces in it: "foo bar" instead 360218885Sdim// of "foo" and "bar"). 361218885Sdim// 362321369Sdim// Spaces are used as a delimiter; however repeated, leading, and trailing 363321369Sdim// whitespace are ignored. Simple escaping is allowed via the '\' 364321369Sdim// character, as seen below: 365321369Sdim// 366321369Sdim// Two consecutive '\' evaluate to a single '\'. 367321369Sdim// A space after a '\' evaluates to a space that is not interpreted as a 368321369Sdim// delimiter. 369321369Sdim// Any other instances of the '\' character are removed. 370321369Sdim// 371321369Sdim// Example: 372321369Sdim// '\\' -> '\' 373321369Sdim// '\ ' -> ' ' 374321369Sdim// 'exa\mple' -> 'example' 375321369Sdim// 376218885Sdimstatic void lexCommand(std::string &Message, const std::string &CommandLine, 377276479Sdim std::string &CmdPath, std::vector<std::string> &Args) { 378193323Sed 379321369Sdim std::string Token; 380321369Sdim std::string Command; 381321369Sdim bool FoundPath = false; 382193323Sed 383321369Sdim // first argument is the PATH. 384321369Sdim // Skip repeated whitespace, leading whitespace and trailing whitespace. 385321369Sdim for (std::size_t Pos = 0u; Pos <= CommandLine.size(); ++Pos) { 386321369Sdim if ('\\' == CommandLine[Pos]) { 387321369Sdim if (Pos + 1 < CommandLine.size()) 388321369Sdim Token.push_back(CommandLine[++Pos]); 389193323Sed 390321369Sdim continue; 391321369Sdim } 392321369Sdim if (' ' == CommandLine[Pos] || CommandLine.size() == Pos) { 393321369Sdim if (Token.empty()) 394321369Sdim continue; 395321369Sdim 396321369Sdim if (!FoundPath) { 397321369Sdim Command = Token; 398321369Sdim FoundPath = true; 399321369Sdim Token.clear(); 400321369Sdim continue; 401321369Sdim } 402321369Sdim 403321369Sdim Args.push_back(Token); 404321369Sdim Token.clear(); 405321369Sdim continue; 406321369Sdim } 407321369Sdim Token.push_back(CommandLine[Pos]); 408193323Sed } 409193323Sed 410280031Sdim auto Path = sys::findProgramByName(Command); 411280031Sdim if (!Path) { 412321369Sdim Message = std::string("Cannot find '") + Command + 413321369Sdim "' in PATH: " + Path.getError().message() + "\n"; 414218885Sdim return; 415193323Sed } 416280031Sdim CmdPath = *Path; 417193323Sed 418193323Sed Message = "Found command in: " + CmdPath + "\n"; 419218885Sdim} 420193323Sed 421218885Sdim// Custom execution environment create method, takes the execution command 422218885Sdim// as arguments 423218885SdimAbstractInterpreter *AbstractInterpreter::createCustomCompiler( 424314564Sdim std::string &Message, const std::string &CompileCommandLine) { 425218885Sdim 426218885Sdim std::string CmdPath; 427218885Sdim std::vector<std::string> Args; 428218885Sdim lexCommand(Message, CompileCommandLine, CmdPath, Args); 429218885Sdim if (CmdPath.empty()) 430276479Sdim return nullptr; 431218885Sdim 432218885Sdim return new CustomCompiler(CmdPath, Args); 433218885Sdim} 434218885Sdim 435218885Sdim// Custom execution environment create method, takes the execution command 436218885Sdim// as arguments 437314564SdimAbstractInterpreter * 438314564SdimAbstractInterpreter::createCustomExecutor(std::string &Message, 439314564Sdim const std::string &ExecCommandLine) { 440218885Sdim 441218885Sdim std::string CmdPath; 442218885Sdim std::vector<std::string> Args; 443218885Sdim lexCommand(Message, ExecCommandLine, CmdPath, Args); 444218885Sdim if (CmdPath.empty()) 445276479Sdim return nullptr; 446218885Sdim 447193323Sed return new CustomExecutor(CmdPath, Args); 448193323Sed} 449193323Sed 450193323Sed//===----------------------------------------------------------------------===// 451193323Sed// LLC Implementation of AbstractIntepreter interface 452193323Sed// 453314564SdimExpected<CC::FileType> LLC::OutputCode(const std::string &Bitcode, 454314564Sdim std::string &OutputAsmFile, 455314564Sdim unsigned Timeout, unsigned MemoryLimit) { 456205218Srdivacky const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); 457261991Sdim 458261991Sdim SmallString<128> UniqueFile; 459276479Sdim std::error_code EC = 460261991Sdim sys::fs::createUniqueFile(Bitcode + "-%%%%%%%" + Suffix, UniqueFile); 461261991Sdim if (EC) { 462261991Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 463193323Sed exit(1); 464193323Sed } 465261991Sdim OutputAsmFile = UniqueFile.str(); 466193323Sed std::vector<const char *> LLCArgs; 467205218Srdivacky LLCArgs.push_back(LLCPath.c_str()); 468193323Sed 469193323Sed // Add any extra LLC args. 470193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 471193323Sed LLCArgs.push_back(ToolArgs[i].c_str()); 472193323Sed 473205218Srdivacky LLCArgs.push_back("-o"); 474205218Srdivacky LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file 475314564Sdim LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 476218885Sdim 477205218Srdivacky if (UseIntegratedAssembler) 478205218Srdivacky LLCArgs.push_back("-filetype=obj"); 479218885Sdim 480314564Sdim LLCArgs.push_back(nullptr); 481193323Sed 482205218Srdivacky outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); 483205218Srdivacky outs().flush(); 484198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 485314564Sdim for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs() 486314564Sdim << " " << LLCArgs[i]; 487314564Sdim errs() << "\n";); 488314564Sdim if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], "", "", "", Timeout, 489314564Sdim MemoryLimit)) 490314564Sdim return ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); 491296417Sdim return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile; 492193323Sed} 493193323Sed 494314564SdimError LLC::compileProgram(const std::string &Bitcode, unsigned Timeout, 495314564Sdim unsigned MemoryLimit) { 496261991Sdim std::string OutputAsmFile; 497314564Sdim Expected<CC::FileType> Result = 498314564Sdim OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit); 499261991Sdim sys::fs::remove(OutputAsmFile); 500314564Sdim if (Error E = Result.takeError()) 501314564Sdim return E; 502314564Sdim return Error::success(); 503193323Sed} 504193323Sed 505314564SdimExpected<int> LLC::ExecuteProgram(const std::string &Bitcode, 506314564Sdim const std::vector<std::string> &Args, 507314564Sdim const std::string &InputFile, 508314564Sdim const std::string &OutputFile, 509314564Sdim const std::vector<std::string> &ArgsForCC, 510314564Sdim const std::vector<std::string> &SharedLibs, 511314564Sdim unsigned Timeout, unsigned MemoryLimit) { 512193323Sed 513261991Sdim std::string OutputAsmFile; 514314564Sdim Expected<CC::FileType> FileKind = 515314564Sdim OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit); 516261991Sdim FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); 517314564Sdim if (Error E = FileKind.takeError()) 518314564Sdim return std::move(E); 519193323Sed 520296417Sdim std::vector<std::string> CCArgs(ArgsForCC); 521296417Sdim CCArgs.insert(CCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 522193323Sed 523296417Sdim // Assuming LLC worked, compile the result with CC and run it. 524314564Sdim return cc->ExecuteProgram(OutputAsmFile, Args, *FileKind, InputFile, 525314564Sdim OutputFile, CCArgs, Timeout, MemoryLimit); 526193323Sed} 527193323Sed 528193323Sed/// createLLC - Try to find the LLC executable 529193323Sed/// 530314564SdimLLC *AbstractInterpreter::createLLC(const char *Argv0, std::string &Message, 531296417Sdim const std::string &CCBinary, 532193323Sed const std::vector<std::string> *Args, 533296417Sdim const std::vector<std::string> *CCArgs, 534205218Srdivacky bool UseIntegratedAssembler) { 535198090Srdivacky std::string LLCPath = 536314564Sdim PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC); 537193323Sed if (LLCPath.empty()) { 538218885Sdim Message = "Cannot find `llc' in executable directory!\n"; 539276479Sdim return nullptr; 540193323Sed } 541193323Sed 542296417Sdim CC *cc = CC::create(Message, CCBinary, CCArgs); 543296417Sdim if (!cc) { 544198090Srdivacky errs() << Message << "\n"; 545193323Sed exit(1); 546193323Sed } 547249423Sdim Message = "Found llc: " + LLCPath + "\n"; 548296417Sdim return new LLC(LLCPath, cc, Args, UseIntegratedAssembler); 549193323Sed} 550193323Sed 551193323Sed//===---------------------------------------------------------------------===// 552193323Sed// JIT Implementation of AbstractIntepreter interface 553193323Sed// 554193323Sednamespace { 555314564Sdimclass JIT : public AbstractInterpreter { 556314564Sdim std::string LLIPath; // The path to the LLI executable 557314564Sdim std::vector<std::string> ToolArgs; // Args to pass to LLI 558314564Sdimpublic: 559314564Sdim JIT(const std::string &Path, const std::vector<std::string> *Args) 560193323Sed : LLIPath(Path) { 561314564Sdim ToolArgs.clear(); 562314564Sdim if (Args) { 563314564Sdim ToolArgs = *Args; 564193323Sed } 565314564Sdim } 566193323Sed 567314564Sdim Expected<int> ExecuteProgram( 568314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 569314564Sdim const std::string &InputFile, const std::string &OutputFile, 570314564Sdim const std::vector<std::string> &CCArgs = std::vector<std::string>(), 571314564Sdim const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 572314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) override; 573314564Sdim}; 574193323Sed} 575193323Sed 576314564SdimExpected<int> JIT::ExecuteProgram(const std::string &Bitcode, 577314564Sdim const std::vector<std::string> &Args, 578314564Sdim const std::string &InputFile, 579314564Sdim const std::string &OutputFile, 580314564Sdim const std::vector<std::string> &CCArgs, 581314564Sdim const std::vector<std::string> &SharedLibs, 582314564Sdim unsigned Timeout, unsigned MemoryLimit) { 583193323Sed // Construct a vector of parameters, incorporating those from the command-line 584314564Sdim std::vector<const char *> JITArgs; 585193323Sed JITArgs.push_back(LLIPath.c_str()); 586193323Sed JITArgs.push_back("-force-interpreter=false"); 587193323Sed 588193323Sed // Add any extra LLI args. 589193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 590193323Sed JITArgs.push_back(ToolArgs[i].c_str()); 591193323Sed 592193323Sed for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 593193323Sed JITArgs.push_back("-load"); 594193323Sed JITArgs.push_back(SharedLibs[i].c_str()); 595193323Sed } 596193323Sed JITArgs.push_back(Bitcode.c_str()); 597193323Sed // Add optional parameters to the running program from Argv 598314564Sdim for (unsigned i = 0, e = Args.size(); i != e; ++i) 599193323Sed JITArgs.push_back(Args[i].c_str()); 600276479Sdim JITArgs.push_back(nullptr); 601193323Sed 602314564Sdim outs() << "<jit>"; 603314564Sdim outs().flush(); 604198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 605314564Sdim for (unsigned i = 0, e = JITArgs.size() - 1; i != e; ++i) errs() 606314564Sdim << " " << JITArgs[i]; 607314564Sdim errs() << "\n";); 608198090Srdivacky DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 609314564Sdim return RunProgramWithTimeout(LLIPath, &JITArgs[0], InputFile, OutputFile, 610314564Sdim OutputFile, Timeout, MemoryLimit); 611193323Sed} 612193323Sed 613193323Sed/// createJIT - Try to find the LLI executable 614193323Sed/// 615314564SdimAbstractInterpreter * 616314564SdimAbstractInterpreter::createJIT(const char *Argv0, std::string &Message, 617314564Sdim const std::vector<std::string> *Args) { 618198090Srdivacky std::string LLIPath = 619314564Sdim PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT); 620193323Sed if (!LLIPath.empty()) { 621193323Sed Message = "Found lli: " + LLIPath + "\n"; 622193323Sed return new JIT(LLIPath, Args); 623193323Sed } 624193323Sed 625218885Sdim Message = "Cannot find `lli' in executable directory!\n"; 626276479Sdim return nullptr; 627193323Sed} 628193323Sed 629193323Sed//===---------------------------------------------------------------------===// 630296417Sdim// CC abstraction 631193323Sed// 632198090Srdivacky 633314564Sdimstatic bool IsARMArchitecture(std::vector<const char *> Args) { 634314564Sdim for (std::vector<const char *>::const_iterator I = Args.begin(), 635314564Sdim E = Args.end(); 636314564Sdim I != E; ++I) { 637208599Srdivacky if (StringRef(*I).equals_lower("-arch")) { 638198090Srdivacky ++I; 639261991Sdim if (I != E && StringRef(*I).startswith_lower("arm")) 640198090Srdivacky return true; 641198090Srdivacky } 642198090Srdivacky } 643198090Srdivacky 644198090Srdivacky return false; 645198090Srdivacky} 646198090Srdivacky 647314564SdimExpected<int> CC::ExecuteProgram(const std::string &ProgramFile, 648314564Sdim const std::vector<std::string> &Args, 649314564Sdim FileType fileType, 650314564Sdim const std::string &InputFile, 651314564Sdim const std::string &OutputFile, 652314564Sdim const std::vector<std::string> &ArgsForCC, 653314564Sdim unsigned Timeout, unsigned MemoryLimit) { 654314564Sdim std::vector<const char *> CCArgs; 655193323Sed 656296417Sdim CCArgs.push_back(CCPath.c_str()); 657193323Sed 658205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 659296417Sdim CCArgs.push_back("-m32"); 660205218Srdivacky 661314564Sdim for (std::vector<std::string>::const_iterator I = ccArgs.begin(), 662314564Sdim E = ccArgs.end(); 663314564Sdim I != E; ++I) 664296417Sdim CCArgs.push_back(I->c_str()); 665193323Sed 666193323Sed // Specify -x explicitly in case the extension is wonky 667205218Srdivacky if (fileType != ObjectFile) { 668296417Sdim CCArgs.push_back("-x"); 669205218Srdivacky if (fileType == CFile) { 670296417Sdim CCArgs.push_back("c"); 671296417Sdim CCArgs.push_back("-fno-strict-aliasing"); 672205218Srdivacky } else { 673296417Sdim CCArgs.push_back("assembler"); 674198090Srdivacky 675205218Srdivacky // For ARM architectures we don't want this flag. bugpoint isn't 676205218Srdivacky // explicitly told what architecture it is working on, so we get 677296417Sdim // it from cc flags 678296417Sdim if (TargetTriple.isOSDarwin() && !IsARMArchitecture(CCArgs)) 679296417Sdim CCArgs.push_back("-force_cpusubtype_ALL"); 680205218Srdivacky } 681193323Sed } 682218885Sdim 683314564Sdim CCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. 684218885Sdim 685296417Sdim CCArgs.push_back("-x"); 686296417Sdim CCArgs.push_back("none"); 687296417Sdim CCArgs.push_back("-o"); 688261991Sdim 689261991Sdim SmallString<128> OutputBinary; 690276479Sdim std::error_code EC = 691296417Sdim sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.cc.exe", OutputBinary); 692261991Sdim if (EC) { 693261991Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 694193323Sed exit(1); 695193323Sed } 696296417Sdim CCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 697193323Sed 698296417Sdim // Add any arguments intended for CC. We locate them here because this is 699193323Sed // most likely -L and -l options that need to come before other libraries but 700193323Sed // after the source. Other options won't be sensitive to placement on the 701193323Sed // command line, so this should be safe. 702296417Sdim for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i) 703296417Sdim CCArgs.push_back(ArgsForCC[i].c_str()); 704193323Sed 705314564Sdim CCArgs.push_back("-lm"); // Hard-code the math library... 706314564Sdim CCArgs.push_back("-O2"); // Optimize the program a bit... 707198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 708296417Sdim CCArgs.push_back("-mcpu=v9"); 709314564Sdim CCArgs.push_back(nullptr); // NULL terminator 710193323Sed 711314564Sdim outs() << "<CC>"; 712314564Sdim outs().flush(); 713198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 714314564Sdim for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs() 715314564Sdim << " " << CCArgs[i]; 716314564Sdim errs() << "\n";); 717314564Sdim if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", "")) 718314564Sdim return ProcessFailure(CCPath, &CCArgs[0]); 719193323Sed 720314564Sdim std::vector<const char *> ProgramArgs; 721193323Sed 722212793Sdim // Declared here so that the destructor only runs after 723212793Sdim // ProgramArgs is used. 724212793Sdim std::string Exec; 725212793Sdim 726261991Sdim if (RemoteClientPath.empty()) 727193323Sed ProgramArgs.push_back(OutputBinary.c_str()); 728193323Sed else { 729193323Sed ProgramArgs.push_back(RemoteClientPath.c_str()); 730193323Sed ProgramArgs.push_back(RemoteHost.c_str()); 731198090Srdivacky if (!RemoteUser.empty()) { 732198090Srdivacky ProgramArgs.push_back("-l"); 733198090Srdivacky ProgramArgs.push_back(RemoteUser.c_str()); 734198090Srdivacky } 735198090Srdivacky if (!RemotePort.empty()) { 736198090Srdivacky ProgramArgs.push_back("-p"); 737198090Srdivacky ProgramArgs.push_back(RemotePort.c_str()); 738198090Srdivacky } 739193323Sed if (!RemoteExtra.empty()) { 740193323Sed ProgramArgs.push_back(RemoteExtra.c_str()); 741193323Sed } 742193323Sed 743198090Srdivacky // Full path to the binary. We need to cd to the exec directory because 744198090Srdivacky // there is a dylib there that the exec expects to find in the CWD 745314564Sdim char *env_pwd = getenv("PWD"); 746212793Sdim Exec = "cd "; 747193323Sed Exec += env_pwd; 748193323Sed Exec += "; ./"; 749193323Sed Exec += OutputBinary.c_str(); 750193323Sed ProgramArgs.push_back(Exec.c_str()); 751193323Sed } 752193323Sed 753193323Sed // Add optional parameters to the running program from Argv 754207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 755193323Sed ProgramArgs.push_back(Args[i].c_str()); 756314564Sdim ProgramArgs.push_back(nullptr); // NULL terminator 757193323Sed 758193323Sed // Now that we have a binary, run it! 759314564Sdim outs() << "<program>"; 760314564Sdim outs().flush(); 761198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 762314564Sdim for (unsigned i = 0, e = ProgramArgs.size() - 1; i != e; ++i) errs() 763314564Sdim << " " << ProgramArgs[i]; 764314564Sdim errs() << "\n";); 765193323Sed 766221337Sdim FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); 767193323Sed 768261991Sdim if (RemoteClientPath.empty()) { 769207618Srdivacky DEBUG(errs() << "<run locally>"); 770314564Sdim std::string Error; 771261991Sdim int ExitCode = RunProgramWithTimeout(OutputBinary.str(), &ProgramArgs[0], 772261991Sdim InputFile, OutputFile, OutputFile, 773314564Sdim Timeout, MemoryLimit, &Error); 774223013Sdim // Treat a signal (usually SIGSEGV) or timeout as part of the program output 775223013Sdim // so that crash-causing miscompilation is handled seamlessly. 776223013Sdim if (ExitCode < -1) { 777223013Sdim std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 778314564Sdim outFile << Error << '\n'; 779223013Sdim outFile.close(); 780223013Sdim } 781223013Sdim return ExitCode; 782198090Srdivacky } else { 783314564Sdim outs() << "<run remotely>"; 784314564Sdim outs().flush(); 785314564Sdim return RunProgramRemotelyWithTimeout(RemoteClientPath, &ProgramArgs[0], 786314564Sdim InputFile, OutputFile, OutputFile, 787314564Sdim Timeout, MemoryLimit); 788198090Srdivacky } 789193323Sed} 790193323Sed 791314564SdimError CC::MakeSharedObject(const std::string &InputFile, FileType fileType, 792314564Sdim std::string &OutputFile, 793314564Sdim const std::vector<std::string> &ArgsForCC) { 794261991Sdim SmallString<128> UniqueFilename; 795276479Sdim std::error_code EC = sys::fs::createUniqueFile( 796261991Sdim InputFile + "-%%%%%%%" + LTDL_SHLIB_EXT, UniqueFilename); 797261991Sdim if (EC) { 798261991Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 799193323Sed exit(1); 800193323Sed } 801261991Sdim OutputFile = UniqueFilename.str(); 802193323Sed 803314564Sdim std::vector<const char *> CCArgs; 804218885Sdim 805296417Sdim CCArgs.push_back(CCPath.c_str()); 806193323Sed 807205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 808296417Sdim CCArgs.push_back("-m32"); 809205218Srdivacky 810314564Sdim for (std::vector<std::string>::const_iterator I = ccArgs.begin(), 811314564Sdim E = ccArgs.end(); 812314564Sdim I != E; ++I) 813296417Sdim CCArgs.push_back(I->c_str()); 814193323Sed 815193323Sed // Compile the C/asm file into a shared object 816205218Srdivacky if (fileType != ObjectFile) { 817296417Sdim CCArgs.push_back("-x"); 818296417Sdim CCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 819205218Srdivacky } 820296417Sdim CCArgs.push_back("-fno-strict-aliasing"); 821314564Sdim CCArgs.push_back(InputFile.c_str()); // Specify the input filename. 822296417Sdim CCArgs.push_back("-x"); 823296417Sdim CCArgs.push_back("none"); 824198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 825314564Sdim CCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 826221337Sdim else if (TargetTriple.isOSDarwin()) { 827198090Srdivacky // link all source files into a single module in data segment, rather than 828218885Sdim // generating blocks. dynamic_lookup requires that you set 829198090Srdivacky // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 830296417Sdim // bugpoint to just pass that in the environment of CC. 831296417Sdim CCArgs.push_back("-single_module"); 832314564Sdim CCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 833296417Sdim CCArgs.push_back("-undefined"); 834296417Sdim CCArgs.push_back("dynamic_lookup"); 835198090Srdivacky } else 836314564Sdim CCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 837193323Sed 838234353Sdim if (TargetTriple.getArch() == Triple::x86_64) 839314564Sdim CCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 840198090Srdivacky 841198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 842296417Sdim CCArgs.push_back("-mcpu=v9"); 843198090Srdivacky 844296417Sdim CCArgs.push_back("-o"); 845296417Sdim CCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 846296417Sdim CCArgs.push_back("-O2"); // Optimize the program a bit. 847193323Sed 848296417Sdim // Add any arguments intended for CC. We locate them here because this is 849193323Sed // most likely -L and -l options that need to come before other libraries but 850193323Sed // after the source. Other options won't be sensitive to placement on the 851193323Sed // command line, so this should be safe. 852296417Sdim for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i) 853296417Sdim CCArgs.push_back(ArgsForCC[i].c_str()); 854314564Sdim CCArgs.push_back(nullptr); // NULL terminator 855193323Sed 856314564Sdim outs() << "<CC>"; 857314564Sdim outs().flush(); 858198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 859314564Sdim for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs() 860314564Sdim << " " << CCArgs[i]; 861314564Sdim errs() << "\n";); 862314564Sdim if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", "")) 863314564Sdim return ProcessFailure(CCPath, &CCArgs[0]); 864321369Sdim return Error::success(); 865193323Sed} 866193323Sed 867296417Sdim/// create - Try to find the CC executable 868193323Sed/// 869314564SdimCC *CC::create(std::string &Message, const std::string &CCBinary, 870314564Sdim const std::vector<std::string> *Args) { 871296417Sdim auto CCPath = sys::findProgramByName(CCBinary); 872296417Sdim if (!CCPath) { 873296417Sdim Message = "Cannot find `" + CCBinary + "' in PATH: " + 874296417Sdim CCPath.getError().message() + "\n"; 875276479Sdim return nullptr; 876193323Sed } 877193323Sed 878261991Sdim std::string RemoteClientPath; 879280031Sdim if (!RemoteClient.empty()) { 880280031Sdim auto Path = sys::findProgramByName(RemoteClient); 881280031Sdim if (!Path) { 882280031Sdim Message = "Cannot find `" + RemoteClient + "' in PATH: " + 883280031Sdim Path.getError().message() + "\n"; 884280031Sdim return nullptr; 885280031Sdim } 886280031Sdim RemoteClientPath = *Path; 887280031Sdim } 888193323Sed 889296417Sdim Message = "Found CC: " + *CCPath + "\n"; 890296417Sdim return new CC(*CCPath, RemoteClientPath, Args); 891193323Sed} 892