ToolRunner.cpp revision 221337
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" 16218885Sdim#include "llvm/Support/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, 62218885Sdim unsigned MemoryLimit = 0, 63218885Sdim std::string *ErrMsg = 0) { 64193323Sed const sys::Path* redirects[3]; 65193323Sed redirects[0] = &StdInFile; 66193323Sed redirects[1] = &StdOutFile; 67193323Sed redirects[2] = &StdErrFile; 68198090Srdivacky 69198090Srdivacky#if 0 // For debug purposes 70198090Srdivacky { 71198090Srdivacky errs() << "RUN:"; 72193323Sed for (unsigned i = 0; Args[i]; ++i) 73198090Srdivacky errs() << " " << Args[i]; 74198090Srdivacky errs() << "\n"; 75193323Sed } 76198090Srdivacky#endif 77193323Sed 78193323Sed return 79193323Sed sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, 80218885Sdim NumSeconds, MemoryLimit, ErrMsg); 81193323Sed} 82193323Sed 83198090Srdivacky/// RunProgramRemotelyWithTimeout - This function runs the given program 84198090Srdivacky/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 85198090Srdivacky/// Returns the remote program exit code or reports a remote client error if it 86198090Srdivacky/// fails. Remote client is required to return 255 if it failed or program exit 87198090Srdivacky/// code otherwise. 88207618Srdivacky/// @see sys::Program::ExecuteAndWait 89198090Srdivackystatic int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, 90198090Srdivacky const char **Args, 91198090Srdivacky const sys::Path &StdInFile, 92198090Srdivacky const sys::Path &StdOutFile, 93198090Srdivacky const sys::Path &StdErrFile, 94198090Srdivacky unsigned NumSeconds = 0, 95198090Srdivacky unsigned MemoryLimit = 0) { 96198090Srdivacky const sys::Path* redirects[3]; 97198090Srdivacky redirects[0] = &StdInFile; 98198090Srdivacky redirects[1] = &StdOutFile; 99198090Srdivacky redirects[2] = &StdErrFile; 100193323Sed 101198090Srdivacky#if 0 // For debug purposes 102198090Srdivacky { 103198090Srdivacky errs() << "RUN:"; 104198090Srdivacky for (unsigned i = 0; Args[i]; ++i) 105198090Srdivacky errs() << " " << Args[i]; 106198090Srdivacky errs() << "\n"; 107198090Srdivacky } 108198090Srdivacky#endif 109193323Sed 110198090Srdivacky // Run the program remotely with the remote client 111198090Srdivacky int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, 112198090Srdivacky 0, redirects, NumSeconds, MemoryLimit); 113198090Srdivacky 114198090Srdivacky // Has the remote client fail? 115198090Srdivacky if (255 == ReturnCode) { 116198090Srdivacky std::ostringstream OS; 117198090Srdivacky OS << "\nError running remote client:\n "; 118198090Srdivacky for (const char **Arg = Args; *Arg; ++Arg) 119198090Srdivacky OS << " " << *Arg; 120198090Srdivacky OS << "\n"; 121198090Srdivacky 122198090Srdivacky // The error message is in the output file, let's print it out from there. 123198090Srdivacky std::ifstream ErrorFile(StdOutFile.c_str()); 124198090Srdivacky if (ErrorFile) { 125198090Srdivacky std::copy(std::istreambuf_iterator<char>(ErrorFile), 126198090Srdivacky std::istreambuf_iterator<char>(), 127198090Srdivacky std::ostreambuf_iterator<char>(OS)); 128198090Srdivacky ErrorFile.close(); 129198090Srdivacky } 130198090Srdivacky 131207618Srdivacky errs() << OS; 132198090Srdivacky } 133198090Srdivacky 134198090Srdivacky return ReturnCode; 135198090Srdivacky} 136198090Srdivacky 137208599Srdivackystatic std::string ProcessFailure(sys::Path ProgPath, const char** Args, 138208599Srdivacky unsigned Timeout = 0, 139208599Srdivacky unsigned MemoryLimit = 0) { 140193323Sed std::ostringstream OS; 141193323Sed OS << "\nError running tool:\n "; 142193323Sed for (const char **Arg = Args; *Arg; ++Arg) 143193323Sed OS << " " << *Arg; 144193323Sed OS << "\n"; 145218885Sdim 146193323Sed // Rerun the compiler, capturing any error messages to print them. 147193323Sed sys::Path ErrorFilename("bugpoint.program_error_messages"); 148193323Sed std::string ErrMsg; 149193323Sed if (ErrorFilename.makeUnique(true, &ErrMsg)) { 150198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 151193323Sed exit(1); 152193323Sed } 153193323Sed RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, 154208599Srdivacky ErrorFilename, Timeout, MemoryLimit); 155208599Srdivacky // FIXME: check return code ? 156193323Sed 157193323Sed // Print out the error messages generated by GCC if possible... 158193323Sed std::ifstream ErrorFile(ErrorFilename.c_str()); 159193323Sed if (ErrorFile) { 160193323Sed std::copy(std::istreambuf_iterator<char>(ErrorFile), 161193323Sed std::istreambuf_iterator<char>(), 162193323Sed std::ostreambuf_iterator<char>(OS)); 163193323Sed ErrorFile.close(); 164193323Sed } 165193323Sed 166193323Sed ErrorFilename.eraseFromDisk(); 167207618Srdivacky return OS.str(); 168193323Sed} 169193323Sed 170193323Sed//===---------------------------------------------------------------------===// 171193323Sed// LLI Implementation of AbstractIntepreter interface 172193323Sed// 173193323Sednamespace { 174193323Sed class LLI : public AbstractInterpreter { 175193323Sed std::string LLIPath; // The path to the LLI executable 176193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 177193323Sed public: 178193323Sed LLI(const std::string &Path, const std::vector<std::string> *Args) 179193323Sed : LLIPath(Path) { 180193323Sed ToolArgs.clear (); 181193323Sed if (Args) { ToolArgs = *Args; } 182193323Sed } 183193323Sed 184193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 185193323Sed const std::vector<std::string> &Args, 186193323Sed const std::string &InputFile, 187193323Sed const std::string &OutputFile, 188207618Srdivacky std::string *Error, 189193323Sed const std::vector<std::string> &GCCArgs, 190193323Sed const std::vector<std::string> &SharedLibs = 191193323Sed std::vector<std::string>(), 192193323Sed unsigned Timeout = 0, 193193323Sed unsigned MemoryLimit = 0); 194193323Sed }; 195193323Sed} 196193323Sed 197193323Sedint LLI::ExecuteProgram(const std::string &Bitcode, 198193323Sed const std::vector<std::string> &Args, 199193323Sed const std::string &InputFile, 200193323Sed const std::string &OutputFile, 201207618Srdivacky std::string *Error, 202193323Sed const std::vector<std::string> &GCCArgs, 203193323Sed const std::vector<std::string> &SharedLibs, 204193323Sed unsigned Timeout, 205193323Sed unsigned MemoryLimit) { 206193323Sed std::vector<const char*> LLIArgs; 207193323Sed LLIArgs.push_back(LLIPath.c_str()); 208193323Sed LLIArgs.push_back("-force-interpreter=true"); 209193323Sed 210218885Sdim for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), 211218885Sdim e = SharedLibs.end(); i != e; ++i) { 212199481Srdivacky LLIArgs.push_back("-load"); 213199481Srdivacky LLIArgs.push_back((*i).c_str()); 214199481Srdivacky } 215199481Srdivacky 216193323Sed // Add any extra LLI args. 217193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 218193323Sed LLIArgs.push_back(ToolArgs[i].c_str()); 219193323Sed 220193323Sed LLIArgs.push_back(Bitcode.c_str()); 221193323Sed // Add optional parameters to the running program from Argv 222193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 223193323Sed LLIArgs.push_back(Args[i].c_str()); 224193323Sed LLIArgs.push_back(0); 225193323Sed 226198090Srdivacky outs() << "<lli>"; outs().flush(); 227198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 228193323Sed for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) 229198090Srdivacky errs() << " " << LLIArgs[i]; 230198090Srdivacky errs() << "\n"; 231193323Sed ); 232193323Sed return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], 233193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 234218885Sdim Timeout, MemoryLimit, Error); 235193323Sed} 236193323Sed 237193323Sed// LLI create method - Try to find the LLI executable 238198090SrdivackyAbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, 239193323Sed std::string &Message, 240193323Sed const std::vector<std::string> *ToolArgs) { 241198090Srdivacky std::string LLIPath = 242218885Sdim PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI).str(); 243193323Sed if (!LLIPath.empty()) { 244193323Sed Message = "Found lli: " + LLIPath + "\n"; 245193323Sed return new LLI(LLIPath, ToolArgs); 246193323Sed } 247193323Sed 248218885Sdim Message = "Cannot find `lli' in executable directory!\n"; 249193323Sed return 0; 250193323Sed} 251193323Sed 252193323Sed//===---------------------------------------------------------------------===// 253218885Sdim// Custom compiler command implementation of AbstractIntepreter interface 254218885Sdim// 255218885Sdim// Allows using a custom command for compiling the bitcode, thus allows, for 256218885Sdim// example, to compile a bitcode fragment without linking or executing, then 257218885Sdim// using a custom wrapper script to check for compiler errors. 258218885Sdimnamespace { 259218885Sdim class CustomCompiler : public AbstractInterpreter { 260218885Sdim std::string CompilerCommand; 261218885Sdim std::vector<std::string> CompilerArgs; 262218885Sdim public: 263218885Sdim CustomCompiler( 264218885Sdim const std::string &CompilerCmd, std::vector<std::string> CompArgs) : 265218885Sdim CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {} 266218885Sdim 267218885Sdim virtual void compileProgram(const std::string &Bitcode, 268218885Sdim std::string *Error, 269218885Sdim unsigned Timeout = 0, 270218885Sdim unsigned MemoryLimit = 0); 271218885Sdim 272218885Sdim virtual int ExecuteProgram(const std::string &Bitcode, 273218885Sdim const std::vector<std::string> &Args, 274218885Sdim const std::string &InputFile, 275218885Sdim const std::string &OutputFile, 276218885Sdim std::string *Error, 277218885Sdim const std::vector<std::string> &GCCArgs = 278218885Sdim std::vector<std::string>(), 279218885Sdim const std::vector<std::string> &SharedLibs = 280218885Sdim std::vector<std::string>(), 281218885Sdim unsigned Timeout = 0, 282218885Sdim unsigned MemoryLimit = 0) { 283218885Sdim *Error = "Execution not supported with -compile-custom"; 284218885Sdim return -1; 285218885Sdim } 286218885Sdim }; 287218885Sdim} 288218885Sdim 289218885Sdimvoid CustomCompiler::compileProgram(const std::string &Bitcode, 290218885Sdim std::string *Error, 291218885Sdim unsigned Timeout, 292218885Sdim unsigned MemoryLimit) { 293218885Sdim 294218885Sdim std::vector<const char*> ProgramArgs; 295218885Sdim ProgramArgs.push_back(CompilerCommand.c_str()); 296218885Sdim 297218885Sdim for (std::size_t i = 0; i < CompilerArgs.size(); ++i) 298218885Sdim ProgramArgs.push_back(CompilerArgs.at(i).c_str()); 299218885Sdim ProgramArgs.push_back(Bitcode.c_str()); 300218885Sdim ProgramArgs.push_back(0); 301218885Sdim 302218885Sdim // Add optional parameters to the running program from Argv 303218885Sdim for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) 304218885Sdim ProgramArgs.push_back(CompilerArgs[i].c_str()); 305218885Sdim 306218885Sdim if (RunProgramWithTimeout( sys::Path(CompilerCommand), &ProgramArgs[0], 307218885Sdim sys::Path(), sys::Path(), sys::Path(), 308218885Sdim Timeout, MemoryLimit, Error)) 309218885Sdim *Error = ProcessFailure(sys::Path(CompilerCommand), &ProgramArgs[0], 310218885Sdim Timeout, MemoryLimit); 311218885Sdim} 312218885Sdim 313218885Sdim//===---------------------------------------------------------------------===// 314193323Sed// Custom execution command implementation of AbstractIntepreter interface 315193323Sed// 316193323Sed// Allows using a custom command for executing the bitcode, thus allows, 317218885Sdim// for example, to invoke a cross compiler for code generation followed by 318193323Sed// a simulator that executes the generated binary. 319193323Sednamespace { 320193323Sed class CustomExecutor : public AbstractInterpreter { 321193323Sed std::string ExecutionCommand; 322193323Sed std::vector<std::string> ExecutorArgs; 323193323Sed public: 324193323Sed CustomExecutor( 325193323Sed const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : 326193323Sed ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} 327193323Sed 328193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 329193323Sed const std::vector<std::string> &Args, 330193323Sed const std::string &InputFile, 331193323Sed const std::string &OutputFile, 332207618Srdivacky std::string *Error, 333193323Sed const std::vector<std::string> &GCCArgs, 334193323Sed const std::vector<std::string> &SharedLibs = 335207618Srdivacky std::vector<std::string>(), 336193323Sed unsigned Timeout = 0, 337193323Sed unsigned MemoryLimit = 0); 338193323Sed }; 339193323Sed} 340193323Sed 341193323Sedint CustomExecutor::ExecuteProgram(const std::string &Bitcode, 342193323Sed const std::vector<std::string> &Args, 343193323Sed const std::string &InputFile, 344193323Sed const std::string &OutputFile, 345207618Srdivacky std::string *Error, 346193323Sed const std::vector<std::string> &GCCArgs, 347193323Sed const std::vector<std::string> &SharedLibs, 348193323Sed unsigned Timeout, 349193323Sed unsigned MemoryLimit) { 350193323Sed 351193323Sed std::vector<const char*> ProgramArgs; 352193323Sed ProgramArgs.push_back(ExecutionCommand.c_str()); 353193323Sed 354193323Sed for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 355193323Sed ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); 356193323Sed ProgramArgs.push_back(Bitcode.c_str()); 357193323Sed ProgramArgs.push_back(0); 358193323Sed 359193323Sed // Add optional parameters to the running program from Argv 360207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 361193323Sed ProgramArgs.push_back(Args[i].c_str()); 362193323Sed 363193323Sed return RunProgramWithTimeout( 364193323Sed sys::Path(ExecutionCommand), 365218885Sdim &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 366218885Sdim sys::Path(OutputFile), Timeout, MemoryLimit, Error); 367193323Sed} 368193323Sed 369218885Sdim// Tokenize the CommandLine to the command and the args to allow 370218885Sdim// defining a full command line as the command instead of just the 371218885Sdim// executed program. We cannot just pass the whole string after the command 372218885Sdim// as a single argument because then program sees only a single 373218885Sdim// command line argument (with spaces in it: "foo bar" instead 374218885Sdim// of "foo" and "bar"). 375218885Sdim// 376218885Sdim// code borrowed from: 377218885Sdim// http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html 378218885Sdimstatic void lexCommand(std::string &Message, const std::string &CommandLine, 379218885Sdim std::string &CmdPath, std::vector<std::string> Args) { 380193323Sed 381193323Sed std::string Command = ""; 382193323Sed std::string delimiters = " "; 383193323Sed 384218885Sdim std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0); 385218885Sdim std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos); 386193323Sed 387193323Sed while (std::string::npos != pos || std::string::npos != lastPos) { 388218885Sdim std::string token = CommandLine.substr(lastPos, pos - lastPos); 389193323Sed if (Command == "") 390193323Sed Command = token; 391193323Sed else 392193323Sed Args.push_back(token); 393193323Sed // Skip delimiters. Note the "not_of" 394218885Sdim lastPos = CommandLine.find_first_not_of(delimiters, pos); 395193323Sed // Find next "non-delimiter" 396218885Sdim pos = CommandLine.find_first_of(delimiters, lastPos); 397193323Sed } 398193323Sed 399218885Sdim CmdPath = sys::Program::FindProgramByName(Command).str(); 400193323Sed if (CmdPath.empty()) { 401218885Sdim Message = 402218885Sdim std::string("Cannot find '") + Command + 403218885Sdim "' in PATH!\n"; 404218885Sdim return; 405193323Sed } 406193323Sed 407193323Sed Message = "Found command in: " + CmdPath + "\n"; 408218885Sdim} 409193323Sed 410218885Sdim// Custom execution environment create method, takes the execution command 411218885Sdim// as arguments 412218885SdimAbstractInterpreter *AbstractInterpreter::createCustomCompiler( 413218885Sdim std::string &Message, 414218885Sdim const std::string &CompileCommandLine) { 415218885Sdim 416218885Sdim std::string CmdPath; 417218885Sdim std::vector<std::string> Args; 418218885Sdim lexCommand(Message, CompileCommandLine, CmdPath, Args); 419218885Sdim if (CmdPath.empty()) 420218885Sdim return 0; 421218885Sdim 422218885Sdim return new CustomCompiler(CmdPath, Args); 423218885Sdim} 424218885Sdim 425218885Sdim// Custom execution environment create method, takes the execution command 426218885Sdim// as arguments 427218885SdimAbstractInterpreter *AbstractInterpreter::createCustomExecutor( 428218885Sdim std::string &Message, 429218885Sdim const std::string &ExecCommandLine) { 430218885Sdim 431218885Sdim 432218885Sdim std::string CmdPath; 433218885Sdim std::vector<std::string> Args; 434218885Sdim lexCommand(Message, ExecCommandLine, CmdPath, Args); 435218885Sdim if (CmdPath.empty()) 436218885Sdim return 0; 437218885Sdim 438193323Sed return new CustomExecutor(CmdPath, Args); 439193323Sed} 440193323Sed 441193323Sed//===----------------------------------------------------------------------===// 442193323Sed// LLC Implementation of AbstractIntepreter interface 443193323Sed// 444218885SdimGCC::FileType LLC::OutputCode(const std::string &Bitcode, 445208599Srdivacky sys::Path &OutputAsmFile, std::string &Error, 446208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 447205218Srdivacky const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); 448205218Srdivacky sys::Path uniqueFile(Bitcode + Suffix); 449193323Sed std::string ErrMsg; 450193323Sed if (uniqueFile.makeUnique(true, &ErrMsg)) { 451198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 452193323Sed exit(1); 453193323Sed } 454193323Sed OutputAsmFile = uniqueFile; 455193323Sed std::vector<const char *> LLCArgs; 456205218Srdivacky LLCArgs.push_back(LLCPath.c_str()); 457193323Sed 458193323Sed // Add any extra LLC args. 459193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 460193323Sed LLCArgs.push_back(ToolArgs[i].c_str()); 461193323Sed 462205218Srdivacky LLCArgs.push_back("-o"); 463205218Srdivacky LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file 464205218Srdivacky LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 465218885Sdim 466205218Srdivacky if (UseIntegratedAssembler) 467205218Srdivacky LLCArgs.push_back("-filetype=obj"); 468218885Sdim 469193323Sed LLCArgs.push_back (0); 470193323Sed 471205218Srdivacky outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); 472205218Srdivacky outs().flush(); 473198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 474207618Srdivacky for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 475198090Srdivacky errs() << " " << LLCArgs[i]; 476198090Srdivacky errs() << "\n"; 477193323Sed ); 478193323Sed if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], 479208599Srdivacky sys::Path(), sys::Path(), sys::Path(), 480208599Srdivacky Timeout, MemoryLimit)) 481208599Srdivacky Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0], 482208599Srdivacky Timeout, MemoryLimit); 483218885Sdim return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; 484193323Sed} 485193323Sed 486208599Srdivackyvoid LLC::compileProgram(const std::string &Bitcode, std::string *Error, 487208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 488193323Sed sys::Path OutputAsmFile; 489208599Srdivacky OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); 490193323Sed OutputAsmFile.eraseFromDisk(); 491193323Sed} 492193323Sed 493193323Sedint LLC::ExecuteProgram(const std::string &Bitcode, 494193323Sed const std::vector<std::string> &Args, 495193323Sed const std::string &InputFile, 496193323Sed const std::string &OutputFile, 497207618Srdivacky std::string *Error, 498193323Sed const std::vector<std::string> &ArgsForGCC, 499193323Sed const std::vector<std::string> &SharedLibs, 500193323Sed unsigned Timeout, 501193323Sed unsigned MemoryLimit) { 502193323Sed 503193323Sed sys::Path OutputAsmFile; 504208599Srdivacky GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, 505208599Srdivacky MemoryLimit); 506221337Sdim FileRemover OutFileRemover(OutputAsmFile.str(), !SaveTemps); 507193323Sed 508193323Sed std::vector<std::string> GCCArgs(ArgsForGCC); 509193323Sed GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 510193323Sed 511193323Sed // Assuming LLC worked, compile the result with GCC and run it. 512205218Srdivacky return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind, 513207618Srdivacky InputFile, OutputFile, Error, GCCArgs, 514193323Sed Timeout, MemoryLimit); 515193323Sed} 516193323Sed 517193323Sed/// createLLC - Try to find the LLC executable 518193323Sed/// 519198090SrdivackyLLC *AbstractInterpreter::createLLC(const char *Argv0, 520193323Sed std::string &Message, 521208599Srdivacky const std::string &GCCBinary, 522193323Sed const std::vector<std::string> *Args, 523205218Srdivacky const std::vector<std::string> *GCCArgs, 524205218Srdivacky bool UseIntegratedAssembler) { 525198090Srdivacky std::string LLCPath = 526218885Sdim PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC).str(); 527193323Sed if (LLCPath.empty()) { 528218885Sdim Message = "Cannot find `llc' in executable directory!\n"; 529193323Sed return 0; 530193323Sed } 531193323Sed 532193323Sed Message = "Found llc: " + LLCPath + "\n"; 533208599Srdivacky GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); 534193323Sed if (!gcc) { 535198090Srdivacky errs() << Message << "\n"; 536193323Sed exit(1); 537193323Sed } 538208599Srdivacky return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler); 539193323Sed} 540193323Sed 541193323Sed//===---------------------------------------------------------------------===// 542193323Sed// JIT Implementation of AbstractIntepreter interface 543193323Sed// 544193323Sednamespace { 545193323Sed class JIT : public AbstractInterpreter { 546193323Sed std::string LLIPath; // The path to the LLI executable 547193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 548193323Sed public: 549193323Sed JIT(const std::string &Path, const std::vector<std::string> *Args) 550193323Sed : LLIPath(Path) { 551193323Sed ToolArgs.clear (); 552193323Sed if (Args) { ToolArgs = *Args; } 553193323Sed } 554193323Sed 555193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 556193323Sed const std::vector<std::string> &Args, 557193323Sed const std::string &InputFile, 558193323Sed const std::string &OutputFile, 559207618Srdivacky std::string *Error, 560193323Sed const std::vector<std::string> &GCCArgs = 561193323Sed std::vector<std::string>(), 562193323Sed const std::vector<std::string> &SharedLibs = 563218885Sdim std::vector<std::string>(), 564207618Srdivacky unsigned Timeout = 0, 565207618Srdivacky unsigned MemoryLimit = 0); 566193323Sed }; 567193323Sed} 568193323Sed 569193323Sedint JIT::ExecuteProgram(const std::string &Bitcode, 570193323Sed const std::vector<std::string> &Args, 571193323Sed const std::string &InputFile, 572193323Sed const std::string &OutputFile, 573207618Srdivacky std::string *Error, 574193323Sed const std::vector<std::string> &GCCArgs, 575193323Sed const std::vector<std::string> &SharedLibs, 576193323Sed unsigned Timeout, 577193323Sed unsigned MemoryLimit) { 578193323Sed // Construct a vector of parameters, incorporating those from the command-line 579193323Sed std::vector<const char*> JITArgs; 580193323Sed JITArgs.push_back(LLIPath.c_str()); 581193323Sed JITArgs.push_back("-force-interpreter=false"); 582193323Sed 583193323Sed // Add any extra LLI args. 584193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 585193323Sed JITArgs.push_back(ToolArgs[i].c_str()); 586193323Sed 587193323Sed for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 588193323Sed JITArgs.push_back("-load"); 589193323Sed JITArgs.push_back(SharedLibs[i].c_str()); 590193323Sed } 591193323Sed JITArgs.push_back(Bitcode.c_str()); 592193323Sed // Add optional parameters to the running program from Argv 593193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 594193323Sed JITArgs.push_back(Args[i].c_str()); 595193323Sed JITArgs.push_back(0); 596193323Sed 597198090Srdivacky outs() << "<jit>"; outs().flush(); 598198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 599193323Sed for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) 600198090Srdivacky errs() << " " << JITArgs[i]; 601198090Srdivacky errs() << "\n"; 602193323Sed ); 603198090Srdivacky DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 604193323Sed return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], 605193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 606218885Sdim Timeout, MemoryLimit, Error); 607193323Sed} 608193323Sed 609193323Sed/// createJIT - Try to find the LLI executable 610193323Sed/// 611198090SrdivackyAbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, 612193323Sed std::string &Message, const std::vector<std::string> *Args) { 613198090Srdivacky std::string LLIPath = 614218885Sdim PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT).str(); 615193323Sed if (!LLIPath.empty()) { 616193323Sed Message = "Found lli: " + LLIPath + "\n"; 617193323Sed return new JIT(LLIPath, Args); 618193323Sed } 619193323Sed 620218885Sdim Message = "Cannot find `lli' in executable directory!\n"; 621193323Sed return 0; 622193323Sed} 623193323Sed 624193323SedGCC::FileType CBE::OutputCode(const std::string &Bitcode, 625208599Srdivacky sys::Path &OutputCFile, std::string &Error, 626208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 627193323Sed sys::Path uniqueFile(Bitcode+".cbe.c"); 628193323Sed std::string ErrMsg; 629193323Sed if (uniqueFile.makeUnique(true, &ErrMsg)) { 630198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 631193323Sed exit(1); 632193323Sed } 633193323Sed OutputCFile = uniqueFile; 634193323Sed std::vector<const char *> LLCArgs; 635207618Srdivacky LLCArgs.push_back(LLCPath.c_str()); 636193323Sed 637193323Sed // Add any extra LLC args. 638193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 639193323Sed LLCArgs.push_back(ToolArgs[i].c_str()); 640193323Sed 641207618Srdivacky LLCArgs.push_back("-o"); 642207618Srdivacky LLCArgs.push_back(OutputCFile.c_str()); // Output to the C file 643207618Srdivacky LLCArgs.push_back("-march=c"); // Output C language 644207618Srdivacky LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 645207618Srdivacky LLCArgs.push_back(0); 646193323Sed 647198090Srdivacky outs() << "<cbe>"; outs().flush(); 648198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 649207618Srdivacky for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 650198090Srdivacky errs() << " " << LLCArgs[i]; 651198090Srdivacky errs() << "\n"; 652193323Sed ); 653193323Sed if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), 654208599Srdivacky sys::Path(), Timeout, MemoryLimit)) 655208599Srdivacky Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); 656193323Sed return GCC::CFile; 657193323Sed} 658193323Sed 659208599Srdivackyvoid CBE::compileProgram(const std::string &Bitcode, std::string *Error, 660208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 661193323Sed sys::Path OutputCFile; 662208599Srdivacky OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); 663193323Sed OutputCFile.eraseFromDisk(); 664193323Sed} 665193323Sed 666193323Sedint CBE::ExecuteProgram(const std::string &Bitcode, 667193323Sed const std::vector<std::string> &Args, 668193323Sed const std::string &InputFile, 669193323Sed const std::string &OutputFile, 670207618Srdivacky std::string *Error, 671193323Sed const std::vector<std::string> &ArgsForGCC, 672193323Sed const std::vector<std::string> &SharedLibs, 673193323Sed unsigned Timeout, 674193323Sed unsigned MemoryLimit) { 675193323Sed sys::Path OutputCFile; 676208599Srdivacky OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); 677193323Sed 678221337Sdim FileRemover CFileRemove(OutputCFile.str(), !SaveTemps); 679193323Sed 680193323Sed std::vector<std::string> GCCArgs(ArgsForGCC); 681193323Sed GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 682193323Sed 683198090Srdivacky return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, 684207618Srdivacky InputFile, OutputFile, Error, GCCArgs, 685193323Sed Timeout, MemoryLimit); 686193323Sed} 687193323Sed 688193323Sed/// createCBE - Try to find the 'llc' executable 689193323Sed/// 690198090SrdivackyCBE *AbstractInterpreter::createCBE(const char *Argv0, 691193323Sed std::string &Message, 692218885Sdim const std::string &GCCBinary, 693193323Sed const std::vector<std::string> *Args, 694193323Sed const std::vector<std::string> *GCCArgs) { 695198090Srdivacky sys::Path LLCPath = 696218885Sdim PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createCBE); 697193323Sed if (LLCPath.isEmpty()) { 698193323Sed Message = 699218885Sdim "Cannot find `llc' in executable directory!\n"; 700193323Sed return 0; 701193323Sed } 702193323Sed 703198090Srdivacky Message = "Found llc: " + LLCPath.str() + "\n"; 704208599Srdivacky GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); 705193323Sed if (!gcc) { 706198090Srdivacky errs() << Message << "\n"; 707193323Sed exit(1); 708193323Sed } 709193323Sed return new CBE(LLCPath, gcc, Args); 710193323Sed} 711193323Sed 712193323Sed//===---------------------------------------------------------------------===// 713193323Sed// GCC abstraction 714193323Sed// 715198090Srdivacky 716212793Sdimstatic bool IsARMArchitecture(std::vector<const char*> Args) { 717212793Sdim for (std::vector<const char*>::const_iterator 718198090Srdivacky I = Args.begin(), E = Args.end(); I != E; ++I) { 719208599Srdivacky if (StringRef(*I).equals_lower("-arch")) { 720198090Srdivacky ++I; 721208599Srdivacky if (I != E && StringRef(*I).substr(0, strlen("arm")).equals_lower("arm")) 722198090Srdivacky return true; 723198090Srdivacky } 724198090Srdivacky } 725198090Srdivacky 726198090Srdivacky return false; 727198090Srdivacky} 728198090Srdivacky 729193323Sedint GCC::ExecuteProgram(const std::string &ProgramFile, 730193323Sed const std::vector<std::string> &Args, 731193323Sed FileType fileType, 732193323Sed const std::string &InputFile, 733193323Sed const std::string &OutputFile, 734207618Srdivacky std::string *Error, 735193323Sed const std::vector<std::string> &ArgsForGCC, 736193323Sed unsigned Timeout, 737193323Sed unsigned MemoryLimit) { 738193323Sed std::vector<const char*> GCCArgs; 739193323Sed 740193323Sed GCCArgs.push_back(GCCPath.c_str()); 741193323Sed 742205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 743205218Srdivacky GCCArgs.push_back("-m32"); 744205218Srdivacky 745193323Sed for (std::vector<std::string>::const_iterator 746193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 747193323Sed GCCArgs.push_back(I->c_str()); 748193323Sed 749193323Sed // Specify -x explicitly in case the extension is wonky 750205218Srdivacky if (fileType != ObjectFile) { 751205218Srdivacky GCCArgs.push_back("-x"); 752205218Srdivacky if (fileType == CFile) { 753205218Srdivacky GCCArgs.push_back("c"); 754205218Srdivacky GCCArgs.push_back("-fno-strict-aliasing"); 755205218Srdivacky } else { 756205218Srdivacky GCCArgs.push_back("assembler"); 757198090Srdivacky 758205218Srdivacky // For ARM architectures we don't want this flag. bugpoint isn't 759205218Srdivacky // explicitly told what architecture it is working on, so we get 760205218Srdivacky // it from gcc flags 761221337Sdim if (TargetTriple.isOSDarwin() && !IsARMArchitecture(GCCArgs)) 762205218Srdivacky GCCArgs.push_back("-force_cpusubtype_ALL"); 763205218Srdivacky } 764193323Sed } 765218885Sdim 766205218Srdivacky GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. 767218885Sdim 768193323Sed GCCArgs.push_back("-x"); 769193323Sed GCCArgs.push_back("none"); 770193323Sed GCCArgs.push_back("-o"); 771193323Sed sys::Path OutputBinary (ProgramFile+".gcc.exe"); 772193323Sed std::string ErrMsg; 773193323Sed if (OutputBinary.makeUnique(true, &ErrMsg)) { 774198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 775193323Sed exit(1); 776193323Sed } 777193323Sed GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 778193323Sed 779193323Sed // Add any arguments intended for GCC. We locate them here because this is 780193323Sed // most likely -L and -l options that need to come before other libraries but 781193323Sed // after the source. Other options won't be sensitive to placement on the 782193323Sed // command line, so this should be safe. 783193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 784193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 785193323Sed 786193323Sed GCCArgs.push_back("-lm"); // Hard-code the math library... 787193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit... 788193323Sed#if defined (HAVE_LINK_R) 789193323Sed GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files 790193323Sed#endif 791198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 792198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 793193323Sed GCCArgs.push_back(0); // NULL terminator 794193323Sed 795198090Srdivacky outs() << "<gcc>"; outs().flush(); 796198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 797207618Srdivacky for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 798198090Srdivacky errs() << " " << GCCArgs[i]; 799198090Srdivacky errs() << "\n"; 800193323Sed ); 801193323Sed if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 802193323Sed sys::Path())) { 803207618Srdivacky *Error = ProcessFailure(GCCPath, &GCCArgs[0]); 804207618Srdivacky return -1; 805193323Sed } 806193323Sed 807193323Sed std::vector<const char*> ProgramArgs; 808193323Sed 809212793Sdim // Declared here so that the destructor only runs after 810212793Sdim // ProgramArgs is used. 811212793Sdim std::string Exec; 812212793Sdim 813193323Sed if (RemoteClientPath.isEmpty()) 814193323Sed ProgramArgs.push_back(OutputBinary.c_str()); 815193323Sed else { 816193323Sed ProgramArgs.push_back(RemoteClientPath.c_str()); 817193323Sed ProgramArgs.push_back(RemoteHost.c_str()); 818198090Srdivacky if (!RemoteUser.empty()) { 819198090Srdivacky ProgramArgs.push_back("-l"); 820198090Srdivacky ProgramArgs.push_back(RemoteUser.c_str()); 821198090Srdivacky } 822198090Srdivacky if (!RemotePort.empty()) { 823198090Srdivacky ProgramArgs.push_back("-p"); 824198090Srdivacky ProgramArgs.push_back(RemotePort.c_str()); 825198090Srdivacky } 826193323Sed if (!RemoteExtra.empty()) { 827193323Sed ProgramArgs.push_back(RemoteExtra.c_str()); 828193323Sed } 829193323Sed 830198090Srdivacky // Full path to the binary. We need to cd to the exec directory because 831198090Srdivacky // there is a dylib there that the exec expects to find in the CWD 832193323Sed char* env_pwd = getenv("PWD"); 833212793Sdim Exec = "cd "; 834193323Sed Exec += env_pwd; 835193323Sed Exec += "; ./"; 836193323Sed Exec += OutputBinary.c_str(); 837193323Sed ProgramArgs.push_back(Exec.c_str()); 838193323Sed } 839193323Sed 840193323Sed // Add optional parameters to the running program from Argv 841207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 842193323Sed ProgramArgs.push_back(Args[i].c_str()); 843193323Sed ProgramArgs.push_back(0); // NULL terminator 844193323Sed 845193323Sed // Now that we have a binary, run it! 846198090Srdivacky outs() << "<program>"; outs().flush(); 847198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 848207618Srdivacky for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) 849198090Srdivacky errs() << " " << ProgramArgs[i]; 850198090Srdivacky errs() << "\n"; 851193323Sed ); 852193323Sed 853221337Sdim FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); 854193323Sed 855198090Srdivacky if (RemoteClientPath.isEmpty()) { 856207618Srdivacky DEBUG(errs() << "<run locally>"); 857193323Sed return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], 858193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 859218885Sdim Timeout, MemoryLimit, Error); 860198090Srdivacky } else { 861198090Srdivacky outs() << "<run remotely>"; outs().flush(); 862198090Srdivacky return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), 863198090Srdivacky &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 864198090Srdivacky sys::Path(OutputFile), Timeout, MemoryLimit); 865198090Srdivacky } 866193323Sed} 867193323Sed 868193323Sedint GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 869193323Sed std::string &OutputFile, 870207618Srdivacky const std::vector<std::string> &ArgsForGCC, 871207618Srdivacky std::string &Error) { 872193323Sed sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); 873193323Sed std::string ErrMsg; 874193323Sed if (uniqueFilename.makeUnique(true, &ErrMsg)) { 875198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 876193323Sed exit(1); 877193323Sed } 878198090Srdivacky OutputFile = uniqueFilename.str(); 879193323Sed 880193323Sed std::vector<const char*> GCCArgs; 881218885Sdim 882193323Sed GCCArgs.push_back(GCCPath.c_str()); 883193323Sed 884205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 885205218Srdivacky GCCArgs.push_back("-m32"); 886205218Srdivacky 887193323Sed for (std::vector<std::string>::const_iterator 888193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 889193323Sed GCCArgs.push_back(I->c_str()); 890193323Sed 891193323Sed // Compile the C/asm file into a shared object 892205218Srdivacky if (fileType != ObjectFile) { 893205218Srdivacky GCCArgs.push_back("-x"); 894205218Srdivacky GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 895205218Srdivacky } 896193323Sed GCCArgs.push_back("-fno-strict-aliasing"); 897193323Sed GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. 898193323Sed GCCArgs.push_back("-x"); 899193323Sed GCCArgs.push_back("none"); 900198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 901198090Srdivacky GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 902221337Sdim else if (TargetTriple.isOSDarwin()) { 903198090Srdivacky // link all source files into a single module in data segment, rather than 904218885Sdim // generating blocks. dynamic_lookup requires that you set 905198090Srdivacky // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 906198090Srdivacky // bugpoint to just pass that in the environment of GCC. 907198090Srdivacky GCCArgs.push_back("-single_module"); 908198090Srdivacky GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 909198090Srdivacky GCCArgs.push_back("-undefined"); 910198090Srdivacky GCCArgs.push_back("dynamic_lookup"); 911198090Srdivacky } else 912198090Srdivacky GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 913193323Sed 914198090Srdivacky if ((TargetTriple.getArch() == Triple::alpha) || 915198090Srdivacky (TargetTriple.getArch() == Triple::x86_64)) 916198090Srdivacky GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 917198090Srdivacky 918198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 919198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 920198090Srdivacky 921193323Sed GCCArgs.push_back("-o"); 922193323Sed GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 923193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit. 924193323Sed 925218885Sdim 926218885Sdim 927193323Sed // Add any arguments intended for GCC. We locate them here because this is 928193323Sed // most likely -L and -l options that need to come before other libraries but 929193323Sed // after the source. Other options won't be sensitive to placement on the 930193323Sed // command line, so this should be safe. 931193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 932193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 933193323Sed GCCArgs.push_back(0); // NULL terminator 934193323Sed 935193323Sed 936218885Sdim 937198090Srdivacky outs() << "<gcc>"; outs().flush(); 938198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 939207618Srdivacky for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 940198090Srdivacky errs() << " " << GCCArgs[i]; 941198090Srdivacky errs() << "\n"; 942193323Sed ); 943193323Sed if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 944193323Sed sys::Path())) { 945207618Srdivacky Error = ProcessFailure(GCCPath, &GCCArgs[0]); 946193323Sed return 1; 947193323Sed } 948193323Sed return 0; 949193323Sed} 950193323Sed 951193323Sed/// create - Try to find the `gcc' executable 952193323Sed/// 953198090SrdivackyGCC *GCC::create(std::string &Message, 954208599Srdivacky const std::string &GCCBinary, 955193323Sed const std::vector<std::string> *Args) { 956208599Srdivacky sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary); 957193323Sed if (GCCPath.isEmpty()) { 958218885Sdim Message = "Cannot find `"+ GCCBinary +"' in PATH!\n"; 959193323Sed return 0; 960193323Sed } 961193323Sed 962193323Sed sys::Path RemoteClientPath; 963193323Sed if (!RemoteClient.empty()) 964198090Srdivacky RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); 965193323Sed 966198090Srdivacky Message = "Found gcc: " + GCCPath.str() + "\n"; 967193323Sed return new GCC(GCCPath, RemoteClientPath, Args); 968193323Sed} 969