ToolRunner.cpp revision 208599
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#define DEBUG_TYPE "toolrunner" 15193323Sed#include "ToolRunner.h" 16193323Sed#include "llvm/System/Program.h" 17193323Sed#include "llvm/Support/CommandLine.h" 18193323Sed#include "llvm/Support/Debug.h" 19193323Sed#include "llvm/Support/FileUtilities.h" 20198090Srdivacky#include "llvm/Support/raw_ostream.h" 21198090Srdivacky#include "llvm/Config/config.h" // for HAVE_LINK_R 22193323Sed#include <fstream> 23193323Sed#include <sstream> 24193323Sedusing namespace llvm; 25193323Sed 26198090Srdivackynamespace llvm { 27198090Srdivacky cl::opt<bool> 28198090Srdivacky SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); 29198090Srdivacky} 30198090Srdivacky 31193323Sednamespace { 32193323Sed cl::opt<std::string> 33193323Sed RemoteClient("remote-client", 34193323Sed cl::desc("Remote execution client (rsh/ssh)")); 35193323Sed 36193323Sed cl::opt<std::string> 37193323Sed RemoteHost("remote-host", 38193323Sed cl::desc("Remote execution (rsh/ssh) host")); 39193323Sed 40193323Sed cl::opt<std::string> 41198090Srdivacky RemotePort("remote-port", 42198090Srdivacky cl::desc("Remote execution (rsh/ssh) port")); 43198090Srdivacky 44198090Srdivacky cl::opt<std::string> 45193323Sed RemoteUser("remote-user", 46193323Sed cl::desc("Remote execution (rsh/ssh) user id")); 47193323Sed 48193323Sed cl::opt<std::string> 49193323Sed RemoteExtra("remote-extra-options", 50193323Sed 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 56193323Sedstatic int RunProgramWithTimeout(const sys::Path &ProgramPath, 57193323Sed const char **Args, 58193323Sed const sys::Path &StdInFile, 59193323Sed const sys::Path &StdOutFile, 60193323Sed const sys::Path &StdErrFile, 61193323Sed unsigned NumSeconds = 0, 62193323Sed unsigned MemoryLimit = 0) { 63193323Sed const sys::Path* redirects[3]; 64193323Sed redirects[0] = &StdInFile; 65193323Sed redirects[1] = &StdOutFile; 66193323Sed redirects[2] = &StdErrFile; 67198090Srdivacky 68198090Srdivacky#if 0 // For debug purposes 69198090Srdivacky { 70198090Srdivacky errs() << "RUN:"; 71193323Sed for (unsigned i = 0; Args[i]; ++i) 72198090Srdivacky errs() << " " << Args[i]; 73198090Srdivacky errs() << "\n"; 74193323Sed } 75198090Srdivacky#endif 76193323Sed 77193323Sed return 78193323Sed sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, 79193323Sed NumSeconds, MemoryLimit); 80193323Sed} 81193323Sed 82198090Srdivacky/// RunProgramRemotelyWithTimeout - This function runs the given program 83198090Srdivacky/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 84198090Srdivacky/// Returns the remote program exit code or reports a remote client error if it 85198090Srdivacky/// fails. Remote client is required to return 255 if it failed or program exit 86198090Srdivacky/// code otherwise. 87207618Srdivacky/// @see sys::Program::ExecuteAndWait 88198090Srdivackystatic int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, 89198090Srdivacky const char **Args, 90198090Srdivacky const sys::Path &StdInFile, 91198090Srdivacky const sys::Path &StdOutFile, 92198090Srdivacky const sys::Path &StdErrFile, 93198090Srdivacky unsigned NumSeconds = 0, 94198090Srdivacky unsigned MemoryLimit = 0) { 95198090Srdivacky const sys::Path* redirects[3]; 96198090Srdivacky redirects[0] = &StdInFile; 97198090Srdivacky redirects[1] = &StdOutFile; 98198090Srdivacky redirects[2] = &StdErrFile; 99193323Sed 100198090Srdivacky#if 0 // For debug purposes 101198090Srdivacky { 102198090Srdivacky errs() << "RUN:"; 103198090Srdivacky for (unsigned i = 0; Args[i]; ++i) 104198090Srdivacky errs() << " " << Args[i]; 105198090Srdivacky errs() << "\n"; 106198090Srdivacky } 107198090Srdivacky#endif 108193323Sed 109198090Srdivacky // Run the program remotely with the remote client 110198090Srdivacky int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, 111198090Srdivacky 0, redirects, NumSeconds, MemoryLimit); 112198090Srdivacky 113198090Srdivacky // Has the remote client fail? 114198090Srdivacky if (255 == ReturnCode) { 115198090Srdivacky std::ostringstream OS; 116198090Srdivacky OS << "\nError running remote client:\n "; 117198090Srdivacky for (const char **Arg = Args; *Arg; ++Arg) 118198090Srdivacky OS << " " << *Arg; 119198090Srdivacky OS << "\n"; 120198090Srdivacky 121198090Srdivacky // The error message is in the output file, let's print it out from there. 122198090Srdivacky std::ifstream ErrorFile(StdOutFile.c_str()); 123198090Srdivacky if (ErrorFile) { 124198090Srdivacky std::copy(std::istreambuf_iterator<char>(ErrorFile), 125198090Srdivacky std::istreambuf_iterator<char>(), 126198090Srdivacky std::ostreambuf_iterator<char>(OS)); 127198090Srdivacky ErrorFile.close(); 128198090Srdivacky } 129198090Srdivacky 130207618Srdivacky errs() << OS; 131198090Srdivacky } 132198090Srdivacky 133198090Srdivacky return ReturnCode; 134198090Srdivacky} 135198090Srdivacky 136208599Srdivackystatic std::string ProcessFailure(sys::Path ProgPath, const char** Args, 137208599Srdivacky unsigned Timeout = 0, 138208599Srdivacky unsigned MemoryLimit = 0) { 139193323Sed std::ostringstream OS; 140193323Sed OS << "\nError running tool:\n "; 141193323Sed for (const char **Arg = Args; *Arg; ++Arg) 142193323Sed OS << " " << *Arg; 143193323Sed OS << "\n"; 144205218Srdivacky 145193323Sed // Rerun the compiler, capturing any error messages to print them. 146193323Sed sys::Path ErrorFilename("bugpoint.program_error_messages"); 147193323Sed std::string ErrMsg; 148193323Sed if (ErrorFilename.makeUnique(true, &ErrMsg)) { 149198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 150193323Sed exit(1); 151193323Sed } 152193323Sed RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, 153208599Srdivacky ErrorFilename, Timeout, MemoryLimit); 154208599Srdivacky // FIXME: check return code ? 155193323Sed 156193323Sed // Print out the error messages generated by GCC if possible... 157193323Sed std::ifstream ErrorFile(ErrorFilename.c_str()); 158193323Sed if (ErrorFile) { 159193323Sed std::copy(std::istreambuf_iterator<char>(ErrorFile), 160193323Sed std::istreambuf_iterator<char>(), 161193323Sed std::ostreambuf_iterator<char>(OS)); 162193323Sed ErrorFile.close(); 163193323Sed } 164193323Sed 165193323Sed ErrorFilename.eraseFromDisk(); 166207618Srdivacky return OS.str(); 167193323Sed} 168193323Sed 169193323Sed//===---------------------------------------------------------------------===// 170193323Sed// LLI Implementation of AbstractIntepreter interface 171193323Sed// 172193323Sednamespace { 173193323Sed class LLI : public AbstractInterpreter { 174193323Sed std::string LLIPath; // The path to the LLI executable 175193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 176193323Sed public: 177193323Sed LLI(const std::string &Path, const std::vector<std::string> *Args) 178193323Sed : LLIPath(Path) { 179193323Sed ToolArgs.clear (); 180193323Sed if (Args) { ToolArgs = *Args; } 181193323Sed } 182193323Sed 183193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 184193323Sed const std::vector<std::string> &Args, 185193323Sed const std::string &InputFile, 186193323Sed const std::string &OutputFile, 187207618Srdivacky std::string *Error, 188193323Sed const std::vector<std::string> &GCCArgs, 189193323Sed const std::vector<std::string> &SharedLibs = 190193323Sed std::vector<std::string>(), 191193323Sed unsigned Timeout = 0, 192193323Sed unsigned MemoryLimit = 0); 193193323Sed }; 194193323Sed} 195193323Sed 196193323Sedint LLI::ExecuteProgram(const std::string &Bitcode, 197193323Sed const std::vector<std::string> &Args, 198193323Sed const std::string &InputFile, 199193323Sed const std::string &OutputFile, 200207618Srdivacky std::string *Error, 201193323Sed const std::vector<std::string> &GCCArgs, 202193323Sed const std::vector<std::string> &SharedLibs, 203193323Sed unsigned Timeout, 204193323Sed unsigned MemoryLimit) { 205193323Sed std::vector<const char*> LLIArgs; 206193323Sed LLIArgs.push_back(LLIPath.c_str()); 207193323Sed LLIArgs.push_back("-force-interpreter=true"); 208193323Sed 209199481Srdivacky for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), e = SharedLibs.end(); i != e; ++i) { 210199481Srdivacky LLIArgs.push_back("-load"); 211199481Srdivacky LLIArgs.push_back((*i).c_str()); 212199481Srdivacky } 213199481Srdivacky 214193323Sed // Add any extra LLI args. 215193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 216193323Sed LLIArgs.push_back(ToolArgs[i].c_str()); 217193323Sed 218193323Sed LLIArgs.push_back(Bitcode.c_str()); 219193323Sed // Add optional parameters to the running program from Argv 220193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 221193323Sed LLIArgs.push_back(Args[i].c_str()); 222193323Sed LLIArgs.push_back(0); 223193323Sed 224198090Srdivacky outs() << "<lli>"; outs().flush(); 225198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 226193323Sed for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) 227198090Srdivacky errs() << " " << LLIArgs[i]; 228198090Srdivacky errs() << "\n"; 229193323Sed ); 230193323Sed return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], 231193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 232193323Sed Timeout, MemoryLimit); 233193323Sed} 234193323Sed 235193323Sed// LLI create method - Try to find the LLI executable 236198090SrdivackyAbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, 237193323Sed std::string &Message, 238193323Sed const std::vector<std::string> *ToolArgs) { 239198090Srdivacky std::string LLIPath = 240198090Srdivacky FindExecutable("lli", Argv0, (void *)(intptr_t)&createLLI).str(); 241193323Sed if (!LLIPath.empty()) { 242193323Sed Message = "Found lli: " + LLIPath + "\n"; 243193323Sed return new LLI(LLIPath, ToolArgs); 244193323Sed } 245193323Sed 246193323Sed Message = "Cannot find `lli' in executable directory or PATH!\n"; 247193323Sed return 0; 248193323Sed} 249193323Sed 250193323Sed//===---------------------------------------------------------------------===// 251193323Sed// Custom execution command implementation of AbstractIntepreter interface 252193323Sed// 253193323Sed// Allows using a custom command for executing the bitcode, thus allows, 254193323Sed// for example, to invoke a cross compiler for code generation followed by 255193323Sed// a simulator that executes the generated binary. 256193323Sednamespace { 257193323Sed class CustomExecutor : public AbstractInterpreter { 258193323Sed std::string ExecutionCommand; 259193323Sed std::vector<std::string> ExecutorArgs; 260193323Sed public: 261193323Sed CustomExecutor( 262193323Sed const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : 263193323Sed ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} 264193323Sed 265193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 266193323Sed const std::vector<std::string> &Args, 267193323Sed const std::string &InputFile, 268193323Sed const std::string &OutputFile, 269207618Srdivacky std::string *Error, 270193323Sed const std::vector<std::string> &GCCArgs, 271193323Sed const std::vector<std::string> &SharedLibs = 272207618Srdivacky std::vector<std::string>(), 273193323Sed unsigned Timeout = 0, 274193323Sed unsigned MemoryLimit = 0); 275193323Sed }; 276193323Sed} 277193323Sed 278193323Sedint CustomExecutor::ExecuteProgram(const std::string &Bitcode, 279193323Sed const std::vector<std::string> &Args, 280193323Sed const std::string &InputFile, 281193323Sed const std::string &OutputFile, 282207618Srdivacky std::string *Error, 283193323Sed const std::vector<std::string> &GCCArgs, 284193323Sed const std::vector<std::string> &SharedLibs, 285193323Sed unsigned Timeout, 286193323Sed unsigned MemoryLimit) { 287193323Sed 288193323Sed std::vector<const char*> ProgramArgs; 289193323Sed ProgramArgs.push_back(ExecutionCommand.c_str()); 290193323Sed 291193323Sed for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 292193323Sed ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); 293193323Sed ProgramArgs.push_back(Bitcode.c_str()); 294193323Sed ProgramArgs.push_back(0); 295193323Sed 296193323Sed // Add optional parameters to the running program from Argv 297207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 298193323Sed ProgramArgs.push_back(Args[i].c_str()); 299193323Sed 300193323Sed return RunProgramWithTimeout( 301193323Sed sys::Path(ExecutionCommand), 302193323Sed &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 303193323Sed sys::Path(OutputFile), Timeout, MemoryLimit); 304193323Sed} 305193323Sed 306193323Sed// Custom execution environment create method, takes the execution command 307193323Sed// as arguments 308193323SedAbstractInterpreter *AbstractInterpreter::createCustom( 309193323Sed std::string &Message, 310193323Sed const std::string &ExecCommandLine) { 311193323Sed 312193323Sed std::string Command = ""; 313193323Sed std::vector<std::string> Args; 314193323Sed std::string delimiters = " "; 315193323Sed 316193323Sed // Tokenize the ExecCommandLine to the command and the args to allow 317193323Sed // defining a full command line as the command instead of just the 318193323Sed // executed program. We cannot just pass the whole string after the command 319193323Sed // as a single argument because then program sees only a single 320193323Sed // command line argument (with spaces in it: "foo bar" instead 321193323Sed // of "foo" and "bar"). 322193323Sed 323193323Sed // code borrowed from: 324193323Sed // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html 325193323Sed std::string::size_type lastPos = 326193323Sed ExecCommandLine.find_first_not_of(delimiters, 0); 327193323Sed std::string::size_type pos = 328193323Sed ExecCommandLine.find_first_of(delimiters, lastPos); 329193323Sed 330193323Sed while (std::string::npos != pos || std::string::npos != lastPos) { 331193323Sed std::string token = ExecCommandLine.substr(lastPos, pos - lastPos); 332193323Sed if (Command == "") 333193323Sed Command = token; 334193323Sed else 335193323Sed Args.push_back(token); 336193323Sed // Skip delimiters. Note the "not_of" 337193323Sed lastPos = ExecCommandLine.find_first_not_of(delimiters, pos); 338193323Sed // Find next "non-delimiter" 339193323Sed pos = ExecCommandLine.find_first_of(delimiters, lastPos); 340193323Sed } 341193323Sed 342198090Srdivacky std::string CmdPath = sys::Program::FindProgramByName(Command).str(); 343193323Sed if (CmdPath.empty()) { 344193323Sed Message = 345193323Sed std::string("Cannot find '") + Command + 346193323Sed "' in executable directory or PATH!\n"; 347193323Sed return 0; 348193323Sed } 349193323Sed 350193323Sed Message = "Found command in: " + CmdPath + "\n"; 351193323Sed 352193323Sed return new CustomExecutor(CmdPath, Args); 353193323Sed} 354193323Sed 355193323Sed//===----------------------------------------------------------------------===// 356193323Sed// LLC Implementation of AbstractIntepreter interface 357193323Sed// 358193323SedGCC::FileType LLC::OutputCode(const std::string &Bitcode, 359208599Srdivacky sys::Path &OutputAsmFile, std::string &Error, 360208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 361205218Srdivacky const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); 362205218Srdivacky sys::Path uniqueFile(Bitcode + Suffix); 363193323Sed std::string ErrMsg; 364193323Sed if (uniqueFile.makeUnique(true, &ErrMsg)) { 365198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 366193323Sed exit(1); 367193323Sed } 368193323Sed OutputAsmFile = uniqueFile; 369193323Sed std::vector<const char *> LLCArgs; 370205218Srdivacky LLCArgs.push_back(LLCPath.c_str()); 371193323Sed 372193323Sed // Add any extra LLC args. 373193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 374193323Sed LLCArgs.push_back(ToolArgs[i].c_str()); 375193323Sed 376205218Srdivacky LLCArgs.push_back("-o"); 377205218Srdivacky LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file 378205218Srdivacky LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 379205218Srdivacky 380205218Srdivacky if (UseIntegratedAssembler) 381205218Srdivacky LLCArgs.push_back("-filetype=obj"); 382205218Srdivacky 383193323Sed LLCArgs.push_back (0); 384193323Sed 385205218Srdivacky outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); 386205218Srdivacky outs().flush(); 387198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 388207618Srdivacky for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 389198090Srdivacky errs() << " " << LLCArgs[i]; 390198090Srdivacky errs() << "\n"; 391193323Sed ); 392193323Sed if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], 393208599Srdivacky sys::Path(), sys::Path(), sys::Path(), 394208599Srdivacky Timeout, MemoryLimit)) 395208599Srdivacky Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0], 396208599Srdivacky Timeout, MemoryLimit); 397207618Srdivacky return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; 398193323Sed} 399193323Sed 400208599Srdivackyvoid LLC::compileProgram(const std::string &Bitcode, std::string *Error, 401208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 402193323Sed sys::Path OutputAsmFile; 403208599Srdivacky OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); 404193323Sed OutputAsmFile.eraseFromDisk(); 405193323Sed} 406193323Sed 407193323Sedint LLC::ExecuteProgram(const std::string &Bitcode, 408193323Sed const std::vector<std::string> &Args, 409193323Sed const std::string &InputFile, 410193323Sed const std::string &OutputFile, 411207618Srdivacky std::string *Error, 412193323Sed const std::vector<std::string> &ArgsForGCC, 413193323Sed const std::vector<std::string> &SharedLibs, 414193323Sed unsigned Timeout, 415193323Sed unsigned MemoryLimit) { 416193323Sed 417193323Sed sys::Path OutputAsmFile; 418208599Srdivacky GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, 419208599Srdivacky MemoryLimit); 420198090Srdivacky FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); 421193323Sed 422193323Sed std::vector<std::string> GCCArgs(ArgsForGCC); 423193323Sed GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 424193323Sed 425193323Sed // Assuming LLC worked, compile the result with GCC and run it. 426205218Srdivacky return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind, 427207618Srdivacky InputFile, OutputFile, Error, GCCArgs, 428193323Sed Timeout, MemoryLimit); 429193323Sed} 430193323Sed 431193323Sed/// createLLC - Try to find the LLC executable 432193323Sed/// 433198090SrdivackyLLC *AbstractInterpreter::createLLC(const char *Argv0, 434193323Sed std::string &Message, 435208599Srdivacky const std::string &GCCBinary, 436193323Sed const std::vector<std::string> *Args, 437205218Srdivacky const std::vector<std::string> *GCCArgs, 438205218Srdivacky bool UseIntegratedAssembler) { 439198090Srdivacky std::string LLCPath = 440198090Srdivacky FindExecutable("llc", Argv0, (void *)(intptr_t)&createLLC).str(); 441193323Sed if (LLCPath.empty()) { 442193323Sed Message = "Cannot find `llc' in executable directory or PATH!\n"; 443193323Sed return 0; 444193323Sed } 445193323Sed 446193323Sed Message = "Found llc: " + LLCPath + "\n"; 447208599Srdivacky GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); 448193323Sed if (!gcc) { 449198090Srdivacky errs() << Message << "\n"; 450193323Sed exit(1); 451193323Sed } 452208599Srdivacky return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler); 453193323Sed} 454193323Sed 455193323Sed//===---------------------------------------------------------------------===// 456193323Sed// JIT Implementation of AbstractIntepreter interface 457193323Sed// 458193323Sednamespace { 459193323Sed class JIT : public AbstractInterpreter { 460193323Sed std::string LLIPath; // The path to the LLI executable 461193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 462193323Sed public: 463193323Sed JIT(const std::string &Path, const std::vector<std::string> *Args) 464193323Sed : LLIPath(Path) { 465193323Sed ToolArgs.clear (); 466193323Sed if (Args) { ToolArgs = *Args; } 467193323Sed } 468193323Sed 469193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 470193323Sed const std::vector<std::string> &Args, 471193323Sed const std::string &InputFile, 472193323Sed const std::string &OutputFile, 473207618Srdivacky std::string *Error, 474193323Sed const std::vector<std::string> &GCCArgs = 475193323Sed std::vector<std::string>(), 476193323Sed const std::vector<std::string> &SharedLibs = 477193323Sed std::vector<std::string>(), 478207618Srdivacky unsigned Timeout = 0, 479207618Srdivacky unsigned MemoryLimit = 0); 480193323Sed }; 481193323Sed} 482193323Sed 483193323Sedint JIT::ExecuteProgram(const std::string &Bitcode, 484193323Sed const std::vector<std::string> &Args, 485193323Sed const std::string &InputFile, 486193323Sed const std::string &OutputFile, 487207618Srdivacky std::string *Error, 488193323Sed const std::vector<std::string> &GCCArgs, 489193323Sed const std::vector<std::string> &SharedLibs, 490193323Sed unsigned Timeout, 491193323Sed unsigned MemoryLimit) { 492193323Sed // Construct a vector of parameters, incorporating those from the command-line 493193323Sed std::vector<const char*> JITArgs; 494193323Sed JITArgs.push_back(LLIPath.c_str()); 495193323Sed JITArgs.push_back("-force-interpreter=false"); 496193323Sed 497193323Sed // Add any extra LLI args. 498193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 499193323Sed JITArgs.push_back(ToolArgs[i].c_str()); 500193323Sed 501193323Sed for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 502193323Sed JITArgs.push_back("-load"); 503193323Sed JITArgs.push_back(SharedLibs[i].c_str()); 504193323Sed } 505193323Sed JITArgs.push_back(Bitcode.c_str()); 506193323Sed // Add optional parameters to the running program from Argv 507193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 508193323Sed JITArgs.push_back(Args[i].c_str()); 509193323Sed JITArgs.push_back(0); 510193323Sed 511198090Srdivacky outs() << "<jit>"; outs().flush(); 512198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 513193323Sed for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) 514198090Srdivacky errs() << " " << JITArgs[i]; 515198090Srdivacky errs() << "\n"; 516193323Sed ); 517198090Srdivacky DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 518193323Sed return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], 519193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 520193323Sed Timeout, MemoryLimit); 521193323Sed} 522193323Sed 523193323Sed/// createJIT - Try to find the LLI executable 524193323Sed/// 525198090SrdivackyAbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, 526193323Sed std::string &Message, const std::vector<std::string> *Args) { 527198090Srdivacky std::string LLIPath = 528198090Srdivacky FindExecutable("lli", Argv0, (void *)(intptr_t)&createJIT).str(); 529193323Sed if (!LLIPath.empty()) { 530193323Sed Message = "Found lli: " + LLIPath + "\n"; 531193323Sed return new JIT(LLIPath, Args); 532193323Sed } 533193323Sed 534193323Sed Message = "Cannot find `lli' in executable directory or PATH!\n"; 535193323Sed return 0; 536193323Sed} 537193323Sed 538193323SedGCC::FileType CBE::OutputCode(const std::string &Bitcode, 539208599Srdivacky sys::Path &OutputCFile, std::string &Error, 540208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 541193323Sed sys::Path uniqueFile(Bitcode+".cbe.c"); 542193323Sed std::string ErrMsg; 543193323Sed if (uniqueFile.makeUnique(true, &ErrMsg)) { 544198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 545193323Sed exit(1); 546193323Sed } 547193323Sed OutputCFile = uniqueFile; 548193323Sed std::vector<const char *> LLCArgs; 549207618Srdivacky LLCArgs.push_back(LLCPath.c_str()); 550193323Sed 551193323Sed // Add any extra LLC args. 552193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 553193323Sed LLCArgs.push_back(ToolArgs[i].c_str()); 554193323Sed 555207618Srdivacky LLCArgs.push_back("-o"); 556207618Srdivacky LLCArgs.push_back(OutputCFile.c_str()); // Output to the C file 557207618Srdivacky LLCArgs.push_back("-march=c"); // Output C language 558207618Srdivacky LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 559207618Srdivacky LLCArgs.push_back(0); 560193323Sed 561198090Srdivacky outs() << "<cbe>"; outs().flush(); 562198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 563207618Srdivacky for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 564198090Srdivacky errs() << " " << LLCArgs[i]; 565198090Srdivacky errs() << "\n"; 566193323Sed ); 567193323Sed if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), 568208599Srdivacky sys::Path(), Timeout, MemoryLimit)) 569208599Srdivacky Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); 570193323Sed return GCC::CFile; 571193323Sed} 572193323Sed 573208599Srdivackyvoid CBE::compileProgram(const std::string &Bitcode, std::string *Error, 574208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 575193323Sed sys::Path OutputCFile; 576208599Srdivacky OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); 577193323Sed OutputCFile.eraseFromDisk(); 578193323Sed} 579193323Sed 580193323Sedint CBE::ExecuteProgram(const std::string &Bitcode, 581193323Sed const std::vector<std::string> &Args, 582193323Sed const std::string &InputFile, 583193323Sed const std::string &OutputFile, 584207618Srdivacky std::string *Error, 585193323Sed const std::vector<std::string> &ArgsForGCC, 586193323Sed const std::vector<std::string> &SharedLibs, 587193323Sed unsigned Timeout, 588193323Sed unsigned MemoryLimit) { 589193323Sed sys::Path OutputCFile; 590208599Srdivacky OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); 591193323Sed 592198090Srdivacky FileRemover CFileRemove(OutputCFile, !SaveTemps); 593193323Sed 594193323Sed std::vector<std::string> GCCArgs(ArgsForGCC); 595193323Sed GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 596193323Sed 597198090Srdivacky return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, 598207618Srdivacky InputFile, OutputFile, Error, GCCArgs, 599193323Sed Timeout, MemoryLimit); 600193323Sed} 601193323Sed 602193323Sed/// createCBE - Try to find the 'llc' executable 603193323Sed/// 604198090SrdivackyCBE *AbstractInterpreter::createCBE(const char *Argv0, 605193323Sed std::string &Message, 606208599Srdivacky const std::string &GCCBinary, 607193323Sed const std::vector<std::string> *Args, 608193323Sed const std::vector<std::string> *GCCArgs) { 609198090Srdivacky sys::Path LLCPath = 610198090Srdivacky FindExecutable("llc", Argv0, (void *)(intptr_t)&createCBE); 611193323Sed if (LLCPath.isEmpty()) { 612193323Sed Message = 613193323Sed "Cannot find `llc' in executable directory or PATH!\n"; 614193323Sed return 0; 615193323Sed } 616193323Sed 617198090Srdivacky Message = "Found llc: " + LLCPath.str() + "\n"; 618208599Srdivacky GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); 619193323Sed if (!gcc) { 620198090Srdivacky errs() << Message << "\n"; 621193323Sed exit(1); 622193323Sed } 623193323Sed return new CBE(LLCPath, gcc, Args); 624193323Sed} 625193323Sed 626193323Sed//===---------------------------------------------------------------------===// 627193323Sed// GCC abstraction 628193323Sed// 629198090Srdivacky 630205218Srdivackystatic bool IsARMArchitecture(std::vector<std::string> Args) { 631198090Srdivacky for (std::vector<std::string>::const_iterator 632198090Srdivacky I = Args.begin(), E = Args.end(); I != E; ++I) { 633208599Srdivacky if (StringRef(*I).equals_lower("-arch")) { 634198090Srdivacky ++I; 635208599Srdivacky if (I != E && StringRef(*I).substr(0, strlen("arm")).equals_lower("arm")) 636198090Srdivacky return true; 637198090Srdivacky } 638198090Srdivacky } 639198090Srdivacky 640198090Srdivacky return false; 641198090Srdivacky} 642198090Srdivacky 643193323Sedint GCC::ExecuteProgram(const std::string &ProgramFile, 644193323Sed const std::vector<std::string> &Args, 645193323Sed FileType fileType, 646193323Sed const std::string &InputFile, 647193323Sed const std::string &OutputFile, 648207618Srdivacky std::string *Error, 649193323Sed const std::vector<std::string> &ArgsForGCC, 650193323Sed unsigned Timeout, 651193323Sed unsigned MemoryLimit) { 652193323Sed std::vector<const char*> GCCArgs; 653193323Sed 654193323Sed GCCArgs.push_back(GCCPath.c_str()); 655193323Sed 656205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 657205218Srdivacky GCCArgs.push_back("-m32"); 658205218Srdivacky 659193323Sed for (std::vector<std::string>::const_iterator 660193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 661193323Sed GCCArgs.push_back(I->c_str()); 662193323Sed 663193323Sed // Specify -x explicitly in case the extension is wonky 664205218Srdivacky if (fileType != ObjectFile) { 665205218Srdivacky GCCArgs.push_back("-x"); 666205218Srdivacky if (fileType == CFile) { 667205218Srdivacky GCCArgs.push_back("c"); 668205218Srdivacky GCCArgs.push_back("-fno-strict-aliasing"); 669205218Srdivacky } else { 670205218Srdivacky GCCArgs.push_back("assembler"); 671198090Srdivacky 672205218Srdivacky // For ARM architectures we don't want this flag. bugpoint isn't 673205218Srdivacky // explicitly told what architecture it is working on, so we get 674205218Srdivacky // it from gcc flags 675205218Srdivacky if ((TargetTriple.getOS() == Triple::Darwin) && 676205218Srdivacky !IsARMArchitecture(ArgsForGCC)) 677205218Srdivacky GCCArgs.push_back("-force_cpusubtype_ALL"); 678205218Srdivacky } 679193323Sed } 680205218Srdivacky 681205218Srdivacky GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. 682205218Srdivacky 683193323Sed GCCArgs.push_back("-x"); 684193323Sed GCCArgs.push_back("none"); 685193323Sed GCCArgs.push_back("-o"); 686193323Sed sys::Path OutputBinary (ProgramFile+".gcc.exe"); 687193323Sed std::string ErrMsg; 688193323Sed if (OutputBinary.makeUnique(true, &ErrMsg)) { 689198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 690193323Sed exit(1); 691193323Sed } 692193323Sed GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 693193323Sed 694193323Sed // Add any arguments intended for GCC. We locate them here because this is 695193323Sed // most likely -L and -l options that need to come before other libraries but 696193323Sed // after the source. Other options won't be sensitive to placement on the 697193323Sed // command line, so this should be safe. 698193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 699193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 700193323Sed 701193323Sed GCCArgs.push_back("-lm"); // Hard-code the math library... 702193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit... 703193323Sed#if defined (HAVE_LINK_R) 704193323Sed GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files 705193323Sed#endif 706198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 707198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 708193323Sed GCCArgs.push_back(0); // NULL terminator 709193323Sed 710198090Srdivacky outs() << "<gcc>"; outs().flush(); 711198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 712207618Srdivacky for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 713198090Srdivacky errs() << " " << GCCArgs[i]; 714198090Srdivacky errs() << "\n"; 715193323Sed ); 716193323Sed if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 717193323Sed sys::Path())) { 718207618Srdivacky *Error = ProcessFailure(GCCPath, &GCCArgs[0]); 719207618Srdivacky return -1; 720193323Sed } 721193323Sed 722193323Sed std::vector<const char*> ProgramArgs; 723193323Sed 724193323Sed if (RemoteClientPath.isEmpty()) 725193323Sed ProgramArgs.push_back(OutputBinary.c_str()); 726193323Sed else { 727193323Sed ProgramArgs.push_back(RemoteClientPath.c_str()); 728193323Sed ProgramArgs.push_back(RemoteHost.c_str()); 729198090Srdivacky if (!RemoteUser.empty()) { 730198090Srdivacky ProgramArgs.push_back("-l"); 731198090Srdivacky ProgramArgs.push_back(RemoteUser.c_str()); 732198090Srdivacky } 733198090Srdivacky if (!RemotePort.empty()) { 734198090Srdivacky ProgramArgs.push_back("-p"); 735198090Srdivacky ProgramArgs.push_back(RemotePort.c_str()); 736198090Srdivacky } 737193323Sed if (!RemoteExtra.empty()) { 738193323Sed ProgramArgs.push_back(RemoteExtra.c_str()); 739193323Sed } 740193323Sed 741198090Srdivacky // Full path to the binary. We need to cd to the exec directory because 742198090Srdivacky // there is a dylib there that the exec expects to find in the CWD 743193323Sed char* env_pwd = getenv("PWD"); 744193323Sed std::string Exec = "cd "; 745193323Sed Exec += env_pwd; 746193323Sed Exec += "; ./"; 747193323Sed Exec += OutputBinary.c_str(); 748193323Sed ProgramArgs.push_back(Exec.c_str()); 749193323Sed } 750193323Sed 751193323Sed // Add optional parameters to the running program from Argv 752207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 753193323Sed ProgramArgs.push_back(Args[i].c_str()); 754193323Sed ProgramArgs.push_back(0); // NULL terminator 755193323Sed 756193323Sed // Now that we have a binary, run it! 757198090Srdivacky outs() << "<program>"; outs().flush(); 758198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 759207618Srdivacky for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) 760198090Srdivacky errs() << " " << ProgramArgs[i]; 761198090Srdivacky errs() << "\n"; 762193323Sed ); 763193323Sed 764198090Srdivacky FileRemover OutputBinaryRemover(OutputBinary, !SaveTemps); 765193323Sed 766198090Srdivacky if (RemoteClientPath.isEmpty()) { 767207618Srdivacky DEBUG(errs() << "<run locally>"); 768193323Sed return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], 769193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 770193323Sed Timeout, MemoryLimit); 771198090Srdivacky } else { 772198090Srdivacky outs() << "<run remotely>"; outs().flush(); 773198090Srdivacky return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), 774198090Srdivacky &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 775198090Srdivacky sys::Path(OutputFile), Timeout, MemoryLimit); 776198090Srdivacky } 777193323Sed} 778193323Sed 779193323Sedint GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 780193323Sed std::string &OutputFile, 781207618Srdivacky const std::vector<std::string> &ArgsForGCC, 782207618Srdivacky std::string &Error) { 783193323Sed sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); 784193323Sed std::string ErrMsg; 785193323Sed if (uniqueFilename.makeUnique(true, &ErrMsg)) { 786198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 787193323Sed exit(1); 788193323Sed } 789198090Srdivacky OutputFile = uniqueFilename.str(); 790193323Sed 791193323Sed std::vector<const char*> GCCArgs; 792193323Sed 793193323Sed GCCArgs.push_back(GCCPath.c_str()); 794193323Sed 795205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 796205218Srdivacky GCCArgs.push_back("-m32"); 797205218Srdivacky 798193323Sed for (std::vector<std::string>::const_iterator 799193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 800193323Sed GCCArgs.push_back(I->c_str()); 801193323Sed 802193323Sed // Compile the C/asm file into a shared object 803205218Srdivacky if (fileType != ObjectFile) { 804205218Srdivacky GCCArgs.push_back("-x"); 805205218Srdivacky GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 806205218Srdivacky } 807193323Sed GCCArgs.push_back("-fno-strict-aliasing"); 808193323Sed GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. 809193323Sed GCCArgs.push_back("-x"); 810193323Sed GCCArgs.push_back("none"); 811198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 812198090Srdivacky GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 813198090Srdivacky else if (TargetTriple.getOS() == Triple::Darwin) { 814198090Srdivacky // link all source files into a single module in data segment, rather than 815198090Srdivacky // generating blocks. dynamic_lookup requires that you set 816198090Srdivacky // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 817198090Srdivacky // bugpoint to just pass that in the environment of GCC. 818198090Srdivacky GCCArgs.push_back("-single_module"); 819198090Srdivacky GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 820198090Srdivacky GCCArgs.push_back("-undefined"); 821198090Srdivacky GCCArgs.push_back("dynamic_lookup"); 822198090Srdivacky } else 823198090Srdivacky GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 824193323Sed 825198090Srdivacky if ((TargetTriple.getArch() == Triple::alpha) || 826198090Srdivacky (TargetTriple.getArch() == Triple::x86_64)) 827198090Srdivacky GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 828198090Srdivacky 829198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 830198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 831198090Srdivacky 832193323Sed GCCArgs.push_back("-o"); 833193323Sed GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 834193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit. 835193323Sed 836193323Sed 837193323Sed 838193323Sed // Add any arguments intended for GCC. We locate them here because this is 839193323Sed // most likely -L and -l options that need to come before other libraries but 840193323Sed // after the source. Other options won't be sensitive to placement on the 841193323Sed // command line, so this should be safe. 842193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 843193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 844193323Sed GCCArgs.push_back(0); // NULL terminator 845193323Sed 846193323Sed 847193323Sed 848198090Srdivacky outs() << "<gcc>"; outs().flush(); 849198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 850207618Srdivacky for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 851198090Srdivacky errs() << " " << GCCArgs[i]; 852198090Srdivacky errs() << "\n"; 853193323Sed ); 854193323Sed if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 855193323Sed sys::Path())) { 856207618Srdivacky Error = ProcessFailure(GCCPath, &GCCArgs[0]); 857193323Sed return 1; 858193323Sed } 859193323Sed return 0; 860193323Sed} 861193323Sed 862193323Sed/// create - Try to find the `gcc' executable 863193323Sed/// 864198090SrdivackyGCC *GCC::create(std::string &Message, 865208599Srdivacky const std::string &GCCBinary, 866193323Sed const std::vector<std::string> *Args) { 867208599Srdivacky sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary); 868193323Sed if (GCCPath.isEmpty()) { 869208599Srdivacky Message = "Cannot find `"+ GCCBinary +"' in executable directory or PATH!\n"; 870193323Sed return 0; 871193323Sed } 872193323Sed 873193323Sed sys::Path RemoteClientPath; 874193323Sed if (!RemoteClient.empty()) 875198090Srdivacky RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); 876193323Sed 877198090Srdivacky Message = "Found gcc: " + GCCPath.str() + "\n"; 878193323Sed return new GCC(GCCPath, RemoteClientPath, Args); 879193323Sed} 880