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