ToolRunner.cpp 31 KB

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