ToolRunner.cpp revision 193323
1//===-- ToolRunner.cpp ----------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the interfaces described in the ToolRunner.h file.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "toolrunner"
15#include "ToolRunner.h"
16#include "llvm/Config/config.h"   // for HAVE_LINK_R
17#include "llvm/System/Program.h"
18#include "llvm/Support/CommandLine.h"
19#include "llvm/Support/Debug.h"
20#include "llvm/Support/FileUtilities.h"
21#include <fstream>
22#include <sstream>
23#include <iostream>
24using namespace llvm;
25
26namespace {
27  cl::opt<std::string>
28  RemoteClient("remote-client",
29               cl::desc("Remote execution client (rsh/ssh)"));
30
31  cl::opt<std::string>
32  RemoteHost("remote-host",
33             cl::desc("Remote execution (rsh/ssh) host"));
34
35  cl::opt<std::string>
36  RemoteUser("remote-user",
37             cl::desc("Remote execution (rsh/ssh) user id"));
38
39  cl::opt<std::string>
40  RemoteExtra("remote-extra-options",
41          cl::desc("Remote execution (rsh/ssh) extra options"));
42}
43
44ToolExecutionError::~ToolExecutionError() throw() { }
45
46/// RunProgramWithTimeout - This function provides an alternate interface to the
47/// sys::Program::ExecuteAndWait interface.
48/// @see sys:Program::ExecuteAndWait
49static int RunProgramWithTimeout(const sys::Path &ProgramPath,
50                                 const char **Args,
51                                 const sys::Path &StdInFile,
52                                 const sys::Path &StdOutFile,
53                                 const sys::Path &StdErrFile,
54                                 unsigned NumSeconds = 0,
55                                 unsigned MemoryLimit = 0) {
56  const sys::Path* redirects[3];
57  redirects[0] = &StdInFile;
58  redirects[1] = &StdOutFile;
59  redirects[2] = &StdErrFile;
60
61  if (0) {
62    std::cerr << "RUN:";
63    for (unsigned i = 0; Args[i]; ++i)
64      std::cerr << " " << Args[i];
65    std::cerr << "\n";
66  }
67
68  return
69    sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects,
70                                 NumSeconds, MemoryLimit);
71}
72
73
74
75static void ProcessFailure(sys::Path ProgPath, const char** Args) {
76  std::ostringstream OS;
77  OS << "\nError running tool:\n ";
78  for (const char **Arg = Args; *Arg; ++Arg)
79    OS << " " << *Arg;
80  OS << "\n";
81
82  // Rerun the compiler, capturing any error messages to print them.
83  sys::Path ErrorFilename("bugpoint.program_error_messages");
84  std::string ErrMsg;
85  if (ErrorFilename.makeUnique(true, &ErrMsg)) {
86    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
87    exit(1);
88  }
89  RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename,
90                        ErrorFilename); // FIXME: check return code ?
91
92  // Print out the error messages generated by GCC if possible...
93  std::ifstream ErrorFile(ErrorFilename.c_str());
94  if (ErrorFile) {
95    std::copy(std::istreambuf_iterator<char>(ErrorFile),
96              std::istreambuf_iterator<char>(),
97              std::ostreambuf_iterator<char>(OS));
98    ErrorFile.close();
99  }
100
101  ErrorFilename.eraseFromDisk();
102  throw ToolExecutionError(OS.str());
103}
104
105//===---------------------------------------------------------------------===//
106// LLI Implementation of AbstractIntepreter interface
107//
108namespace {
109  class LLI : public AbstractInterpreter {
110    std::string LLIPath;          // The path to the LLI executable
111    std::vector<std::string> ToolArgs; // Args to pass to LLI
112  public:
113    LLI(const std::string &Path, const std::vector<std::string> *Args)
114      : LLIPath(Path) {
115      ToolArgs.clear ();
116      if (Args) { ToolArgs = *Args; }
117    }
118
119    virtual int ExecuteProgram(const std::string &Bitcode,
120                               const std::vector<std::string> &Args,
121                               const std::string &InputFile,
122                               const std::string &OutputFile,
123                               const std::vector<std::string> &GCCArgs,
124                               const std::vector<std::string> &SharedLibs =
125                               std::vector<std::string>(),
126                               unsigned Timeout = 0,
127                               unsigned MemoryLimit = 0);
128  };
129}
130
131int LLI::ExecuteProgram(const std::string &Bitcode,
132                        const std::vector<std::string> &Args,
133                        const std::string &InputFile,
134                        const std::string &OutputFile,
135                        const std::vector<std::string> &GCCArgs,
136                        const std::vector<std::string> &SharedLibs,
137                        unsigned Timeout,
138                        unsigned MemoryLimit) {
139  if (!SharedLibs.empty())
140    throw ToolExecutionError("LLI currently does not support "
141                             "loading shared libraries.");
142
143  std::vector<const char*> LLIArgs;
144  LLIArgs.push_back(LLIPath.c_str());
145  LLIArgs.push_back("-force-interpreter=true");
146
147  // Add any extra LLI args.
148  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
149    LLIArgs.push_back(ToolArgs[i].c_str());
150
151  LLIArgs.push_back(Bitcode.c_str());
152  // Add optional parameters to the running program from Argv
153  for (unsigned i=0, e = Args.size(); i != e; ++i)
154    LLIArgs.push_back(Args[i].c_str());
155  LLIArgs.push_back(0);
156
157  std::cout << "<lli>" << std::flush;
158  DEBUG(std::cerr << "\nAbout to run:\t";
159        for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i)
160          std::cerr << " " << LLIArgs[i];
161        std::cerr << "\n";
162        );
163  return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
164      sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
165      Timeout, MemoryLimit);
166}
167
168// LLI create method - Try to find the LLI executable
169AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath,
170                                                    std::string &Message,
171                                     const std::vector<std::string> *ToolArgs) {
172  std::string LLIPath = FindExecutable("lli", ProgPath).toString();
173  if (!LLIPath.empty()) {
174    Message = "Found lli: " + LLIPath + "\n";
175    return new LLI(LLIPath, ToolArgs);
176  }
177
178  Message = "Cannot find `lli' in executable directory or PATH!\n";
179  return 0;
180}
181
182//===---------------------------------------------------------------------===//
183// Custom execution command implementation of AbstractIntepreter interface
184//
185// Allows using a custom command for executing the bitcode, thus allows,
186// for example, to invoke a cross compiler for code generation followed by
187// a simulator that executes the generated binary.
188namespace {
189  class CustomExecutor : public AbstractInterpreter {
190    std::string ExecutionCommand;
191    std::vector<std::string> ExecutorArgs;
192  public:
193    CustomExecutor(
194      const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) :
195      ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {}
196
197    virtual int ExecuteProgram(const std::string &Bitcode,
198                               const std::vector<std::string> &Args,
199                               const std::string &InputFile,
200                               const std::string &OutputFile,
201                               const std::vector<std::string> &GCCArgs,
202                               const std::vector<std::string> &SharedLibs =
203                               std::vector<std::string>(),
204                               unsigned Timeout = 0,
205                               unsigned MemoryLimit = 0);
206  };
207}
208
209int CustomExecutor::ExecuteProgram(const std::string &Bitcode,
210                        const std::vector<std::string> &Args,
211                        const std::string &InputFile,
212                        const std::string &OutputFile,
213                        const std::vector<std::string> &GCCArgs,
214                        const std::vector<std::string> &SharedLibs,
215                        unsigned Timeout,
216                        unsigned MemoryLimit) {
217
218  std::vector<const char*> ProgramArgs;
219  ProgramArgs.push_back(ExecutionCommand.c_str());
220
221  for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
222    ProgramArgs.push_back(ExecutorArgs.at(i).c_str());
223  ProgramArgs.push_back(Bitcode.c_str());
224  ProgramArgs.push_back(0);
225
226  // Add optional parameters to the running program from Argv
227  for (unsigned i=0, e = Args.size(); i != e; ++i)
228    ProgramArgs.push_back(Args[i].c_str());
229
230  return RunProgramWithTimeout(
231    sys::Path(ExecutionCommand),
232    &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile),
233    sys::Path(OutputFile), Timeout, MemoryLimit);
234}
235
236// Custom execution environment create method, takes the execution command
237// as arguments
238AbstractInterpreter *AbstractInterpreter::createCustom(
239                    const std::string &ProgramPath,
240                    std::string &Message,
241                    const std::string &ExecCommandLine) {
242
243  std::string Command = "";
244  std::vector<std::string> Args;
245  std::string delimiters = " ";
246
247  // Tokenize the ExecCommandLine to the command and the args to allow
248  // defining a full command line as the command instead of just the
249  // executed program. We cannot just pass the whole string after the command
250  // as a single argument because then program sees only a single
251  // command line argument (with spaces in it: "foo bar" instead
252  // of "foo" and "bar").
253
254  // code borrowed from:
255  // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
256  std::string::size_type lastPos =
257    ExecCommandLine.find_first_not_of(delimiters, 0);
258  std::string::size_type pos =
259    ExecCommandLine.find_first_of(delimiters, lastPos);
260
261  while (std::string::npos != pos || std::string::npos != lastPos) {
262    std::string token = ExecCommandLine.substr(lastPos, pos - lastPos);
263    if (Command == "")
264       Command = token;
265    else
266       Args.push_back(token);
267    // Skip delimiters.  Note the "not_of"
268    lastPos = ExecCommandLine.find_first_not_of(delimiters, pos);
269    // Find next "non-delimiter"
270    pos = ExecCommandLine.find_first_of(delimiters, lastPos);
271  }
272
273  std::string CmdPath = FindExecutable(Command, ProgramPath).toString();
274  if (CmdPath.empty()) {
275    Message =
276      std::string("Cannot find '") + Command +
277      "' in executable directory or PATH!\n";
278    return 0;
279  }
280
281  Message = "Found command in: " + CmdPath + "\n";
282
283  return new CustomExecutor(CmdPath, Args);
284}
285
286//===----------------------------------------------------------------------===//
287// LLC Implementation of AbstractIntepreter interface
288//
289GCC::FileType LLC::OutputCode(const std::string &Bitcode,
290                              sys::Path &OutputAsmFile) {
291  sys::Path uniqueFile(Bitcode+".llc.s");
292  std::string ErrMsg;
293  if (uniqueFile.makeUnique(true, &ErrMsg)) {
294    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
295    exit(1);
296  }
297  OutputAsmFile = uniqueFile;
298  std::vector<const char *> LLCArgs;
299  LLCArgs.push_back (LLCPath.c_str());
300
301  // Add any extra LLC args.
302  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
303    LLCArgs.push_back(ToolArgs[i].c_str());
304
305  LLCArgs.push_back ("-o");
306  LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file
307  LLCArgs.push_back ("-f");                  // Overwrite as necessary...
308  LLCArgs.push_back (Bitcode.c_str());      // This is the input bitcode
309  LLCArgs.push_back (0);
310
311  std::cout << "<llc>" << std::flush;
312  DEBUG(std::cerr << "\nAbout to run:\t";
313        for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
314          std::cerr << " " << LLCArgs[i];
315        std::cerr << "\n";
316        );
317  if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0],
318                            sys::Path(), sys::Path(), sys::Path()))
319    ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]);
320
321  return GCC::AsmFile;
322}
323
324void LLC::compileProgram(const std::string &Bitcode) {
325  sys::Path OutputAsmFile;
326  OutputCode(Bitcode, OutputAsmFile);
327  OutputAsmFile.eraseFromDisk();
328}
329
330int LLC::ExecuteProgram(const std::string &Bitcode,
331                        const std::vector<std::string> &Args,
332                        const std::string &InputFile,
333                        const std::string &OutputFile,
334                        const std::vector<std::string> &ArgsForGCC,
335                        const std::vector<std::string> &SharedLibs,
336                        unsigned Timeout,
337                        unsigned MemoryLimit) {
338
339  sys::Path OutputAsmFile;
340  OutputCode(Bitcode, OutputAsmFile);
341  FileRemover OutFileRemover(OutputAsmFile);
342
343  std::vector<std::string> GCCArgs(ArgsForGCC);
344  GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end());
345  GCCArgs.insert(GCCArgs.end(), gccArgs.begin(), gccArgs.end());
346
347  // Assuming LLC worked, compile the result with GCC and run it.
348  return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile,
349                             InputFile, OutputFile, GCCArgs,
350                             Timeout, MemoryLimit);
351}
352
353/// createLLC - Try to find the LLC executable
354///
355LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath,
356                                    std::string &Message,
357                                    const std::vector<std::string> *Args,
358                                    const std::vector<std::string> *GCCArgs) {
359  std::string LLCPath = FindExecutable("llc", ProgramPath).toString();
360  if (LLCPath.empty()) {
361    Message = "Cannot find `llc' in executable directory or PATH!\n";
362    return 0;
363  }
364
365  Message = "Found llc: " + LLCPath + "\n";
366  GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs);
367  if (!gcc) {
368    std::cerr << Message << "\n";
369    exit(1);
370  }
371  return new LLC(LLCPath, gcc, Args, GCCArgs);
372}
373
374//===---------------------------------------------------------------------===//
375// JIT Implementation of AbstractIntepreter interface
376//
377namespace {
378  class JIT : public AbstractInterpreter {
379    std::string LLIPath;          // The path to the LLI executable
380    std::vector<std::string> ToolArgs; // Args to pass to LLI
381  public:
382    JIT(const std::string &Path, const std::vector<std::string> *Args)
383      : LLIPath(Path) {
384      ToolArgs.clear ();
385      if (Args) { ToolArgs = *Args; }
386    }
387
388    virtual int ExecuteProgram(const std::string &Bitcode,
389                               const std::vector<std::string> &Args,
390                               const std::string &InputFile,
391                               const std::string &OutputFile,
392                               const std::vector<std::string> &GCCArgs =
393                                 std::vector<std::string>(),
394                               const std::vector<std::string> &SharedLibs =
395                                 std::vector<std::string>(),
396                               unsigned Timeout =0,
397                               unsigned MemoryLimit =0);
398  };
399}
400
401int JIT::ExecuteProgram(const std::string &Bitcode,
402                        const std::vector<std::string> &Args,
403                        const std::string &InputFile,
404                        const std::string &OutputFile,
405                        const std::vector<std::string> &GCCArgs,
406                        const std::vector<std::string> &SharedLibs,
407                        unsigned Timeout,
408                        unsigned MemoryLimit) {
409  // Construct a vector of parameters, incorporating those from the command-line
410  std::vector<const char*> JITArgs;
411  JITArgs.push_back(LLIPath.c_str());
412  JITArgs.push_back("-force-interpreter=false");
413
414  // Add any extra LLI args.
415  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
416    JITArgs.push_back(ToolArgs[i].c_str());
417
418  for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
419    JITArgs.push_back("-load");
420    JITArgs.push_back(SharedLibs[i].c_str());
421  }
422  JITArgs.push_back(Bitcode.c_str());
423  // Add optional parameters to the running program from Argv
424  for (unsigned i=0, e = Args.size(); i != e; ++i)
425    JITArgs.push_back(Args[i].c_str());
426  JITArgs.push_back(0);
427
428  std::cout << "<jit>" << std::flush;
429  DEBUG(std::cerr << "\nAbout to run:\t";
430        for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i)
431          std::cerr << " " << JITArgs[i];
432        std::cerr << "\n";
433        );
434  DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n");
435  return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
436      sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
437      Timeout, MemoryLimit);
438}
439
440/// createJIT - Try to find the LLI executable
441///
442AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath,
443                   std::string &Message, const std::vector<std::string> *Args) {
444  std::string LLIPath = FindExecutable("lli", ProgPath).toString();
445  if (!LLIPath.empty()) {
446    Message = "Found lli: " + LLIPath + "\n";
447    return new JIT(LLIPath, Args);
448  }
449
450  Message = "Cannot find `lli' in executable directory or PATH!\n";
451  return 0;
452}
453
454GCC::FileType CBE::OutputCode(const std::string &Bitcode,
455                              sys::Path &OutputCFile) {
456  sys::Path uniqueFile(Bitcode+".cbe.c");
457  std::string ErrMsg;
458  if (uniqueFile.makeUnique(true, &ErrMsg)) {
459    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
460    exit(1);
461  }
462  OutputCFile = uniqueFile;
463  std::vector<const char *> LLCArgs;
464  LLCArgs.push_back (LLCPath.c_str());
465
466  // Add any extra LLC args.
467  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
468    LLCArgs.push_back(ToolArgs[i].c_str());
469
470  LLCArgs.push_back ("-o");
471  LLCArgs.push_back (OutputCFile.c_str());   // Output to the C file
472  LLCArgs.push_back ("-march=c");            // Output C language
473  LLCArgs.push_back ("-f");                  // Overwrite as necessary...
474  LLCArgs.push_back (Bitcode.c_str());      // This is the input bitcode
475  LLCArgs.push_back (0);
476
477  std::cout << "<cbe>" << std::flush;
478  DEBUG(std::cerr << "\nAbout to run:\t";
479        for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
480          std::cerr << " " << LLCArgs[i];
481        std::cerr << "\n";
482        );
483  if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(),
484                            sys::Path()))
485    ProcessFailure(LLCPath, &LLCArgs[0]);
486  return GCC::CFile;
487}
488
489void CBE::compileProgram(const std::string &Bitcode) {
490  sys::Path OutputCFile;
491  OutputCode(Bitcode, OutputCFile);
492  OutputCFile.eraseFromDisk();
493}
494
495int CBE::ExecuteProgram(const std::string &Bitcode,
496                        const std::vector<std::string> &Args,
497                        const std::string &InputFile,
498                        const std::string &OutputFile,
499                        const std::vector<std::string> &ArgsForGCC,
500                        const std::vector<std::string> &SharedLibs,
501                        unsigned Timeout,
502                        unsigned MemoryLimit) {
503  sys::Path OutputCFile;
504  OutputCode(Bitcode, OutputCFile);
505
506  FileRemover CFileRemove(OutputCFile);
507
508  std::vector<std::string> GCCArgs(ArgsForGCC);
509  GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end());
510
511  return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile,
512                             InputFile, OutputFile, GCCArgs,
513                             Timeout, MemoryLimit);
514}
515
516/// createCBE - Try to find the 'llc' executable
517///
518CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath,
519                                    std::string &Message,
520                                    const std::vector<std::string> *Args,
521                                    const std::vector<std::string> *GCCArgs) {
522  sys::Path LLCPath = FindExecutable("llc", ProgramPath);
523  if (LLCPath.isEmpty()) {
524    Message =
525      "Cannot find `llc' in executable directory or PATH!\n";
526    return 0;
527  }
528
529  Message = "Found llc: " + LLCPath.toString() + "\n";
530  GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs);
531  if (!gcc) {
532    std::cerr << Message << "\n";
533    exit(1);
534  }
535  return new CBE(LLCPath, gcc, Args);
536}
537
538//===---------------------------------------------------------------------===//
539// GCC abstraction
540//
541int GCC::ExecuteProgram(const std::string &ProgramFile,
542                        const std::vector<std::string> &Args,
543                        FileType fileType,
544                        const std::string &InputFile,
545                        const std::string &OutputFile,
546                        const std::vector<std::string> &ArgsForGCC,
547                        unsigned Timeout,
548                        unsigned MemoryLimit) {
549  std::vector<const char*> GCCArgs;
550
551  GCCArgs.push_back(GCCPath.c_str());
552
553  for (std::vector<std::string>::const_iterator
554         I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I)
555    GCCArgs.push_back(I->c_str());
556
557  // Specify -x explicitly in case the extension is wonky
558  GCCArgs.push_back("-x");
559  if (fileType == CFile) {
560    GCCArgs.push_back("c");
561    GCCArgs.push_back("-fno-strict-aliasing");
562  } else {
563    GCCArgs.push_back("assembler");
564#ifdef __APPLE__
565    GCCArgs.push_back("-force_cpusubtype_ALL");
566#endif
567  }
568  GCCArgs.push_back(ProgramFile.c_str());  // Specify the input filename...
569  GCCArgs.push_back("-x");
570  GCCArgs.push_back("none");
571  GCCArgs.push_back("-o");
572  sys::Path OutputBinary (ProgramFile+".gcc.exe");
573  std::string ErrMsg;
574  if (OutputBinary.makeUnique(true, &ErrMsg)) {
575    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
576    exit(1);
577  }
578  GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
579
580  // Add any arguments intended for GCC. We locate them here because this is
581  // most likely -L and -l options that need to come before other libraries but
582  // after the source. Other options won't be sensitive to placement on the
583  // command line, so this should be safe.
584  for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
585    GCCArgs.push_back(ArgsForGCC[i].c_str());
586
587  GCCArgs.push_back("-lm");                // Hard-code the math library...
588  GCCArgs.push_back("-O2");                // Optimize the program a bit...
589#if defined (HAVE_LINK_R)
590  GCCArgs.push_back("-Wl,-R.");            // Search this dir for .so files
591#endif
592#ifdef __sparc__
593  GCCArgs.push_back("-mcpu=v9");
594#endif
595  GCCArgs.push_back(0);                    // NULL terminator
596
597  std::cout << "<gcc>" << std::flush;
598  DEBUG(std::cerr << "\nAbout to run:\t";
599        for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
600          std::cerr << " " << GCCArgs[i];
601        std::cerr << "\n";
602        );
603  if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
604        sys::Path())) {
605    ProcessFailure(GCCPath, &GCCArgs[0]);
606    exit(1);
607  }
608
609  std::vector<const char*> ProgramArgs;
610
611  if (RemoteClientPath.isEmpty())
612    ProgramArgs.push_back(OutputBinary.c_str());
613  else {
614    ProgramArgs.push_back(RemoteClientPath.c_str());
615    ProgramArgs.push_back(RemoteHost.c_str());
616    ProgramArgs.push_back("-l");
617    ProgramArgs.push_back(RemoteUser.c_str());
618    if (!RemoteExtra.empty()) {
619      ProgramArgs.push_back(RemoteExtra.c_str());
620    }
621
622    char* env_pwd = getenv("PWD");
623    std::string Exec = "cd ";
624    Exec += env_pwd;
625    Exec += "; ./";
626    Exec += OutputBinary.c_str();
627    ProgramArgs.push_back(Exec.c_str());
628  }
629
630  // Add optional parameters to the running program from Argv
631  for (unsigned i=0, e = Args.size(); i != e; ++i)
632    ProgramArgs.push_back(Args[i].c_str());
633  ProgramArgs.push_back(0);                // NULL terminator
634
635  // Now that we have a binary, run it!
636  std::cout << "<program>" << std::flush;
637  DEBUG(std::cerr << "\nAbout to run:\t";
638        for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i)
639          std::cerr << " " << ProgramArgs[i];
640        std::cerr << "\n";
641        );
642
643  FileRemover OutputBinaryRemover(OutputBinary);
644
645  if (RemoteClientPath.isEmpty())
646    return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
647        sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
648        Timeout, MemoryLimit);
649  else
650    return RunProgramWithTimeout(sys::Path(RemoteClientPath), &ProgramArgs[0],
651        sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
652        Timeout, MemoryLimit);
653}
654
655int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
656                          std::string &OutputFile,
657                          const std::vector<std::string> &ArgsForGCC) {
658  sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT);
659  std::string ErrMsg;
660  if (uniqueFilename.makeUnique(true, &ErrMsg)) {
661    std::cerr << "Error making unique filename: " << ErrMsg << "\n";
662    exit(1);
663  }
664  OutputFile = uniqueFilename.toString();
665
666  std::vector<const char*> GCCArgs;
667
668  GCCArgs.push_back(GCCPath.c_str());
669
670  for (std::vector<std::string>::const_iterator
671         I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I)
672    GCCArgs.push_back(I->c_str());
673
674  // Compile the C/asm file into a shared object
675  GCCArgs.push_back("-x");
676  GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
677  GCCArgs.push_back("-fno-strict-aliasing");
678  GCCArgs.push_back(InputFile.c_str());   // Specify the input filename.
679  GCCArgs.push_back("-x");
680  GCCArgs.push_back("none");
681#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
682  GCCArgs.push_back("-G");       // Compile a shared library, `-G' for Sparc
683#elif defined(__APPLE__)
684  // link all source files into a single module in data segment, rather than
685  // generating blocks. dynamic_lookup requires that you set
686  // MACOSX_DEPLOYMENT_TARGET=10.3 in your env.  FIXME: it would be better for
687  // bugpoint to just pass that in the environment of GCC.
688  GCCArgs.push_back("-single_module");
689  GCCArgs.push_back("-dynamiclib");   // `-dynamiclib' for MacOS X/PowerPC
690  GCCArgs.push_back("-undefined");
691  GCCArgs.push_back("dynamic_lookup");
692#else
693  GCCArgs.push_back("-shared");  // `-shared' for Linux/X86, maybe others
694#endif
695
696#if defined(__ia64__) || defined(__alpha__) || defined(__amd64__)
697  GCCArgs.push_back("-fPIC");   // Requires shared objs to contain PIC
698#endif
699#ifdef __sparc__
700  GCCArgs.push_back("-mcpu=v9");
701#endif
702  GCCArgs.push_back("-o");
703  GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
704  GCCArgs.push_back("-O2");              // Optimize the program a bit.
705
706
707
708  // Add any arguments intended for GCC. We locate them here because this is
709  // most likely -L and -l options that need to come before other libraries but
710  // after the source. Other options won't be sensitive to placement on the
711  // command line, so this should be safe.
712  for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
713    GCCArgs.push_back(ArgsForGCC[i].c_str());
714  GCCArgs.push_back(0);                    // NULL terminator
715
716
717
718  std::cout << "<gcc>" << std::flush;
719  DEBUG(std::cerr << "\nAbout to run:\t";
720        for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
721          std::cerr << " " << GCCArgs[i];
722        std::cerr << "\n";
723        );
724  if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
725                            sys::Path())) {
726    ProcessFailure(GCCPath, &GCCArgs[0]);
727    return 1;
728  }
729  return 0;
730}
731
732/// create - Try to find the `gcc' executable
733///
734GCC *GCC::create(const std::string &ProgramPath, std::string &Message,
735                 const std::vector<std::string> *Args) {
736  sys::Path GCCPath = FindExecutable("gcc", ProgramPath);
737  if (GCCPath.isEmpty()) {
738    Message = "Cannot find `gcc' in executable directory or PATH!\n";
739    return 0;
740  }
741
742  sys::Path RemoteClientPath;
743  if (!RemoteClient.empty())
744    RemoteClientPath = FindExecutable(RemoteClient.c_str(), ProgramPath);
745
746  Message = "Found gcc: " + GCCPath.toString() + "\n";
747  return new GCC(GCCPath, RemoteClientPath, Args);
748}
749