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