ToolRunner.cpp revision 207618
190075Sobrien//===-- ToolRunner.cpp ----------------------------------------------------===// 2169689Skan// 3169689Skan// The LLVM Compiler Infrastructure 490075Sobrien// 590075Sobrien// This file is distributed under the University of Illinois Open Source 690075Sobrien// License. See LICENSE.TXT for details. 790075Sobrien// 890075Sobrien//===----------------------------------------------------------------------===// 990075Sobrien// 1090075Sobrien// This file implements the interfaces described in the ToolRunner.h file. 1190075Sobrien// 1290075Sobrien//===----------------------------------------------------------------------===// 1390075Sobrien 1490075Sobrien#define DEBUG_TYPE "toolrunner" 1590075Sobrien#include "ToolRunner.h" 1690075Sobrien#include "llvm/System/Program.h" 1790075Sobrien#include "llvm/Support/CommandLine.h" 1890075Sobrien#include "llvm/Support/Debug.h" 19169689Skan#include "llvm/Support/FileUtilities.h" 20169689Skan#include "llvm/Support/raw_ostream.h" 2190075Sobrien#include "llvm/Config/config.h" // for HAVE_LINK_R 2290075Sobrien#include <fstream> 2390075Sobrien#include <sstream> 24132718Skanusing namespace llvm; 25132718Skan 2690075Sobriennamespace llvm { 2790075Sobrien cl::opt<bool> 2890075Sobrien SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); 2990075Sobrien} 3090075Sobrien 3190075Sobriennamespace { 3290075Sobrien cl::opt<std::string> 3396263Sobrien RemoteClient("remote-client", 3490075Sobrien cl::desc("Remote execution client (rsh/ssh)")); 3590075Sobrien 3690075Sobrien cl::opt<std::string> 3790075Sobrien RemoteHost("remote-host", 3890075Sobrien cl::desc("Remote execution (rsh/ssh) host")); 39132718Skan 4090075Sobrien cl::opt<std::string> 4190075Sobrien RemotePort("remote-port", 42132718Skan cl::desc("Remote execution (rsh/ssh) port")); 43132718Skan 44169689Skan cl::opt<std::string> 45169689Skan RemoteUser("remote-user", 4690075Sobrien cl::desc("Remote execution (rsh/ssh) user id")); 4790075Sobrien 4890075Sobrien cl::opt<std::string> 4990075Sobrien RemoteExtra("remote-extra-options", 5090075Sobrien cl::desc("Remote execution (rsh/ssh) extra options")); 5190075Sobrien} 5290075Sobrien 5390075Sobrien/// RunProgramWithTimeout - This function provides an alternate interface 5490075Sobrien/// to the sys::Program::ExecuteAndWait interface. 5590075Sobrien/// @see sys::Program::ExecuteAndWait 5690075Sobrienstatic int RunProgramWithTimeout(const sys::Path &ProgramPath, 5790075Sobrien const char **Args, 5890075Sobrien const sys::Path &StdInFile, 5990075Sobrien const sys::Path &StdOutFile, 6090075Sobrien const sys::Path &StdErrFile, 6190075Sobrien unsigned NumSeconds = 0, 6290075Sobrien unsigned MemoryLimit = 0) { 6390075Sobrien const sys::Path* redirects[3]; 6490075Sobrien redirects[0] = &StdInFile; 6590075Sobrien redirects[1] = &StdOutFile; 6690075Sobrien redirects[2] = &StdErrFile; 6790075Sobrien 6890075Sobrien#if 0 // For debug purposes 6990075Sobrien { 7090075Sobrien errs() << "RUN:"; 71169689Skan for (unsigned i = 0; Args[i]; ++i) 7290075Sobrien errs() << " " << Args[i]; 7390075Sobrien errs() << "\n"; 7490075Sobrien } 7590075Sobrien#endif 7690075Sobrien 7790075Sobrien return 7890075Sobrien sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, 7990075Sobrien NumSeconds, MemoryLimit); 80132718Skan} 81132718Skan 8290075Sobrien/// RunProgramRemotelyWithTimeout - This function runs the given program 83117395Skan/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 84117395Skan/// Returns the remote program exit code or reports a remote client error if it 85117395Skan/// fails. Remote client is required to return 255 if it failed or program exit 8690075Sobrien/// code otherwise. 8790075Sobrien/// @see sys::Program::ExecuteAndWait 8890075Sobrienstatic int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, 8990075Sobrien const char **Args, 90132718Skan const sys::Path &StdInFile, 91169689Skan const sys::Path &StdOutFile, 92132718Skan const sys::Path &StdErrFile, 93132718Skan unsigned NumSeconds = 0, 94132718Skan unsigned MemoryLimit = 0) { 95132718Skan const sys::Path* redirects[3]; 96132718Skan redirects[0] = &StdInFile; 97132718Skan redirects[1] = &StdOutFile; 98132718Skan redirects[2] = &StdErrFile; 99132718Skan 100132718Skan#if 0 // For debug purposes 101132718Skan { 102132718Skan errs() << "RUN:"; 103132718Skan for (unsigned i = 0; Args[i]; ++i) 104132718Skan errs() << " " << Args[i]; 105132718Skan errs() << "\n"; 106132718Skan } 107132718Skan#endif 108132718Skan 109132718Skan // Run the program remotely with the remote client 110132718Skan int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, 111132718Skan 0, redirects, NumSeconds, MemoryLimit); 112132718Skan 113132718Skan // Has the remote client fail? 11490075Sobrien if (255 == ReturnCode) { 115169689Skan std::ostringstream OS; 116169689Skan OS << "\nError running remote client:\n "; 117169689Skan for (const char **Arg = Args; *Arg; ++Arg) 118169689Skan OS << " " << *Arg; 119132718Skan OS << "\n"; 120169689Skan 121169689Skan // The error message is in the output file, let's print it out from there. 122169689Skan std::ifstream ErrorFile(StdOutFile.c_str()); 123169689Skan if (ErrorFile) { 124132718Skan std::copy(std::istreambuf_iterator<char>(ErrorFile), 125169689Skan std::istreambuf_iterator<char>(), 126169689Skan std::ostreambuf_iterator<char>(OS)); 127169689Skan ErrorFile.close(); 128169689Skan } 129169689Skan 130169689Skan errs() << OS; 131132718Skan } 132132718Skan 133169689Skan return ReturnCode; 134132718Skan} 135132718Skan 136169689Skanstatic std::string ProcessFailure(sys::Path ProgPath, const char** Args) { 137169689Skan std::ostringstream OS; 138169689Skan OS << "\nError running tool:\n "; 13990075Sobrien for (const char **Arg = Args; *Arg; ++Arg) 140169689Skan OS << " " << *Arg; 141169689Skan OS << "\n"; 14290075Sobrien 14390075Sobrien // Rerun the compiler, capturing any error messages to print them. 144132718Skan sys::Path ErrorFilename("bugpoint.program_error_messages"); 14590075Sobrien std::string ErrMsg; 14690075Sobrien if (ErrorFilename.makeUnique(true, &ErrMsg)) { 14790075Sobrien errs() << "Error making unique filename: " << ErrMsg << "\n"; 148169689Skan exit(1); 149169689Skan } 150169689Skan RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, 151169689Skan ErrorFilename); // FIXME: check return code ? 152169689Skan 15390075Sobrien // Print out the error messages generated by GCC if possible... 154169689Skan std::ifstream ErrorFile(ErrorFilename.c_str()); 155169689Skan if (ErrorFile) { 156169689Skan std::copy(std::istreambuf_iterator<char>(ErrorFile), 157169689Skan std::istreambuf_iterator<char>(), 158169689Skan std::ostreambuf_iterator<char>(OS)); 159169689Skan ErrorFile.close(); 160169689Skan } 161169689Skan 162169689Skan ErrorFilename.eraseFromDisk(); 163169689Skan return OS.str(); 164169689Skan} 165169689Skan 166169689Skan//===---------------------------------------------------------------------===// 167169689Skan// LLI Implementation of AbstractIntepreter interface 168169689Skan// 169169689Skannamespace { 170169689Skan class LLI : public AbstractInterpreter { 171169689Skan std::string LLIPath; // The path to the LLI executable 172169689Skan std::vector<std::string> ToolArgs; // Args to pass to LLI 173169689Skan public: 174169689Skan LLI(const std::string &Path, const std::vector<std::string> *Args) 175169689Skan : LLIPath(Path) { 176132718Skan ToolArgs.clear (); 17790075Sobrien if (Args) { ToolArgs = *Args; } 17890075Sobrien } 17990075Sobrien 18090075Sobrien virtual int ExecuteProgram(const std::string &Bitcode, 181169689Skan const std::vector<std::string> &Args, 18290075Sobrien const std::string &InputFile, 18390075Sobrien const std::string &OutputFile, 18490075Sobrien std::string *Error, 18590075Sobrien const std::vector<std::string> &GCCArgs, 18690075Sobrien const std::vector<std::string> &SharedLibs = 187132718Skan std::vector<std::string>(), 18890075Sobrien unsigned Timeout = 0, 189132718Skan unsigned MemoryLimit = 0); 19090075Sobrien }; 191169689Skan} 19290075Sobrien 193132718Skanint LLI::ExecuteProgram(const std::string &Bitcode, 19490075Sobrien const std::vector<std::string> &Args, 19590075Sobrien const std::string &InputFile, 19690075Sobrien const std::string &OutputFile, 19790075Sobrien std::string *Error, 198169689Skan const std::vector<std::string> &GCCArgs, 19990075Sobrien const std::vector<std::string> &SharedLibs, 200132718Skan unsigned Timeout, 20190075Sobrien unsigned MemoryLimit) { 20290075Sobrien std::vector<const char*> LLIArgs; 20390075Sobrien LLIArgs.push_back(LLIPath.c_str()); 20490075Sobrien LLIArgs.push_back("-force-interpreter=true"); 205169689Skan 20690075Sobrien for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), e = SharedLibs.end(); i != e; ++i) { 20790075Sobrien LLIArgs.push_back("-load"); 20890075Sobrien LLIArgs.push_back((*i).c_str()); 20990075Sobrien } 21090075Sobrien 211117395Skan // Add any extra LLI args. 21290075Sobrien for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 213117395Skan LLIArgs.push_back(ToolArgs[i].c_str()); 214132718Skan 21590075Sobrien LLIArgs.push_back(Bitcode.c_str()); 216132718Skan // Add optional parameters to the running program from Argv 217132718Skan for (unsigned i=0, e = Args.size(); i != e; ++i) 218117395Skan LLIArgs.push_back(Args[i].c_str()); 219169689Skan LLIArgs.push_back(0); 220169689Skan 221117395Skan outs() << "<lli>"; outs().flush(); 222169689Skan DEBUG(errs() << "\nAbout to run:\t"; 223117395Skan for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) 22490075Sobrien errs() << " " << LLIArgs[i]; 225117395Skan errs() << "\n"; 226117395Skan ); 227117395Skan return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], 22890075Sobrien sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 22990075Sobrien Timeout, MemoryLimit); 230169689Skan} 231117395Skan 232117395Skan// LLI create method - Try to find the LLI executable 233117395SkanAbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, 23490075Sobrien std::string &Message, 23590075Sobrien const std::vector<std::string> *ToolArgs) { 236169689Skan std::string LLIPath = 23790075Sobrien FindExecutable("lli", Argv0, (void *)(intptr_t)&createLLI).str(); 238117395Skan if (!LLIPath.empty()) { 239132718Skan Message = "Found lli: " + LLIPath + "\n"; 240117395Skan return new LLI(LLIPath, ToolArgs); 241117395Skan } 242169689Skan 243117395Skan Message = "Cannot find `lli' in executable directory or PATH!\n"; 244169689Skan return 0; 245169689Skan} 246169689Skan 247117395Skan//===---------------------------------------------------------------------===// 248117395Skan// Custom execution command implementation of AbstractIntepreter interface 249117395Skan// 25090075Sobrien// Allows using a custom command for executing the bitcode, thus allows, 25190075Sobrien// for example, to invoke a cross compiler for code generation followed by 25290075Sobrien// a simulator that executes the generated binary. 25390075Sobriennamespace { 25490075Sobrien class CustomExecutor : public AbstractInterpreter { 25590075Sobrien std::string ExecutionCommand; 256132718Skan std::vector<std::string> ExecutorArgs; 257132718Skan public: 258132718Skan CustomExecutor( 259132718Skan const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : 260132718Skan ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} 261132718Skan 26290075Sobrien virtual int ExecuteProgram(const std::string &Bitcode, 26390075Sobrien const std::vector<std::string> &Args, 26490075Sobrien const std::string &InputFile, 265117395Skan const std::string &OutputFile, 26690075Sobrien std::string *Error, 26790075Sobrien const std::vector<std::string> &GCCArgs, 268117395Skan const std::vector<std::string> &SharedLibs = 269117395Skan std::vector<std::string>(), 270117395Skan unsigned Timeout = 0, 27190075Sobrien unsigned MemoryLimit = 0); 27290075Sobrien }; 273169689Skan} 27490075Sobrien 27590075Sobrienint CustomExecutor::ExecuteProgram(const std::string &Bitcode, 276169689Skan const std::vector<std::string> &Args, 27790075Sobrien const std::string &InputFile, 27890075Sobrien const std::string &OutputFile, 27990075Sobrien std::string *Error, 28090075Sobrien const std::vector<std::string> &GCCArgs, 281132718Skan const std::vector<std::string> &SharedLibs, 28290075Sobrien unsigned Timeout, 283169689Skan unsigned MemoryLimit) { 28490075Sobrien 28590075Sobrien std::vector<const char*> ProgramArgs; 28690075Sobrien ProgramArgs.push_back(ExecutionCommand.c_str()); 28790075Sobrien 28890075Sobrien for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 28990075Sobrien ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); 29090075Sobrien ProgramArgs.push_back(Bitcode.c_str()); 29190075Sobrien ProgramArgs.push_back(0); 29290075Sobrien 29390075Sobrien // Add optional parameters to the running program from Argv 29490075Sobrien for (unsigned i = 0, e = Args.size(); i != e; ++i) 29590075Sobrien ProgramArgs.push_back(Args[i].c_str()); 29690075Sobrien 29790075Sobrien return RunProgramWithTimeout( 29890075Sobrien sys::Path(ExecutionCommand), 29990075Sobrien &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 300117395Skan sys::Path(OutputFile), Timeout, MemoryLimit); 30190075Sobrien} 302117395Skan 303117395Skan// Custom execution environment create method, takes the execution command 304117395Skan// as arguments 305117395SkanAbstractInterpreter *AbstractInterpreter::createCustom( 306117395Skan std::string &Message, 307117395Skan const std::string &ExecCommandLine) { 308117395Skan 309117395Skan std::string Command = ""; 310117395Skan std::vector<std::string> Args; 311117395Skan std::string delimiters = " "; 312117395Skan 313117395Skan // Tokenize the ExecCommandLine to the command and the args to allow 314117395Skan // defining a full command line as the command instead of just the 315117395Skan // executed program. We cannot just pass the whole string after the command 31690075Sobrien // as a single argument because then program sees only a single 31790075Sobrien // command line argument (with spaces in it: "foo bar" instead 31890075Sobrien // of "foo" and "bar"). 31990075Sobrien 320117395Skan // code borrowed from: 32190075Sobrien // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html 32290075Sobrien std::string::size_type lastPos = 32390075Sobrien ExecCommandLine.find_first_not_of(delimiters, 0); 32490075Sobrien std::string::size_type pos = 325117395Skan ExecCommandLine.find_first_of(delimiters, lastPos); 32690075Sobrien 327169689Skan while (std::string::npos != pos || std::string::npos != lastPos) { 32890075Sobrien std::string token = ExecCommandLine.substr(lastPos, pos - lastPos); 32990075Sobrien if (Command == "") 33090075Sobrien Command = token; 33190075Sobrien else 33290075Sobrien Args.push_back(token); 33390075Sobrien // Skip delimiters. Note the "not_of" 33490075Sobrien lastPos = ExecCommandLine.find_first_not_of(delimiters, pos); 33590075Sobrien // Find next "non-delimiter" 33690075Sobrien pos = ExecCommandLine.find_first_of(delimiters, lastPos); 33790075Sobrien } 33890075Sobrien 33990075Sobrien std::string CmdPath = sys::Program::FindProgramByName(Command).str(); 34090075Sobrien if (CmdPath.empty()) { 34190075Sobrien Message = 34290075Sobrien std::string("Cannot find '") + Command + 343132718Skan "' in executable directory or PATH!\n"; 34490075Sobrien return 0; 34590075Sobrien } 34690075Sobrien 34790075Sobrien Message = "Found command in: " + CmdPath + "\n"; 34890075Sobrien 34990075Sobrien return new CustomExecutor(CmdPath, Args); 35090075Sobrien} 35190075Sobrien 35290075Sobrien//===----------------------------------------------------------------------===// 35390075Sobrien// LLC Implementation of AbstractIntepreter interface 35490075Sobrien// 35590075SobrienGCC::FileType LLC::OutputCode(const std::string &Bitcode, 35690075Sobrien sys::Path &OutputAsmFile, std::string &Error) { 35790075Sobrien const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); 35890075Sobrien sys::Path uniqueFile(Bitcode + Suffix); 35990075Sobrien std::string ErrMsg; 36090075Sobrien if (uniqueFile.makeUnique(true, &ErrMsg)) { 36190075Sobrien errs() << "Error making unique filename: " << ErrMsg << "\n"; 36290075Sobrien exit(1); 36390075Sobrien } 36490075Sobrien OutputAsmFile = uniqueFile; 36590075Sobrien std::vector<const char *> LLCArgs; 36690075Sobrien LLCArgs.push_back(LLCPath.c_str()); 36790075Sobrien 36890075Sobrien // Add any extra LLC args. 36990075Sobrien for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 37090075Sobrien LLCArgs.push_back(ToolArgs[i].c_str()); 371117395Skan 37290075Sobrien LLCArgs.push_back("-o"); 37390075Sobrien LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file 374132718Skan LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 375132718Skan 37690075Sobrien if (UseIntegratedAssembler) 377117395Skan LLCArgs.push_back("-filetype=obj"); 378117395Skan 379117395Skan LLCArgs.push_back (0); 38090075Sobrien 38190075Sobrien outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); 38290075Sobrien outs().flush(); 38390075Sobrien DEBUG(errs() << "\nAbout to run:\t"; 38490075Sobrien for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 38590075Sobrien errs() << " " << LLCArgs[i]; 38690075Sobrien errs() << "\n"; 38790075Sobrien ); 38890075Sobrien if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], 38990075Sobrien sys::Path(), sys::Path(), sys::Path())) 39090075Sobrien Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]); 39190075Sobrien return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; 39290075Sobrien} 39390075Sobrien 394117395Skanvoid LLC::compileProgram(const std::string &Bitcode, std::string *Error) { 395117395Skan sys::Path OutputAsmFile; 396117395Skan OutputCode(Bitcode, OutputAsmFile, *Error); 397117395Skan OutputAsmFile.eraseFromDisk(); 398117395Skan} 399117395Skan 400117395Skanint LLC::ExecuteProgram(const std::string &Bitcode, 401117395Skan const std::vector<std::string> &Args, 402117395Skan const std::string &InputFile, 403117395Skan const std::string &OutputFile, 404117395Skan std::string *Error, 405117395Skan const std::vector<std::string> &ArgsForGCC, 406117395Skan const std::vector<std::string> &SharedLibs, 407117395Skan unsigned Timeout, 40890075Sobrien unsigned MemoryLimit) { 40990075Sobrien 410132718Skan sys::Path OutputAsmFile; 41190075Sobrien GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error); 41290075Sobrien FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); 41390075Sobrien 41490075Sobrien std::vector<std::string> GCCArgs(ArgsForGCC); 41590075Sobrien GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 416132718Skan GCCArgs.insert(GCCArgs.end(), gccArgs.begin(), gccArgs.end()); 41790075Sobrien 41890075Sobrien // Assuming LLC worked, compile the result with GCC and run it. 419117395Skan return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind, 420117395Skan InputFile, OutputFile, Error, GCCArgs, 421117395Skan Timeout, MemoryLimit); 422117395Skan} 423117395Skan 424117395Skan/// createLLC - Try to find the LLC executable 425117395Skan/// 42690075SobrienLLC *AbstractInterpreter::createLLC(const char *Argv0, 42790075Sobrien std::string &Message, 42890075Sobrien const std::vector<std::string> *Args, 429117395Skan const std::vector<std::string> *GCCArgs, 430117395Skan bool UseIntegratedAssembler) { 431117395Skan std::string LLCPath = 432117395Skan FindExecutable("llc", Argv0, (void *)(intptr_t)&createLLC).str(); 43390075Sobrien if (LLCPath.empty()) { 43490075Sobrien Message = "Cannot find `llc' in executable directory or PATH!\n"; 43590075Sobrien return 0; 43690075Sobrien } 43790075Sobrien 43890075Sobrien Message = "Found llc: " + LLCPath + "\n"; 43990075Sobrien GCC *gcc = GCC::create(Message, GCCArgs); 440132718Skan if (!gcc) { 44190075Sobrien errs() << Message << "\n"; 44290075Sobrien exit(1); 443132718Skan } 44490075Sobrien return new LLC(LLCPath, gcc, Args, GCCArgs, UseIntegratedAssembler); 44590075Sobrien} 44690075Sobrien 44790075Sobrien//===---------------------------------------------------------------------===// 44890075Sobrien// JIT Implementation of AbstractIntepreter interface 44990075Sobrien// 45090075Sobriennamespace { 45190075Sobrien class JIT : public AbstractInterpreter { 45290075Sobrien std::string LLIPath; // The path to the LLI executable 453117395Skan std::vector<std::string> ToolArgs; // Args to pass to LLI 45490075Sobrien public: 455132718Skan JIT(const std::string &Path, const std::vector<std::string> *Args) 45690075Sobrien : LLIPath(Path) { 45790075Sobrien ToolArgs.clear (); 45890075Sobrien if (Args) { ToolArgs = *Args; } 45990075Sobrien } 460132718Skan 46190075Sobrien virtual int ExecuteProgram(const std::string &Bitcode, 46290075Sobrien const std::vector<std::string> &Args, 46390075Sobrien const std::string &InputFile, 46490075Sobrien const std::string &OutputFile, 46590075Sobrien std::string *Error, 46690075Sobrien const std::vector<std::string> &GCCArgs = 46790075Sobrien std::vector<std::string>(), 46890075Sobrien const std::vector<std::string> &SharedLibs = 469117395Skan std::vector<std::string>(), 470117395Skan unsigned Timeout = 0, 471117395Skan unsigned MemoryLimit = 0); 472117395Skan }; 473117395Skan} 474117395Skan 475117395Skanint JIT::ExecuteProgram(const std::string &Bitcode, 476117395Skan const std::vector<std::string> &Args, 477117395Skan const std::string &InputFile, 478117395Skan const std::string &OutputFile, 479117395Skan std::string *Error, 480117395Skan const std::vector<std::string> &GCCArgs, 481117395Skan const std::vector<std::string> &SharedLibs, 482117395Skan unsigned Timeout, 483169689Skan unsigned MemoryLimit) { 484117395Skan // Construct a vector of parameters, incorporating those from the command-line 485117395Skan std::vector<const char*> JITArgs; 486117395Skan JITArgs.push_back(LLIPath.c_str()); 487117395Skan JITArgs.push_back("-force-interpreter=false"); 488117395Skan 489117395Skan // Add any extra LLI args. 490117395Skan for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 491117395Skan JITArgs.push_back(ToolArgs[i].c_str()); 492117395Skan 493117395Skan for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 494117395Skan JITArgs.push_back("-load"); 495132718Skan JITArgs.push_back(SharedLibs[i].c_str()); 496117395Skan } 497117395Skan JITArgs.push_back(Bitcode.c_str()); 498117395Skan // Add optional parameters to the running program from Argv 499132718Skan for (unsigned i=0, e = Args.size(); i != e; ++i) 500117395Skan JITArgs.push_back(Args[i].c_str()); 501117395Skan JITArgs.push_back(0); 502117395Skan 503169689Skan outs() << "<jit>"; outs().flush(); 504169689Skan DEBUG(errs() << "\nAbout to run:\t"; 505169689Skan for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) 506117395Skan errs() << " " << JITArgs[i]; 507169689Skan errs() << "\n"; 508117395Skan ); 509117395Skan DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 510117395Skan return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], 511117395Skan sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 512117395Skan Timeout, MemoryLimit); 513117395Skan} 514117395Skan 515117395Skan/// createJIT - Try to find the LLI executable 516117395Skan/// 517117395SkanAbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, 518117395Skan std::string &Message, const std::vector<std::string> *Args) { 519117395Skan std::string LLIPath = 520117395Skan FindExecutable("lli", Argv0, (void *)(intptr_t)&createJIT).str(); 521117395Skan if (!LLIPath.empty()) { 522117395Skan Message = "Found lli: " + LLIPath + "\n"; 523117395Skan return new JIT(LLIPath, Args); 524117395Skan } 525132718Skan 526117395Skan Message = "Cannot find `lli' in executable directory or PATH!\n"; 527117395Skan return 0; 528117395Skan} 529117395Skan 530117395SkanGCC::FileType CBE::OutputCode(const std::string &Bitcode, 531117395Skan sys::Path &OutputCFile, std::string &Error) { 532117395Skan sys::Path uniqueFile(Bitcode+".cbe.c"); 533117395Skan std::string ErrMsg; 534117395Skan if (uniqueFile.makeUnique(true, &ErrMsg)) { 535117395Skan errs() << "Error making unique filename: " << ErrMsg << "\n"; 53690075Sobrien exit(1); 53790075Sobrien } 53890075Sobrien OutputCFile = uniqueFile; 53990075Sobrien std::vector<const char *> LLCArgs; 54090075Sobrien LLCArgs.push_back(LLCPath.c_str()); 54190075Sobrien 54290075Sobrien // Add any extra LLC args. 54390075Sobrien for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 54490075Sobrien LLCArgs.push_back(ToolArgs[i].c_str()); 545117395Skan 546117395Skan LLCArgs.push_back("-o"); 547117395Skan LLCArgs.push_back(OutputCFile.c_str()); // Output to the C file 54890075Sobrien LLCArgs.push_back("-march=c"); // Output C language 54990075Sobrien LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 550117395Skan LLCArgs.push_back(0); 551117395Skan 55290075Sobrien outs() << "<cbe>"; outs().flush(); 55390075Sobrien DEBUG(errs() << "\nAbout to run:\t"; 55490075Sobrien for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 555117395Skan errs() << " " << LLCArgs[i]; 556117395Skan errs() << "\n"; 55790075Sobrien ); 558117395Skan if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), 559117395Skan sys::Path())) 560117395Skan Error = ProcessFailure(LLCPath, &LLCArgs[0]); 561117395Skan return GCC::CFile; 562117395Skan} 563117395Skan 564117395Skanvoid CBE::compileProgram(const std::string &Bitcode, std::string *Error) { 56590075Sobrien sys::Path OutputCFile; 56690075Sobrien OutputCode(Bitcode, OutputCFile, *Error); 567132718Skan OutputCFile.eraseFromDisk(); 568117395Skan} 56990075Sobrien 57090075Sobrienint CBE::ExecuteProgram(const std::string &Bitcode, 57190075Sobrien const std::vector<std::string> &Args, 572169689Skan const std::string &InputFile, 573169689Skan const std::string &OutputFile, 57490075Sobrien std::string *Error, 57590075Sobrien const std::vector<std::string> &ArgsForGCC, 57690075Sobrien const std::vector<std::string> &SharedLibs, 577117395Skan unsigned Timeout, 578117395Skan unsigned MemoryLimit) { 57990075Sobrien sys::Path OutputCFile; 58090075Sobrien OutputCode(Bitcode, OutputCFile, *Error); 58190075Sobrien 58290075Sobrien FileRemover CFileRemove(OutputCFile, !SaveTemps); 58390075Sobrien 584117395Skan std::vector<std::string> GCCArgs(ArgsForGCC); 58590075Sobrien GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 58690075Sobrien 58790075Sobrien return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, 58890075Sobrien InputFile, OutputFile, Error, GCCArgs, 58990075Sobrien Timeout, MemoryLimit); 59090075Sobrien} 591132718Skan 59290075Sobrien/// createCBE - Try to find the 'llc' executable 59390075Sobrien/// 594132718SkanCBE *AbstractInterpreter::createCBE(const char *Argv0, 59590075Sobrien std::string &Message, 59690075Sobrien const std::vector<std::string> *Args, 59790075Sobrien const std::vector<std::string> *GCCArgs) { 59890075Sobrien sys::Path LLCPath = 59990075Sobrien FindExecutable("llc", Argv0, (void *)(intptr_t)&createCBE); 60090075Sobrien if (LLCPath.isEmpty()) { 60190075Sobrien Message = 60290075Sobrien "Cannot find `llc' in executable directory or PATH!\n"; 603169689Skan return 0; 604169689Skan } 60590075Sobrien 60690075Sobrien Message = "Found llc: " + LLCPath.str() + "\n"; 607132718Skan GCC *gcc = GCC::create(Message, GCCArgs); 608132718Skan if (!gcc) { 609132718Skan errs() << Message << "\n"; 610132718Skan exit(1); 611132718Skan } 612132718Skan return new CBE(LLCPath, gcc, Args); 613132718Skan} 614132718Skan 615132718Skan//===---------------------------------------------------------------------===// 616132718Skan// GCC abstraction 617132718Skan// 618132718Skan 619132718Skanstatic bool IsARMArchitecture(std::vector<std::string> Args) { 620169689Skan for (std::vector<std::string>::const_iterator 62190075Sobrien I = Args.begin(), E = Args.end(); I != E; ++I) { 62290075Sobrien StringRef S(*I); 62390075Sobrien if (!S.equals_lower("-arch")) { 62490075Sobrien ++I; 625132718Skan if (I != E && !S.substr(0, strlen("arm")).equals_lower("arm")) 626132718Skan return true; 62790075Sobrien } 62890075Sobrien } 62990075Sobrien 63090075Sobrien return false; 63190075Sobrien} 63290075Sobrien 63390075Sobrienint GCC::ExecuteProgram(const std::string &ProgramFile, 63490075Sobrien const std::vector<std::string> &Args, 63590075Sobrien FileType fileType, 63690075Sobrien const std::string &InputFile, 63790075Sobrien const std::string &OutputFile, 63890075Sobrien std::string *Error, 63990075Sobrien const std::vector<std::string> &ArgsForGCC, 64090075Sobrien unsigned Timeout, 64190075Sobrien unsigned MemoryLimit) { 64290075Sobrien std::vector<const char*> GCCArgs; 64390075Sobrien 64490075Sobrien GCCArgs.push_back(GCCPath.c_str()); 64590075Sobrien 64690075Sobrien if (TargetTriple.getArch() == Triple::x86) 64790075Sobrien GCCArgs.push_back("-m32"); 64890075Sobrien 64990075Sobrien for (std::vector<std::string>::const_iterator 65090075Sobrien I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 65190075Sobrien GCCArgs.push_back(I->c_str()); 65290075Sobrien 65390075Sobrien // Specify -x explicitly in case the extension is wonky 65490075Sobrien if (fileType != ObjectFile) { 65590075Sobrien GCCArgs.push_back("-x"); 65690075Sobrien if (fileType == CFile) { 65790075Sobrien GCCArgs.push_back("c"); 65890075Sobrien GCCArgs.push_back("-fno-strict-aliasing"); 65990075Sobrien } else { 66090075Sobrien GCCArgs.push_back("assembler"); 66190075Sobrien 662117395Skan // For ARM architectures we don't want this flag. bugpoint isn't 66390075Sobrien // explicitly told what architecture it is working on, so we get 66490075Sobrien // it from gcc flags 66590075Sobrien if ((TargetTriple.getOS() == Triple::Darwin) && 66690075Sobrien !IsARMArchitecture(ArgsForGCC)) 66790075Sobrien GCCArgs.push_back("-force_cpusubtype_ALL"); 66890075Sobrien } 66990075Sobrien } 67090075Sobrien 67190075Sobrien GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. 672117395Skan 673117395Skan GCCArgs.push_back("-x"); 67490075Sobrien GCCArgs.push_back("none"); 67590075Sobrien GCCArgs.push_back("-o"); 67690075Sobrien sys::Path OutputBinary (ProgramFile+".gcc.exe"); 67790075Sobrien std::string ErrMsg; 67890075Sobrien if (OutputBinary.makeUnique(true, &ErrMsg)) { 67990075Sobrien errs() << "Error making unique filename: " << ErrMsg << "\n"; 68090075Sobrien exit(1); 68190075Sobrien } 682132718Skan GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 683132718Skan 684132718Skan // Add any arguments intended for GCC. We locate them here because this is 68590075Sobrien // most likely -L and -l options that need to come before other libraries but 686132718Skan // after the source. Other options won't be sensitive to placement on the 68790075Sobrien // command line, so this should be safe. 688169689Skan for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 68990075Sobrien GCCArgs.push_back(ArgsForGCC[i].c_str()); 69090075Sobrien 69190075Sobrien GCCArgs.push_back("-lm"); // Hard-code the math library... 69290075Sobrien GCCArgs.push_back("-O2"); // Optimize the program a bit... 69390075Sobrien#if defined (HAVE_LINK_R) 694169689Skan GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files 695169689Skan#endif 696169689Skan if (TargetTriple.getArch() == Triple::sparc) 697169689Skan GCCArgs.push_back("-mcpu=v9"); 698169689Skan GCCArgs.push_back(0); // NULL terminator 699169689Skan 700169689Skan outs() << "<gcc>"; outs().flush(); 701169689Skan DEBUG(errs() << "\nAbout to run:\t"; 702169689Skan for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 703169689Skan errs() << " " << GCCArgs[i]; 704169689Skan errs() << "\n"; 705169689Skan ); 706169689Skan if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 707169689Skan sys::Path())) { 708169689Skan *Error = ProcessFailure(GCCPath, &GCCArgs[0]); 709169689Skan return -1; 710169689Skan } 711169689Skan 712169689Skan std::vector<const char*> ProgramArgs; 713169689Skan 714169689Skan if (RemoteClientPath.isEmpty()) 715169689Skan ProgramArgs.push_back(OutputBinary.c_str()); 716169689Skan else { 717169689Skan ProgramArgs.push_back(RemoteClientPath.c_str()); 718169689Skan ProgramArgs.push_back(RemoteHost.c_str()); 719169689Skan if (!RemoteUser.empty()) { 720169689Skan ProgramArgs.push_back("-l"); 721169689Skan ProgramArgs.push_back(RemoteUser.c_str()); 722169689Skan } 723169689Skan if (!RemotePort.empty()) { 724169689Skan ProgramArgs.push_back("-p"); 725169689Skan ProgramArgs.push_back(RemotePort.c_str()); 726169689Skan } 727169689Skan if (!RemoteExtra.empty()) { 728169689Skan ProgramArgs.push_back(RemoteExtra.c_str()); 729169689Skan } 730169689Skan 731169689Skan // Full path to the binary. We need to cd to the exec directory because 732169689Skan // there is a dylib there that the exec expects to find in the CWD 733169689Skan char* env_pwd = getenv("PWD"); 734169689Skan std::string Exec = "cd "; 735169689Skan Exec += env_pwd; 736169689Skan Exec += "; ./"; 737169689Skan Exec += OutputBinary.c_str(); 738169689Skan ProgramArgs.push_back(Exec.c_str()); 739169689Skan } 740169689Skan 741169689Skan // Add optional parameters to the running program from Argv 742169689Skan for (unsigned i = 0, e = Args.size(); i != e; ++i) 743169689Skan ProgramArgs.push_back(Args[i].c_str()); 744169689Skan ProgramArgs.push_back(0); // NULL terminator 745169689Skan 746169689Skan // Now that we have a binary, run it! 747169689Skan outs() << "<program>"; outs().flush(); 748169689Skan DEBUG(errs() << "\nAbout to run:\t"; 749169689Skan for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) 750169689Skan errs() << " " << ProgramArgs[i]; 751169689Skan errs() << "\n"; 752169689Skan ); 753169689Skan 754169689Skan FileRemover OutputBinaryRemover(OutputBinary, !SaveTemps); 755169689Skan 756169689Skan if (RemoteClientPath.isEmpty()) { 757169689Skan DEBUG(errs() << "<run locally>"); 758169689Skan return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], 759169689Skan sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 760169689Skan Timeout, MemoryLimit); 761169689Skan } else { 762169689Skan outs() << "<run remotely>"; outs().flush(); 763169689Skan return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), 764169689Skan &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 765169689Skan sys::Path(OutputFile), Timeout, MemoryLimit); 766169689Skan } 767169689Skan} 768169689Skan 769169689Skanint GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 770169689Skan std::string &OutputFile, 771169689Skan const std::vector<std::string> &ArgsForGCC, 772169689Skan std::string &Error) { 773169689Skan sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); 774169689Skan std::string ErrMsg; 775169689Skan if (uniqueFilename.makeUnique(true, &ErrMsg)) { 776169689Skan errs() << "Error making unique filename: " << ErrMsg << "\n"; 777169689Skan exit(1); 77890075Sobrien } 77990075Sobrien OutputFile = uniqueFilename.str(); 78090075Sobrien 78190075Sobrien std::vector<const char*> GCCArgs; 78290075Sobrien 78390075Sobrien GCCArgs.push_back(GCCPath.c_str()); 78490075Sobrien 785169689Skan if (TargetTriple.getArch() == Triple::x86) 78690075Sobrien GCCArgs.push_back("-m32"); 78790075Sobrien 788169689Skan for (std::vector<std::string>::const_iterator 789169689Skan I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 790169689Skan GCCArgs.push_back(I->c_str()); 791169689Skan 792169689Skan // Compile the C/asm file into a shared object 793169689Skan if (fileType != ObjectFile) { 794169689Skan GCCArgs.push_back("-x"); 795132718Skan GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 796169689Skan } 797169689Skan GCCArgs.push_back("-fno-strict-aliasing"); 798169689Skan GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. 799132718Skan GCCArgs.push_back("-x"); 800132718Skan GCCArgs.push_back("none"); 801132718Skan if (TargetTriple.getArch() == Triple::sparc) 802169689Skan GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 803169689Skan else if (TargetTriple.getOS() == Triple::Darwin) { 804169689Skan // link all source files into a single module in data segment, rather than 805169689Skan // generating blocks. dynamic_lookup requires that you set 806169689Skan // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 807169689Skan // bugpoint to just pass that in the environment of GCC. 808169689Skan GCCArgs.push_back("-single_module"); 809169689Skan GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 810169689Skan GCCArgs.push_back("-undefined"); 811169689Skan GCCArgs.push_back("dynamic_lookup"); 812169689Skan } else 813169689Skan GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 814132718Skan 815132718Skan if ((TargetTriple.getArch() == Triple::alpha) || 816132718Skan (TargetTriple.getArch() == Triple::x86_64)) 817132718Skan GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 818132718Skan 819132718Skan if (TargetTriple.getArch() == Triple::sparc) 820132718Skan GCCArgs.push_back("-mcpu=v9"); 821132718Skan 822132718Skan GCCArgs.push_back("-o"); 823132718Skan GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 824132718Skan GCCArgs.push_back("-O2"); // Optimize the program a bit. 825132718Skan 826132718Skan 827132718Skan 828132718Skan // Add any arguments intended for GCC. We locate them here because this is 829132718Skan // most likely -L and -l options that need to come before other libraries but 830132718Skan // after the source. Other options won't be sensitive to placement on the 831132718Skan // command line, so this should be safe. 832132718Skan for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 833132718Skan GCCArgs.push_back(ArgsForGCC[i].c_str()); 834132718Skan GCCArgs.push_back(0); // NULL terminator 835132718Skan 836132718Skan 837132718Skan 838132718Skan outs() << "<gcc>"; outs().flush(); 839132718Skan DEBUG(errs() << "\nAbout to run:\t"; 840132718Skan for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 841132718Skan errs() << " " << GCCArgs[i]; 842132718Skan errs() << "\n"; 843132718Skan ); 844132718Skan if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 845132718Skan sys::Path())) { 846132718Skan Error = ProcessFailure(GCCPath, &GCCArgs[0]); 847132718Skan return 1; 848132718Skan } 849169689Skan return 0; 850169689Skan} 851169689Skan 852132718Skan/// create - Try to find the `gcc' executable 853132718Skan/// 854132718SkanGCC *GCC::create(std::string &Message, 855132718Skan const std::vector<std::string> *Args) { 856132718Skan sys::Path GCCPath = sys::Program::FindProgramByName("gcc"); 857132718Skan if (GCCPath.isEmpty()) { 858132718Skan Message = "Cannot find `gcc' in executable directory or PATH!\n"; 859132718Skan return 0; 860132718Skan } 86190075Sobrien 86290075Sobrien sys::Path RemoteClientPath; 86390075Sobrien if (!RemoteClient.empty()) 86490075Sobrien RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); 86590075Sobrien 86690075Sobrien Message = "Found gcc: " + GCCPath.str() + "\n"; 86790075Sobrien return new GCC(GCCPath, RemoteClientPath, Args); 868132718Skan} 86990075Sobrien