1//===-- ToolRunner.cpp ----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the interfaces described in the ToolRunner.h file.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ToolRunner.h"
14#include "llvm/Config/config.h"
15#include "llvm/Support/CommandLine.h"
16#include "llvm/Support/Debug.h"
17#include "llvm/Support/FileSystem.h"
18#include "llvm/Support/FileUtilities.h"
19#include "llvm/Support/Program.h"
20#include "llvm/Support/raw_ostream.h"
21#include <fstream>
22#include <sstream>
23#include <utility>
24using namespace llvm;
25
26#define DEBUG_TYPE "toolrunner"
27
28namespace llvm {
29cl::opt<bool> SaveTemps("save-temps", cl::init(false),
30                        cl::desc("Save temporary files"));
31}
32
33namespace {
34cl::opt<std::string>
35    RemoteClient("remote-client",
36                 cl::desc("Remote execution client (rsh/ssh)"));
37
38cl::opt<std::string> RemoteHost("remote-host",
39                                cl::desc("Remote execution (rsh/ssh) host"));
40
41cl::opt<std::string> RemotePort("remote-port",
42                                cl::desc("Remote execution (rsh/ssh) port"));
43
44cl::opt<std::string> RemoteUser("remote-user",
45                                cl::desc("Remote execution (rsh/ssh) user id"));
46
47cl::opt<std::string>
48    RemoteExtra("remote-extra-options",
49                cl::desc("Remote execution (rsh/ssh) extra options"));
50}
51
52/// RunProgramWithTimeout - This function provides an alternate interface
53/// to the sys::Program::ExecuteAndWait interface.
54/// @see sys::Program::ExecuteAndWait
55static int RunProgramWithTimeout(StringRef ProgramPath,
56                                 ArrayRef<StringRef> Args, StringRef StdInFile,
57                                 StringRef StdOutFile, StringRef StdErrFile,
58                                 unsigned NumSeconds = 0,
59                                 unsigned MemoryLimit = 0,
60                                 std::string *ErrMsg = nullptr) {
61  std::optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
62  return sys::ExecuteAndWait(ProgramPath, Args, std::nullopt, Redirects,
63                             NumSeconds, MemoryLimit, ErrMsg);
64}
65
66/// RunProgramRemotelyWithTimeout - This function runs the given program
67/// remotely using the given remote client and the sys::Program::ExecuteAndWait.
68/// Returns the remote program exit code or reports a remote client error if it
69/// fails. Remote client is required to return 255 if it failed or program exit
70/// code otherwise.
71/// @see sys::Program::ExecuteAndWait
72static int RunProgramRemotelyWithTimeout(
73    StringRef RemoteClientPath, ArrayRef<StringRef> Args, StringRef StdInFile,
74    StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0,
75    unsigned MemoryLimit = 0) {
76  std::optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
77
78  // Run the program remotely with the remote client
79  int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, std::nullopt,
80                                       Redirects, NumSeconds, MemoryLimit);
81
82  // Has the remote client fail?
83  if (255 == ReturnCode) {
84    std::ostringstream OS;
85    OS << "\nError running remote client:\n ";
86    for (StringRef Arg : Args)
87      OS << " " << Arg.str();
88    OS << "\n";
89
90    // The error message is in the output file, let's print it out from there.
91    std::string StdOutFileName = StdOutFile.str();
92    std::ifstream ErrorFile(StdOutFileName.c_str());
93    if (ErrorFile) {
94      std::copy(std::istreambuf_iterator<char>(ErrorFile),
95                std::istreambuf_iterator<char>(),
96                std::ostreambuf_iterator<char>(OS));
97      ErrorFile.close();
98    }
99
100    errs() << OS.str();
101  }
102
103  return ReturnCode;
104}
105
106static Error ProcessFailure(StringRef ProgPath, ArrayRef<StringRef> Args,
107                            unsigned Timeout = 0, unsigned MemoryLimit = 0) {
108  std::ostringstream OS;
109  OS << "\nError running tool:\n ";
110  for (StringRef Arg : Args)
111    OS << " " << Arg.str();
112  OS << "\n";
113
114  // Rerun the compiler, capturing any error messages to print them.
115  SmallString<128> ErrorFilename;
116  std::error_code EC = sys::fs::createTemporaryFile(
117      "bugpoint.program_error_messages", "", ErrorFilename);
118  if (EC) {
119    errs() << "Error making unique filename: " << EC.message() << "\n";
120    exit(1);
121  }
122
123  RunProgramWithTimeout(ProgPath, Args, "", ErrorFilename.str(),
124                        ErrorFilename.str(), Timeout, MemoryLimit);
125  // FIXME: check return code ?
126
127  // Print out the error messages generated by CC if possible...
128  std::ifstream ErrorFile(ErrorFilename.c_str());
129  if (ErrorFile) {
130    std::copy(std::istreambuf_iterator<char>(ErrorFile),
131              std::istreambuf_iterator<char>(),
132              std::ostreambuf_iterator<char>(OS));
133    ErrorFile.close();
134  }
135
136  sys::fs::remove(ErrorFilename.c_str());
137  return make_error<StringError>(OS.str(), inconvertibleErrorCode());
138}
139
140//===---------------------------------------------------------------------===//
141// LLI Implementation of AbstractIntepreter interface
142//
143namespace {
144class LLI : public AbstractInterpreter {
145  std::string LLIPath;               // The path to the LLI executable
146  std::vector<std::string> ToolArgs; // Args to pass to LLI
147public:
148  LLI(const std::string &Path, const std::vector<std::string> *Args)
149      : LLIPath(Path) {
150    ToolArgs.clear();
151    if (Args) {
152      ToolArgs = *Args;
153    }
154  }
155
156  Expected<int> ExecuteProgram(
157      const std::string &Bitcode, const std::vector<std::string> &Args,
158      const std::string &InputFile, const std::string &OutputFile,
159      const std::vector<std::string> &CCArgs,
160      const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
161      unsigned Timeout = 0, unsigned MemoryLimit = 0) override;
162};
163}
164
165Expected<int> LLI::ExecuteProgram(const std::string &Bitcode,
166                                  const std::vector<std::string> &Args,
167                                  const std::string &InputFile,
168                                  const std::string &OutputFile,
169                                  const std::vector<std::string> &CCArgs,
170                                  const std::vector<std::string> &SharedLibs,
171                                  unsigned Timeout, unsigned MemoryLimit) {
172  std::vector<StringRef> LLIArgs;
173  LLIArgs.push_back(LLIPath);
174  LLIArgs.push_back("-force-interpreter=true");
175
176  for (std::vector<std::string>::const_iterator i = SharedLibs.begin(),
177                                                e = SharedLibs.end();
178       i != e; ++i) {
179    LLIArgs.push_back("-load");
180    LLIArgs.push_back(*i);
181  }
182
183  // Add any extra LLI args.
184  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
185    LLIArgs.push_back(ToolArgs[i]);
186
187  LLIArgs.push_back(Bitcode);
188  // Add optional parameters to the running program from Argv
189  for (unsigned i = 0, e = Args.size(); i != e; ++i)
190    LLIArgs.push_back(Args[i]);
191
192  outs() << "<lli>";
193  outs().flush();
194  LLVM_DEBUG(errs() << "\nAbout to run:\t";
195             for (unsigned i = 0, e = LLIArgs.size(); i != e; ++i) errs()
196             << " " << LLIArgs[i];
197             errs() << "\n";);
198  return RunProgramWithTimeout(LLIPath, LLIArgs, InputFile, OutputFile,
199                               OutputFile, Timeout, MemoryLimit);
200}
201
202void AbstractInterpreter::anchor() {}
203
204ErrorOr<std::string> llvm::FindProgramByName(const std::string &ExeName,
205                                             const char *Argv0,
206                                             void *MainAddr) {
207  // Check the directory that the calling program is in.  We can do
208  // this if ProgramPath contains at least one / character, indicating that it
209  // is a relative path to the executable itself.
210  std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr);
211  StringRef Result = sys::path::parent_path(Main);
212  if (ErrorOr<std::string> Path = sys::findProgramByName(ExeName, Result))
213    return *Path;
214
215  // Check the user PATH.
216  return sys::findProgramByName(ExeName);
217}
218
219// LLI create method - Try to find the LLI executable
220AbstractInterpreter *
221AbstractInterpreter::createLLI(const char *Argv0, std::string &Message,
222                               const std::vector<std::string> *ToolArgs) {
223  if (ErrorOr<std::string> LLIPath =
224      FindProgramByName("lli", Argv0, (void *)(intptr_t)&createLLI)) {
225    Message = "Found lli: " + *LLIPath + "\n";
226    return new LLI(*LLIPath, ToolArgs);
227  } else {
228    Message = LLIPath.getError().message() + "\n";
229    return nullptr;
230  }
231}
232
233//===---------------------------------------------------------------------===//
234// Custom compiler command implementation of AbstractIntepreter interface
235//
236// Allows using a custom command for compiling the bitcode, thus allows, for
237// example, to compile a bitcode fragment without linking or executing, then
238// using a custom wrapper script to check for compiler errors.
239namespace {
240class CustomCompiler : public AbstractInterpreter {
241  std::string CompilerCommand;
242  std::vector<std::string> CompilerArgs;
243
244public:
245  CustomCompiler(const std::string &CompilerCmd,
246                 std::vector<std::string> CompArgs)
247      : CompilerCommand(CompilerCmd), CompilerArgs(std::move(CompArgs)) {}
248
249  Error compileProgram(const std::string &Bitcode, unsigned Timeout = 0,
250                       unsigned MemoryLimit = 0) override;
251
252  Expected<int> ExecuteProgram(
253      const std::string &Bitcode, const std::vector<std::string> &Args,
254      const std::string &InputFile, const std::string &OutputFile,
255      const std::vector<std::string> &CCArgs = std::vector<std::string>(),
256      const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
257      unsigned Timeout = 0, unsigned MemoryLimit = 0) override {
258    return make_error<StringError>(
259        "Execution not supported with -compile-custom",
260        inconvertibleErrorCode());
261  }
262};
263}
264
265Error CustomCompiler::compileProgram(const std::string &Bitcode,
266                                     unsigned Timeout, unsigned MemoryLimit) {
267
268  std::vector<StringRef> ProgramArgs;
269  ProgramArgs.push_back(CompilerCommand);
270
271  for (const auto &Arg : CompilerArgs)
272    ProgramArgs.push_back(Arg);
273  ProgramArgs.push_back(Bitcode);
274
275  // Add optional parameters to the running program from Argv
276  for (const auto &Arg : CompilerArgs)
277    ProgramArgs.push_back(Arg);
278
279  if (RunProgramWithTimeout(CompilerCommand, ProgramArgs, "", "", "", Timeout,
280                            MemoryLimit))
281    return ProcessFailure(CompilerCommand, ProgramArgs, Timeout, MemoryLimit);
282  return Error::success();
283}
284
285//===---------------------------------------------------------------------===//
286// Custom execution command implementation of AbstractIntepreter interface
287//
288// Allows using a custom command for executing the bitcode, thus allows,
289// for example, to invoke a cross compiler for code generation followed by
290// a simulator that executes the generated binary.
291namespace {
292class CustomExecutor : public AbstractInterpreter {
293  std::string ExecutionCommand;
294  std::vector<std::string> ExecutorArgs;
295
296public:
297  CustomExecutor(const std::string &ExecutionCmd,
298                 std::vector<std::string> ExecArgs)
299      : ExecutionCommand(ExecutionCmd), ExecutorArgs(std::move(ExecArgs)) {}
300
301  Expected<int> ExecuteProgram(
302      const std::string &Bitcode, const std::vector<std::string> &Args,
303      const std::string &InputFile, const std::string &OutputFile,
304      const std::vector<std::string> &CCArgs,
305      const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
306      unsigned Timeout = 0, unsigned MemoryLimit = 0) override;
307};
308}
309
310Expected<int> CustomExecutor::ExecuteProgram(
311    const std::string &Bitcode, const std::vector<std::string> &Args,
312    const std::string &InputFile, const std::string &OutputFile,
313    const std::vector<std::string> &CCArgs,
314    const std::vector<std::string> &SharedLibs, unsigned Timeout,
315    unsigned MemoryLimit) {
316
317  std::vector<StringRef> ProgramArgs;
318  ProgramArgs.push_back(ExecutionCommand);
319
320  for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
321    ProgramArgs.push_back(ExecutorArgs[i]);
322  ProgramArgs.push_back(Bitcode);
323
324  // Add optional parameters to the running program from Argv
325  for (unsigned i = 0, e = Args.size(); i != e; ++i)
326    ProgramArgs.push_back(Args[i]);
327
328  return RunProgramWithTimeout(ExecutionCommand, ProgramArgs, InputFile,
329                               OutputFile, OutputFile, Timeout, MemoryLimit);
330}
331
332// Tokenize the CommandLine to the command and the args to allow
333// defining a full command line as the command instead of just the
334// executed program. We cannot just pass the whole string after the command
335// as a single argument because then the program sees only a single
336// command line argument (with spaces in it: "foo bar" instead
337// of "foo" and "bar").
338//
339// Spaces are used as a delimiter; however repeated, leading, and trailing
340// whitespace are ignored. Simple escaping is allowed via the '\'
341// character, as seen below:
342//
343// Two consecutive '\' evaluate to a single '\'.
344// A space after a '\' evaluates to a space that is not interpreted as a
345// delimiter.
346// Any other instances of the '\' character are removed.
347//
348// Example:
349// '\\' -> '\'
350// '\ ' -> ' '
351// 'exa\mple' -> 'example'
352//
353static void lexCommand(const char *Argv0, std::string &Message,
354                       const std::string &CommandLine, std::string &CmdPath,
355                       std::vector<std::string> &Args) {
356
357  std::string Token;
358  std::string Command;
359  bool FoundPath = false;
360
361  // first argument is the PATH.
362  // Skip repeated whitespace, leading whitespace and trailing whitespace.
363  for (std::size_t Pos = 0u; Pos <= CommandLine.size(); ++Pos) {
364    if ('\\' == CommandLine[Pos]) {
365      if (Pos + 1 < CommandLine.size())
366        Token.push_back(CommandLine[++Pos]);
367
368      continue;
369    }
370    if (' ' == CommandLine[Pos] || CommandLine.size() == Pos) {
371      if (Token.empty())
372        continue;
373
374      if (!FoundPath) {
375        Command = Token;
376        FoundPath = true;
377        Token.clear();
378        continue;
379      }
380
381      Args.push_back(Token);
382      Token.clear();
383      continue;
384    }
385    Token.push_back(CommandLine[Pos]);
386  }
387
388  auto Path = FindProgramByName(Command, Argv0, (void *)(intptr_t)&lexCommand);
389  if (!Path) {
390    Message = std::string("Cannot find '") + Command +
391              "' in PATH: " + Path.getError().message() + "\n";
392    return;
393  }
394  CmdPath = *Path;
395
396  Message = "Found command in: " + CmdPath + "\n";
397}
398
399// Custom execution environment create method, takes the execution command
400// as arguments
401AbstractInterpreter *AbstractInterpreter::createCustomCompiler(
402    const char *Argv0, std::string &Message,
403    const std::string &CompileCommandLine) {
404
405  std::string CmdPath;
406  std::vector<std::string> Args;
407  lexCommand(Argv0, Message, CompileCommandLine, CmdPath, Args);
408  if (CmdPath.empty())
409    return nullptr;
410
411  return new CustomCompiler(CmdPath, Args);
412}
413
414// Custom execution environment create method, takes the execution command
415// as arguments
416AbstractInterpreter *
417AbstractInterpreter::createCustomExecutor(const char *Argv0,
418                                          std::string &Message,
419                                          const std::string &ExecCommandLine) {
420
421  std::string CmdPath;
422  std::vector<std::string> Args;
423  lexCommand(Argv0, Message, ExecCommandLine, CmdPath, Args);
424  if (CmdPath.empty())
425    return nullptr;
426
427  return new CustomExecutor(CmdPath, Args);
428}
429
430//===----------------------------------------------------------------------===//
431// LLC Implementation of AbstractIntepreter interface
432//
433Expected<CC::FileType> LLC::OutputCode(const std::string &Bitcode,
434                                       std::string &OutputAsmFile,
435                                       unsigned Timeout, unsigned MemoryLimit) {
436  const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s");
437
438  SmallString<128> UniqueFile;
439  std::error_code EC =
440      sys::fs::createUniqueFile(Bitcode + "-%%%%%%%" + Suffix, UniqueFile);
441  if (EC) {
442    errs() << "Error making unique filename: " << EC.message() << "\n";
443    exit(1);
444  }
445  OutputAsmFile = std::string(UniqueFile);
446  std::vector<StringRef> LLCArgs;
447  LLCArgs.push_back(LLCPath);
448
449  // Add any extra LLC args.
450  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
451    LLCArgs.push_back(ToolArgs[i]);
452
453  LLCArgs.push_back("-o");
454  LLCArgs.push_back(OutputAsmFile); // Output to the Asm file
455  LLCArgs.push_back(Bitcode);       // This is the input bitcode
456
457  if (UseIntegratedAssembler)
458    LLCArgs.push_back("-filetype=obj");
459
460  outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>");
461  outs().flush();
462  LLVM_DEBUG(errs() << "\nAbout to run:\t";
463             for (unsigned i = 0, e = LLCArgs.size(); i != e; ++i) errs()
464             << " " << LLCArgs[i];
465             errs() << "\n";);
466  if (RunProgramWithTimeout(LLCPath, LLCArgs, "", "", "", Timeout, MemoryLimit))
467    return ProcessFailure(LLCPath, LLCArgs, Timeout, MemoryLimit);
468  return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile;
469}
470
471Error LLC::compileProgram(const std::string &Bitcode, unsigned Timeout,
472                          unsigned MemoryLimit) {
473  std::string OutputAsmFile;
474  Expected<CC::FileType> Result =
475      OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit);
476  sys::fs::remove(OutputAsmFile);
477  if (Error E = Result.takeError())
478    return E;
479  return Error::success();
480}
481
482Expected<int> LLC::ExecuteProgram(const std::string &Bitcode,
483                                  const std::vector<std::string> &Args,
484                                  const std::string &InputFile,
485                                  const std::string &OutputFile,
486                                  const std::vector<std::string> &ArgsForCC,
487                                  const std::vector<std::string> &SharedLibs,
488                                  unsigned Timeout, unsigned MemoryLimit) {
489
490  std::string OutputAsmFile;
491  Expected<CC::FileType> FileKind =
492      OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit);
493  FileRemover OutFileRemover(OutputAsmFile, !SaveTemps);
494  if (Error E = FileKind.takeError())
495    return std::move(E);
496
497  std::vector<std::string> CCArgs(ArgsForCC);
498  llvm::append_range(CCArgs, SharedLibs);
499
500  // Assuming LLC worked, compile the result with CC and run it.
501  return cc->ExecuteProgram(OutputAsmFile, Args, *FileKind, InputFile,
502                            OutputFile, CCArgs, Timeout, MemoryLimit);
503}
504
505/// createLLC - Try to find the LLC executable
506///
507LLC *AbstractInterpreter::createLLC(const char *Argv0, std::string &Message,
508                                    const std::string &CCBinary,
509                                    const std::vector<std::string> *Args,
510                                    const std::vector<std::string> *CCArgs,
511                                    bool UseIntegratedAssembler) {
512  ErrorOr<std::string> LLCPath =
513      FindProgramByName("llc", Argv0, (void *)(intptr_t)&createLLC);
514  if (!LLCPath) {
515    Message = LLCPath.getError().message() + "\n";
516    return nullptr;
517  }
518
519  CC *cc = CC::create(Argv0, Message, CCBinary, CCArgs);
520  if (!cc) {
521    errs() << Message << "\n";
522    exit(1);
523  }
524  Message = "Found llc: " + *LLCPath + "\n";
525  return new LLC(*LLCPath, cc, Args, UseIntegratedAssembler);
526}
527
528//===---------------------------------------------------------------------===//
529// JIT Implementation of AbstractIntepreter interface
530//
531namespace {
532class JIT : public AbstractInterpreter {
533  std::string LLIPath;               // The path to the LLI executable
534  std::vector<std::string> ToolArgs; // Args to pass to LLI
535public:
536  JIT(const std::string &Path, const std::vector<std::string> *Args)
537      : LLIPath(Path) {
538    ToolArgs.clear();
539    if (Args) {
540      ToolArgs = *Args;
541    }
542  }
543
544  Expected<int> ExecuteProgram(
545      const std::string &Bitcode, const std::vector<std::string> &Args,
546      const std::string &InputFile, const std::string &OutputFile,
547      const std::vector<std::string> &CCArgs = std::vector<std::string>(),
548      const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
549      unsigned Timeout = 0, unsigned MemoryLimit = 0) override;
550};
551}
552
553Expected<int> JIT::ExecuteProgram(const std::string &Bitcode,
554                                  const std::vector<std::string> &Args,
555                                  const std::string &InputFile,
556                                  const std::string &OutputFile,
557                                  const std::vector<std::string> &CCArgs,
558                                  const std::vector<std::string> &SharedLibs,
559                                  unsigned Timeout, unsigned MemoryLimit) {
560  // Construct a vector of parameters, incorporating those from the command-line
561  std::vector<StringRef> JITArgs;
562  JITArgs.push_back(LLIPath);
563  JITArgs.push_back("-force-interpreter=false");
564
565  // Add any extra LLI args.
566  for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
567    JITArgs.push_back(ToolArgs[i]);
568
569  for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
570    JITArgs.push_back("-load");
571    JITArgs.push_back(SharedLibs[i]);
572  }
573  JITArgs.push_back(Bitcode);
574  // Add optional parameters to the running program from Argv
575  for (unsigned i = 0, e = Args.size(); i != e; ++i)
576    JITArgs.push_back(Args[i]);
577
578  outs() << "<jit>";
579  outs().flush();
580  LLVM_DEBUG(errs() << "\nAbout to run:\t";
581             for (unsigned i = 0, e = JITArgs.size(); i != e; ++i) errs()
582             << " " << JITArgs[i];
583             errs() << "\n";);
584  LLVM_DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
585  return RunProgramWithTimeout(LLIPath, JITArgs, InputFile, OutputFile,
586                               OutputFile, Timeout, MemoryLimit);
587}
588
589/// createJIT - Try to find the LLI executable
590///
591AbstractInterpreter *
592AbstractInterpreter::createJIT(const char *Argv0, std::string &Message,
593                               const std::vector<std::string> *Args) {
594  if (ErrorOr<std::string> LLIPath =
595          FindProgramByName("lli", Argv0, (void *)(intptr_t)&createJIT)) {
596    Message = "Found lli: " + *LLIPath + "\n";
597    return new JIT(*LLIPath, Args);
598  } else {
599    Message = LLIPath.getError().message() + "\n";
600    return nullptr;
601  }
602}
603
604//===---------------------------------------------------------------------===//
605// CC abstraction
606//
607
608static bool IsARMArchitecture(std::vector<StringRef> Args) {
609  for (size_t I = 0; I < Args.size(); ++I) {
610    if (!Args[I].equals_insensitive("-arch"))
611      continue;
612    ++I;
613    if (I == Args.size())
614      break;
615    if (Args[I].starts_with_insensitive("arm"))
616      return true;
617  }
618
619  return false;
620}
621
622Expected<int> CC::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> &ArgsForCC,
628                                 unsigned Timeout, unsigned MemoryLimit) {
629  std::vector<StringRef> CCArgs;
630
631  CCArgs.push_back(CCPath);
632
633  if (TargetTriple.getArch() == Triple::x86)
634    CCArgs.push_back("-m32");
635
636  for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
637                                                E = ccArgs.end();
638       I != E; ++I)
639    CCArgs.push_back(*I);
640
641  // Specify -x explicitly in case the extension is wonky
642  if (fileType != ObjectFile) {
643    CCArgs.push_back("-x");
644    if (fileType == CFile) {
645      CCArgs.push_back("c");
646      CCArgs.push_back("-fno-strict-aliasing");
647    } else {
648      CCArgs.push_back("assembler");
649
650      // For ARM architectures we don't want this flag. bugpoint isn't
651      // explicitly told what architecture it is working on, so we get
652      // it from cc flags
653      if (TargetTriple.isOSDarwin() && !IsARMArchitecture(CCArgs))
654        CCArgs.push_back("-force_cpusubtype_ALL");
655    }
656  }
657
658  CCArgs.push_back(ProgramFile); // Specify the input filename.
659
660  CCArgs.push_back("-x");
661  CCArgs.push_back("none");
662  CCArgs.push_back("-o");
663
664  SmallString<128> OutputBinary;
665  std::error_code EC =
666      sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.cc.exe", OutputBinary);
667  if (EC) {
668    errs() << "Error making unique filename: " << EC.message() << "\n";
669    exit(1);
670  }
671  CCArgs.push_back(OutputBinary); // Output to the right file...
672
673  // Add any arguments intended for CC. We locate them here because this is
674  // most likely -L and -l options that need to come before other libraries but
675  // after the source. Other options won't be sensitive to placement on the
676  // command line, so this should be safe.
677  for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
678    CCArgs.push_back(ArgsForCC[i]);
679
680  CCArgs.push_back("-lm"); // Hard-code the math library...
681  CCArgs.push_back("-O2"); // Optimize the program a bit...
682  if (TargetTriple.getArch() == Triple::sparc)
683    CCArgs.push_back("-mcpu=v9");
684
685  outs() << "<CC>";
686  outs().flush();
687  LLVM_DEBUG(errs() << "\nAbout to run:\t";
688             for (unsigned i = 0, e = CCArgs.size(); i != e; ++i) errs()
689             << " " << CCArgs[i];
690             errs() << "\n";);
691  if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
692    return ProcessFailure(CCPath, CCArgs);
693
694  std::vector<StringRef> ProgramArgs;
695
696  // Declared here so that the destructor only runs after
697  // ProgramArgs is used.
698  std::string Exec;
699
700  if (RemoteClientPath.empty())
701    ProgramArgs.push_back(OutputBinary);
702  else {
703    ProgramArgs.push_back(RemoteClientPath);
704    ProgramArgs.push_back(RemoteHost);
705    if (!RemoteUser.empty()) {
706      ProgramArgs.push_back("-l");
707      ProgramArgs.push_back(RemoteUser);
708    }
709    if (!RemotePort.empty()) {
710      ProgramArgs.push_back("-p");
711      ProgramArgs.push_back(RemotePort);
712    }
713    if (!RemoteExtra.empty()) {
714      ProgramArgs.push_back(RemoteExtra);
715    }
716
717    // Full path to the binary. We need to cd to the exec directory because
718    // there is a dylib there that the exec expects to find in the CWD
719    char *env_pwd = getenv("PWD");
720    Exec = "cd ";
721    Exec += env_pwd;
722    Exec += "; ./";
723    Exec += OutputBinary.c_str();
724    ProgramArgs.push_back(Exec);
725  }
726
727  // Add optional parameters to the running program from Argv
728  for (unsigned i = 0, e = Args.size(); i != e; ++i)
729    ProgramArgs.push_back(Args[i]);
730
731  // Now that we have a binary, run it!
732  outs() << "<program>";
733  outs().flush();
734  LLVM_DEBUG(
735      errs() << "\nAbout to run:\t";
736      for (unsigned i = 0, e = ProgramArgs.size(); i != e; ++i) errs()
737      << " " << ProgramArgs[i];
738      errs() << "\n";);
739
740  FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps);
741
742  if (RemoteClientPath.empty()) {
743    LLVM_DEBUG(errs() << "<run locally>");
744    std::string Error;
745    int ExitCode = RunProgramWithTimeout(OutputBinary.str(), ProgramArgs,
746                                         InputFile, OutputFile, OutputFile,
747                                         Timeout, MemoryLimit, &Error);
748    // Treat a signal (usually SIGSEGV) or timeout as part of the program output
749    // so that crash-causing miscompilation is handled seamlessly.
750    if (ExitCode < -1) {
751      std::ofstream outFile(OutputFile.c_str(), std::ios_base::app);
752      outFile << Error << '\n';
753      outFile.close();
754    }
755    return ExitCode;
756  } else {
757    outs() << "<run remotely>";
758    outs().flush();
759    return RunProgramRemotelyWithTimeout(RemoteClientPath, ProgramArgs,
760                                         InputFile, OutputFile, OutputFile,
761                                         Timeout, MemoryLimit);
762  }
763}
764
765Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
766                           std::string &OutputFile,
767                           const std::vector<std::string> &ArgsForCC) {
768  SmallString<128> UniqueFilename;
769  std::error_code EC = sys::fs::createUniqueFile(
770      InputFile + "-%%%%%%%" + LTDL_SHLIB_EXT, UniqueFilename);
771  if (EC) {
772    errs() << "Error making unique filename: " << EC.message() << "\n";
773    exit(1);
774  }
775  OutputFile = std::string(UniqueFilename);
776
777  std::vector<StringRef> CCArgs;
778
779  CCArgs.push_back(CCPath);
780
781  if (TargetTriple.getArch() == Triple::x86)
782    CCArgs.push_back("-m32");
783
784  for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
785                                                E = ccArgs.end();
786       I != E; ++I)
787    CCArgs.push_back(*I);
788
789  // Compile the C/asm file into a shared object
790  if (fileType != ObjectFile) {
791    CCArgs.push_back("-x");
792    CCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
793  }
794  CCArgs.push_back("-fno-strict-aliasing");
795  CCArgs.push_back(InputFile); // Specify the input filename.
796  CCArgs.push_back("-x");
797  CCArgs.push_back("none");
798  if (TargetTriple.getArch() == Triple::sparc)
799    CCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
800  else if (TargetTriple.isOSDarwin()) {
801    // link all source files into a single module in data segment, rather than
802    // generating blocks. dynamic_lookup requires that you set
803    // MACOSX_DEPLOYMENT_TARGET=10.3 in your env.  FIXME: it would be better for
804    // bugpoint to just pass that in the environment of CC.
805    CCArgs.push_back("-single_module");
806    CCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC
807    CCArgs.push_back("-undefined");
808    CCArgs.push_back("dynamic_lookup");
809  } else
810    CCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others
811
812  if (TargetTriple.getArch() == Triple::x86_64)
813    CCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
814
815  if (TargetTriple.getArch() == Triple::sparc)
816    CCArgs.push_back("-mcpu=v9");
817
818  CCArgs.push_back("-o");
819  CCArgs.push_back(OutputFile);         // Output to the right filename.
820  CCArgs.push_back("-O2");              // Optimize the program a bit.
821
822  // Add any arguments intended for CC. We locate them here because this is
823  // most likely -L and -l options that need to come before other libraries but
824  // after the source. Other options won't be sensitive to placement on the
825  // command line, so this should be safe.
826  for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
827    CCArgs.push_back(ArgsForCC[i]);
828
829  outs() << "<CC>";
830  outs().flush();
831  LLVM_DEBUG(errs() << "\nAbout to run:\t";
832             for (unsigned i = 0, e = CCArgs.size(); i != e; ++i) errs()
833             << " " << CCArgs[i];
834             errs() << "\n";);
835  if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
836    return ProcessFailure(CCPath, CCArgs);
837  return Error::success();
838}
839
840/// create - Try to find the CC executable
841///
842CC *CC::create(const char *Argv0, std::string &Message,
843               const std::string &CCBinary,
844               const std::vector<std::string> *Args) {
845  auto CCPath = FindProgramByName(CCBinary, Argv0, (void *)(intptr_t)&create);
846  if (!CCPath) {
847    Message = "Cannot find `" + CCBinary + "' in PATH: " +
848              CCPath.getError().message() + "\n";
849    return nullptr;
850  }
851
852  std::string RemoteClientPath;
853  if (!RemoteClient.empty()) {
854    auto Path = sys::findProgramByName(RemoteClient);
855    if (!Path) {
856      Message = "Cannot find `" + RemoteClient + "' in PATH: " +
857                Path.getError().message() + "\n";
858      return nullptr;
859    }
860    RemoteClientPath = *Path;
861  }
862
863  Message = "Found CC: " + *CCPath + "\n";
864  return new CC(*CCPath, RemoteClientPath, Args);
865}
866