blob: d1e058e3ceb95aec3fcee6dd1eb664b8c3f3bed9 [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 Lattner0b1fe842003-10-19 02:27:40 +000014#define DEBUG_TYPE "toolrunner"
Chris Lattnerf1b20d82006-06-06 22:30:59 +000015#include "ToolRunner.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000016#include "llvm/Config/config.h" // for HAVE_LINK_R
Chris Lattner45495c52005-02-13 23:13:47 +000017#include "llvm/System/Program.h"
Evan Cheng34e400e2007-05-03 18:36:15 +000018#include "llvm/Support/CommandLine.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000019#include "llvm/Support/Debug.h"
20#include "llvm/Support/FileUtilities.h"
Chris Lattner7915a1e2003-10-14 21:34:11 +000021#include <fstream>
Chris Lattner89bf9ea2004-02-18 20:38:00 +000022#include <sstream>
Chris Lattner86a54842006-01-22 22:53:01 +000023#include <iostream>
Chris Lattner2cdd21c2003-12-14 21:35:53 +000024using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000025
Evan Cheng34e400e2007-05-03 18:36:15 +000026namespace {
27 cl::opt<std::string>
28 RSHHost("rsh-host",
29 cl::desc("Remote execution (rsh) host"));
30
31 cl::opt<std::string>
32 RSHUser("rsh-user",
33 cl::desc("Remote execution (rsh) user id"));
34}
35
Alkis Evlogimenos1d29a6d2004-02-19 07:39:26 +000036ToolExecutionError::~ToolExecutionError() throw() { }
37
Chris Lattner45495c52005-02-13 23:13:47 +000038/// RunProgramWithTimeout - This function provides an alternate interface to the
39/// sys::Program::ExecuteAndWait interface.
40/// @see sys:Program::ExecuteAndWait
41static int RunProgramWithTimeout(const sys::Path &ProgramPath,
42 const char **Args,
43 const sys::Path &StdInFile,
44 const sys::Path &StdOutFile,
45 const sys::Path &StdErrFile,
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +000046 unsigned NumSeconds = 0,
47 unsigned MemoryLimit = 0) {
Chris Lattner45495c52005-02-13 23:13:47 +000048 const sys::Path* redirects[3];
49 redirects[0] = &StdInFile;
50 redirects[1] = &StdOutFile;
51 redirects[2] = &StdErrFile;
Chris Lattnerc600f3c2006-09-15 21:29:15 +000052
Chris Lattnerd4223502006-09-15 23:01:10 +000053 if (0) {
54 std::cerr << "RUN:";
55 for (unsigned i = 0; Args[i]; ++i)
56 std::cerr << " " << Args[i];
57 std::cerr << "\n";
58 }
Misha Brukmanf976c852005-04-21 22:55:34 +000059
60 return
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +000061 sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects,
62 NumSeconds, MemoryLimit);
Chris Lattner45495c52005-02-13 23:13:47 +000063}
64
65
66
Reid Spencerb31baa82004-12-19 18:00:21 +000067static void ProcessFailure(sys::Path ProgPath, const char** Args) {
Chris Lattner89bf9ea2004-02-18 20:38:00 +000068 std::ostringstream OS;
Chris Lattnera3de1172004-02-18 20:58:00 +000069 OS << "\nError running tool:\n ";
Chris Lattner89bf9ea2004-02-18 20:38:00 +000070 for (const char **Arg = Args; *Arg; ++Arg)
71 OS << " " << *Arg;
72 OS << "\n";
73
74 // Rerun the compiler, capturing any error messages to print them.
Reid Spencercda985e2004-12-15 01:51:56 +000075 sys::Path ErrorFilename("error_messages");
Reid Spencer51c5a282006-08-23 20:34:57 +000076 std::string ErrMsg;
77 if (ErrorFilename.makeUnique(true, &ErrMsg)) {
78 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
79 exit(1);
80 }
Reid Spencerb31baa82004-12-19 18:00:21 +000081 RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename,
Reid Spencer8ea5ecb2006-08-21 06:04:45 +000082 ErrorFilename); // FIXME: check return code ?
Chris Lattner89bf9ea2004-02-18 20:38:00 +000083
84 // Print out the error messages generated by GCC if possible...
85 std::ifstream ErrorFile(ErrorFilename.c_str());
86 if (ErrorFile) {
87 std::copy(std::istreambuf_iterator<char>(ErrorFile),
88 std::istreambuf_iterator<char>(),
89 std::ostreambuf_iterator<char>(OS));
90 ErrorFile.close();
91 }
92
Reid Spencera229c5c2005-07-08 03:08:58 +000093 ErrorFilename.eraseFromDisk();
Chris Lattner89bf9ea2004-02-18 20:38:00 +000094 throw ToolExecutionError(OS.str());
95}
96
Misha Brukman9558c6a2003-09-29 22:39:25 +000097//===---------------------------------------------------------------------===//
98// LLI Implementation of AbstractIntepreter interface
99//
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000100namespace {
101 class LLI : public AbstractInterpreter {
102 std::string LLIPath; // The path to the LLI executable
Brian Gaeked11577b2004-05-04 21:09:01 +0000103 std::vector<std::string> ToolArgs; // Args to pass to LLI
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000104 public:
Brian Gaeked11577b2004-05-04 21:09:01 +0000105 LLI(const std::string &Path, const std::vector<std::string> *Args)
106 : LLIPath(Path) {
107 ToolArgs.clear ();
Brian Gaeke48b008d2004-05-04 22:02:41 +0000108 if (Args) { ToolArgs = *Args; }
Brian Gaeked11577b2004-05-04 21:09:01 +0000109 }
Misha Brukmanf976c852005-04-21 22:55:34 +0000110
Gabor Greif8ff70c22007-07-04 21:55:50 +0000111 virtual int ExecuteProgram(const std::string &Bitcode,
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000112 const std::vector<std::string> &Args,
113 const std::string &InputFile,
114 const std::string &OutputFile,
Reid Spencer51ab5c82006-06-06 00:00:42 +0000115 const std::vector<std::string> &GCCArgs,
Misha Brukmanf976c852005-04-21 22:55:34 +0000116 const std::vector<std::string> &SharedLibs =
Chris Lattnere96b2ed2004-07-24 07:49:11 +0000117 std::vector<std::string>(),
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000118 unsigned Timeout = 0,
119 unsigned MemoryLimit = 0);
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000120 };
121}
Misha Brukman9558c6a2003-09-29 22:39:25 +0000122
Gabor Greif8ff70c22007-07-04 21:55:50 +0000123int LLI::ExecuteProgram(const std::string &Bitcode,
Chris Lattner7915a1e2003-10-14 21:34:11 +0000124 const std::vector<std::string> &Args,
Misha Brukman9558c6a2003-09-29 22:39:25 +0000125 const std::string &InputFile,
126 const std::string &OutputFile,
Reid Spencer51ab5c82006-06-06 00:00:42 +0000127 const std::vector<std::string> &GCCArgs,
Chris Lattnere96b2ed2004-07-24 07:49:11 +0000128 const std::vector<std::string> &SharedLibs,
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000129 unsigned Timeout,
130 unsigned MemoryLimit) {
Chris Lattner8c56be52004-02-18 20:21:57 +0000131 if (!SharedLibs.empty())
132 throw ToolExecutionError("LLI currently does not support "
133 "loading shared libraries.");
Misha Brukman9558c6a2003-09-29 22:39:25 +0000134
Reid Spencer51ab5c82006-06-06 00:00:42 +0000135 if (!GCCArgs.empty())
136 throw ToolExecutionError("LLI currently does not support "
137 "GCC Arguments.");
Misha Brukman9558c6a2003-09-29 22:39:25 +0000138 std::vector<const char*> LLIArgs;
139 LLIArgs.push_back(LLIPath.c_str());
Misha Brukman9558c6a2003-09-29 22:39:25 +0000140 LLIArgs.push_back("-force-interpreter=true");
Brian Gaeked11577b2004-05-04 21:09:01 +0000141
142 // Add any extra LLI args.
143 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
144 LLIArgs.push_back(ToolArgs[i].c_str());
145
Gabor Greif8ff70c22007-07-04 21:55:50 +0000146 LLIArgs.push_back(Bitcode.c_str());
Misha Brukman9558c6a2003-09-29 22:39:25 +0000147 // Add optional parameters to the running program from Argv
148 for (unsigned i=0, e = Args.size(); i != e; ++i)
149 LLIArgs.push_back(Args[i].c_str());
150 LLIArgs.push_back(0);
151
152 std::cout << "<lli>" << std::flush;
Chris Lattner0b1fe842003-10-19 02:27:40 +0000153 DEBUG(std::cerr << "\nAbout to run:\t";
Chris Lattner7b2ccff2003-10-19 02:14:58 +0000154 for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i)
Misha Brukman9558c6a2003-09-29 22:39:25 +0000155 std::cerr << " " << LLIArgs[i];
156 std::cerr << "\n";
157 );
Reid Spencerb31baa82004-12-19 18:00:21 +0000158 return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0],
Misha Brukmanf976c852005-04-21 22:55:34 +0000159 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000160 Timeout, MemoryLimit);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000161}
162
163// LLI create method - Try to find the LLI executable
Chris Lattner7915a1e2003-10-14 21:34:11 +0000164AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath,
Brian Gaeked11577b2004-05-04 21:09:01 +0000165 std::string &Message,
166 const std::vector<std::string> *ToolArgs) {
Reid Spencer51ab8ec2004-12-13 23:43:44 +0000167 std::string LLIPath = FindExecutable("lli", ProgPath).toString();
Misha Brukman9558c6a2003-09-29 22:39:25 +0000168 if (!LLIPath.empty()) {
169 Message = "Found lli: " + LLIPath + "\n";
Brian Gaeked11577b2004-05-04 21:09:01 +0000170 return new LLI(LLIPath, ToolArgs);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000171 }
172
173 Message = "Cannot find `lli' in executable directory or PATH!\n";
174 return 0;
175}
176
177//===----------------------------------------------------------------------===//
178// LLC Implementation of AbstractIntepreter interface
179//
Gabor Greif8ff70c22007-07-04 21:55:50 +0000180GCC::FileType LLC::OutputCode(const std::string &Bitcode,
Chris Lattnerc600f3c2006-09-15 21:29:15 +0000181 sys::Path &OutputAsmFile) {
Gabor Greif8ff70c22007-07-04 21:55:50 +0000182 sys::Path uniqueFile(Bitcode+".llc.s");
Reid Spencer51c5a282006-08-23 20:34:57 +0000183 std::string ErrMsg;
184 if (uniqueFile.makeUnique(true, &ErrMsg)) {
185 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
186 exit(1);
187 }
Reid Spencer9ac14182004-12-16 23:01:34 +0000188 OutputAsmFile = uniqueFile;
Brian Gaeked11577b2004-05-04 21:09:01 +0000189 std::vector<const char *> LLCArgs;
190 LLCArgs.push_back (LLCPath.c_str());
191
192 // Add any extra LLC args.
193 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
194 LLCArgs.push_back(ToolArgs[i].c_str());
195
196 LLCArgs.push_back ("-o");
197 LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file
198 LLCArgs.push_back ("-f"); // Overwrite as necessary...
Gabor Greif8ff70c22007-07-04 21:55:50 +0000199 LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
Brian Gaeked11577b2004-05-04 21:09:01 +0000200 LLCArgs.push_back (0);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000201
202 std::cout << "<llc>" << std::flush;
Brian Gaeked11577b2004-05-04 21:09:01 +0000203 DEBUG(std::cerr << "\nAbout to run:\t";
204 for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
205 std::cerr << " " << LLCArgs[i];
206 std::cerr << "\n";
207 );
Misha Brukmanf976c852005-04-21 22:55:34 +0000208 if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0],
Reid Spencerb31baa82004-12-19 18:00:21 +0000209 sys::Path(), sys::Path(), sys::Path()))
210 ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]);
Chris Lattnerc600f3c2006-09-15 21:29:15 +0000211
212 return GCC::AsmFile;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000213}
214
Gabor Greif8ff70c22007-07-04 21:55:50 +0000215void LLC::compileProgram(const std::string &Bitcode) {
Reid Spencer9ac14182004-12-16 23:01:34 +0000216 sys::Path OutputAsmFile;
Gabor Greif8ff70c22007-07-04 21:55:50 +0000217 OutputCode(Bitcode, OutputAsmFile);
Reid Spencera229c5c2005-07-08 03:08:58 +0000218 OutputAsmFile.eraseFromDisk();
Chris Lattner9cbbee32004-02-18 23:24:41 +0000219}
220
Gabor Greif8ff70c22007-07-04 21:55:50 +0000221int LLC::ExecuteProgram(const std::string &Bitcode,
Chris Lattner7915a1e2003-10-14 21:34:11 +0000222 const std::vector<std::string> &Args,
Misha Brukman9558c6a2003-09-29 22:39:25 +0000223 const std::string &InputFile,
224 const std::string &OutputFile,
Reid Spencer51ab5c82006-06-06 00:00:42 +0000225 const std::vector<std::string> &ArgsForGCC,
Chris Lattnere96b2ed2004-07-24 07:49:11 +0000226 const std::vector<std::string> &SharedLibs,
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000227 unsigned Timeout,
228 unsigned MemoryLimit) {
Chris Lattnereeed9832003-10-14 21:52:52 +0000229
Reid Spencer9ac14182004-12-16 23:01:34 +0000230 sys::Path OutputAsmFile;
Gabor Greif8ff70c22007-07-04 21:55:50 +0000231 OutputCode(Bitcode, OutputAsmFile);
Chris Lattner8c56be52004-02-18 20:21:57 +0000232 FileRemover OutFileRemover(OutputAsmFile);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000233
Reid Spencer51ab5c82006-06-06 00:00:42 +0000234 std::vector<std::string> GCCArgs(ArgsForGCC);
235 GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end());
236
Misha Brukman9558c6a2003-09-29 22:39:25 +0000237 // Assuming LLC worked, compile the result with GCC and run it.
Reid Spencer9ac14182004-12-16 23:01:34 +0000238 return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile,
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000239 InputFile, OutputFile, GCCArgs,
240 Timeout, MemoryLimit);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000241}
242
Chris Lattner7915a1e2003-10-14 21:34:11 +0000243/// createLLC - Try to find the LLC executable
Misha Brukman9558c6a2003-09-29 22:39:25 +0000244///
Chris Lattner7915a1e2003-10-14 21:34:11 +0000245LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath,
Brian Gaeked11577b2004-05-04 21:09:01 +0000246 std::string &Message,
247 const std::vector<std::string> *Args) {
Reid Spencer51ab8ec2004-12-13 23:43:44 +0000248 std::string LLCPath = FindExecutable("llc", ProgramPath).toString();
Misha Brukman9558c6a2003-09-29 22:39:25 +0000249 if (LLCPath.empty()) {
250 Message = "Cannot find `llc' in executable directory or PATH!\n";
251 return 0;
252 }
253
254 Message = "Found llc: " + LLCPath + "\n";
Chris Lattner7915a1e2003-10-14 21:34:11 +0000255 GCC *gcc = GCC::create(ProgramPath, Message);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000256 if (!gcc) {
257 std::cerr << Message << "\n";
258 exit(1);
259 }
Brian Gaeked11577b2004-05-04 21:09:01 +0000260 return new LLC(LLCPath, gcc, Args);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000261}
262
263//===---------------------------------------------------------------------===//
264// JIT Implementation of AbstractIntepreter interface
265//
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000266namespace {
267 class JIT : public AbstractInterpreter {
268 std::string LLIPath; // The path to the LLI executable
Brian Gaeked11577b2004-05-04 21:09:01 +0000269 std::vector<std::string> ToolArgs; // Args to pass to LLI
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000270 public:
Brian Gaeked11577b2004-05-04 21:09:01 +0000271 JIT(const std::string &Path, const std::vector<std::string> *Args)
272 : LLIPath(Path) {
273 ToolArgs.clear ();
Brian Gaeke48b008d2004-05-04 22:02:41 +0000274 if (Args) { ToolArgs = *Args; }
Brian Gaeked11577b2004-05-04 21:09:01 +0000275 }
Misha Brukmanf976c852005-04-21 22:55:34 +0000276
Gabor Greif8ff70c22007-07-04 21:55:50 +0000277 virtual int ExecuteProgram(const std::string &Bitcode,
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000278 const std::vector<std::string> &Args,
279 const std::string &InputFile,
280 const std::string &OutputFile,
Reid Spencer51ab5c82006-06-06 00:00:42 +0000281 const std::vector<std::string> &GCCArgs =
282 std::vector<std::string>(),
Misha Brukmanf976c852005-04-21 22:55:34 +0000283 const std::vector<std::string> &SharedLibs =
Reid Spencer51ab5c82006-06-06 00:00:42 +0000284 std::vector<std::string>(),
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000285 unsigned Timeout =0,
286 unsigned MemoryLimit =0);
Chris Lattner2cdd21c2003-12-14 21:35:53 +0000287 };
288}
Misha Brukman9558c6a2003-09-29 22:39:25 +0000289
Gabor Greif8ff70c22007-07-04 21:55:50 +0000290int JIT::ExecuteProgram(const std::string &Bitcode,
Chris Lattner7915a1e2003-10-14 21:34:11 +0000291 const std::vector<std::string> &Args,
Misha Brukman9558c6a2003-09-29 22:39:25 +0000292 const std::string &InputFile,
293 const std::string &OutputFile,
Reid Spencer51ab5c82006-06-06 00:00:42 +0000294 const std::vector<std::string> &GCCArgs,
Chris Lattnere96b2ed2004-07-24 07:49:11 +0000295 const std::vector<std::string> &SharedLibs,
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000296 unsigned Timeout,
297 unsigned MemoryLimit) {
Reid Spencer51ab5c82006-06-06 00:00:42 +0000298 if (!GCCArgs.empty())
299 throw ToolExecutionError("JIT does not support GCC Arguments.");
Misha Brukman9558c6a2003-09-29 22:39:25 +0000300 // Construct a vector of parameters, incorporating those from the command-line
301 std::vector<const char*> JITArgs;
302 JITArgs.push_back(LLIPath.c_str());
Misha Brukman9558c6a2003-09-29 22:39:25 +0000303 JITArgs.push_back("-force-interpreter=false");
Chris Lattnereeed9832003-10-14 21:52:52 +0000304
Brian Gaeked11577b2004-05-04 21:09:01 +0000305 // Add any extra LLI args.
306 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
307 JITArgs.push_back(ToolArgs[i].c_str());
308
Chris Lattnereeed9832003-10-14 21:52:52 +0000309 for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
Misha Brukman9558c6a2003-09-29 22:39:25 +0000310 JITArgs.push_back("-load");
Chris Lattnereeed9832003-10-14 21:52:52 +0000311 JITArgs.push_back(SharedLibs[i].c_str());
Misha Brukman9558c6a2003-09-29 22:39:25 +0000312 }
Gabor Greif8ff70c22007-07-04 21:55:50 +0000313 JITArgs.push_back(Bitcode.c_str());
Misha Brukman9558c6a2003-09-29 22:39:25 +0000314 // Add optional parameters to the running program from Argv
315 for (unsigned i=0, e = Args.size(); i != e; ++i)
316 JITArgs.push_back(Args[i].c_str());
317 JITArgs.push_back(0);
318
319 std::cout << "<jit>" << std::flush;
Chris Lattner0b1fe842003-10-19 02:27:40 +0000320 DEBUG(std::cerr << "\nAbout to run:\t";
Chris Lattner7b2ccff2003-10-19 02:14:58 +0000321 for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i)
Misha Brukman9558c6a2003-09-29 22:39:25 +0000322 std::cerr << " " << JITArgs[i];
323 std::cerr << "\n";
324 );
325 DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n");
Reid Spencerb31baa82004-12-19 18:00:21 +0000326 return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0],
Misha Brukmanf976c852005-04-21 22:55:34 +0000327 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000328 Timeout, MemoryLimit);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000329}
330
Chris Lattner7915a1e2003-10-14 21:34:11 +0000331/// createJIT - Try to find the LLI executable
Misha Brukman9558c6a2003-09-29 22:39:25 +0000332///
Chris Lattner7915a1e2003-10-14 21:34:11 +0000333AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath,
Brian Gaeked11577b2004-05-04 21:09:01 +0000334 std::string &Message, const std::vector<std::string> *Args) {
Reid Spencer51ab8ec2004-12-13 23:43:44 +0000335 std::string LLIPath = FindExecutable("lli", ProgPath).toString();
Misha Brukman9558c6a2003-09-29 22:39:25 +0000336 if (!LLIPath.empty()) {
337 Message = "Found lli: " + LLIPath + "\n";
Brian Gaeked11577b2004-05-04 21:09:01 +0000338 return new JIT(LLIPath, Args);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000339 }
340
341 Message = "Cannot find `lli' in executable directory or PATH!\n";
342 return 0;
343}
344
Gabor Greif8ff70c22007-07-04 21:55:50 +0000345GCC::FileType CBE::OutputCode(const std::string &Bitcode,
Chris Lattnerc600f3c2006-09-15 21:29:15 +0000346 sys::Path &OutputCFile) {
Gabor Greif8ff70c22007-07-04 21:55:50 +0000347 sys::Path uniqueFile(Bitcode+".cbe.c");
Reid Spencer51c5a282006-08-23 20:34:57 +0000348 std::string ErrMsg;
349 if (uniqueFile.makeUnique(true, &ErrMsg)) {
350 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
351 exit(1);
352 }
Reid Spencer9ac14182004-12-16 23:01:34 +0000353 OutputCFile = uniqueFile;
Brian Gaeked11577b2004-05-04 21:09:01 +0000354 std::vector<const char *> LLCArgs;
355 LLCArgs.push_back (LLCPath.c_str());
356
357 // Add any extra LLC args.
358 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
359 LLCArgs.push_back(ToolArgs[i].c_str());
360
361 LLCArgs.push_back ("-o");
362 LLCArgs.push_back (OutputCFile.c_str()); // Output to the C file
363 LLCArgs.push_back ("-march=c"); // Output C language
364 LLCArgs.push_back ("-f"); // Overwrite as necessary...
Gabor Greif8ff70c22007-07-04 21:55:50 +0000365 LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
Brian Gaeked11577b2004-05-04 21:09:01 +0000366 LLCArgs.push_back (0);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000367
368 std::cout << "<cbe>" << std::flush;
Brian Gaeked11577b2004-05-04 21:09:01 +0000369 DEBUG(std::cerr << "\nAbout to run:\t";
370 for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i)
371 std::cerr << " " << LLCArgs[i];
372 std::cerr << "\n";
373 );
Misha Brukmanf976c852005-04-21 22:55:34 +0000374 if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(),
Reid Spencerb31baa82004-12-19 18:00:21 +0000375 sys::Path()))
Brian Gaeked11577b2004-05-04 21:09:01 +0000376 ProcessFailure(LLCPath, &LLCArgs[0]);
Chris Lattnerc600f3c2006-09-15 21:29:15 +0000377 return GCC::CFile;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000378}
379
Gabor Greif8ff70c22007-07-04 21:55:50 +0000380void CBE::compileProgram(const std::string &Bitcode) {
Reid Spencer9ac14182004-12-16 23:01:34 +0000381 sys::Path OutputCFile;
Gabor Greif8ff70c22007-07-04 21:55:50 +0000382 OutputCode(Bitcode, OutputCFile);
Reid Spencera229c5c2005-07-08 03:08:58 +0000383 OutputCFile.eraseFromDisk();
Chris Lattner9cbbee32004-02-18 23:24:41 +0000384}
385
Gabor Greif8ff70c22007-07-04 21:55:50 +0000386int CBE::ExecuteProgram(const std::string &Bitcode,
Chris Lattner7915a1e2003-10-14 21:34:11 +0000387 const std::vector<std::string> &Args,
Misha Brukman9558c6a2003-09-29 22:39:25 +0000388 const std::string &InputFile,
389 const std::string &OutputFile,
Reid Spencer51ab5c82006-06-06 00:00:42 +0000390 const std::vector<std::string> &ArgsForGCC,
Chris Lattnere96b2ed2004-07-24 07:49:11 +0000391 const std::vector<std::string> &SharedLibs,
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000392 unsigned Timeout,
393 unsigned MemoryLimit) {
Reid Spencer9ac14182004-12-16 23:01:34 +0000394 sys::Path OutputCFile;
Gabor Greif8ff70c22007-07-04 21:55:50 +0000395 OutputCode(Bitcode, OutputCFile);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000396
Chris Lattner8c56be52004-02-18 20:21:57 +0000397 FileRemover CFileRemove(OutputCFile);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000398
Reid Spencer51ab5c82006-06-06 00:00:42 +0000399 std::vector<std::string> GCCArgs(ArgsForGCC);
400 GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end());
Misha Brukmanf976c852005-04-21 22:55:34 +0000401 return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile,
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000402 InputFile, OutputFile, GCCArgs,
403 Timeout, MemoryLimit);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000404}
405
Chris Lattner9915cd92004-02-17 06:40:06 +0000406/// createCBE - Try to find the 'llc' executable
Misha Brukman9558c6a2003-09-29 22:39:25 +0000407///
Chris Lattner7915a1e2003-10-14 21:34:11 +0000408CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath,
Brian Gaeked11577b2004-05-04 21:09:01 +0000409 std::string &Message,
410 const std::vector<std::string> *Args) {
Reid Spencerb31baa82004-12-19 18:00:21 +0000411 sys::Path LLCPath = FindExecutable("llc", ProgramPath);
412 if (LLCPath.isEmpty()) {
Misha Brukmanf976c852005-04-21 22:55:34 +0000413 Message =
Chris Lattner9915cd92004-02-17 06:40:06 +0000414 "Cannot find `llc' in executable directory or PATH!\n";
Misha Brukman9558c6a2003-09-29 22:39:25 +0000415 return 0;
416 }
417
Reid Spencerb31baa82004-12-19 18:00:21 +0000418 Message = "Found llc: " + LLCPath.toString() + "\n";
Chris Lattner7915a1e2003-10-14 21:34:11 +0000419 GCC *gcc = GCC::create(ProgramPath, Message);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000420 if (!gcc) {
421 std::cerr << Message << "\n";
422 exit(1);
423 }
Brian Gaeked11577b2004-05-04 21:09:01 +0000424 return new CBE(LLCPath, gcc, Args);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000425}
426
427//===---------------------------------------------------------------------===//
428// GCC abstraction
429//
Misha Brukman9558c6a2003-09-29 22:39:25 +0000430int GCC::ExecuteProgram(const std::string &ProgramFile,
Chris Lattner7915a1e2003-10-14 21:34:11 +0000431 const std::vector<std::string> &Args,
Misha Brukman9558c6a2003-09-29 22:39:25 +0000432 FileType fileType,
433 const std::string &InputFile,
434 const std::string &OutputFile,
Reid Spencer51ab5c82006-06-06 00:00:42 +0000435 const std::vector<std::string> &ArgsForGCC,
Anton Korobeynikov9ba8a762007-02-16 19:11:07 +0000436 unsigned Timeout,
437 unsigned MemoryLimit) {
Misha Brukman9558c6a2003-09-29 22:39:25 +0000438 std::vector<const char*> GCCArgs;
439
440 GCCArgs.push_back(GCCPath.c_str());
Chris Lattnereeed9832003-10-14 21:52:52 +0000441
Chris Lattnereeed9832003-10-14 21:52:52 +0000442 // Specify -x explicitly in case the extension is wonky
Misha Brukman9558c6a2003-09-29 22:39:25 +0000443 GCCArgs.push_back("-x");
444 if (fileType == CFile) {
445 GCCArgs.push_back("c");
446 GCCArgs.push_back("-fno-strict-aliasing");
447 } else {
448 GCCArgs.push_back("assembler");
Chris Lattnerd00b2882005-08-29 13:14:24 +0000449#ifdef __APPLE__
450 GCCArgs.push_back("-force_cpusubtype_ALL");
451#endif
Misha Brukman9558c6a2003-09-29 22:39:25 +0000452 }
453 GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename...
Chris Lattner629e4872006-06-09 21:31:53 +0000454 GCCArgs.push_back("-x");
455 GCCArgs.push_back("none");
Misha Brukman9558c6a2003-09-29 22:39:25 +0000456 GCCArgs.push_back("-o");
Reid Spencercda985e2004-12-15 01:51:56 +0000457 sys::Path OutputBinary (ProgramFile+".gcc.exe");
Reid Spencer51c5a282006-08-23 20:34:57 +0000458 std::string ErrMsg;
459 if (OutputBinary.makeUnique(true, &ErrMsg)) {
460 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
461 exit(1);
462 }
Misha Brukman9558c6a2003-09-29 22:39:25 +0000463 GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
Reid Spencer51ab5c82006-06-06 00:00:42 +0000464
465 // Add any arguments intended for GCC. We locate them here because this is
466 // most likely -L and -l options that need to come before other libraries but
467 // after the source. Other options won't be sensitive to placement on the
468 // command line, so this should be safe.
469 for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
470 GCCArgs.push_back(ArgsForGCC[i].c_str());
471
Misha Brukman9558c6a2003-09-29 22:39:25 +0000472 GCCArgs.push_back("-lm"); // Hard-code the math library...
473 GCCArgs.push_back("-O2"); // Optimize the program a bit...
Brian Gaekec8db76c2003-11-18 06:31:17 +0000474#if defined (HAVE_LINK_R)
Chris Lattner1f0f1622003-10-18 21:54:47 +0000475 GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files
Brian Gaekec8db76c2003-11-18 06:31:17 +0000476#endif
Chris Lattnerfdcc71e2006-02-04 05:02:27 +0000477#ifdef __sparc__
478 GCCArgs.push_back("-mcpu=v9");
479#endif
Misha Brukman9558c6a2003-09-29 22:39:25 +0000480 GCCArgs.push_back(0); // NULL terminator
481
482 std::cout << "<gcc>" << std::flush;
Evan Cheng7f7fdcc2007-01-03 07:44:30 +0000483 DEBUG(std::cerr << "\nAbout to run:\t";
484 for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
485 std::cerr << " " << GCCArgs[i];
486 std::cerr << "\n";
487 );
Reid Spencerb31baa82004-12-19 18:00:21 +0000488 if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
489 sys::Path())) {
Chris Lattner89bf9ea2004-02-18 20:38:00 +0000490 ProcessFailure(GCCPath, &GCCArgs[0]);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000491 exit(1);
492 }
493
494 std::vector<const char*> ProgramArgs;
Chris Lattner45495c52005-02-13 23:13:47 +0000495
Evan Cheng34e400e2007-05-03 18:36:15 +0000496 if (RSHPath.isEmpty())
497 ProgramArgs.push_back(OutputBinary.c_str());
498 else {
499 ProgramArgs.push_back(RSHPath.c_str());
500 ProgramArgs.push_back(RSHHost.c_str());
501 ProgramArgs.push_back("-l");
502 ProgramArgs.push_back(RSHUser.c_str());
503
504 char* env_pwd = getenv("PWD");
505 std::string Exec = "cd ";
506 Exec += env_pwd;
507 Exec += "; ./";
508 Exec += OutputBinary.c_str();
509 ProgramArgs.push_back(Exec.c_str());
510 }
511
Misha Brukman9558c6a2003-09-29 22:39:25 +0000512 // Add optional parameters to the running program from Argv
513 for (unsigned i=0, e = Args.size(); i != e; ++i)
514 ProgramArgs.push_back(Args[i].c_str());
515 ProgramArgs.push_back(0); // NULL terminator
516
517 // Now that we have a binary, run it!
518 std::cout << "<program>" << std::flush;
Chris Lattner0b1fe842003-10-19 02:27:40 +0000519 DEBUG(std::cerr << "\nAbout to run:\t";
Chris Lattner7b2ccff2003-10-19 02:14:58 +0000520 for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i)
Misha Brukman9558c6a2003-09-29 22:39:25 +0000521 std::cerr << " " << ProgramArgs[i];
522 std::cerr << "\n";
523 );
Chris Lattner8c56be52004-02-18 20:21:57 +0000524
Reid Spencer9ac14182004-12-16 23:01:34 +0000525 FileRemover OutputBinaryRemover(OutputBinary);
Evan Cheng34e400e2007-05-03 18:36:15 +0000526
527 if (RSHPath.isEmpty())
528 return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
529 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
530 Timeout, MemoryLimit);
531 else
532 return RunProgramWithTimeout(sys::Path(RSHPath), &ProgramArgs[0],
533 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
534 Timeout, MemoryLimit);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000535}
536
Chris Lattner1798e4a2003-10-14 21:07:25 +0000537int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType,
Chris Lattner130e2a32006-06-27 20:35:36 +0000538 std::string &OutputFile,
539 const std::vector<std::string> &ArgsForGCC) {
Reid Spencercda985e2004-12-15 01:51:56 +0000540 sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT);
Reid Spencer51c5a282006-08-23 20:34:57 +0000541 std::string ErrMsg;
542 if (uniqueFilename.makeUnique(true, &ErrMsg)) {
543 std::cerr << "Error making unique filename: " << ErrMsg << "\n";
544 exit(1);
545 }
Reid Spencercda985e2004-12-15 01:51:56 +0000546 OutputFile = uniqueFilename.toString();
547
Chris Lattner130e2a32006-06-27 20:35:36 +0000548 std::vector<const char*> GCCArgs;
549
550 GCCArgs.push_back(GCCPath.c_str());
551
552
Misha Brukman9558c6a2003-09-29 22:39:25 +0000553 // Compile the C/asm file into a shared object
Chris Lattner130e2a32006-06-27 20:35:36 +0000554 GCCArgs.push_back("-x");
555 GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
556 GCCArgs.push_back("-fno-strict-aliasing");
557 GCCArgs.push_back(InputFile.c_str()); // Specify the input filename.
Lauro Ramos Venancio497391a2007-06-06 23:10:56 +0000558 GCCArgs.push_back("-x");
559 GCCArgs.push_back("none");
Misha Brukman9558c6a2003-09-29 22:39:25 +0000560#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
Chris Lattner130e2a32006-06-27 20:35:36 +0000561 GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
Nate Begeman72b286b2005-07-08 00:23:26 +0000562#elif defined(__APPLE__)
Chris Lattner130e2a32006-06-27 20:35:36 +0000563 // link all source files into a single module in data segment, rather than
564 // generating blocks. dynamic_lookup requires that you set
565 // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for
566 // bugpoint to just pass that in the environment of GCC.
567 GCCArgs.push_back("-single_module");
568 GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC
569 GCCArgs.push_back("-undefined");
570 GCCArgs.push_back("dynamic_lookup");
Misha Brukmanb3998ec2004-07-16 19:45:45 +0000571#else
Chris Lattner130e2a32006-06-27 20:35:36 +0000572 GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others
Misha Brukman9558c6a2003-09-29 22:39:25 +0000573#endif
Chris Lattner1c81f132005-03-09 03:31:02 +0000574
Torok Edwinaf4fc282008-04-06 12:42:29 +0000575#if defined(__ia64__) || defined(__alpha__) || defined(__amd64__)
Chris Lattner130e2a32006-06-27 20:35:36 +0000576 GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
Chris Lattner1c81f132005-03-09 03:31:02 +0000577#endif
Chris Lattnerfdcc71e2006-02-04 05:02:27 +0000578#ifdef __sparc__
Chris Lattner130e2a32006-06-27 20:35:36 +0000579 GCCArgs.push_back("-mcpu=v9");
Chris Lattnerfdcc71e2006-02-04 05:02:27 +0000580#endif
Chris Lattner130e2a32006-06-27 20:35:36 +0000581 GCCArgs.push_back("-o");
582 GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
583 GCCArgs.push_back("-O2"); // Optimize the program a bit.
584
585
586
587 // Add any arguments intended for GCC. We locate them here because this is
588 // most likely -L and -l options that need to come before other libraries but
589 // after the source. Other options won't be sensitive to placement on the
590 // command line, so this should be safe.
591 for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i)
592 GCCArgs.push_back(ArgsForGCC[i].c_str());
593 GCCArgs.push_back(0); // NULL terminator
594
595
Misha Brukmanf976c852005-04-21 22:55:34 +0000596
Misha Brukman9558c6a2003-09-29 22:39:25 +0000597 std::cout << "<gcc>" << std::flush;
Evan Cheng7f7fdcc2007-01-03 07:44:30 +0000598 DEBUG(std::cerr << "\nAbout to run:\t";
599 for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i)
600 std::cerr << " " << GCCArgs[i];
601 std::cerr << "\n";
602 );
Chris Lattner130e2a32006-06-27 20:35:36 +0000603 if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(),
Reid Spencerb31baa82004-12-19 18:00:21 +0000604 sys::Path())) {
Chris Lattner130e2a32006-06-27 20:35:36 +0000605 ProcessFailure(GCCPath, &GCCArgs[0]);
Chris Lattner1798e4a2003-10-14 21:07:25 +0000606 return 1;
Misha Brukman9558c6a2003-09-29 22:39:25 +0000607 }
608 return 0;
609}
610
Chris Lattner7915a1e2003-10-14 21:34:11 +0000611/// create - Try to find the `gcc' executable
Misha Brukman9558c6a2003-09-29 22:39:25 +0000612///
Chris Lattner7915a1e2003-10-14 21:34:11 +0000613GCC *GCC::create(const std::string &ProgramPath, std::string &Message) {
Reid Spencerb31baa82004-12-19 18:00:21 +0000614 sys::Path GCCPath = FindExecutable("gcc", ProgramPath);
615 if (GCCPath.isEmpty()) {
Misha Brukman9558c6a2003-09-29 22:39:25 +0000616 Message = "Cannot find `gcc' in executable directory or PATH!\n";
617 return 0;
618 }
619
Evan Cheng34e400e2007-05-03 18:36:15 +0000620 sys::Path RSHPath;
621 if (!RSHHost.empty())
622 RSHPath = FindExecutable("rsh", ProgramPath);
623
Reid Spencerb31baa82004-12-19 18:00:21 +0000624 Message = "Found gcc: " + GCCPath.toString() + "\n";
Evan Cheng34e400e2007-05-03 18:36:15 +0000625 return new GCC(GCCPath, RSHPath);
Misha Brukman9558c6a2003-09-29 22:39:25 +0000626}