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"
16249423Sdim#include "llvm/Config/config.h"   // for HAVE_LINK_R
17193323Sed#include "llvm/Support/CommandLine.h"
18193323Sed#include "llvm/Support/Debug.h"
19263508Sdim#include "llvm/Support/FileSystem.h"
20193323Sed#include "llvm/Support/FileUtilities.h"
21249423Sdim#include "llvm/Support/Program.h"
22198090Srdivacky#include "llvm/Support/raw_ostream.h"
23193323Sed#include <fstream>
24193323Sed#include <sstream>
25193323Sedusing namespace llvm;
26193323Sed
27198090Srdivackynamespace llvm {
28198090Srdivacky  cl::opt<bool>
29198090Srdivacky  SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files"));
30198090Srdivacky}
31198090Srdivacky
32193323Sednamespace {
33193323Sed  cl::opt<std::string>
34193323Sed  RemoteClient("remote-client",
35193323Sed               cl::desc("Remote execution client (rsh/ssh)"));
36193323Sed
37193323Sed  cl::opt<std::string>
38193323Sed  RemoteHost("remote-host",
39193323Sed             cl::desc("Remote execution (rsh/ssh) host"));
40193323Sed
41193323Sed  cl::opt<std::string>
42198090Srdivacky  RemotePort("remote-port",
43198090Srdivacky             cl::desc("Remote execution (rsh/ssh) port"));
44198090Srdivacky
45198090Srdivacky  cl::opt<std::string>
46193323Sed  RemoteUser("remote-user",
47193323Sed             cl::desc("Remote execution (rsh/ssh) user id"));
48193323Sed
49193323Sed  cl::opt<std::string>
50193323Sed  RemoteExtra("remote-extra-options",
51193323Sed          cl::desc("Remote execution (rsh/ssh) extra options"));
52193323Sed}
53193323Sed
54198090Srdivacky/// RunProgramWithTimeout - This function provides an alternate interface
55198090Srdivacky/// to the sys::Program::ExecuteAndWait interface.
56207618Srdivacky/// @see sys::Program::ExecuteAndWait
57263508Sdimstatic int RunProgramWithTimeout(StringRef ProgramPath,
58193323Sed                                 const char **Args,
59263508Sdim                                 StringRef StdInFile,
60263508Sdim                                 StringRef StdOutFile,
61263508Sdim                                 StringRef StdErrFile,
62193323Sed                                 unsigned NumSeconds = 0,
63218885Sdim                                 unsigned MemoryLimit = 0,
64218885Sdim                                 std::string *ErrMsg = 0) {
65263508Sdim  const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile };
66198090Srdivacky
67198090Srdivacky#if 0 // For debug purposes
68198090Srdivacky  {
69198090Srdivacky    errs() << "RUN:";
70193323Sed    for (unsigned i = 0; Args[i]; ++i)
71198090Srdivacky      errs() << " " << Args[i];
72198090Srdivacky    errs() << "\n";
73193323Sed  }
74198090Srdivacky#endif
75193323Sed
76263508Sdim  return sys::ExecuteAndWait(ProgramPath, Args, 0, Redirects,
77263508Sdim                             NumSeconds, MemoryLimit, ErrMsg);
78193323Sed}
79193323Sed
80198090Srdivacky/// RunProgramRemotelyWithTimeout - This function runs the given program
81198090Srdivacky/// remotely using the given remote client and the sys::Program::ExecuteAndWait.
82198090Srdivacky/// Returns the remote program exit code or reports a remote client error if it
83198090Srdivacky/// fails. Remote client is required to return 255 if it failed or program exit
84198090Srdivacky/// code otherwise.
85207618Srdivacky/// @see sys::Program::ExecuteAndWait
86263508Sdimstatic int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath,
87198090Srdivacky                                         const char **Args,
88263508Sdim                                         StringRef StdInFile,
89263508Sdim                                         StringRef StdOutFile,
90263508Sdim                                         StringRef StdErrFile,
91198090Srdivacky                                         unsigned NumSeconds = 0,
92198090Srdivacky                                         unsigned MemoryLimit = 0) {
93263508Sdim  const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile };
94193323Sed
95198090Srdivacky#if 0 // For debug purposes
96198090Srdivacky  {
97198090Srdivacky    errs() << "RUN:";
98198090Srdivacky    for (unsigned i = 0; Args[i]; ++i)
99198090Srdivacky      errs() << " " << Args[i];
100198090Srdivacky    errs() << "\n";
101198090Srdivacky  }
102198090Srdivacky#endif
103193323Sed
104198090Srdivacky  // Run the program remotely with the remote client
105263508Sdim  int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, 0,
106263508Sdim                                       Redirects, NumSeconds, MemoryLimit);
107198090Srdivacky
108198090Srdivacky  // Has the remote client fail?
109198090Srdivacky  if (255 == ReturnCode) {
110198090Srdivacky    std::ostringstream OS;
111198090Srdivacky    OS << "\nError running remote client:\n ";
112198090Srdivacky    for (const char **Arg = Args; *Arg; ++Arg)
113198090Srdivacky      OS << " " << *Arg;
114198090Srdivacky    OS << "\n";
115198090Srdivacky
116198090Srdivacky    // The error message is in the output file, let's print it out from there.
117263508Sdim    std::string StdOutFileName = StdOutFile.str();
118263508Sdim    std::ifstream ErrorFile(StdOutFileName.c_str());
119198090Srdivacky    if (ErrorFile) {
120198090Srdivacky      std::copy(std::istreambuf_iterator<char>(ErrorFile),
121198090Srdivacky                std::istreambuf_iterator<char>(),
122198090Srdivacky                std::ostreambuf_iterator<char>(OS));
123198090Srdivacky      ErrorFile.close();
124198090Srdivacky    }
125198090Srdivacky
126236386Sdim    errs() << OS.str();
127198090Srdivacky  }
128198090Srdivacky
129198090Srdivacky  return ReturnCode;
130198090Srdivacky}
131198090Srdivacky
132263508Sdimstatic std::string ProcessFailure(StringRef ProgPath, const char** Args,
133208599Srdivacky                                  unsigned Timeout = 0,
134208599Srdivacky                                  unsigned MemoryLimit = 0) {
135193323Sed  std::ostringstream OS;
136193323Sed  OS << "\nError running tool:\n ";
137193323Sed  for (const char **Arg = Args; *Arg; ++Arg)
138193323Sed    OS << " " << *Arg;
139193323Sed  OS << "\n";
140218885Sdim
141193323Sed  // Rerun the compiler, capturing any error messages to print them.
142263508Sdim  SmallString<128> ErrorFilename;
143263508Sdim  int ErrorFD;
144263508Sdim  error_code EC = sys::fs::createTemporaryFile(
145263508Sdim      "bugpoint.program_error_messages", "", ErrorFD, ErrorFilename);
146263508Sdim  if (EC) {
147263508Sdim    errs() << "Error making unique filename: " << EC.message() << "\n";
148193323Sed    exit(1);
149193323Sed  }
150263508Sdim  RunProgramWithTimeout(ProgPath, Args, "", ErrorFilename.str(),
151263508Sdim                        ErrorFilename.str(), Timeout, MemoryLimit);
152208599Srdivacky  // FIXME: check return code ?
153193323Sed
154193323Sed  // Print out the error messages generated by GCC if possible...
155193323Sed  std::ifstream ErrorFile(ErrorFilename.c_str());
156193323Sed  if (ErrorFile) {
157193323Sed    std::copy(std::istreambuf_iterator<char>(ErrorFile),
158193323Sed              std::istreambuf_iterator<char>(),
159193323Sed              std::ostreambuf_iterator<char>(OS));
160193323Sed    ErrorFile.close();
161193323Sed  }
162193323Sed
163263508Sdim  sys::fs::remove(ErrorFilename.c_str());
164207618Srdivacky  return OS.str();
165193323Sed}
166193323Sed
167193323Sed//===---------------------------------------------------------------------===//
168193323Sed// LLI Implementation of AbstractIntepreter interface
169193323Sed//
170193323Sednamespace {
171193323Sed  class LLI : public AbstractInterpreter {
172193323Sed    std::string LLIPath;          // The path to the LLI executable
173193323Sed    std::vector<std::string> ToolArgs; // Args to pass to LLI
174193323Sed  public:
175193323Sed    LLI(const std::string &Path, const std::vector<std::string> *Args)
176193323Sed      : LLIPath(Path) {
177193323Sed      ToolArgs.clear ();
178193323Sed      if (Args) { ToolArgs = *Args; }
179193323Sed    }
180193323Sed
181193323Sed    virtual int ExecuteProgram(const std::string &Bitcode,
182193323Sed                               const std::vector<std::string> &Args,
183193323Sed                               const std::string &InputFile,
184193323Sed                               const std::string &OutputFile,
185207618Srdivacky                               std::string *Error,
186193323Sed                               const std::vector<std::string> &GCCArgs,
187193323Sed                               const std::vector<std::string> &SharedLibs =
188193323Sed                               std::vector<std::string>(),
189193323Sed                               unsigned Timeout = 0,
190193323Sed                               unsigned MemoryLimit = 0);
191193323Sed  };
192193323Sed}
193193323Sed
194193323Sedint LLI::ExecuteProgram(const std::string &Bitcode,
195193323Sed                        const std::vector<std::string> &Args,
196193323Sed                        const std::string &InputFile,
197193323Sed                        const std::string &OutputFile,
198207618Srdivacky                        std::string *Error,
199193323Sed                        const std::vector<std::string> &GCCArgs,
200193323Sed                        const std::vector<std::string> &SharedLibs,
201193323Sed                        unsigned Timeout,
202193323Sed                        unsigned MemoryLimit) {
203193323Sed  std::vector<const char*> LLIArgs;
204193323Sed  LLIArgs.push_back(LLIPath.c_str());
205193323Sed  LLIArgs.push_back("-force-interpreter=true");
206193323Sed
207218885Sdim  for (std::vector<std::string>::const_iterator i = SharedLibs.begin(),
208218885Sdim         e = SharedLibs.end(); i != e; ++i) {
209199481Srdivacky    LLIArgs.push_back("-load");
210199481Srdivacky    LLIArgs.push_back((*i).c_str());
211199481Srdivacky  }
212199481Srdivacky
213193323Sed  // Add any extra LLI args.
214193323Sed  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
215193323Sed    LLIArgs.push_back(ToolArgs[i].c_str());
216193323Sed
217193323Sed  LLIArgs.push_back(Bitcode.c_str());
218193323Sed  // Add optional parameters to the running program from Argv
219193323Sed  for (unsigned i=0, e = Args.size(); i != e; ++i)
220193323Sed    LLIArgs.push_back(Args[i].c_str());
221193323Sed  LLIArgs.push_back(0);
222193323Sed
223198090Srdivacky  outs() << "<lli>"; outs().flush();
224198090Srdivacky  DEBUG(errs() << "\nAbout to run:\t";
225193323Sed        for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i)
226198090Srdivacky          errs() << " " << LLIArgs[i];
227198090Srdivacky        errs() << "\n";
228193323Sed        );
229263508Sdim  return RunProgramWithTimeout(LLIPath, &LLIArgs[0],
230263508Sdim      InputFile, OutputFile, OutputFile,
231218885Sdim      Timeout, MemoryLimit, Error);
232193323Sed}
233193323Sed
234234353Sdimvoid AbstractInterpreter::anchor() { }
235234353Sdim
236263508Sdim#if defined(LLVM_ON_UNIX)
237263508Sdimconst char EXESuffix[] = "";
238263508Sdim#elif defined (LLVM_ON_WIN32)
239263508Sdimconst char EXESuffix[] = "exe";
240263508Sdim#endif
241263508Sdim
242263508Sdim/// Prepend the path to the program being executed
243263508Sdim/// to \p ExeName, given the value of argv[0] and the address of main()
244263508Sdim/// itself. This allows us to find another LLVM tool if it is built in the same
245263508Sdim/// directory. An empty string is returned on error; note that this function
246263508Sdim/// just mainpulates the path and doesn't check for executability.
247263508Sdim/// @brief Find a named executable.
248263508Sdimstatic std::string PrependMainExecutablePath(const std::string &ExeName,
249263508Sdim                                             const char *Argv0,
250263508Sdim                                             void *MainAddr) {
251263508Sdim  // Check the directory that the calling program is in.  We can do
252263508Sdim  // this if ProgramPath contains at least one / character, indicating that it
253263508Sdim  // is a relative path to the executable itself.
254263508Sdim  std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr);
255263508Sdim  StringRef Result = sys::path::parent_path(Main);
256263508Sdim
257263508Sdim  if (!Result.empty()) {
258263508Sdim    SmallString<128> Storage = Result;
259263508Sdim    sys::path::append(Storage, ExeName);
260263508Sdim    sys::path::replace_extension(Storage, EXESuffix);
261263508Sdim    return Storage.str();
262263508Sdim  }
263263508Sdim
264263508Sdim  return Result.str();
265263508Sdim}
266263508Sdim
267193323Sed// LLI create method - Try to find the LLI executable
268198090SrdivackyAbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0,
269193323Sed                                                    std::string &Message,
270193323Sed                                     const std::vector<std::string> *ToolArgs) {
271198090Srdivacky  std::string LLIPath =
272263508Sdim      PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createLLI);
273193323Sed  if (!LLIPath.empty()) {
274193323Sed    Message = "Found lli: " + LLIPath + "\n";
275193323Sed    return new LLI(LLIPath, ToolArgs);
276193323Sed  }
277193323Sed
278218885Sdim  Message = "Cannot find `lli' in executable directory!\n";
279193323Sed  return 0;
280193323Sed}
281193323Sed
282193323Sed//===---------------------------------------------------------------------===//
283218885Sdim// Custom compiler command implementation of AbstractIntepreter interface
284218885Sdim//
285218885Sdim// Allows using a custom command for compiling the bitcode, thus allows, for
286218885Sdim// example, to compile a bitcode fragment without linking or executing, then
287218885Sdim// using a custom wrapper script to check for compiler errors.
288218885Sdimnamespace {
289218885Sdim  class CustomCompiler : public AbstractInterpreter {
290218885Sdim    std::string CompilerCommand;
291218885Sdim    std::vector<std::string> CompilerArgs;
292218885Sdim  public:
293218885Sdim    CustomCompiler(
294218885Sdim      const std::string &CompilerCmd, std::vector<std::string> CompArgs) :
295218885Sdim      CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {}
296218885Sdim
297218885Sdim    virtual void compileProgram(const std::string &Bitcode,
298218885Sdim                                std::string *Error,
299218885Sdim                                unsigned Timeout = 0,
300218885Sdim                                unsigned MemoryLimit = 0);
301218885Sdim
302218885Sdim    virtual int ExecuteProgram(const std::string &Bitcode,
303218885Sdim                               const std::vector<std::string> &Args,
304218885Sdim                               const std::string &InputFile,
305218885Sdim                               const std::string &OutputFile,
306218885Sdim                               std::string *Error,
307218885Sdim                               const std::vector<std::string> &GCCArgs =
308218885Sdim                               std::vector<std::string>(),
309218885Sdim                               const std::vector<std::string> &SharedLibs =
310218885Sdim                               std::vector<std::string>(),
311218885Sdim                               unsigned Timeout = 0,
312218885Sdim                               unsigned MemoryLimit = 0) {
313218885Sdim      *Error = "Execution not supported with -compile-custom";
314218885Sdim      return -1;
315218885Sdim    }
316218885Sdim  };
317218885Sdim}
318218885Sdim
319218885Sdimvoid CustomCompiler::compileProgram(const std::string &Bitcode,
320218885Sdim                                    std::string *Error,
321218885Sdim                                    unsigned Timeout,
322218885Sdim                                    unsigned MemoryLimit) {
323218885Sdim
324218885Sdim  std::vector<const char*> ProgramArgs;
325218885Sdim  ProgramArgs.push_back(CompilerCommand.c_str());
326218885Sdim
327218885Sdim  for (std::size_t i = 0; i < CompilerArgs.size(); ++i)
328218885Sdim    ProgramArgs.push_back(CompilerArgs.at(i).c_str());
329218885Sdim  ProgramArgs.push_back(Bitcode.c_str());
330218885Sdim  ProgramArgs.push_back(0);
331218885Sdim
332218885Sdim  // Add optional parameters to the running program from Argv
333218885Sdim  for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i)
334218885Sdim    ProgramArgs.push_back(CompilerArgs[i].c_str());
335218885Sdim
336263508Sdim  if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0],
337263508Sdim                             "", "", "",
338218885Sdim                             Timeout, MemoryLimit, Error))
339263508Sdim    *Error = ProcessFailure(CompilerCommand, &ProgramArgs[0],
340218885Sdim                           Timeout, MemoryLimit);
341218885Sdim}
342218885Sdim
343218885Sdim//===---------------------------------------------------------------------===//
344193323Sed// Custom execution command implementation of AbstractIntepreter interface
345193323Sed//
346193323Sed// Allows using a custom command for executing the bitcode, thus allows,
347218885Sdim// for example, to invoke a cross compiler for code generation followed by
348193323Sed// a simulator that executes the generated binary.
349193323Sednamespace {
350193323Sed  class CustomExecutor : public AbstractInterpreter {
351193323Sed    std::string ExecutionCommand;
352193323Sed    std::vector<std::string> ExecutorArgs;
353193323Sed  public:
354193323Sed    CustomExecutor(
355193323Sed      const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) :
356193323Sed      ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {}
357193323Sed
358193323Sed    virtual int ExecuteProgram(const std::string &Bitcode,
359193323Sed                               const std::vector<std::string> &Args,
360193323Sed                               const std::string &InputFile,
361193323Sed                               const std::string &OutputFile,
362207618Srdivacky                               std::string *Error,
363193323Sed                               const std::vector<std::string> &GCCArgs,
364193323Sed                               const std::vector<std::string> &SharedLibs =
365207618Srdivacky                                 std::vector<std::string>(),
366193323Sed                               unsigned Timeout = 0,
367193323Sed                               unsigned MemoryLimit = 0);
368193323Sed  };
369193323Sed}
370193323Sed
371193323Sedint CustomExecutor::ExecuteProgram(const std::string &Bitcode,
372193323Sed                        const std::vector<std::string> &Args,
373193323Sed                        const std::string &InputFile,
374193323Sed                        const std::string &OutputFile,
375207618Srdivacky                        std::string *Error,
376193323Sed                        const std::vector<std::string> &GCCArgs,
377193323Sed                        const std::vector<std::string> &SharedLibs,
378193323Sed                        unsigned Timeout,
379193323Sed                        unsigned MemoryLimit) {
380193323Sed
381193323Sed  std::vector<const char*> ProgramArgs;
382193323Sed  ProgramArgs.push_back(ExecutionCommand.c_str());
383193323Sed
384193323Sed  for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
385193323Sed    ProgramArgs.push_back(ExecutorArgs.at(i).c_str());
386193323Sed  ProgramArgs.push_back(Bitcode.c_str());
387193323Sed  ProgramArgs.push_back(0);
388193323Sed
389193323Sed  // Add optional parameters to the running program from Argv
390207618Srdivacky  for (unsigned i = 0, e = Args.size(); i != e; ++i)
391193323Sed    ProgramArgs.push_back(Args[i].c_str());
392193323Sed
393193323Sed  return RunProgramWithTimeout(
394263508Sdim    ExecutionCommand,
395263508Sdim    &ProgramArgs[0], InputFile, OutputFile,
396263508Sdim    OutputFile, Timeout, MemoryLimit, Error);
397193323Sed}
398193323Sed
399218885Sdim// Tokenize the CommandLine to the command and the args to allow
400218885Sdim// defining a full command line as the command instead of just the
401218885Sdim// executed program. We cannot just pass the whole string after the command
402218885Sdim// as a single argument because then program sees only a single
403218885Sdim// command line argument (with spaces in it: "foo bar" instead
404218885Sdim// of "foo" and "bar").
405218885Sdim//
406218885Sdim// code borrowed from:
407218885Sdim// http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
408218885Sdimstatic void lexCommand(std::string &Message, const std::string &CommandLine,
409218885Sdim                       std::string &CmdPath, std::vector<std::string> Args) {
410193323Sed
411193323Sed  std::string Command = "";
412193323Sed  std::string delimiters = " ";
413193323Sed
414218885Sdim  std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0);
415218885Sdim  std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos);
416193323Sed
417193323Sed  while (std::string::npos != pos || std::string::npos != lastPos) {
418218885Sdim    std::string token = CommandLine.substr(lastPos, pos - lastPos);
419193323Sed    if (Command == "")
420193323Sed       Command = token;
421193323Sed    else
422193323Sed       Args.push_back(token);
423193323Sed    // Skip delimiters.  Note the "not_of"
424218885Sdim    lastPos = CommandLine.find_first_not_of(delimiters, pos);
425193323Sed    // Find next "non-delimiter"
426218885Sdim    pos = CommandLine.find_first_of(delimiters, lastPos);
427193323Sed  }
428193323Sed
429263508Sdim  CmdPath = sys::FindProgramByName(Command);
430193323Sed  if (CmdPath.empty()) {
431218885Sdim    Message =
432218885Sdim      std::string("Cannot find '") + Command +
433218885Sdim      "' in PATH!\n";
434218885Sdim    return;
435193323Sed  }
436193323Sed
437193323Sed  Message = "Found command in: " + CmdPath + "\n";
438218885Sdim}
439193323Sed
440218885Sdim// Custom execution environment create method, takes the execution command
441218885Sdim// as arguments
442218885SdimAbstractInterpreter *AbstractInterpreter::createCustomCompiler(
443218885Sdim                    std::string &Message,
444218885Sdim                    const std::string &CompileCommandLine) {
445218885Sdim
446218885Sdim  std::string CmdPath;
447218885Sdim  std::vector<std::string> Args;
448218885Sdim  lexCommand(Message, CompileCommandLine, CmdPath, Args);
449218885Sdim  if (CmdPath.empty())
450218885Sdim    return 0;
451218885Sdim
452218885Sdim  return new CustomCompiler(CmdPath, Args);
453218885Sdim}
454218885Sdim
455218885Sdim// Custom execution environment create method, takes the execution command
456218885Sdim// as arguments
457218885SdimAbstractInterpreter *AbstractInterpreter::createCustomExecutor(
458218885Sdim                    std::string &Message,
459218885Sdim                    const std::string &ExecCommandLine) {
460218885Sdim
461218885Sdim
462218885Sdim  std::string CmdPath;
463218885Sdim  std::vector<std::string> Args;
464218885Sdim  lexCommand(Message, ExecCommandLine, CmdPath, Args);
465218885Sdim  if (CmdPath.empty())
466218885Sdim    return 0;
467218885Sdim
468193323Sed  return new CustomExecutor(CmdPath, Args);
469193323Sed}
470193323Sed
471193323Sed//===----------------------------------------------------------------------===//
472193323Sed// LLC Implementation of AbstractIntepreter interface
473193323Sed//
474218885SdimGCC::FileType LLC::OutputCode(const std::string &Bitcode,
475263508Sdim                              std::string &OutputAsmFile, std::string &Error,
476208599Srdivacky                              unsigned Timeout, unsigned MemoryLimit) {
477205218Srdivacky  const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s");
478263508Sdim
479263508Sdim  SmallString<128> UniqueFile;
480263508Sdim  error_code EC =
481263508Sdim      sys::fs::createUniqueFile(Bitcode + "-%%%%%%%" + Suffix, UniqueFile);
482263508Sdim  if (EC) {
483263508Sdim    errs() << "Error making unique filename: " << EC.message() << "\n";
484193323Sed    exit(1);
485193323Sed  }
486263508Sdim  OutputAsmFile = UniqueFile.str();
487193323Sed  std::vector<const char *> LLCArgs;
488205218Srdivacky  LLCArgs.push_back(LLCPath.c_str());
489193323Sed
490193323Sed  // Add any extra LLC args.
491193323Sed  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
492193323Sed    LLCArgs.push_back(ToolArgs[i].c_str());
493193323Sed
494205218Srdivacky  LLCArgs.push_back("-o");
495205218Srdivacky  LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file
496205218Srdivacky  LLCArgs.push_back(Bitcode.c_str());      // This is the input bitcode
497218885Sdim
498205218Srdivacky  if (UseIntegratedAssembler)
499205218Srdivacky    LLCArgs.push_back("-filetype=obj");
500218885Sdim
501193323Sed  LLCArgs.push_back (0);
502193323Sed
503205218Srdivacky  outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>");
504205218Srdivacky  outs().flush();
505198090Srdivacky  DEBUG(errs() << "\nAbout to run:\t";
506207618Srdivacky        for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i)
507198090Srdivacky          errs() << " " << LLCArgs[i];
508198090Srdivacky        errs() << "\n";
509193323Sed        );
510263508Sdim  if (RunProgramWithTimeout(LLCPath, &LLCArgs[0],
511263508Sdim                            "", "", "",
512208599Srdivacky                            Timeout, MemoryLimit))
513263508Sdim    Error = ProcessFailure(LLCPath, &LLCArgs[0],
514208599Srdivacky                           Timeout, MemoryLimit);
515218885Sdim  return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile;
516193323Sed}
517193323Sed
518208599Srdivackyvoid LLC::compileProgram(const std::string &Bitcode, std::string *Error,
519208599Srdivacky                         unsigned Timeout, unsigned MemoryLimit) {
520263508Sdim  std::string OutputAsmFile;
521208599Srdivacky  OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit);
522263508Sdim  sys::fs::remove(OutputAsmFile);
523193323Sed}
524193323Sed
525193323Sedint LLC::ExecuteProgram(const std::string &Bitcode,
526193323Sed                        const std::vector<std::string> &Args,
527193323Sed                        const std::string &InputFile,
528193323Sed                        const std::string &OutputFile,
529207618Srdivacky                        std::string *Error,
530193323Sed                        const std::vector<std::string> &ArgsForGCC,
531193323Sed                        const std::vector<std::string> &SharedLibs,
532193323Sed                        unsigned Timeout,
533193323Sed                        unsigned MemoryLimit) {
534193323Sed
535263508Sdim  std::string OutputAsmFile;
536208599Srdivacky  GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout,
537208599Srdivacky                                      MemoryLimit);
538263508Sdim  FileRemover OutFileRemover(OutputAsmFile, !SaveTemps);
539193323Sed
540193323Sed  std::vector<std::string> GCCArgs(ArgsForGCC);
541193323Sed  GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end());
542193323Sed
543193323Sed  // Assuming LLC worked, compile the result with GCC and run it.
544263508Sdim  return gcc->ExecuteProgram(OutputAsmFile, Args, FileKind,
545207618Srdivacky                             InputFile, OutputFile, Error, GCCArgs,
546193323Sed                             Timeout, MemoryLimit);
547193323Sed}
548193323Sed
549193323Sed/// createLLC - Try to find the LLC executable
550193323Sed///
551198090SrdivackyLLC *AbstractInterpreter::createLLC(const char *Argv0,
552193323Sed                                    std::string &Message,
553208599Srdivacky                                    const std::string &GCCBinary,
554193323Sed                                    const std::vector<std::string> *Args,
555205218Srdivacky                                    const std::vector<std::string> *GCCArgs,
556205218Srdivacky                                    bool UseIntegratedAssembler) {
557198090Srdivacky  std::string LLCPath =
558263508Sdim      PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t) & createLLC);
559193323Sed  if (LLCPath.empty()) {
560218885Sdim    Message = "Cannot find `llc' in executable directory!\n";
561193323Sed    return 0;
562193323Sed  }
563193323Sed
564208599Srdivacky  GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs);
565193323Sed  if (!gcc) {
566198090Srdivacky    errs() << Message << "\n";
567193323Sed    exit(1);
568193323Sed  }
569249423Sdim  Message = "Found llc: " + LLCPath + "\n";
570208599Srdivacky  return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler);
571193323Sed}
572193323Sed
573193323Sed//===---------------------------------------------------------------------===//
574193323Sed// JIT Implementation of AbstractIntepreter interface
575193323Sed//
576193323Sednamespace {
577193323Sed  class JIT : public AbstractInterpreter {
578193323Sed    std::string LLIPath;          // The path to the LLI executable
579193323Sed    std::vector<std::string> ToolArgs; // Args to pass to LLI
580193323Sed  public:
581193323Sed    JIT(const std::string &Path, const std::vector<std::string> *Args)
582193323Sed      : LLIPath(Path) {
583193323Sed      ToolArgs.clear ();
584193323Sed      if (Args) { ToolArgs = *Args; }
585193323Sed    }
586193323Sed
587193323Sed    virtual int ExecuteProgram(const std::string &Bitcode,
588193323Sed                               const std::vector<std::string> &Args,
589193323Sed                               const std::string &InputFile,
590193323Sed                               const std::string &OutputFile,
591207618Srdivacky                               std::string *Error,
592193323Sed                               const std::vector<std::string> &GCCArgs =
593193323Sed                                 std::vector<std::string>(),
594193323Sed                               const std::vector<std::string> &SharedLibs =
595218885Sdim                                 std::vector<std::string>(),
596207618Srdivacky                               unsigned Timeout = 0,
597207618Srdivacky                               unsigned MemoryLimit = 0);
598193323Sed  };
599193323Sed}
600193323Sed
601193323Sedint JIT::ExecuteProgram(const std::string &Bitcode,
602193323Sed                        const std::vector<std::string> &Args,
603193323Sed                        const std::string &InputFile,
604193323Sed                        const std::string &OutputFile,
605207618Srdivacky                        std::string *Error,
606193323Sed                        const std::vector<std::string> &GCCArgs,
607193323Sed                        const std::vector<std::string> &SharedLibs,
608193323Sed                        unsigned Timeout,
609193323Sed                        unsigned MemoryLimit) {
610193323Sed  // Construct a vector of parameters, incorporating those from the command-line
611193323Sed  std::vector<const char*> JITArgs;
612193323Sed  JITArgs.push_back(LLIPath.c_str());
613193323Sed  JITArgs.push_back("-force-interpreter=false");
614193323Sed
615193323Sed  // Add any extra LLI args.
616193323Sed  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
617193323Sed    JITArgs.push_back(ToolArgs[i].c_str());
618193323Sed
619193323Sed  for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
620193323Sed    JITArgs.push_back("-load");
621193323Sed    JITArgs.push_back(SharedLibs[i].c_str());
622193323Sed  }
623193323Sed  JITArgs.push_back(Bitcode.c_str());
624193323Sed  // Add optional parameters to the running program from Argv
625193323Sed  for (unsigned i=0, e = Args.size(); i != e; ++i)
626193323Sed    JITArgs.push_back(Args[i].c_str());
627193323Sed  JITArgs.push_back(0);
628193323Sed
629198090Srdivacky  outs() << "<jit>"; outs().flush();
630198090Srdivacky  DEBUG(errs() << "\nAbout to run:\t";
631193323Sed        for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i)
632198090Srdivacky          errs() << " " << JITArgs[i];
633198090Srdivacky        errs() << "\n";
634193323Sed        );
635198090Srdivacky  DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
636263508Sdim  return RunProgramWithTimeout(LLIPath, &JITArgs[0],
637263508Sdim      InputFile, OutputFile, OutputFile,
638218885Sdim      Timeout, MemoryLimit, Error);
639193323Sed}
640193323Sed
641193323Sed/// createJIT - Try to find the LLI executable
642193323Sed///
643198090SrdivackyAbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0,
644193323Sed                   std::string &Message, const std::vector<std::string> *Args) {
645198090Srdivacky  std::string LLIPath =
646263508Sdim      PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createJIT);
647193323Sed  if (!LLIPath.empty()) {
648193323Sed    Message = "Found lli: " + LLIPath + "\n";
649193323Sed    return new JIT(LLIPath, Args);
650193323Sed  }
651193323Sed
652218885Sdim  Message = "Cannot find `lli' in executable directory!\n";
653193323Sed  return 0;
654193323Sed}
655193323Sed
656193323Sed//===---------------------------------------------------------------------===//
657193323Sed// GCC abstraction
658193323Sed//
659198090Srdivacky
660212793Sdimstatic bool IsARMArchitecture(std::vector<const char*> Args) {
661212793Sdim  for (std::vector<const char*>::const_iterator
662198090Srdivacky         I = Args.begin(), E = Args.end(); I != E; ++I) {
663208599Srdivacky    if (StringRef(*I).equals_lower("-arch")) {
664198090Srdivacky      ++I;
665263508Sdim      if (I != E && StringRef(*I).startswith_lower("arm"))
666198090Srdivacky        return true;
667198090Srdivacky    }
668198090Srdivacky  }
669198090Srdivacky
670198090Srdivacky  return false;
671198090Srdivacky}
672198090Srdivacky
673193323Sedint GCC::ExecuteProgram(const std::string &ProgramFile,
674193323Sed                        const std::vector<std::string> &Args,
675193323Sed                        FileType fileType,
676193323Sed                        const std::string &InputFile,
677193323Sed                        const std::string &OutputFile,
678207618Srdivacky                        std::string *Error,
679193323Sed                        const std::vector<std::string> &ArgsForGCC,
680193323Sed                        unsigned Timeout,
681193323Sed                        unsigned MemoryLimit) {
682193323Sed  std::vector<const char*> GCCArgs;
683193323Sed
684193323Sed  GCCArgs.push_back(GCCPath.c_str());
685193323Sed
686205218Srdivacky  if (TargetTriple.getArch() == Triple::x86)
687205218Srdivacky    GCCArgs.push_back("-m32");
688205218Srdivacky
689193323Sed  for (std::vector<std::string>::const_iterator
690193323Sed         I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I)
691193323Sed    GCCArgs.push_back(I->c_str());
692193323Sed
693193323Sed  // Specify -x explicitly in case the extension is wonky
694205218Srdivacky  if (fileType != ObjectFile) {
695205218Srdivacky    GCCArgs.push_back("-x");
696205218Srdivacky    if (fileType == CFile) {
697205218Srdivacky      GCCArgs.push_back("c");
698205218Srdivacky      GCCArgs.push_back("-fno-strict-aliasing");
699205218Srdivacky    } else {
700205218Srdivacky      GCCArgs.push_back("assembler");
701198090Srdivacky
702205218Srdivacky      // For ARM architectures we don't want this flag. bugpoint isn't
703205218Srdivacky      // explicitly told what architecture it is working on, so we get
704205218Srdivacky      // it from gcc flags
705221337Sdim      if (TargetTriple.isOSDarwin() && !IsARMArchitecture(GCCArgs))
706205218Srdivacky        GCCArgs.push_back("-force_cpusubtype_ALL");
707205218Srdivacky    }
708193323Sed  }
709218885Sdim
710205218Srdivacky  GCCArgs.push_back(ProgramFile.c_str());  // Specify the input filename.
711218885Sdim
712193323Sed  GCCArgs.push_back("-x");
713193323Sed  GCCArgs.push_back("none");
714193323Sed  GCCArgs.push_back("-o");
715263508Sdim
716263508Sdim  SmallString<128> OutputBinary;
717263508Sdim  error_code EC =
718263508Sdim      sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.gcc.exe", OutputBinary);
719263508Sdim  if (EC) {
720263508Sdim    errs() << "Error making unique filename: " << EC.message() << "\n";
721193323Sed    exit(1);
722193323Sed  }
723193323Sed  GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
724193323Sed
725193323Sed  // Add any arguments intended for GCC. We locate them here because this is
726193323Sed  // most likely -L and -l options that need to come before other libraries but
727193323Sed  // after the source. Other options won't be sensitive to placement on the
728193323Sed  // command line, so this should be safe.
729193323Sed  for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
730193323Sed    GCCArgs.push_back(ArgsForGCC[i].c_str());
731193323Sed
732193323Sed  GCCArgs.push_back("-lm");                // Hard-code the math library...
733193323Sed  GCCArgs.push_back("-O2");                // Optimize the program a bit...
734193323Sed#if defined (HAVE_LINK_R)
735193323Sed  GCCArgs.push_back("-Wl,-R.");            // Search this dir for .so files
736193323Sed#endif
737198090Srdivacky  if (TargetTriple.getArch() == Triple::sparc)
738198090Srdivacky    GCCArgs.push_back("-mcpu=v9");
739193323Sed  GCCArgs.push_back(0);                    // NULL terminator
740193323Sed
741198090Srdivacky  outs() << "<gcc>"; outs().flush();
742198090Srdivacky  DEBUG(errs() << "\nAbout to run:\t";
743207618Srdivacky        for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i)
744198090Srdivacky          errs() << " " << GCCArgs[i];
745198090Srdivacky        errs() << "\n";
746193323Sed        );
747263508Sdim  if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) {
748207618Srdivacky    *Error = ProcessFailure(GCCPath, &GCCArgs[0]);
749207618Srdivacky    return -1;
750193323Sed  }
751193323Sed
752193323Sed  std::vector<const char*> ProgramArgs;
753193323Sed
754212793Sdim  // Declared here so that the destructor only runs after
755212793Sdim  // ProgramArgs is used.
756212793Sdim  std::string Exec;
757212793Sdim
758263508Sdim  if (RemoteClientPath.empty())
759193323Sed    ProgramArgs.push_back(OutputBinary.c_str());
760193323Sed  else {
761193323Sed    ProgramArgs.push_back(RemoteClientPath.c_str());
762193323Sed    ProgramArgs.push_back(RemoteHost.c_str());
763198090Srdivacky    if (!RemoteUser.empty()) {
764198090Srdivacky      ProgramArgs.push_back("-l");
765198090Srdivacky      ProgramArgs.push_back(RemoteUser.c_str());
766198090Srdivacky    }
767198090Srdivacky    if (!RemotePort.empty()) {
768198090Srdivacky      ProgramArgs.push_back("-p");
769198090Srdivacky      ProgramArgs.push_back(RemotePort.c_str());
770198090Srdivacky    }
771193323Sed    if (!RemoteExtra.empty()) {
772193323Sed      ProgramArgs.push_back(RemoteExtra.c_str());
773193323Sed    }
774193323Sed
775198090Srdivacky    // Full path to the binary. We need to cd to the exec directory because
776198090Srdivacky    // there is a dylib there that the exec expects to find in the CWD
777193323Sed    char* env_pwd = getenv("PWD");
778212793Sdim    Exec = "cd ";
779193323Sed    Exec += env_pwd;
780193323Sed    Exec += "; ./";
781193323Sed    Exec += OutputBinary.c_str();
782193323Sed    ProgramArgs.push_back(Exec.c_str());
783193323Sed  }
784193323Sed
785193323Sed  // Add optional parameters to the running program from Argv
786207618Srdivacky  for (unsigned i = 0, e = Args.size(); i != e; ++i)
787193323Sed    ProgramArgs.push_back(Args[i].c_str());
788193323Sed  ProgramArgs.push_back(0);                // NULL terminator
789193323Sed
790193323Sed  // Now that we have a binary, run it!
791198090Srdivacky  outs() << "<program>"; outs().flush();
792198090Srdivacky  DEBUG(errs() << "\nAbout to run:\t";
793207618Srdivacky        for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i)
794198090Srdivacky          errs() << " " << ProgramArgs[i];
795198090Srdivacky        errs() << "\n";
796193323Sed        );
797193323Sed
798221337Sdim  FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps);
799193323Sed
800263508Sdim  if (RemoteClientPath.empty()) {
801207618Srdivacky    DEBUG(errs() << "<run locally>");
802263508Sdim    int ExitCode = RunProgramWithTimeout(OutputBinary.str(), &ProgramArgs[0],
803263508Sdim                                         InputFile, OutputFile, OutputFile,
804263508Sdim                                         Timeout, MemoryLimit, Error);
805223013Sdim    // Treat a signal (usually SIGSEGV) or timeout as part of the program output
806223013Sdim    // so that crash-causing miscompilation is handled seamlessly.
807223013Sdim    if (ExitCode < -1) {
808223013Sdim      std::ofstream outFile(OutputFile.c_str(), std::ios_base::app);
809223013Sdim      outFile << *Error << '\n';
810223013Sdim      outFile.close();
811223013Sdim      Error->clear();
812223013Sdim    }
813223013Sdim    return ExitCode;
814198090Srdivacky  } else {
815198090Srdivacky    outs() << "<run remotely>"; outs().flush();
816263508Sdim    return RunProgramRemotelyWithTimeout(RemoteClientPath,
817263508Sdim        &ProgramArgs[0], InputFile, OutputFile,
818263508Sdim        OutputFile, Timeout, MemoryLimit);
819198090Srdivacky  }
820193323Sed}
821193323Sed
822193323Sedint GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
823193323Sed                          std::string &OutputFile,
824207618Srdivacky                          const std::vector<std::string> &ArgsForGCC,
825207618Srdivacky                          std::string &Error) {
826263508Sdim  SmallString<128> UniqueFilename;
827263508Sdim  error_code EC = sys::fs::createUniqueFile(
828263508Sdim      InputFile + "-%%%%%%%" + LTDL_SHLIB_EXT, UniqueFilename);
829263508Sdim  if (EC) {
830263508Sdim    errs() << "Error making unique filename: " << EC.message() << "\n";
831193323Sed    exit(1);
832193323Sed  }
833263508Sdim  OutputFile = UniqueFilename.str();
834193323Sed
835193323Sed  std::vector<const char*> GCCArgs;
836218885Sdim
837193323Sed  GCCArgs.push_back(GCCPath.c_str());
838193323Sed
839205218Srdivacky  if (TargetTriple.getArch() == Triple::x86)
840205218Srdivacky    GCCArgs.push_back("-m32");
841205218Srdivacky
842193323Sed  for (std::vector<std::string>::const_iterator
843193323Sed         I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I)
844193323Sed    GCCArgs.push_back(I->c_str());
845193323Sed
846193323Sed  // Compile the C/asm file into a shared object
847205218Srdivacky  if (fileType != ObjectFile) {
848205218Srdivacky    GCCArgs.push_back("-x");
849205218Srdivacky    GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
850205218Srdivacky  }
851193323Sed  GCCArgs.push_back("-fno-strict-aliasing");
852193323Sed  GCCArgs.push_back(InputFile.c_str());   // Specify the input filename.
853193323Sed  GCCArgs.push_back("-x");
854193323Sed  GCCArgs.push_back("none");
855198090Srdivacky  if (TargetTriple.getArch() == Triple::sparc)
856198090Srdivacky    GCCArgs.push_back("-G");       // Compile a shared library, `-G' for Sparc
857221337Sdim  else if (TargetTriple.isOSDarwin()) {
858198090Srdivacky    // link all source files into a single module in data segment, rather than
859218885Sdim    // generating blocks. dynamic_lookup requires that you set
860198090Srdivacky    // MACOSX_DEPLOYMENT_TARGET=10.3 in your env.  FIXME: it would be better for
861198090Srdivacky    // bugpoint to just pass that in the environment of GCC.
862198090Srdivacky    GCCArgs.push_back("-single_module");
863198090Srdivacky    GCCArgs.push_back("-dynamiclib");   // `-dynamiclib' for MacOS X/PowerPC
864198090Srdivacky    GCCArgs.push_back("-undefined");
865198090Srdivacky    GCCArgs.push_back("dynamic_lookup");
866198090Srdivacky  } else
867198090Srdivacky    GCCArgs.push_back("-shared");  // `-shared' for Linux/X86, maybe others
868193323Sed
869234353Sdim  if (TargetTriple.getArch() == Triple::x86_64)
870198090Srdivacky    GCCArgs.push_back("-fPIC");   // Requires shared objs to contain PIC
871198090Srdivacky
872198090Srdivacky  if (TargetTriple.getArch() == Triple::sparc)
873198090Srdivacky    GCCArgs.push_back("-mcpu=v9");
874198090Srdivacky
875193323Sed  GCCArgs.push_back("-o");
876193323Sed  GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
877193323Sed  GCCArgs.push_back("-O2");              // Optimize the program a bit.
878193323Sed
879218885Sdim
880218885Sdim
881193323Sed  // Add any arguments intended for GCC. We locate them here because this is
882193323Sed  // most likely -L and -l options that need to come before other libraries but
883193323Sed  // after the source. Other options won't be sensitive to placement on the
884193323Sed  // command line, so this should be safe.
885193323Sed  for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
886193323Sed    GCCArgs.push_back(ArgsForGCC[i].c_str());
887193323Sed  GCCArgs.push_back(0);                    // NULL terminator
888193323Sed
889193323Sed
890218885Sdim
891198090Srdivacky  outs() << "<gcc>"; outs().flush();
892198090Srdivacky  DEBUG(errs() << "\nAbout to run:\t";
893207618Srdivacky        for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i)
894198090Srdivacky          errs() << " " << GCCArgs[i];
895198090Srdivacky        errs() << "\n";
896193323Sed        );
897263508Sdim  if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) {
898207618Srdivacky    Error = ProcessFailure(GCCPath, &GCCArgs[0]);
899193323Sed    return 1;
900193323Sed  }
901193323Sed  return 0;
902193323Sed}
903193323Sed
904193323Sed/// create - Try to find the `gcc' executable
905193323Sed///
906198090SrdivackyGCC *GCC::create(std::string &Message,
907208599Srdivacky                 const std::string &GCCBinary,
908193323Sed                 const std::vector<std::string> *Args) {
909263508Sdim  std::string GCCPath = sys::FindProgramByName(GCCBinary);
910263508Sdim  if (GCCPath.empty()) {
911218885Sdim    Message = "Cannot find `"+ GCCBinary +"' in PATH!\n";
912193323Sed    return 0;
913193323Sed  }
914193323Sed
915263508Sdim  std::string RemoteClientPath;
916193323Sed  if (!RemoteClient.empty())
917263508Sdim    RemoteClientPath = sys::FindProgramByName(RemoteClient);
918193323Sed
919263508Sdim  Message = "Found gcc: " + GCCPath + "\n";
920193323Sed  return new GCC(GCCPath, RemoteClientPath, Args);
921193323Sed}
922