1193323Sed//===-- ToolRunner.cpp ----------------------------------------------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file implements the interfaces described in the ToolRunner.h file. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#define DEBUG_TYPE "toolrunner" 15193323Sed#include "ToolRunner.h" 16249423Sdim#include "llvm/Config/config.h" // for HAVE_LINK_R 17193323Sed#include "llvm/Support/CommandLine.h" 18193323Sed#include "llvm/Support/Debug.h" 19263508Sdim#include "llvm/Support/FileSystem.h" 20193323Sed#include "llvm/Support/FileUtilities.h" 21249423Sdim#include "llvm/Support/Program.h" 22198090Srdivacky#include "llvm/Support/raw_ostream.h" 23193323Sed#include <fstream> 24193323Sed#include <sstream> 25193323Sedusing namespace llvm; 26193323Sed 27198090Srdivackynamespace llvm { 28198090Srdivacky cl::opt<bool> 29198090Srdivacky SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); 30198090Srdivacky} 31198090Srdivacky 32193323Sednamespace { 33193323Sed cl::opt<std::string> 34193323Sed RemoteClient("remote-client", 35193323Sed cl::desc("Remote execution client (rsh/ssh)")); 36193323Sed 37193323Sed cl::opt<std::string> 38193323Sed RemoteHost("remote-host", 39193323Sed cl::desc("Remote execution (rsh/ssh) host")); 40193323Sed 41193323Sed cl::opt<std::string> 42198090Srdivacky RemotePort("remote-port", 43198090Srdivacky cl::desc("Remote execution (rsh/ssh) port")); 44198090Srdivacky 45198090Srdivacky cl::opt<std::string> 46193323Sed RemoteUser("remote-user", 47193323Sed cl::desc("Remote execution (rsh/ssh) user id")); 48193323Sed 49193323Sed cl::opt<std::string> 50193323Sed RemoteExtra("remote-extra-options", 51193323Sed cl::desc("Remote execution (rsh/ssh) extra options")); 52193323Sed} 53193323Sed 54198090Srdivacky/// RunProgramWithTimeout - This function provides an alternate interface 55198090Srdivacky/// to the sys::Program::ExecuteAndWait interface. 56207618Srdivacky/// @see sys::Program::ExecuteAndWait 57263508Sdimstatic int RunProgramWithTimeout(StringRef ProgramPath, 58193323Sed const char **Args, 59263508Sdim StringRef StdInFile, 60263508Sdim StringRef StdOutFile, 61263508Sdim StringRef StdErrFile, 62193323Sed unsigned NumSeconds = 0, 63218885Sdim unsigned MemoryLimit = 0, 64218885Sdim std::string *ErrMsg = 0) { 65263508Sdim const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile }; 66198090Srdivacky 67198090Srdivacky#if 0 // For debug purposes 68198090Srdivacky { 69198090Srdivacky errs() << "RUN:"; 70193323Sed for (unsigned i = 0; Args[i]; ++i) 71198090Srdivacky errs() << " " << Args[i]; 72198090Srdivacky errs() << "\n"; 73193323Sed } 74198090Srdivacky#endif 75193323Sed 76263508Sdim return sys::ExecuteAndWait(ProgramPath, Args, 0, Redirects, 77263508Sdim NumSeconds, MemoryLimit, ErrMsg); 78193323Sed} 79193323Sed 80198090Srdivacky/// RunProgramRemotelyWithTimeout - This function runs the given program 81198090Srdivacky/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 82198090Srdivacky/// Returns the remote program exit code or reports a remote client error if it 83198090Srdivacky/// fails. Remote client is required to return 255 if it failed or program exit 84198090Srdivacky/// code otherwise. 85207618Srdivacky/// @see sys::Program::ExecuteAndWait 86263508Sdimstatic int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath, 87198090Srdivacky const char **Args, 88263508Sdim StringRef StdInFile, 89263508Sdim StringRef StdOutFile, 90263508Sdim StringRef StdErrFile, 91198090Srdivacky unsigned NumSeconds = 0, 92198090Srdivacky unsigned MemoryLimit = 0) { 93263508Sdim const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile }; 94193323Sed 95198090Srdivacky#if 0 // For debug purposes 96198090Srdivacky { 97198090Srdivacky errs() << "RUN:"; 98198090Srdivacky for (unsigned i = 0; Args[i]; ++i) 99198090Srdivacky errs() << " " << Args[i]; 100198090Srdivacky errs() << "\n"; 101198090Srdivacky } 102198090Srdivacky#endif 103193323Sed 104198090Srdivacky // Run the program remotely with the remote client 105263508Sdim int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, 0, 106263508Sdim Redirects, NumSeconds, MemoryLimit); 107198090Srdivacky 108198090Srdivacky // Has the remote client fail? 109198090Srdivacky if (255 == ReturnCode) { 110198090Srdivacky std::ostringstream OS; 111198090Srdivacky OS << "\nError running remote client:\n "; 112198090Srdivacky for (const char **Arg = Args; *Arg; ++Arg) 113198090Srdivacky OS << " " << *Arg; 114198090Srdivacky OS << "\n"; 115198090Srdivacky 116198090Srdivacky // The error message is in the output file, let's print it out from there. 117263508Sdim std::string StdOutFileName = StdOutFile.str(); 118263508Sdim std::ifstream ErrorFile(StdOutFileName.c_str()); 119198090Srdivacky if (ErrorFile) { 120198090Srdivacky std::copy(std::istreambuf_iterator<char>(ErrorFile), 121198090Srdivacky std::istreambuf_iterator<char>(), 122198090Srdivacky std::ostreambuf_iterator<char>(OS)); 123198090Srdivacky ErrorFile.close(); 124198090Srdivacky } 125198090Srdivacky 126236386Sdim errs() << OS.str(); 127198090Srdivacky } 128198090Srdivacky 129198090Srdivacky return ReturnCode; 130198090Srdivacky} 131198090Srdivacky 132263508Sdimstatic std::string ProcessFailure(StringRef ProgPath, const char** Args, 133208599Srdivacky unsigned Timeout = 0, 134208599Srdivacky unsigned MemoryLimit = 0) { 135193323Sed std::ostringstream OS; 136193323Sed OS << "\nError running tool:\n "; 137193323Sed for (const char **Arg = Args; *Arg; ++Arg) 138193323Sed OS << " " << *Arg; 139193323Sed OS << "\n"; 140218885Sdim 141193323Sed // Rerun the compiler, capturing any error messages to print them. 142263508Sdim SmallString<128> ErrorFilename; 143263508Sdim int ErrorFD; 144263508Sdim error_code EC = sys::fs::createTemporaryFile( 145263508Sdim "bugpoint.program_error_messages", "", ErrorFD, ErrorFilename); 146263508Sdim if (EC) { 147263508Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 148193323Sed exit(1); 149193323Sed } 150263508Sdim RunProgramWithTimeout(ProgPath, Args, "", ErrorFilename.str(), 151263508Sdim ErrorFilename.str(), Timeout, MemoryLimit); 152208599Srdivacky // FIXME: check return code ? 153193323Sed 154193323Sed // Print out the error messages generated by GCC if possible... 155193323Sed std::ifstream ErrorFile(ErrorFilename.c_str()); 156193323Sed if (ErrorFile) { 157193323Sed std::copy(std::istreambuf_iterator<char>(ErrorFile), 158193323Sed std::istreambuf_iterator<char>(), 159193323Sed std::ostreambuf_iterator<char>(OS)); 160193323Sed ErrorFile.close(); 161193323Sed } 162193323Sed 163263508Sdim sys::fs::remove(ErrorFilename.c_str()); 164207618Srdivacky return OS.str(); 165193323Sed} 166193323Sed 167193323Sed//===---------------------------------------------------------------------===// 168193323Sed// LLI Implementation of AbstractIntepreter interface 169193323Sed// 170193323Sednamespace { 171193323Sed class LLI : public AbstractInterpreter { 172193323Sed std::string LLIPath; // The path to the LLI executable 173193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 174193323Sed public: 175193323Sed LLI(const std::string &Path, const std::vector<std::string> *Args) 176193323Sed : LLIPath(Path) { 177193323Sed ToolArgs.clear (); 178193323Sed if (Args) { ToolArgs = *Args; } 179193323Sed } 180193323Sed 181193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 182193323Sed const std::vector<std::string> &Args, 183193323Sed const std::string &InputFile, 184193323Sed const std::string &OutputFile, 185207618Srdivacky std::string *Error, 186193323Sed const std::vector<std::string> &GCCArgs, 187193323Sed const std::vector<std::string> &SharedLibs = 188193323Sed std::vector<std::string>(), 189193323Sed unsigned Timeout = 0, 190193323Sed unsigned MemoryLimit = 0); 191193323Sed }; 192193323Sed} 193193323Sed 194193323Sedint LLI::ExecuteProgram(const std::string &Bitcode, 195193323Sed const std::vector<std::string> &Args, 196193323Sed const std::string &InputFile, 197193323Sed const std::string &OutputFile, 198207618Srdivacky std::string *Error, 199193323Sed const std::vector<std::string> &GCCArgs, 200193323Sed const std::vector<std::string> &SharedLibs, 201193323Sed unsigned Timeout, 202193323Sed unsigned MemoryLimit) { 203193323Sed std::vector<const char*> LLIArgs; 204193323Sed LLIArgs.push_back(LLIPath.c_str()); 205193323Sed LLIArgs.push_back("-force-interpreter=true"); 206193323Sed 207218885Sdim for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), 208218885Sdim e = SharedLibs.end(); i != e; ++i) { 209199481Srdivacky LLIArgs.push_back("-load"); 210199481Srdivacky LLIArgs.push_back((*i).c_str()); 211199481Srdivacky } 212199481Srdivacky 213193323Sed // Add any extra LLI args. 214193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 215193323Sed LLIArgs.push_back(ToolArgs[i].c_str()); 216193323Sed 217193323Sed LLIArgs.push_back(Bitcode.c_str()); 218193323Sed // Add optional parameters to the running program from Argv 219193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 220193323Sed LLIArgs.push_back(Args[i].c_str()); 221193323Sed LLIArgs.push_back(0); 222193323Sed 223198090Srdivacky outs() << "<lli>"; outs().flush(); 224198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 225193323Sed for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) 226198090Srdivacky errs() << " " << LLIArgs[i]; 227198090Srdivacky errs() << "\n"; 228193323Sed ); 229263508Sdim return RunProgramWithTimeout(LLIPath, &LLIArgs[0], 230263508Sdim InputFile, OutputFile, OutputFile, 231218885Sdim Timeout, MemoryLimit, Error); 232193323Sed} 233193323Sed 234234353Sdimvoid AbstractInterpreter::anchor() { } 235234353Sdim 236263508Sdim#if defined(LLVM_ON_UNIX) 237263508Sdimconst char EXESuffix[] = ""; 238263508Sdim#elif defined (LLVM_ON_WIN32) 239263508Sdimconst char EXESuffix[] = "exe"; 240263508Sdim#endif 241263508Sdim 242263508Sdim/// Prepend the path to the program being executed 243263508Sdim/// to \p ExeName, given the value of argv[0] and the address of main() 244263508Sdim/// itself. This allows us to find another LLVM tool if it is built in the same 245263508Sdim/// directory. An empty string is returned on error; note that this function 246263508Sdim/// just mainpulates the path and doesn't check for executability. 247263508Sdim/// @brief Find a named executable. 248263508Sdimstatic std::string PrependMainExecutablePath(const std::string &ExeName, 249263508Sdim const char *Argv0, 250263508Sdim void *MainAddr) { 251263508Sdim // Check the directory that the calling program is in. We can do 252263508Sdim // this if ProgramPath contains at least one / character, indicating that it 253263508Sdim // is a relative path to the executable itself. 254263508Sdim std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr); 255263508Sdim StringRef Result = sys::path::parent_path(Main); 256263508Sdim 257263508Sdim if (!Result.empty()) { 258263508Sdim SmallString<128> Storage = Result; 259263508Sdim sys::path::append(Storage, ExeName); 260263508Sdim sys::path::replace_extension(Storage, EXESuffix); 261263508Sdim return Storage.str(); 262263508Sdim } 263263508Sdim 264263508Sdim return Result.str(); 265263508Sdim} 266263508Sdim 267193323Sed// LLI create method - Try to find the LLI executable 268198090SrdivackyAbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, 269193323Sed std::string &Message, 270193323Sed const std::vector<std::string> *ToolArgs) { 271198090Srdivacky std::string LLIPath = 272263508Sdim PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createLLI); 273193323Sed if (!LLIPath.empty()) { 274193323Sed Message = "Found lli: " + LLIPath + "\n"; 275193323Sed return new LLI(LLIPath, ToolArgs); 276193323Sed } 277193323Sed 278218885Sdim Message = "Cannot find `lli' in executable directory!\n"; 279193323Sed return 0; 280193323Sed} 281193323Sed 282193323Sed//===---------------------------------------------------------------------===// 283218885Sdim// Custom compiler command implementation of AbstractIntepreter interface 284218885Sdim// 285218885Sdim// Allows using a custom command for compiling the bitcode, thus allows, for 286218885Sdim// example, to compile a bitcode fragment without linking or executing, then 287218885Sdim// using a custom wrapper script to check for compiler errors. 288218885Sdimnamespace { 289218885Sdim class CustomCompiler : public AbstractInterpreter { 290218885Sdim std::string CompilerCommand; 291218885Sdim std::vector<std::string> CompilerArgs; 292218885Sdim public: 293218885Sdim CustomCompiler( 294218885Sdim const std::string &CompilerCmd, std::vector<std::string> CompArgs) : 295218885Sdim CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {} 296218885Sdim 297218885Sdim virtual void compileProgram(const std::string &Bitcode, 298218885Sdim std::string *Error, 299218885Sdim unsigned Timeout = 0, 300218885Sdim unsigned MemoryLimit = 0); 301218885Sdim 302218885Sdim virtual int ExecuteProgram(const std::string &Bitcode, 303218885Sdim const std::vector<std::string> &Args, 304218885Sdim const std::string &InputFile, 305218885Sdim const std::string &OutputFile, 306218885Sdim std::string *Error, 307218885Sdim const std::vector<std::string> &GCCArgs = 308218885Sdim std::vector<std::string>(), 309218885Sdim const std::vector<std::string> &SharedLibs = 310218885Sdim std::vector<std::string>(), 311218885Sdim unsigned Timeout = 0, 312218885Sdim unsigned MemoryLimit = 0) { 313218885Sdim *Error = "Execution not supported with -compile-custom"; 314218885Sdim return -1; 315218885Sdim } 316218885Sdim }; 317218885Sdim} 318218885Sdim 319218885Sdimvoid CustomCompiler::compileProgram(const std::string &Bitcode, 320218885Sdim std::string *Error, 321218885Sdim unsigned Timeout, 322218885Sdim unsigned MemoryLimit) { 323218885Sdim 324218885Sdim std::vector<const char*> ProgramArgs; 325218885Sdim ProgramArgs.push_back(CompilerCommand.c_str()); 326218885Sdim 327218885Sdim for (std::size_t i = 0; i < CompilerArgs.size(); ++i) 328218885Sdim ProgramArgs.push_back(CompilerArgs.at(i).c_str()); 329218885Sdim ProgramArgs.push_back(Bitcode.c_str()); 330218885Sdim ProgramArgs.push_back(0); 331218885Sdim 332218885Sdim // Add optional parameters to the running program from Argv 333218885Sdim for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) 334218885Sdim ProgramArgs.push_back(CompilerArgs[i].c_str()); 335218885Sdim 336263508Sdim if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0], 337263508Sdim "", "", "", 338218885Sdim Timeout, MemoryLimit, Error)) 339263508Sdim *Error = ProcessFailure(CompilerCommand, &ProgramArgs[0], 340218885Sdim Timeout, MemoryLimit); 341218885Sdim} 342218885Sdim 343218885Sdim//===---------------------------------------------------------------------===// 344193323Sed// Custom execution command implementation of AbstractIntepreter interface 345193323Sed// 346193323Sed// Allows using a custom command for executing the bitcode, thus allows, 347218885Sdim// for example, to invoke a cross compiler for code generation followed by 348193323Sed// a simulator that executes the generated binary. 349193323Sednamespace { 350193323Sed class CustomExecutor : public AbstractInterpreter { 351193323Sed std::string ExecutionCommand; 352193323Sed std::vector<std::string> ExecutorArgs; 353193323Sed public: 354193323Sed CustomExecutor( 355193323Sed const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : 356193323Sed ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} 357193323Sed 358193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 359193323Sed const std::vector<std::string> &Args, 360193323Sed const std::string &InputFile, 361193323Sed const std::string &OutputFile, 362207618Srdivacky std::string *Error, 363193323Sed const std::vector<std::string> &GCCArgs, 364193323Sed const std::vector<std::string> &SharedLibs = 365207618Srdivacky std::vector<std::string>(), 366193323Sed unsigned Timeout = 0, 367193323Sed unsigned MemoryLimit = 0); 368193323Sed }; 369193323Sed} 370193323Sed 371193323Sedint CustomExecutor::ExecuteProgram(const std::string &Bitcode, 372193323Sed const std::vector<std::string> &Args, 373193323Sed const std::string &InputFile, 374193323Sed const std::string &OutputFile, 375207618Srdivacky std::string *Error, 376193323Sed const std::vector<std::string> &GCCArgs, 377193323Sed const std::vector<std::string> &SharedLibs, 378193323Sed unsigned Timeout, 379193323Sed unsigned MemoryLimit) { 380193323Sed 381193323Sed std::vector<const char*> ProgramArgs; 382193323Sed ProgramArgs.push_back(ExecutionCommand.c_str()); 383193323Sed 384193323Sed for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 385193323Sed ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); 386193323Sed ProgramArgs.push_back(Bitcode.c_str()); 387193323Sed ProgramArgs.push_back(0); 388193323Sed 389193323Sed // Add optional parameters to the running program from Argv 390207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 391193323Sed ProgramArgs.push_back(Args[i].c_str()); 392193323Sed 393193323Sed return RunProgramWithTimeout( 394263508Sdim ExecutionCommand, 395263508Sdim &ProgramArgs[0], InputFile, OutputFile, 396263508Sdim OutputFile, Timeout, MemoryLimit, Error); 397193323Sed} 398193323Sed 399218885Sdim// Tokenize the CommandLine to the command and the args to allow 400218885Sdim// defining a full command line as the command instead of just the 401218885Sdim// executed program. We cannot just pass the whole string after the command 402218885Sdim// as a single argument because then program sees only a single 403218885Sdim// command line argument (with spaces in it: "foo bar" instead 404218885Sdim// of "foo" and "bar"). 405218885Sdim// 406218885Sdim// code borrowed from: 407218885Sdim// http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html 408218885Sdimstatic void lexCommand(std::string &Message, const std::string &CommandLine, 409218885Sdim std::string &CmdPath, std::vector<std::string> Args) { 410193323Sed 411193323Sed std::string Command = ""; 412193323Sed std::string delimiters = " "; 413193323Sed 414218885Sdim std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0); 415218885Sdim std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos); 416193323Sed 417193323Sed while (std::string::npos != pos || std::string::npos != lastPos) { 418218885Sdim std::string token = CommandLine.substr(lastPos, pos - lastPos); 419193323Sed if (Command == "") 420193323Sed Command = token; 421193323Sed else 422193323Sed Args.push_back(token); 423193323Sed // Skip delimiters. Note the "not_of" 424218885Sdim lastPos = CommandLine.find_first_not_of(delimiters, pos); 425193323Sed // Find next "non-delimiter" 426218885Sdim pos = CommandLine.find_first_of(delimiters, lastPos); 427193323Sed } 428193323Sed 429263508Sdim CmdPath = sys::FindProgramByName(Command); 430193323Sed if (CmdPath.empty()) { 431218885Sdim Message = 432218885Sdim std::string("Cannot find '") + Command + 433218885Sdim "' in PATH!\n"; 434218885Sdim return; 435193323Sed } 436193323Sed 437193323Sed Message = "Found command in: " + CmdPath + "\n"; 438218885Sdim} 439193323Sed 440218885Sdim// Custom execution environment create method, takes the execution command 441218885Sdim// as arguments 442218885SdimAbstractInterpreter *AbstractInterpreter::createCustomCompiler( 443218885Sdim std::string &Message, 444218885Sdim const std::string &CompileCommandLine) { 445218885Sdim 446218885Sdim std::string CmdPath; 447218885Sdim std::vector<std::string> Args; 448218885Sdim lexCommand(Message, CompileCommandLine, CmdPath, Args); 449218885Sdim if (CmdPath.empty()) 450218885Sdim return 0; 451218885Sdim 452218885Sdim return new CustomCompiler(CmdPath, Args); 453218885Sdim} 454218885Sdim 455218885Sdim// Custom execution environment create method, takes the execution command 456218885Sdim// as arguments 457218885SdimAbstractInterpreter *AbstractInterpreter::createCustomExecutor( 458218885Sdim std::string &Message, 459218885Sdim const std::string &ExecCommandLine) { 460218885Sdim 461218885Sdim 462218885Sdim std::string CmdPath; 463218885Sdim std::vector<std::string> Args; 464218885Sdim lexCommand(Message, ExecCommandLine, CmdPath, Args); 465218885Sdim if (CmdPath.empty()) 466218885Sdim return 0; 467218885Sdim 468193323Sed return new CustomExecutor(CmdPath, Args); 469193323Sed} 470193323Sed 471193323Sed//===----------------------------------------------------------------------===// 472193323Sed// LLC Implementation of AbstractIntepreter interface 473193323Sed// 474218885SdimGCC::FileType LLC::OutputCode(const std::string &Bitcode, 475263508Sdim std::string &OutputAsmFile, std::string &Error, 476208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 477205218Srdivacky const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); 478263508Sdim 479263508Sdim SmallString<128> UniqueFile; 480263508Sdim error_code EC = 481263508Sdim sys::fs::createUniqueFile(Bitcode + "-%%%%%%%" + Suffix, UniqueFile); 482263508Sdim if (EC) { 483263508Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 484193323Sed exit(1); 485193323Sed } 486263508Sdim OutputAsmFile = UniqueFile.str(); 487193323Sed std::vector<const char *> LLCArgs; 488205218Srdivacky LLCArgs.push_back(LLCPath.c_str()); 489193323Sed 490193323Sed // Add any extra LLC args. 491193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 492193323Sed LLCArgs.push_back(ToolArgs[i].c_str()); 493193323Sed 494205218Srdivacky LLCArgs.push_back("-o"); 495205218Srdivacky LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file 496205218Srdivacky LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 497218885Sdim 498205218Srdivacky if (UseIntegratedAssembler) 499205218Srdivacky LLCArgs.push_back("-filetype=obj"); 500218885Sdim 501193323Sed LLCArgs.push_back (0); 502193323Sed 503205218Srdivacky outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); 504205218Srdivacky outs().flush(); 505198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 506207618Srdivacky for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 507198090Srdivacky errs() << " " << LLCArgs[i]; 508198090Srdivacky errs() << "\n"; 509193323Sed ); 510263508Sdim if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], 511263508Sdim "", "", "", 512208599Srdivacky Timeout, MemoryLimit)) 513263508Sdim Error = ProcessFailure(LLCPath, &LLCArgs[0], 514208599Srdivacky Timeout, MemoryLimit); 515218885Sdim return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; 516193323Sed} 517193323Sed 518208599Srdivackyvoid LLC::compileProgram(const std::string &Bitcode, std::string *Error, 519208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 520263508Sdim std::string OutputAsmFile; 521208599Srdivacky OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); 522263508Sdim sys::fs::remove(OutputAsmFile); 523193323Sed} 524193323Sed 525193323Sedint LLC::ExecuteProgram(const std::string &Bitcode, 526193323Sed const std::vector<std::string> &Args, 527193323Sed const std::string &InputFile, 528193323Sed const std::string &OutputFile, 529207618Srdivacky std::string *Error, 530193323Sed const std::vector<std::string> &ArgsForGCC, 531193323Sed const std::vector<std::string> &SharedLibs, 532193323Sed unsigned Timeout, 533193323Sed unsigned MemoryLimit) { 534193323Sed 535263508Sdim std::string OutputAsmFile; 536208599Srdivacky GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, 537208599Srdivacky MemoryLimit); 538263508Sdim FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); 539193323Sed 540193323Sed std::vector<std::string> GCCArgs(ArgsForGCC); 541193323Sed GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 542193323Sed 543193323Sed // Assuming LLC worked, compile the result with GCC and run it. 544263508Sdim return gcc->ExecuteProgram(OutputAsmFile, Args, FileKind, 545207618Srdivacky InputFile, OutputFile, Error, GCCArgs, 546193323Sed Timeout, MemoryLimit); 547193323Sed} 548193323Sed 549193323Sed/// createLLC - Try to find the LLC executable 550193323Sed/// 551198090SrdivackyLLC *AbstractInterpreter::createLLC(const char *Argv0, 552193323Sed std::string &Message, 553208599Srdivacky const std::string &GCCBinary, 554193323Sed const std::vector<std::string> *Args, 555205218Srdivacky const std::vector<std::string> *GCCArgs, 556205218Srdivacky bool UseIntegratedAssembler) { 557198090Srdivacky std::string LLCPath = 558263508Sdim PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t) & createLLC); 559193323Sed if (LLCPath.empty()) { 560218885Sdim Message = "Cannot find `llc' in executable directory!\n"; 561193323Sed return 0; 562193323Sed } 563193323Sed 564208599Srdivacky GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); 565193323Sed if (!gcc) { 566198090Srdivacky errs() << Message << "\n"; 567193323Sed exit(1); 568193323Sed } 569249423Sdim Message = "Found llc: " + LLCPath + "\n"; 570208599Srdivacky return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler); 571193323Sed} 572193323Sed 573193323Sed//===---------------------------------------------------------------------===// 574193323Sed// JIT Implementation of AbstractIntepreter interface 575193323Sed// 576193323Sednamespace { 577193323Sed class JIT : public AbstractInterpreter { 578193323Sed std::string LLIPath; // The path to the LLI executable 579193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 580193323Sed public: 581193323Sed JIT(const std::string &Path, const std::vector<std::string> *Args) 582193323Sed : LLIPath(Path) { 583193323Sed ToolArgs.clear (); 584193323Sed if (Args) { ToolArgs = *Args; } 585193323Sed } 586193323Sed 587193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 588193323Sed const std::vector<std::string> &Args, 589193323Sed const std::string &InputFile, 590193323Sed const std::string &OutputFile, 591207618Srdivacky std::string *Error, 592193323Sed const std::vector<std::string> &GCCArgs = 593193323Sed std::vector<std::string>(), 594193323Sed const std::vector<std::string> &SharedLibs = 595218885Sdim std::vector<std::string>(), 596207618Srdivacky unsigned Timeout = 0, 597207618Srdivacky unsigned MemoryLimit = 0); 598193323Sed }; 599193323Sed} 600193323Sed 601193323Sedint JIT::ExecuteProgram(const std::string &Bitcode, 602193323Sed const std::vector<std::string> &Args, 603193323Sed const std::string &InputFile, 604193323Sed const std::string &OutputFile, 605207618Srdivacky std::string *Error, 606193323Sed const std::vector<std::string> &GCCArgs, 607193323Sed const std::vector<std::string> &SharedLibs, 608193323Sed unsigned Timeout, 609193323Sed unsigned MemoryLimit) { 610193323Sed // Construct a vector of parameters, incorporating those from the command-line 611193323Sed std::vector<const char*> JITArgs; 612193323Sed JITArgs.push_back(LLIPath.c_str()); 613193323Sed JITArgs.push_back("-force-interpreter=false"); 614193323Sed 615193323Sed // Add any extra LLI args. 616193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 617193323Sed JITArgs.push_back(ToolArgs[i].c_str()); 618193323Sed 619193323Sed for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 620193323Sed JITArgs.push_back("-load"); 621193323Sed JITArgs.push_back(SharedLibs[i].c_str()); 622193323Sed } 623193323Sed JITArgs.push_back(Bitcode.c_str()); 624193323Sed // Add optional parameters to the running program from Argv 625193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 626193323Sed JITArgs.push_back(Args[i].c_str()); 627193323Sed JITArgs.push_back(0); 628193323Sed 629198090Srdivacky outs() << "<jit>"; outs().flush(); 630198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 631193323Sed for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) 632198090Srdivacky errs() << " " << JITArgs[i]; 633198090Srdivacky errs() << "\n"; 634193323Sed ); 635198090Srdivacky DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 636263508Sdim return RunProgramWithTimeout(LLIPath, &JITArgs[0], 637263508Sdim InputFile, OutputFile, OutputFile, 638218885Sdim Timeout, MemoryLimit, Error); 639193323Sed} 640193323Sed 641193323Sed/// createJIT - Try to find the LLI executable 642193323Sed/// 643198090SrdivackyAbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, 644193323Sed std::string &Message, const std::vector<std::string> *Args) { 645198090Srdivacky std::string LLIPath = 646263508Sdim PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createJIT); 647193323Sed if (!LLIPath.empty()) { 648193323Sed Message = "Found lli: " + LLIPath + "\n"; 649193323Sed return new JIT(LLIPath, Args); 650193323Sed } 651193323Sed 652218885Sdim Message = "Cannot find `lli' in executable directory!\n"; 653193323Sed return 0; 654193323Sed} 655193323Sed 656193323Sed//===---------------------------------------------------------------------===// 657193323Sed// GCC abstraction 658193323Sed// 659198090Srdivacky 660212793Sdimstatic bool IsARMArchitecture(std::vector<const char*> Args) { 661212793Sdim for (std::vector<const char*>::const_iterator 662198090Srdivacky I = Args.begin(), E = Args.end(); I != E; ++I) { 663208599Srdivacky if (StringRef(*I).equals_lower("-arch")) { 664198090Srdivacky ++I; 665263508Sdim if (I != E && StringRef(*I).startswith_lower("arm")) 666198090Srdivacky return true; 667198090Srdivacky } 668198090Srdivacky } 669198090Srdivacky 670198090Srdivacky return false; 671198090Srdivacky} 672198090Srdivacky 673193323Sedint GCC::ExecuteProgram(const std::string &ProgramFile, 674193323Sed const std::vector<std::string> &Args, 675193323Sed FileType fileType, 676193323Sed const std::string &InputFile, 677193323Sed const std::string &OutputFile, 678207618Srdivacky std::string *Error, 679193323Sed const std::vector<std::string> &ArgsForGCC, 680193323Sed unsigned Timeout, 681193323Sed unsigned MemoryLimit) { 682193323Sed std::vector<const char*> GCCArgs; 683193323Sed 684193323Sed GCCArgs.push_back(GCCPath.c_str()); 685193323Sed 686205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 687205218Srdivacky GCCArgs.push_back("-m32"); 688205218Srdivacky 689193323Sed for (std::vector<std::string>::const_iterator 690193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 691193323Sed GCCArgs.push_back(I->c_str()); 692193323Sed 693193323Sed // Specify -x explicitly in case the extension is wonky 694205218Srdivacky if (fileType != ObjectFile) { 695205218Srdivacky GCCArgs.push_back("-x"); 696205218Srdivacky if (fileType == CFile) { 697205218Srdivacky GCCArgs.push_back("c"); 698205218Srdivacky GCCArgs.push_back("-fno-strict-aliasing"); 699205218Srdivacky } else { 700205218Srdivacky GCCArgs.push_back("assembler"); 701198090Srdivacky 702205218Srdivacky // For ARM architectures we don't want this flag. bugpoint isn't 703205218Srdivacky // explicitly told what architecture it is working on, so we get 704205218Srdivacky // it from gcc flags 705221337Sdim if (TargetTriple.isOSDarwin() && !IsARMArchitecture(GCCArgs)) 706205218Srdivacky GCCArgs.push_back("-force_cpusubtype_ALL"); 707205218Srdivacky } 708193323Sed } 709218885Sdim 710205218Srdivacky GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. 711218885Sdim 712193323Sed GCCArgs.push_back("-x"); 713193323Sed GCCArgs.push_back("none"); 714193323Sed GCCArgs.push_back("-o"); 715263508Sdim 716263508Sdim SmallString<128> OutputBinary; 717263508Sdim error_code EC = 718263508Sdim sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.gcc.exe", OutputBinary); 719263508Sdim if (EC) { 720263508Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 721193323Sed exit(1); 722193323Sed } 723193323Sed GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 724193323Sed 725193323Sed // Add any arguments intended for GCC. We locate them here because this is 726193323Sed // most likely -L and -l options that need to come before other libraries but 727193323Sed // after the source. Other options won't be sensitive to placement on the 728193323Sed // command line, so this should be safe. 729193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 730193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 731193323Sed 732193323Sed GCCArgs.push_back("-lm"); // Hard-code the math library... 733193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit... 734193323Sed#if defined (HAVE_LINK_R) 735193323Sed GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files 736193323Sed#endif 737198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 738198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 739193323Sed GCCArgs.push_back(0); // NULL terminator 740193323Sed 741198090Srdivacky outs() << "<gcc>"; outs().flush(); 742198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 743207618Srdivacky for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 744198090Srdivacky errs() << " " << GCCArgs[i]; 745198090Srdivacky errs() << "\n"; 746193323Sed ); 747263508Sdim if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) { 748207618Srdivacky *Error = ProcessFailure(GCCPath, &GCCArgs[0]); 749207618Srdivacky return -1; 750193323Sed } 751193323Sed 752193323Sed std::vector<const char*> ProgramArgs; 753193323Sed 754212793Sdim // Declared here so that the destructor only runs after 755212793Sdim // ProgramArgs is used. 756212793Sdim std::string Exec; 757212793Sdim 758263508Sdim if (RemoteClientPath.empty()) 759193323Sed ProgramArgs.push_back(OutputBinary.c_str()); 760193323Sed else { 761193323Sed ProgramArgs.push_back(RemoteClientPath.c_str()); 762193323Sed ProgramArgs.push_back(RemoteHost.c_str()); 763198090Srdivacky if (!RemoteUser.empty()) { 764198090Srdivacky ProgramArgs.push_back("-l"); 765198090Srdivacky ProgramArgs.push_back(RemoteUser.c_str()); 766198090Srdivacky } 767198090Srdivacky if (!RemotePort.empty()) { 768198090Srdivacky ProgramArgs.push_back("-p"); 769198090Srdivacky ProgramArgs.push_back(RemotePort.c_str()); 770198090Srdivacky } 771193323Sed if (!RemoteExtra.empty()) { 772193323Sed ProgramArgs.push_back(RemoteExtra.c_str()); 773193323Sed } 774193323Sed 775198090Srdivacky // Full path to the binary. We need to cd to the exec directory because 776198090Srdivacky // there is a dylib there that the exec expects to find in the CWD 777193323Sed char* env_pwd = getenv("PWD"); 778212793Sdim Exec = "cd "; 779193323Sed Exec += env_pwd; 780193323Sed Exec += "; ./"; 781193323Sed Exec += OutputBinary.c_str(); 782193323Sed ProgramArgs.push_back(Exec.c_str()); 783193323Sed } 784193323Sed 785193323Sed // Add optional parameters to the running program from Argv 786207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 787193323Sed ProgramArgs.push_back(Args[i].c_str()); 788193323Sed ProgramArgs.push_back(0); // NULL terminator 789193323Sed 790193323Sed // Now that we have a binary, run it! 791198090Srdivacky outs() << "<program>"; outs().flush(); 792198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 793207618Srdivacky for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) 794198090Srdivacky errs() << " " << ProgramArgs[i]; 795198090Srdivacky errs() << "\n"; 796193323Sed ); 797193323Sed 798221337Sdim FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); 799193323Sed 800263508Sdim if (RemoteClientPath.empty()) { 801207618Srdivacky DEBUG(errs() << "<run locally>"); 802263508Sdim int ExitCode = RunProgramWithTimeout(OutputBinary.str(), &ProgramArgs[0], 803263508Sdim InputFile, OutputFile, OutputFile, 804263508Sdim Timeout, MemoryLimit, Error); 805223013Sdim // Treat a signal (usually SIGSEGV) or timeout as part of the program output 806223013Sdim // so that crash-causing miscompilation is handled seamlessly. 807223013Sdim if (ExitCode < -1) { 808223013Sdim std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 809223013Sdim outFile << *Error << '\n'; 810223013Sdim outFile.close(); 811223013Sdim Error->clear(); 812223013Sdim } 813223013Sdim return ExitCode; 814198090Srdivacky } else { 815198090Srdivacky outs() << "<run remotely>"; outs().flush(); 816263508Sdim return RunProgramRemotelyWithTimeout(RemoteClientPath, 817263508Sdim &ProgramArgs[0], InputFile, OutputFile, 818263508Sdim OutputFile, Timeout, MemoryLimit); 819198090Srdivacky } 820193323Sed} 821193323Sed 822193323Sedint GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 823193323Sed std::string &OutputFile, 824207618Srdivacky const std::vector<std::string> &ArgsForGCC, 825207618Srdivacky std::string &Error) { 826263508Sdim SmallString<128> UniqueFilename; 827263508Sdim error_code EC = sys::fs::createUniqueFile( 828263508Sdim InputFile + "-%%%%%%%" + LTDL_SHLIB_EXT, UniqueFilename); 829263508Sdim if (EC) { 830263508Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 831193323Sed exit(1); 832193323Sed } 833263508Sdim OutputFile = UniqueFilename.str(); 834193323Sed 835193323Sed std::vector<const char*> GCCArgs; 836218885Sdim 837193323Sed GCCArgs.push_back(GCCPath.c_str()); 838193323Sed 839205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 840205218Srdivacky GCCArgs.push_back("-m32"); 841205218Srdivacky 842193323Sed for (std::vector<std::string>::const_iterator 843193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 844193323Sed GCCArgs.push_back(I->c_str()); 845193323Sed 846193323Sed // Compile the C/asm file into a shared object 847205218Srdivacky if (fileType != ObjectFile) { 848205218Srdivacky GCCArgs.push_back("-x"); 849205218Srdivacky GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 850205218Srdivacky } 851193323Sed GCCArgs.push_back("-fno-strict-aliasing"); 852193323Sed GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. 853193323Sed GCCArgs.push_back("-x"); 854193323Sed GCCArgs.push_back("none"); 855198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 856198090Srdivacky GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 857221337Sdim else if (TargetTriple.isOSDarwin()) { 858198090Srdivacky // link all source files into a single module in data segment, rather than 859218885Sdim // generating blocks. dynamic_lookup requires that you set 860198090Srdivacky // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 861198090Srdivacky // bugpoint to just pass that in the environment of GCC. 862198090Srdivacky GCCArgs.push_back("-single_module"); 863198090Srdivacky GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 864198090Srdivacky GCCArgs.push_back("-undefined"); 865198090Srdivacky GCCArgs.push_back("dynamic_lookup"); 866198090Srdivacky } else 867198090Srdivacky GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 868193323Sed 869234353Sdim if (TargetTriple.getArch() == Triple::x86_64) 870198090Srdivacky GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 871198090Srdivacky 872198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 873198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 874198090Srdivacky 875193323Sed GCCArgs.push_back("-o"); 876193323Sed GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 877193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit. 878193323Sed 879218885Sdim 880218885Sdim 881193323Sed // Add any arguments intended for GCC. We locate them here because this is 882193323Sed // most likely -L and -l options that need to come before other libraries but 883193323Sed // after the source. Other options won't be sensitive to placement on the 884193323Sed // command line, so this should be safe. 885193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 886193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 887193323Sed GCCArgs.push_back(0); // NULL terminator 888193323Sed 889193323Sed 890218885Sdim 891198090Srdivacky outs() << "<gcc>"; outs().flush(); 892198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 893207618Srdivacky for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 894198090Srdivacky errs() << " " << GCCArgs[i]; 895198090Srdivacky errs() << "\n"; 896193323Sed ); 897263508Sdim if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) { 898207618Srdivacky Error = ProcessFailure(GCCPath, &GCCArgs[0]); 899193323Sed return 1; 900193323Sed } 901193323Sed return 0; 902193323Sed} 903193323Sed 904193323Sed/// create - Try to find the `gcc' executable 905193323Sed/// 906198090SrdivackyGCC *GCC::create(std::string &Message, 907208599Srdivacky const std::string &GCCBinary, 908193323Sed const std::vector<std::string> *Args) { 909263508Sdim std::string GCCPath = sys::FindProgramByName(GCCBinary); 910263508Sdim if (GCCPath.empty()) { 911218885Sdim Message = "Cannot find `"+ GCCBinary +"' in PATH!\n"; 912193323Sed return 0; 913193323Sed } 914193323Sed 915263508Sdim std::string RemoteClientPath; 916193323Sed if (!RemoteClient.empty()) 917263508Sdim RemoteClientPath = sys::FindProgramByName(RemoteClient); 918193323Sed 919263508Sdim Message = "Found gcc: " + GCCPath + "\n"; 920193323Sed return new GCC(GCCPath, RemoteClientPath, Args); 921193323Sed} 922