blob: 7ba8ea1f16c572bccf9b99c1d419f9ccd007743c [file] [log] [blame]
Chris Lattner7915a1e2003-10-14 21:34:11 +00001//===-- ToolRunner.cpp ----------------------------------------------------===//
Misha Brukmanf976c852005-04-21 22:55:34 +00002//
John Criswellb576c942003-10-20 19:43:21 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattner21c62da2007-12-29 20:44:31 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Misha Brukmanf976c852005-04-21 22:55:34 +00007//
John Criswellb576c942003-10-20 19:43:21 +00008//===----------------------------------------------------------------------===//
Chris Lattner7915a1e2003-10-14 21:34:11 +00009//
10// This file implements the interfaces described in the ToolRunner.h file.
11//
12//===----------------------------------------------------------------------===//
13
Chris Lattnerf1b20d82006-06-06 22:30:59 +000014#include "ToolRunner.h"
Joerg Sonnenberger4c3dd492016-09-30 20:11:21 +000015#include "llvm/Config/config.h"
Evan Cheng34e400e2007-05-03 18:36:15 +000016#include "llvm/Support/CommandLine.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000017#include "llvm/Support/Debug.h"
Rafael Espindola3991c722013-06-18 17:20:08 +000018#include "llvm/Support/FileSystem.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000019#include "llvm/Support/FileUtilities.h"
Chandler Carruthf010c462012-12-04 10:44:52 +000020#include "llvm/Support/Program.h"
Chris Lattner74382b72009-08-23 22:45:37 +000021#include "llvm/Support/raw_ostream.h"
Chris Lattner7915a1e2003-10-14 21:34:11 +000022#include <fstream>
Chris Lattner89bf9ea2004-02-18 20:38:00 +000023#include <sstream>
Benjamin Kramer14aae012016-05-27 14:27:24 +000024#include <utility>
Chris Lattner2cdd21c2003-12-14 21:35:53 +000025using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000026
Chandler Carruth843eb0c2014-04-22 03:10:36 +000027#define DEBUG_TYPE "toolrunner"
28
Anton Korobeynikov86c006a2009-08-05 09:32:10 +000029namespace llvm {
Justin Bogner388e8b92016-09-02 01:21:37 +000030cl::opt<bool> SaveTemps("save-temps", cl::init(false),
31 cl::desc("Save temporary files"));
Anton Korobeynikov86c006a2009-08-05 09:32:10 +000032}
33
Evan Cheng34e400e2007-05-03 18:36:15 +000034namespace {
Justin Bogner388e8b92016-09-02 01:21:37 +000035cl::opt<std::string>
36 RemoteClient("remote-client",
37 cl::desc("Remote execution client (rsh/ssh)"));
Evan Cheng34e400e2007-05-03 18:36:15 +000038
Justin Bogner388e8b92016-09-02 01:21:37 +000039cl::opt<std::string> RemoteHost("remote-host",
40 cl::desc("Remote execution (rsh/ssh) host"));
Evan Cheng70f684f2008-09-09 06:11:26 +000041
Justin Bogner388e8b92016-09-02 01:21:37 +000042cl::opt<std::string> RemotePort("remote-port",
43 cl::desc("Remote execution (rsh/ssh) port"));
David Goodwin80becf12009-07-10 21:39:28 +000044
Justin Bogner388e8b92016-09-02 01:21:37 +000045cl::opt<std::string> RemoteUser("remote-user",
46 cl::desc("Remote execution (rsh/ssh) user id"));
Evan Cheng70f684f2008-09-09 06:11:26 +000047
Justin Bogner388e8b92016-09-02 01:21:37 +000048cl::opt<std::string>
49 RemoteExtra("remote-extra-options",
50 cl::desc("Remote execution (rsh/ssh) extra options"));
Evan Cheng34e400e2007-05-03 18:36:15 +000051}
52
Viktor Kutuzovfc2271f2009-07-18 18:39:24 +000053/// RunProgramWithTimeout - This function provides an alternate interface
54/// to the sys::Program::ExecuteAndWait interface.
Nick Lewycky22ff7482010-04-12 05:08:25 +000055/// @see sys::Program::ExecuteAndWait
Zachary Turner0dcc1152018-06-12 17:43:52 +000056static int RunProgramWithTimeout(StringRef ProgramPath,
57 ArrayRef<StringRef> Args, StringRef StdInFile,
58 StringRef StdOutFile, StringRef StdErrFile,
59 unsigned NumSeconds = 0,
Dan Gohmane1f2e502010-11-09 01:13:31 +000060 unsigned MemoryLimit = 0,
Craig Topper573faec2014-04-25 04:24:47 +000061 std::string *ErrMsg = nullptr) {
Alexander Kornienko87e117d2017-09-13 17:03:37 +000062 Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
Zachary Turner0dcc1152018-06-12 17:43:52 +000063 return sys::ExecuteAndWait(ProgramPath, Args, None, Redirects, NumSeconds,
Justin Bogner388e8b92016-09-02 01:21:37 +000064 MemoryLimit, ErrMsg);
Chris Lattner45495c52005-02-13 23:13:47 +000065}
66
Viktor Kutuzovfc2271f2009-07-18 18:39:24 +000067/// RunProgramRemotelyWithTimeout - This function runs the given program
68/// remotely using the given remote client and the sys::Program::ExecuteAndWait.
69/// Returns the remote program exit code or reports a remote client error if it
70/// fails. Remote client is required to return 255 if it failed or program exit
71/// code otherwise.
Nick Lewycky22ff7482010-04-12 05:08:25 +000072/// @see sys::Program::ExecuteAndWait
Zachary Turner0dcc1152018-06-12 17:43:52 +000073static int RunProgramRemotelyWithTimeout(
74 StringRef RemoteClientPath, ArrayRef<StringRef> Args, StringRef StdInFile,
75 StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0,
76 unsigned MemoryLimit = 0) {
Alexander Kornienko87e117d2017-09-13 17:03:37 +000077 Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
Chris Lattner45495c52005-02-13 23:13:47 +000078
Viktor Kutuzovfc2271f2009-07-18 18:39:24 +000079 // Run the program remotely with the remote client
Zachary Turner0dcc1152018-06-12 17:43:52 +000080 int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, None, Redirects,
81 NumSeconds, MemoryLimit);
Viktor Kutuzovfc2271f2009-07-18 18:39:24 +000082
83 // Has the remote client fail?
84 if (255 == ReturnCode) {
85 std::ostringstream OS;
86 OS << "\nError running remote client:\n ";
Zachary Turner0dcc1152018-06-12 17:43:52 +000087 for (StringRef Arg : Args)
88 OS << " " << Arg.str();
Viktor Kutuzovfc2271f2009-07-18 18:39:24 +000089 OS << "\n";
90
91 // The error message is in the output file, let's print it out from there.
Rafael Espindolaf3780282013-06-13 15:52:54 +000092 std::string StdOutFileName = StdOutFile.str();
93 std::ifstream ErrorFile(StdOutFileName.c_str());
Viktor Kutuzovfc2271f2009-07-18 18:39:24 +000094 if (ErrorFile) {
95 std::copy(std::istreambuf_iterator<char>(ErrorFile),
96 std::istreambuf_iterator<char>(),
97 std::ostreambuf_iterator<char>(OS));
98 ErrorFile.close();
99 }
100
John McCall9679f0f2012-05-02 05:39:10 +0000101 errs() << OS.str();
Viktor Kutuzovfc2271f2009-07-18 18:39:24 +0000102 }
103
104 return ReturnCode;
105}
Chris Lattner45495c52005-02-13 23:13:47 +0000106
Zachary Turner0dcc1152018-06-12 17:43:52 +0000107static Error ProcessFailure(StringRef ProgPath, ArrayRef<StringRef> Args,
Justin Bognerd8090ae2016-09-06 17:18:22 +0000108 unsigned Timeout = 0, unsigned MemoryLimit = 0) {
Chris Lattner89bf9ea2004-02-18 20:38:00 +0000109 std::ostringstream OS;
Chris Lattnera3de1172004-02-18 20:58:00 +0000110 OS << "\nError running tool:\n ";
Zachary Turner0dcc1152018-06-12 17:43:52 +0000111 for (StringRef Arg : Args)
112 OS << " " << Arg.str();
Chris Lattner89bf9ea2004-02-18 20:38:00 +0000113 OS << "\n";
Mikhail Glushenkov544fba12010-11-03 16:14:07 +0000114
Chris Lattner89bf9ea2004-02-18 20:38:00 +0000115 // Rerun the compiler, capturing any error messages to print them.
Rafael Espindola3991c722013-06-18 17:20:08 +0000116 SmallString<128> ErrorFilename;
Rafael Espindola1ad45022014-06-13 03:07:50 +0000117 std::error_code EC = sys::fs::createTemporaryFile(
Lang Hames7106ab72014-10-07 21:47:23 +0000118 "bugpoint.program_error_messages", "", ErrorFilename);
Rafael Espindola3991c722013-06-18 17:20:08 +0000119 if (EC) {
120 errs() << "Error making unique filename: " << EC.message() << "\n";
Reid Spencer51c5a282006-08-23 20:34:57 +0000121 exit(1);
122 }
NAKAMURA Takumieddc4852014-07-13 13:28:18 +0000123
Rafael Espindolaa4b504a2013-06-13 15:47:11 +0000124 RunProgramWithTimeout(ProgPath, Args, "", ErrorFilename.str(),
125 ErrorFilename.str(), Timeout, MemoryLimit);
Duncan Sands41396302010-05-24 07:49:55 +0000126 // FIXME: check return code ?
Chris Lattner89bf9ea2004-02-18 20:38:00 +0000127
Davide Italianof7b2acb2015-10-14 20:29:54 +0000128 // Print out the error messages generated by CC if possible...
Chris Lattner89bf9ea2004-02-18 20:38:00 +0000129 std::ifstream ErrorFile(ErrorFilename.c_str());
130 if (ErrorFile) {
131 std::copy(std::istreambuf_iterator<char>(ErrorFile),
132 std::istreambuf_iterator<char>(),
133 std::ostreambuf_iterator<char>(OS));
134 ErrorFile.close();
135 }
136
Rafael Espindola3991c722013-06-18 17:20:08 +0000137 sys::fs::remove(ErrorFilename.c_str());
Justin Bognerd8090ae2016-09-06 17:18:22 +0000138 return make_error<StringError>(OS.str(), inconvertibleErrorCode());
Chris Lattner89bf9ea2004-02-18 20:38:00 +0000139}
140
Misha Brukman9558c6a2003-09-29 22:39:25 +0000141//===---------------------------------------------------------------------===//
142// LLI Implementation of AbstractIntepreter interface
143//
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000144namespace {
Justin Bogner388e8b92016-09-02 01:21:37 +0000145class LLI : public AbstractInterpreter {
146 std::string LLIPath; // The path to the LLI executable
147 std::vector<std::string> ToolArgs; // Args to pass to LLI
148public:
149 LLI(const std::string &Path, const std::vector<std::string> *Args)
Brian Gaeked11577b2004-05-04 21:09:01 +0000150 : LLIPath(Path) {
Justin Bogner388e8b92016-09-02 01:21:37 +0000151 ToolArgs.clear();
152 if (Args) {
153 ToolArgs = *Args;
Brian Gaeked11577b2004-05-04 21:09:01 +0000154 }
Justin Bogner388e8b92016-09-02 01:21:37 +0000155 }
Misha Brukmanf976c852005-04-21 22:55:34 +0000156
Justin Bognerd8090ae2016-09-06 17:18:22 +0000157 Expected<int> ExecuteProgram(
Justin Bogner388e8b92016-09-02 01:21:37 +0000158 const std::string &Bitcode, const std::vector<std::string> &Args,
159 const std::string &InputFile, const std::string &OutputFile,
Justin Bognerd8090ae2016-09-06 17:18:22 +0000160 const std::vector<std::string> &CCArgs,
Justin Bogner388e8b92016-09-02 01:21:37 +0000161 const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
162 unsigned Timeout = 0, unsigned MemoryLimit = 0) override;
163};
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000164}
Misha Brukman9558c6a2003-09-29 22:39:25 +0000165
Justin Bognerd8090ae2016-09-06 17:18:22 +0000166Expected<int> LLI::ExecuteProgram(const std::string &Bitcode,
167 const std::vector<std::string> &Args,
168 const std::string &InputFile,
169 const std::string &OutputFile,
170 const std::vector<std::string> &CCArgs,
171 const std::vector<std::string> &SharedLibs,
172 unsigned Timeout, unsigned MemoryLimit) {
Zachary Turner0dcc1152018-06-12 17:43:52 +0000173 std::vector<StringRef> LLIArgs;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000174 LLIArgs.push_back(LLIPath.c_str());
Misha Brukman9558c6a2003-09-29 22:39:25 +0000175 LLIArgs.push_back("-force-interpreter=true");
Brian Gaeked11577b2004-05-04 21:09:01 +0000176
Mikhail Glushenkov544fba12010-11-03 16:14:07 +0000177 for (std::vector<std::string>::const_iterator i = SharedLibs.begin(),
Justin Bogner388e8b92016-09-02 01:21:37 +0000178 e = SharedLibs.end();
179 i != e; ++i) {
Duncan Sands3ea11cf2009-11-17 10:20:22 +0000180 LLIArgs.push_back("-load");
Zachary Turner0dcc1152018-06-12 17:43:52 +0000181 LLIArgs.push_back(*i);
Duncan Sands3ea11cf2009-11-17 10:20:22 +0000182 }
183
Brian Gaeked11577b2004-05-04 21:09:01 +0000184 // Add any extra LLI args.
185 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000186 LLIArgs.push_back(ToolArgs[i]);
Brian Gaeked11577b2004-05-04 21:09:01 +0000187
Zachary Turner0dcc1152018-06-12 17:43:52 +0000188 LLIArgs.push_back(Bitcode);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000189 // Add optional parameters to the running program from Argv
Justin Bogner388e8b92016-09-02 01:21:37 +0000190 for (unsigned i = 0, e = Args.size(); i != e; ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000191 LLIArgs.push_back(Args[i]);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000192
Justin Bogner388e8b92016-09-02 01:21:37 +0000193 outs() << "<lli>";
194 outs().flush();
Nicola Zaghen0818e782018-05-14 12:53:11 +0000195 LLVM_DEBUG(errs() << "\nAbout to run:\t";
196 for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs()
197 << " " << LLIArgs[i];
198 errs() << "\n";);
Zachary Turner0dcc1152018-06-12 17:43:52 +0000199 return RunProgramWithTimeout(LLIPath, LLIArgs, InputFile, OutputFile,
Justin Bognerd8090ae2016-09-06 17:18:22 +0000200 OutputFile, Timeout, MemoryLimit);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000201}
202
Justin Bogner388e8b92016-09-02 01:21:37 +0000203void AbstractInterpreter::anchor() {}
David Blaikie2d24e2a2011-12-20 02:50:00 +0000204
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000205ErrorOr<std::string> llvm::FindProgramByName(const std::string &ExeName,
Rafael Espindola21a78d12013-06-18 16:47:55 +0000206 const char *Argv0,
207 void *MainAddr) {
Rafael Espindolac65aba02013-06-14 15:12:13 +0000208 // Check the directory that the calling program is in. We can do
209 // this if ProgramPath contains at least one / character, indicating that it
210 // is a relative path to the executable itself.
Rafael Espindola50188c12013-06-26 05:01:35 +0000211 std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr);
212 StringRef Result = sys::path::parent_path(Main);
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000213 if (ErrorOr<std::string> Path = sys::findProgramByName(ExeName, Result))
214 return *Path;
Rafael Espindolac65aba02013-06-14 15:12:13 +0000215
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000216 // Check the user PATH.
217 return sys::findProgramByName(ExeName);
Rafael Espindolac65aba02013-06-14 15:12:13 +0000218}
219
Misha Brukman9558c6a2003-09-29 22:39:25 +0000220// LLI create method - Try to find the LLI executable
Justin Bogner388e8b92016-09-02 01:21:37 +0000221AbstractInterpreter *
222AbstractInterpreter::createLLI(const char *Argv0, std::string &Message,
223 const std::vector<std::string> *ToolArgs) {
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000224 if (ErrorOr<std::string> LLIPath =
225 FindProgramByName("lli", Argv0, (void *)(intptr_t)&createLLI)) {
226 Message = "Found lli: " + *LLIPath + "\n";
227 return new LLI(*LLIPath, ToolArgs);
228 } else {
229 Message = LLIPath.getError().message() + "\n";
230 return nullptr;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000231 }
Misha Brukman9558c6a2003-09-29 22:39:25 +0000232}
233
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000234//===---------------------------------------------------------------------===//
Andrew Trickf73311b2011-02-08 18:20:48 +0000235// Custom compiler command implementation of AbstractIntepreter interface
236//
237// Allows using a custom command for compiling the bitcode, thus allows, for
238// example, to compile a bitcode fragment without linking or executing, then
239// using a custom wrapper script to check for compiler errors.
240namespace {
Justin Bogner388e8b92016-09-02 01:21:37 +0000241class CustomCompiler : public AbstractInterpreter {
242 std::string CompilerCommand;
243 std::vector<std::string> CompilerArgs;
Andrew Trickf73311b2011-02-08 18:20:48 +0000244
Justin Bogner388e8b92016-09-02 01:21:37 +0000245public:
246 CustomCompiler(const std::string &CompilerCmd,
247 std::vector<std::string> CompArgs)
248 : CompilerCommand(CompilerCmd), CompilerArgs(std::move(CompArgs)) {}
Andrew Trickf73311b2011-02-08 18:20:48 +0000249
Justin Bognerd8090ae2016-09-06 17:18:22 +0000250 Error compileProgram(const std::string &Bitcode, unsigned Timeout = 0,
251 unsigned MemoryLimit = 0) override;
Justin Bogner388e8b92016-09-02 01:21:37 +0000252
Justin Bognerd8090ae2016-09-06 17:18:22 +0000253 Expected<int> ExecuteProgram(
Justin Bogner388e8b92016-09-02 01:21:37 +0000254 const std::string &Bitcode, const std::vector<std::string> &Args,
255 const std::string &InputFile, const std::string &OutputFile,
Justin Bogner388e8b92016-09-02 01:21:37 +0000256 const std::vector<std::string> &CCArgs = std::vector<std::string>(),
257 const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
258 unsigned Timeout = 0, unsigned MemoryLimit = 0) override {
Justin Bognerd8090ae2016-09-06 17:18:22 +0000259 return make_error<StringError>(
260 "Execution not supported with -compile-custom",
261 inconvertibleErrorCode());
Justin Bogner388e8b92016-09-02 01:21:37 +0000262 }
263};
Andrew Trickf73311b2011-02-08 18:20:48 +0000264}
265
Justin Bognerd8090ae2016-09-06 17:18:22 +0000266Error CustomCompiler::compileProgram(const std::string &Bitcode,
267 unsigned Timeout, unsigned MemoryLimit) {
Andrew Trickf73311b2011-02-08 18:20:48 +0000268
Zachary Turner0dcc1152018-06-12 17:43:52 +0000269 std::vector<StringRef> ProgramArgs;
Andrew Trickf73311b2011-02-08 18:20:48 +0000270 ProgramArgs.push_back(CompilerCommand.c_str());
271
272 for (std::size_t i = 0; i < CompilerArgs.size(); ++i)
273 ProgramArgs.push_back(CompilerArgs.at(i).c_str());
Zachary Turner0dcc1152018-06-12 17:43:52 +0000274 ProgramArgs.push_back(Bitcode);
Andrew Trickf73311b2011-02-08 18:20:48 +0000275
276 // Add optional parameters to the running program from Argv
277 for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i)
278 ProgramArgs.push_back(CompilerArgs[i].c_str());
279
Zachary Turner0dcc1152018-06-12 17:43:52 +0000280 if (RunProgramWithTimeout(CompilerCommand, ProgramArgs, "", "", "", Timeout,
281 MemoryLimit))
282 return ProcessFailure(CompilerCommand, ProgramArgs, Timeout, MemoryLimit);
Justin Bognerd8090ae2016-09-06 17:18:22 +0000283 return Error::success();
Andrew Trickf73311b2011-02-08 18:20:48 +0000284}
285
286//===---------------------------------------------------------------------===//
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000287// Custom execution command implementation of AbstractIntepreter interface
288//
289// Allows using a custom command for executing the bitcode, thus allows,
Mikhail Glushenkov544fba12010-11-03 16:14:07 +0000290// for example, to invoke a cross compiler for code generation followed by
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000291// a simulator that executes the generated binary.
292namespace {
Justin Bogner388e8b92016-09-02 01:21:37 +0000293class CustomExecutor : public AbstractInterpreter {
294 std::string ExecutionCommand;
295 std::vector<std::string> ExecutorArgs;
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000296
Justin Bogner388e8b92016-09-02 01:21:37 +0000297public:
298 CustomExecutor(const std::string &ExecutionCmd,
299 std::vector<std::string> ExecArgs)
300 : ExecutionCommand(ExecutionCmd), ExecutorArgs(std::move(ExecArgs)) {}
301
Justin Bognerd8090ae2016-09-06 17:18:22 +0000302 Expected<int> ExecuteProgram(
Justin Bogner388e8b92016-09-02 01:21:37 +0000303 const std::string &Bitcode, const std::vector<std::string> &Args,
304 const std::string &InputFile, const std::string &OutputFile,
Justin Bognerd8090ae2016-09-06 17:18:22 +0000305 const std::vector<std::string> &CCArgs,
Justin Bogner388e8b92016-09-02 01:21:37 +0000306 const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
307 unsigned Timeout = 0, unsigned MemoryLimit = 0) override;
308};
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000309}
310
Justin Bognerd8090ae2016-09-06 17:18:22 +0000311Expected<int> CustomExecutor::ExecuteProgram(
312 const std::string &Bitcode, const std::vector<std::string> &Args,
313 const std::string &InputFile, const std::string &OutputFile,
314 const std::vector<std::string> &CCArgs,
315 const std::vector<std::string> &SharedLibs, unsigned Timeout,
316 unsigned MemoryLimit) {
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000317
Zachary Turner0dcc1152018-06-12 17:43:52 +0000318 std::vector<StringRef> ProgramArgs;
319 ProgramArgs.push_back(ExecutionCommand);
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000320
321 for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000322 ProgramArgs.push_back(ExecutorArgs[i]);
323 ProgramArgs.push_back(Bitcode);
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000324
325 // Add optional parameters to the running program from Argv
Nick Lewycky22ff7482010-04-12 05:08:25 +0000326 for (unsigned i = 0, e = Args.size(); i != e; ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000327 ProgramArgs.push_back(Args[i]);
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000328
Zachary Turner0dcc1152018-06-12 17:43:52 +0000329 return RunProgramWithTimeout(ExecutionCommand, ProgramArgs, InputFile,
Justin Bognerd8090ae2016-09-06 17:18:22 +0000330 OutputFile, OutputFile, Timeout, MemoryLimit);
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000331}
332
Andrew Trickf73311b2011-02-08 18:20:48 +0000333// Tokenize the CommandLine to the command and the args to allow
334// defining a full command line as the command instead of just the
335// executed program. We cannot just pass the whole string after the command
David Bozier05f3b732017-03-02 16:50:48 +0000336// as a single argument because then the program sees only a single
Andrew Trickf73311b2011-02-08 18:20:48 +0000337// command line argument (with spaces in it: "foo bar" instead
338// of "foo" and "bar").
339//
David Bozier05f3b732017-03-02 16:50:48 +0000340// Spaces are used as a delimiter; however repeated, leading, and trailing
341// whitespace are ignored. Simple escaping is allowed via the '\'
342// character, as seen below:
343//
344// Two consecutive '\' evaluate to a single '\'.
345// A space after a '\' evaluates to a space that is not interpreted as a
346// delimiter.
347// Any other instances of the '\' character are removed.
348//
349// Example:
350// '\\' -> '\'
351// '\ ' -> ' '
352// 'exa\mple' -> 'example'
353//
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000354static void lexCommand(const char *Argv0, std::string &Message,
355 const std::string &CommandLine, std::string &CmdPath,
356 std::vector<std::string> &Args) {
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000357
David Bozier05f3b732017-03-02 16:50:48 +0000358 std::string Token;
359 std::string Command;
360 bool FoundPath = false;
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000361
David Bozier05f3b732017-03-02 16:50:48 +0000362 // first argument is the PATH.
363 // Skip repeated whitespace, leading whitespace and trailing whitespace.
364 for (std::size_t Pos = 0u; Pos <= CommandLine.size(); ++Pos) {
365 if ('\\' == CommandLine[Pos]) {
366 if (Pos + 1 < CommandLine.size())
367 Token.push_back(CommandLine[++Pos]);
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000368
David Bozier05f3b732017-03-02 16:50:48 +0000369 continue;
370 }
371 if (' ' == CommandLine[Pos] || CommandLine.size() == Pos) {
372 if (Token.empty())
373 continue;
374
375 if (!FoundPath) {
376 Command = Token;
377 FoundPath = true;
378 Token.clear();
379 continue;
380 }
381
382 Args.push_back(Token);
383 Token.clear();
384 continue;
385 }
386 Token.push_back(CommandLine[Pos]);
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000387 }
388
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000389 auto Path = FindProgramByName(Command, Argv0, (void *)(intptr_t)&lexCommand);
Michael J. Spencer58206dd2014-11-04 01:29:59 +0000390 if (!Path) {
David Bozier05f3b732017-03-02 16:50:48 +0000391 Message = std::string("Cannot find '") + Command +
392 "' in PATH: " + Path.getError().message() + "\n";
Andrew Trickf73311b2011-02-08 18:20:48 +0000393 return;
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000394 }
Michael J. Spencer58206dd2014-11-04 01:29:59 +0000395 CmdPath = *Path;
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000396
397 Message = "Found command in: " + CmdPath + "\n";
Andrew Trickf73311b2011-02-08 18:20:48 +0000398}
399
400// Custom execution environment create method, takes the execution command
401// as arguments
402AbstractInterpreter *AbstractInterpreter::createCustomCompiler(
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000403 const char *Argv0, std::string &Message,
404 const std::string &CompileCommandLine) {
Andrew Trickf73311b2011-02-08 18:20:48 +0000405
406 std::string CmdPath;
407 std::vector<std::string> Args;
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000408 lexCommand(Argv0, Message, CompileCommandLine, CmdPath, Args);
Andrew Trickf73311b2011-02-08 18:20:48 +0000409 if (CmdPath.empty())
Craig Topper573faec2014-04-25 04:24:47 +0000410 return nullptr;
Andrew Trickf73311b2011-02-08 18:20:48 +0000411
412 return new CustomCompiler(CmdPath, Args);
413}
414
415// Custom execution environment create method, takes the execution command
416// as arguments
Justin Bogner388e8b92016-09-02 01:21:37 +0000417AbstractInterpreter *
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000418AbstractInterpreter::createCustomExecutor(const char *Argv0,
419 std::string &Message,
Justin Bogner388e8b92016-09-02 01:21:37 +0000420 const std::string &ExecCommandLine) {
Andrew Trickf73311b2011-02-08 18:20:48 +0000421
422 std::string CmdPath;
423 std::vector<std::string> Args;
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000424 lexCommand(Argv0, Message, ExecCommandLine, CmdPath, Args);
Andrew Trickf73311b2011-02-08 18:20:48 +0000425 if (CmdPath.empty())
Craig Topper573faec2014-04-25 04:24:47 +0000426 return nullptr;
Anton Korobeynikov9ef74252008-04-28 20:53:48 +0000427
428 return new CustomExecutor(CmdPath, Args);
429}
430
Misha Brukman9558c6a2003-09-29 22:39:25 +0000431//===----------------------------------------------------------------------===//
432// LLC Implementation of AbstractIntepreter interface
433//
Justin Bognerd8090ae2016-09-06 17:18:22 +0000434Expected<CC::FileType> LLC::OutputCode(const std::string &Bitcode,
435 std::string &OutputAsmFile,
436 unsigned Timeout, unsigned MemoryLimit) {
Chris Lattner50010422010-03-16 06:41:47 +0000437 const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s");
Rafael Espindola3991c722013-06-18 17:20:08 +0000438
439 SmallString<128> UniqueFile;
Rafael Espindola1ad45022014-06-13 03:07:50 +0000440 std::error_code EC =
Rafael Espindola200c7482013-07-05 21:01:08 +0000441 sys::fs::createUniqueFile(Bitcode + "-%%%%%%%" + Suffix, UniqueFile);
Rafael Espindola3991c722013-06-18 17:20:08 +0000442 if (EC) {
443 errs() << "Error making unique filename: " << EC.message() << "\n";
Reid Spencer51c5a282006-08-23 20:34:57 +0000444 exit(1);
445 }
Rafael Espindola3991c722013-06-18 17:20:08 +0000446 OutputAsmFile = UniqueFile.str();
Zachary Turner0dcc1152018-06-12 17:43:52 +0000447 std::vector<StringRef> LLCArgs;
448 LLCArgs.push_back(LLCPath);
Brian Gaeked11577b2004-05-04 21:09:01 +0000449
450 // Add any extra LLC args.
451 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000452 LLCArgs.push_back(ToolArgs[i]);
Brian Gaeked11577b2004-05-04 21:09:01 +0000453
Chris Lattner50010422010-03-16 06:41:47 +0000454 LLCArgs.push_back("-o");
Zachary Turner0dcc1152018-06-12 17:43:52 +0000455 LLCArgs.push_back(OutputAsmFile); // Output to the Asm file
456 LLCArgs.push_back(Bitcode); // This is the input bitcode
Mikhail Glushenkov544fba12010-11-03 16:14:07 +0000457
Chris Lattner50010422010-03-16 06:41:47 +0000458 if (UseIntegratedAssembler)
459 LLCArgs.push_back("-filetype=obj");
Mikhail Glushenkov544fba12010-11-03 16:14:07 +0000460
Chris Lattner50010422010-03-16 06:41:47 +0000461 outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>");
462 outs().flush();
Nicola Zaghen0818e782018-05-14 12:53:11 +0000463 LLVM_DEBUG(errs() << "\nAbout to run:\t";
464 for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs()
465 << " " << LLCArgs[i];
466 errs() << "\n";);
Zachary Turner0dcc1152018-06-12 17:43:52 +0000467 if (RunProgramWithTimeout(LLCPath, LLCArgs, "", "", "", Timeout, MemoryLimit))
468 return ProcessFailure(LLCPath, LLCArgs, Timeout, MemoryLimit);
Davide Italianof7b2acb2015-10-14 20:29:54 +0000469 return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000470}
471
Justin Bognerd8090ae2016-09-06 17:18:22 +0000472Error LLC::compileProgram(const std::string &Bitcode, unsigned Timeout,
473 unsigned MemoryLimit) {
Rafael Espindolaf656a1d2013-06-17 19:21:38 +0000474 std::string OutputAsmFile;
Justin Bognerd8090ae2016-09-06 17:18:22 +0000475 Expected<CC::FileType> Result =
476 OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit);
Rafael Espindolaf656a1d2013-06-17 19:21:38 +0000477 sys::fs::remove(OutputAsmFile);
Justin Bognerd8090ae2016-09-06 17:18:22 +0000478 if (Error E = Result.takeError())
479 return E;
480 return Error::success();
Chris Lattner9cbbee32004-02-18 23:24:41 +0000481}
482
Justin Bognerd8090ae2016-09-06 17:18:22 +0000483Expected<int> LLC::ExecuteProgram(const std::string &Bitcode,
484 const std::vector<std::string> &Args,
485 const std::string &InputFile,
486 const std::string &OutputFile,
487 const std::vector<std::string> &ArgsForCC,
488 const std::vector<std::string> &SharedLibs,
489 unsigned Timeout, unsigned MemoryLimit) {
Chris Lattnereeed9832003-10-14 21:52:52 +0000490
Rafael Espindolaf656a1d2013-06-17 19:21:38 +0000491 std::string OutputAsmFile;
Justin Bognerd8090ae2016-09-06 17:18:22 +0000492 Expected<CC::FileType> FileKind =
493 OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit);
Rafael Espindolaf656a1d2013-06-17 19:21:38 +0000494 FileRemover OutFileRemover(OutputAsmFile, !SaveTemps);
Justin Bognerd8090ae2016-09-06 17:18:22 +0000495 if (Error E = FileKind.takeError())
496 return std::move(E);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000497
Davide Italianof7b2acb2015-10-14 20:29:54 +0000498 std::vector<std::string> CCArgs(ArgsForCC);
499 CCArgs.insert(CCArgs.end(), SharedLibs.begin(), SharedLibs.end());
Reid Spencer51ab5c82006-06-06 00:00:42 +0000500
Davide Italianof7b2acb2015-10-14 20:29:54 +0000501 // Assuming LLC worked, compile the result with CC and run it.
Justin Bognerd8090ae2016-09-06 17:18:22 +0000502 return cc->ExecuteProgram(OutputAsmFile, Args, *FileKind, InputFile,
503 OutputFile, CCArgs, Timeout, MemoryLimit);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000504}
505
Chris Lattner7915a1e2003-10-14 21:34:11 +0000506/// createLLC - Try to find the LLC executable
Misha Brukman9558c6a2003-09-29 22:39:25 +0000507///
Justin Bogner388e8b92016-09-02 01:21:37 +0000508LLC *AbstractInterpreter::createLLC(const char *Argv0, std::string &Message,
Davide Italianof7b2acb2015-10-14 20:29:54 +0000509 const std::string &CCBinary,
Bill Wendling38efa382009-03-02 23:13:18 +0000510 const std::vector<std::string> *Args,
Davide Italianof7b2acb2015-10-14 20:29:54 +0000511 const std::vector<std::string> *CCArgs,
Chris Lattner50010422010-03-16 06:41:47 +0000512 bool UseIntegratedAssembler) {
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000513 ErrorOr<std::string> LLCPath =
514 FindProgramByName("llc", Argv0, (void *)(intptr_t)&createLLC);
515 if (!LLCPath) {
516 Message = LLCPath.getError().message() + "\n";
Craig Topper573faec2014-04-25 04:24:47 +0000517 return nullptr;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000518 }
519
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000520 CC *cc = CC::create(Argv0, Message, CCBinary, CCArgs);
Davide Italianof7b2acb2015-10-14 20:29:54 +0000521 if (!cc) {
Dan Gohman65f57c22009-07-15 16:35:29 +0000522 errs() << Message << "\n";
Misha Brukman9558c6a2003-09-29 22:39:25 +0000523 exit(1);
524 }
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000525 Message = "Found llc: " + *LLCPath + "\n";
526 return new LLC(*LLCPath, cc, Args, UseIntegratedAssembler);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000527}
528
529//===---------------------------------------------------------------------===//
530// JIT Implementation of AbstractIntepreter interface
531//
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000532namespace {
Justin Bogner388e8b92016-09-02 01:21:37 +0000533class JIT : public AbstractInterpreter {
534 std::string LLIPath; // The path to the LLI executable
535 std::vector<std::string> ToolArgs; // Args to pass to LLI
536public:
537 JIT(const std::string &Path, const std::vector<std::string> *Args)
Brian Gaeked11577b2004-05-04 21:09:01 +0000538 : LLIPath(Path) {
Justin Bogner388e8b92016-09-02 01:21:37 +0000539 ToolArgs.clear();
540 if (Args) {
541 ToolArgs = *Args;
Brian Gaeked11577b2004-05-04 21:09:01 +0000542 }
Justin Bogner388e8b92016-09-02 01:21:37 +0000543 }
Misha Brukmanf976c852005-04-21 22:55:34 +0000544
Justin Bognerd8090ae2016-09-06 17:18:22 +0000545 Expected<int> ExecuteProgram(
Justin Bogner388e8b92016-09-02 01:21:37 +0000546 const std::string &Bitcode, const std::vector<std::string> &Args,
547 const std::string &InputFile, const std::string &OutputFile,
Justin Bogner388e8b92016-09-02 01:21:37 +0000548 const std::vector<std::string> &CCArgs = std::vector<std::string>(),
549 const std::vector<std::string> &SharedLibs = std::vector<std::string>(),
550 unsigned Timeout = 0, unsigned MemoryLimit = 0) override;
551};
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000552}
Misha Brukman9558c6a2003-09-29 22:39:25 +0000553
Justin Bognerd8090ae2016-09-06 17:18:22 +0000554Expected<int> JIT::ExecuteProgram(const std::string &Bitcode,
555 const std::vector<std::string> &Args,
556 const std::string &InputFile,
557 const std::string &OutputFile,
558 const std::vector<std::string> &CCArgs,
559 const std::vector<std::string> &SharedLibs,
560 unsigned Timeout, unsigned MemoryLimit) {
Misha Brukman9558c6a2003-09-29 22:39:25 +0000561 // Construct a vector of parameters, incorporating those from the command-line
Zachary Turner0dcc1152018-06-12 17:43:52 +0000562 std::vector<StringRef> JITArgs;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000563 JITArgs.push_back(LLIPath.c_str());
Misha Brukman9558c6a2003-09-29 22:39:25 +0000564 JITArgs.push_back("-force-interpreter=false");
Chris Lattnereeed9832003-10-14 21:52:52 +0000565
Brian Gaeked11577b2004-05-04 21:09:01 +0000566 // Add any extra LLI args.
567 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000568 JITArgs.push_back(ToolArgs[i]);
Brian Gaeked11577b2004-05-04 21:09:01 +0000569
Chris Lattnereeed9832003-10-14 21:52:52 +0000570 for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
Misha Brukman9558c6a2003-09-29 22:39:25 +0000571 JITArgs.push_back("-load");
Zachary Turner0dcc1152018-06-12 17:43:52 +0000572 JITArgs.push_back(SharedLibs[i]);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000573 }
Gabor Greif8ff70c22007-07-04 21:55:50 +0000574 JITArgs.push_back(Bitcode.c_str());
Misha Brukman9558c6a2003-09-29 22:39:25 +0000575 // Add optional parameters to the running program from Argv
Justin Bogner388e8b92016-09-02 01:21:37 +0000576 for (unsigned i = 0, e = Args.size(); i != e; ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000577 JITArgs.push_back(Args[i]);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000578
Justin Bogner388e8b92016-09-02 01:21:37 +0000579 outs() << "<jit>";
580 outs().flush();
Nicola Zaghen0818e782018-05-14 12:53:11 +0000581 LLVM_DEBUG(errs() << "\nAbout to run:\t";
582 for (unsigned i = 0, e = JITArgs.size() - 1; i != e; ++i) errs()
583 << " " << JITArgs[i];
584 errs() << "\n";);
585 LLVM_DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
Zachary Turner0dcc1152018-06-12 17:43:52 +0000586 return RunProgramWithTimeout(LLIPath, JITArgs, InputFile, OutputFile,
Justin Bognerd8090ae2016-09-06 17:18:22 +0000587 OutputFile, Timeout, MemoryLimit);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000588}
589
Chris Lattner7915a1e2003-10-14 21:34:11 +0000590/// createJIT - Try to find the LLI executable
Misha Brukman9558c6a2003-09-29 22:39:25 +0000591///
Justin Bogner388e8b92016-09-02 01:21:37 +0000592AbstractInterpreter *
593AbstractInterpreter::createJIT(const char *Argv0, std::string &Message,
594 const std::vector<std::string> *Args) {
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000595 if (ErrorOr<std::string> LLIPath =
596 FindProgramByName("lli", Argv0, (void *)(intptr_t)&createJIT)) {
597 Message = "Found lli: " + *LLIPath + "\n";
598 return new JIT(*LLIPath, Args);
599 } else {
600 Message = LLIPath.getError().message() + "\n";
601 return nullptr;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000602 }
Misha Brukman9558c6a2003-09-29 22:39:25 +0000603}
604
Misha Brukman9558c6a2003-09-29 22:39:25 +0000605//===---------------------------------------------------------------------===//
Davide Italianof7b2acb2015-10-14 20:29:54 +0000606// CC abstraction
Misha Brukman9558c6a2003-09-29 22:39:25 +0000607//
David Goodwin80becf12009-07-10 21:39:28 +0000608
Zachary Turner0dcc1152018-06-12 17:43:52 +0000609static bool IsARMArchitecture(std::vector<StringRef> Args) {
610 for (size_t I = 0; I < Args.size(); ++I) {
611 if (!Args[I].equals_lower("-arch"))
612 continue;
613 ++I;
614 if (I == Args.size())
615 break;
616 if (Args[I].startswith_lower("arm"))
617 return true;
David Goodwin80becf12009-07-10 21:39:28 +0000618 }
619
620 return false;
621}
622
Justin Bognerd8090ae2016-09-06 17:18:22 +0000623Expected<int> CC::ExecuteProgram(const std::string &ProgramFile,
624 const std::vector<std::string> &Args,
625 FileType fileType,
626 const std::string &InputFile,
627 const std::string &OutputFile,
628 const std::vector<std::string> &ArgsForCC,
629 unsigned Timeout, unsigned MemoryLimit) {
Zachary Turner0dcc1152018-06-12 17:43:52 +0000630 std::vector<StringRef> CCArgs;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000631
Zachary Turner0dcc1152018-06-12 17:43:52 +0000632 CCArgs.push_back(CCPath);
Chris Lattnereeed9832003-10-14 21:52:52 +0000633
Chris Lattner50010422010-03-16 06:41:47 +0000634 if (TargetTriple.getArch() == Triple::x86)
Davide Italianof7b2acb2015-10-14 20:29:54 +0000635 CCArgs.push_back("-m32");
Chris Lattner50010422010-03-16 06:41:47 +0000636
Justin Bogner388e8b92016-09-02 01:21:37 +0000637 for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
638 E = ccArgs.end();
639 I != E; ++I)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000640 CCArgs.push_back(*I);
Bill Wendling38efa382009-03-02 23:13:18 +0000641
Chris Lattnereeed9832003-10-14 21:52:52 +0000642 // Specify -x explicitly in case the extension is wonky
Chris Lattner50010422010-03-16 06:41:47 +0000643 if (fileType != ObjectFile) {
Davide Italianof7b2acb2015-10-14 20:29:54 +0000644 CCArgs.push_back("-x");
Chris Lattner50010422010-03-16 06:41:47 +0000645 if (fileType == CFile) {
Davide Italianof7b2acb2015-10-14 20:29:54 +0000646 CCArgs.push_back("c");
647 CCArgs.push_back("-fno-strict-aliasing");
Chris Lattner50010422010-03-16 06:41:47 +0000648 } else {
Davide Italianof7b2acb2015-10-14 20:29:54 +0000649 CCArgs.push_back("assembler");
Daniel Dunbarca740962009-08-18 03:35:57 +0000650
Chris Lattner50010422010-03-16 06:41:47 +0000651 // For ARM architectures we don't want this flag. bugpoint isn't
652 // explicitly told what architecture it is working on, so we get
Davide Italianof7b2acb2015-10-14 20:29:54 +0000653 // it from cc flags
654 if (TargetTriple.isOSDarwin() && !IsARMArchitecture(CCArgs))
655 CCArgs.push_back("-force_cpusubtype_ALL");
Chris Lattner50010422010-03-16 06:41:47 +0000656 }
Misha Brukman9558c6a2003-09-29 22:39:25 +0000657 }
Mikhail Glushenkov544fba12010-11-03 16:14:07 +0000658
Zachary Turner0dcc1152018-06-12 17:43:52 +0000659 CCArgs.push_back(ProgramFile); // Specify the input filename.
Mikhail Glushenkov544fba12010-11-03 16:14:07 +0000660
Davide Italianof7b2acb2015-10-14 20:29:54 +0000661 CCArgs.push_back("-x");
662 CCArgs.push_back("none");
663 CCArgs.push_back("-o");
Rafael Espindola3991c722013-06-18 17:20:08 +0000664
665 SmallString<128> OutputBinary;
Rafael Espindola1ad45022014-06-13 03:07:50 +0000666 std::error_code EC =
Davide Italianof7b2acb2015-10-14 20:29:54 +0000667 sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.cc.exe", OutputBinary);
Rafael Espindola3991c722013-06-18 17:20:08 +0000668 if (EC) {
669 errs() << "Error making unique filename: " << EC.message() << "\n";
Reid Spencer51c5a282006-08-23 20:34:57 +0000670 exit(1);
671 }
Zachary Turner0dcc1152018-06-12 17:43:52 +0000672 CCArgs.push_back(OutputBinary); // Output to the right file...
Reid Spencer51ab5c82006-06-06 00:00:42 +0000673
Davide Italianof7b2acb2015-10-14 20:29:54 +0000674 // Add any arguments intended for CC. We locate them here because this is
Reid Spencer51ab5c82006-06-06 00:00:42 +0000675 // most likely -L and -l options that need to come before other libraries but
676 // after the source. Other options won't be sensitive to placement on the
677 // command line, so this should be safe.
Davide Italianof7b2acb2015-10-14 20:29:54 +0000678 for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000679 CCArgs.push_back(ArgsForCC[i]);
Reid Spencer51ab5c82006-06-06 00:00:42 +0000680
Justin Bogner388e8b92016-09-02 01:21:37 +0000681 CCArgs.push_back("-lm"); // Hard-code the math library...
682 CCArgs.push_back("-O2"); // Optimize the program a bit...
Daniel Dunbarca740962009-08-18 03:35:57 +0000683 if (TargetTriple.getArch() == Triple::sparc)
Davide Italianof7b2acb2015-10-14 20:29:54 +0000684 CCArgs.push_back("-mcpu=v9");
Misha Brukman9558c6a2003-09-29 22:39:25 +0000685
Justin Bogner388e8b92016-09-02 01:21:37 +0000686 outs() << "<CC>";
687 outs().flush();
Nicola Zaghen0818e782018-05-14 12:53:11 +0000688 LLVM_DEBUG(errs() << "\nAbout to run:\t";
689 for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
690 << " " << CCArgs[i];
691 errs() << "\n";);
Zachary Turner0dcc1152018-06-12 17:43:52 +0000692 if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
693 return ProcessFailure(CCPath, CCArgs);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000694
Zachary Turner0dcc1152018-06-12 17:43:52 +0000695 std::vector<StringRef> ProgramArgs;
Rafael Espindola97595eb2010-07-24 23:02:11 +0000696
697 // Declared here so that the destructor only runs after
698 // ProgramArgs is used.
699 std::string Exec;
Chris Lattner45495c52005-02-13 23:13:47 +0000700
Rafael Espindola13f17ea2013-06-13 16:22:26 +0000701 if (RemoteClientPath.empty())
Zachary Turner0dcc1152018-06-12 17:43:52 +0000702 ProgramArgs.push_back(OutputBinary);
Evan Cheng34e400e2007-05-03 18:36:15 +0000703 else {
Zachary Turner0dcc1152018-06-12 17:43:52 +0000704 ProgramArgs.push_back(RemoteClientPath);
705 ProgramArgs.push_back(RemoteHost);
Anton Korobeynikov26964b62009-08-05 09:32:53 +0000706 if (!RemoteUser.empty()) {
707 ProgramArgs.push_back("-l");
Zachary Turner0dcc1152018-06-12 17:43:52 +0000708 ProgramArgs.push_back(RemoteUser);
Anton Korobeynikov26964b62009-08-05 09:32:53 +0000709 }
David Goodwin80becf12009-07-10 21:39:28 +0000710 if (!RemotePort.empty()) {
711 ProgramArgs.push_back("-p");
Zachary Turner0dcc1152018-06-12 17:43:52 +0000712 ProgramArgs.push_back(RemotePort);
David Goodwin80becf12009-07-10 21:39:28 +0000713 }
Evan Cheng70f684f2008-09-09 06:11:26 +0000714 if (!RemoteExtra.empty()) {
Zachary Turner0dcc1152018-06-12 17:43:52 +0000715 ProgramArgs.push_back(RemoteExtra);
Evan Cheng70f684f2008-09-09 06:11:26 +0000716 }
Evan Cheng34e400e2007-05-03 18:36:15 +0000717
David Goodwin91cf3612009-07-20 17:15:03 +0000718 // Full path to the binary. We need to cd to the exec directory because
719 // there is a dylib there that the exec expects to find in the CWD
Justin Bogner388e8b92016-09-02 01:21:37 +0000720 char *env_pwd = getenv("PWD");
Rafael Espindola97595eb2010-07-24 23:02:11 +0000721 Exec = "cd ";
Evan Cheng34e400e2007-05-03 18:36:15 +0000722 Exec += env_pwd;
David Goodwin91cf3612009-07-20 17:15:03 +0000723 Exec += "; ./";
Evan Cheng34e400e2007-05-03 18:36:15 +0000724 Exec += OutputBinary.c_str();
Zachary Turner0dcc1152018-06-12 17:43:52 +0000725 ProgramArgs.push_back(Exec);
Evan Cheng34e400e2007-05-03 18:36:15 +0000726 }
727
Misha Brukman9558c6a2003-09-29 22:39:25 +0000728 // Add optional parameters to the running program from Argv
Nick Lewycky22ff7482010-04-12 05:08:25 +0000729 for (unsigned i = 0, e = Args.size(); i != e; ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000730 ProgramArgs.push_back(Args[i]);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000731
732 // Now that we have a binary, run it!
Justin Bogner388e8b92016-09-02 01:21:37 +0000733 outs() << "<program>";
734 outs().flush();
Nicola Zaghen0818e782018-05-14 12:53:11 +0000735 LLVM_DEBUG(
736 errs() << "\nAbout to run:\t";
737 for (unsigned i = 0, e = ProgramArgs.size() - 1; i != e; ++i) errs()
738 << " " << ProgramArgs[i];
739 errs() << "\n";);
Chris Lattner8c56be52004-02-18 20:21:57 +0000740
Michael J. Spencerc9c08fb2011-03-31 13:04:19 +0000741 FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps);
Evan Cheng34e400e2007-05-03 18:36:15 +0000742
Rafael Espindola13f17ea2013-06-13 16:22:26 +0000743 if (RemoteClientPath.empty()) {
Nicola Zaghen0818e782018-05-14 12:53:11 +0000744 LLVM_DEBUG(errs() << "<run locally>");
Justin Bognerd8090ae2016-09-06 17:18:22 +0000745 std::string Error;
Zachary Turner0dcc1152018-06-12 17:43:52 +0000746 int ExitCode = RunProgramWithTimeout(OutputBinary.str(), ProgramArgs,
Rafael Espindolaa4b504a2013-06-13 15:47:11 +0000747 InputFile, OutputFile, OutputFile,
Justin Bognerd8090ae2016-09-06 17:18:22 +0000748 Timeout, MemoryLimit, &Error);
Andrew Trickdc5948d2011-05-21 00:56:46 +0000749 // Treat a signal (usually SIGSEGV) or timeout as part of the program output
750 // so that crash-causing miscompilation is handled seamlessly.
751 if (ExitCode < -1) {
Andrew Trick7c863eb2011-05-11 16:31:24 +0000752 std::ofstream outFile(OutputFile.c_str(), std::ios_base::app);
Justin Bognerd8090ae2016-09-06 17:18:22 +0000753 outFile << Error << '\n';
Andrew Trick7c863eb2011-05-11 16:31:24 +0000754 outFile.close();
Andrew Trick7c863eb2011-05-11 16:31:24 +0000755 }
756 return ExitCode;
Viktor Kutuzov699220b2009-07-14 19:10:55 +0000757 } else {
Justin Bogner388e8b92016-09-02 01:21:37 +0000758 outs() << "<run remotely>";
759 outs().flush();
Zachary Turner0dcc1152018-06-12 17:43:52 +0000760 return RunProgramRemotelyWithTimeout(RemoteClientPath, ProgramArgs,
Justin Bogner388e8b92016-09-02 01:21:37 +0000761 InputFile, OutputFile, OutputFile,
762 Timeout, MemoryLimit);
Viktor Kutuzov699220b2009-07-14 19:10:55 +0000763 }
Misha Brukman9558c6a2003-09-29 22:39:25 +0000764}
765
Justin Bognerd8090ae2016-09-06 17:18:22 +0000766Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType,
767 std::string &OutputFile,
768 const std::vector<std::string> &ArgsForCC) {
Rafael Espindola3991c722013-06-18 17:20:08 +0000769 SmallString<128> UniqueFilename;
Rafael Espindola1ad45022014-06-13 03:07:50 +0000770 std::error_code EC = sys::fs::createUniqueFile(
Rafael Espindola200c7482013-07-05 21:01:08 +0000771 InputFile + "-%%%%%%%" + LTDL_SHLIB_EXT, UniqueFilename);
Rafael Espindola3991c722013-06-18 17:20:08 +0000772 if (EC) {
773 errs() << "Error making unique filename: " << EC.message() << "\n";
Reid Spencer51c5a282006-08-23 20:34:57 +0000774 exit(1);
775 }
Rafael Espindola3991c722013-06-18 17:20:08 +0000776 OutputFile = UniqueFilename.str();
Reid Spencercda985e2004-12-15 01:51:56 +0000777
Zachary Turner0dcc1152018-06-12 17:43:52 +0000778 std::vector<StringRef> CCArgs;
Mikhail Glushenkov544fba12010-11-03 16:14:07 +0000779
Zachary Turner0dcc1152018-06-12 17:43:52 +0000780 CCArgs.push_back(CCPath);
Evan Chengfd829952009-03-12 00:53:34 +0000781
Chris Lattner50010422010-03-16 06:41:47 +0000782 if (TargetTriple.getArch() == Triple::x86)
Davide Italianof7b2acb2015-10-14 20:29:54 +0000783 CCArgs.push_back("-m32");
Chris Lattner50010422010-03-16 06:41:47 +0000784
Justin Bogner388e8b92016-09-02 01:21:37 +0000785 for (std::vector<std::string>::const_iterator I = ccArgs.begin(),
786 E = ccArgs.end();
787 I != E; ++I)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000788 CCArgs.push_back(*I);
Evan Chengfd829952009-03-12 00:53:34 +0000789
Misha Brukman9558c6a2003-09-29 22:39:25 +0000790 // Compile the C/asm file into a shared object
Chris Lattner50010422010-03-16 06:41:47 +0000791 if (fileType != ObjectFile) {
Davide Italianof7b2acb2015-10-14 20:29:54 +0000792 CCArgs.push_back("-x");
793 CCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
Chris Lattner50010422010-03-16 06:41:47 +0000794 }
Davide Italianof7b2acb2015-10-14 20:29:54 +0000795 CCArgs.push_back("-fno-strict-aliasing");
Zachary Turner0dcc1152018-06-12 17:43:52 +0000796 CCArgs.push_back(InputFile); // Specify the input filename.
Davide Italianof7b2acb2015-10-14 20:29:54 +0000797 CCArgs.push_back("-x");
798 CCArgs.push_back("none");
Daniel Dunbarca740962009-08-18 03:35:57 +0000799 if (TargetTriple.getArch() == Triple::sparc)
Justin Bogner388e8b92016-09-02 01:21:37 +0000800 CCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
Daniel Dunbar912225e2011-04-19 21:14:45 +0000801 else if (TargetTriple.isOSDarwin()) {
Daniel Dunbarca740962009-08-18 03:35:57 +0000802 // link all source files into a single module in data segment, rather than
Mikhail Glushenkov544fba12010-11-03 16:14:07 +0000803 // generating blocks. dynamic_lookup requires that you set
Daniel Dunbarca740962009-08-18 03:35:57 +0000804 // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for
Davide Italianof7b2acb2015-10-14 20:29:54 +0000805 // bugpoint to just pass that in the environment of CC.
806 CCArgs.push_back("-single_module");
Justin Bogner388e8b92016-09-02 01:21:37 +0000807 CCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC
Davide Italianof7b2acb2015-10-14 20:29:54 +0000808 CCArgs.push_back("-undefined");
809 CCArgs.push_back("dynamic_lookup");
Daniel Dunbarca740962009-08-18 03:35:57 +0000810 } else
Justin Bogner388e8b92016-09-02 01:21:37 +0000811 CCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others
Chris Lattner1c81f132005-03-09 03:31:02 +0000812
Dan Gohman33ba8b02011-10-27 22:56:32 +0000813 if (TargetTriple.getArch() == Triple::x86_64)
Justin Bogner388e8b92016-09-02 01:21:37 +0000814 CCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
Daniel Dunbarca740962009-08-18 03:35:57 +0000815
816 if (TargetTriple.getArch() == Triple::sparc)
Davide Italianof7b2acb2015-10-14 20:29:54 +0000817 CCArgs.push_back("-mcpu=v9");
Daniel Dunbarca740962009-08-18 03:35:57 +0000818
Davide Italianof7b2acb2015-10-14 20:29:54 +0000819 CCArgs.push_back("-o");
Zachary Turner0dcc1152018-06-12 17:43:52 +0000820 CCArgs.push_back(OutputFile); // Output to the right filename.
Davide Italianof7b2acb2015-10-14 20:29:54 +0000821 CCArgs.push_back("-O2"); // Optimize the program a bit.
Chris Lattner130e2a32006-06-27 20:35:36 +0000822
Davide Italianof7b2acb2015-10-14 20:29:54 +0000823 // Add any arguments intended for CC. We locate them here because this is
Chris Lattner130e2a32006-06-27 20:35:36 +0000824 // most likely -L and -l options that need to come before other libraries but
825 // after the source. Other options won't be sensitive to placement on the
826 // command line, so this should be safe.
Davide Italianof7b2acb2015-10-14 20:29:54 +0000827 for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
Zachary Turner0dcc1152018-06-12 17:43:52 +0000828 CCArgs.push_back(ArgsForCC[i]);
Chris Lattner130e2a32006-06-27 20:35:36 +0000829
Justin Bogner388e8b92016-09-02 01:21:37 +0000830 outs() << "<CC>";
831 outs().flush();
Nicola Zaghen0818e782018-05-14 12:53:11 +0000832 LLVM_DEBUG(errs() << "\nAbout to run:\t";
833 for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
834 << " " << CCArgs[i];
835 errs() << "\n";);
Zachary Turner0dcc1152018-06-12 17:43:52 +0000836 if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
837 return ProcessFailure(CCPath, CCArgs);
Mandeep Singh Granga4998402017-06-28 23:15:16 +0000838 return Error::success();
Misha Brukman9558c6a2003-09-29 22:39:25 +0000839}
840
Davide Italianof7b2acb2015-10-14 20:29:54 +0000841/// create - Try to find the CC executable
Misha Brukman9558c6a2003-09-29 22:39:25 +0000842///
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000843CC *CC::create(const char *Argv0, std::string &Message,
844 const std::string &CCBinary,
Justin Bogner388e8b92016-09-02 01:21:37 +0000845 const std::vector<std::string> *Args) {
Brian Gesiakdcf592e2018-12-10 00:56:13 +0000846 auto CCPath = FindProgramByName(CCBinary, Argv0, (void *)(intptr_t)&create);
Davide Italianof7b2acb2015-10-14 20:29:54 +0000847 if (!CCPath) {
848 Message = "Cannot find `" + CCBinary + "' in PATH: " +
849 CCPath.getError().message() + "\n";
Craig Topper573faec2014-04-25 04:24:47 +0000850 return nullptr;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000851 }
852
Rafael Espindola6585b382013-06-13 19:25:37 +0000853 std::string RemoteClientPath;
Michael J. Spencer58206dd2014-11-04 01:29:59 +0000854 if (!RemoteClient.empty()) {
855 auto Path = sys::findProgramByName(RemoteClient);
856 if (!Path) {
857 Message = "Cannot find `" + RemoteClient + "' in PATH: " +
858 Path.getError().message() + "\n";
859 return nullptr;
860 }
861 RemoteClientPath = *Path;
862 }
Evan Cheng34e400e2007-05-03 18:36:15 +0000863
Davide Italianof7b2acb2015-10-14 20:29:54 +0000864 Message = "Found CC: " + *CCPath + "\n";
865 return new CC(*CCPath, RemoteClientPath, Args);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000866}