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" 19193323Sed#include "llvm/Support/FileUtilities.h" 20249423Sdim#include "llvm/Support/Program.h" 21198090Srdivacky#include "llvm/Support/raw_ostream.h" 22193323Sed#include <fstream> 23193323Sed#include <sstream> 24193323Sedusing namespace llvm; 25193323Sed 26198090Srdivackynamespace llvm { 27198090Srdivacky cl::opt<bool> 28198090Srdivacky SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); 29198090Srdivacky} 30198090Srdivacky 31193323Sednamespace { 32193323Sed cl::opt<std::string> 33193323Sed RemoteClient("remote-client", 34193323Sed cl::desc("Remote execution client (rsh/ssh)")); 35193323Sed 36193323Sed cl::opt<std::string> 37193323Sed RemoteHost("remote-host", 38193323Sed cl::desc("Remote execution (rsh/ssh) host")); 39193323Sed 40193323Sed cl::opt<std::string> 41198090Srdivacky RemotePort("remote-port", 42198090Srdivacky cl::desc("Remote execution (rsh/ssh) port")); 43198090Srdivacky 44198090Srdivacky cl::opt<std::string> 45193323Sed RemoteUser("remote-user", 46193323Sed cl::desc("Remote execution (rsh/ssh) user id")); 47193323Sed 48193323Sed cl::opt<std::string> 49193323Sed RemoteExtra("remote-extra-options", 50193323Sed cl::desc("Remote execution (rsh/ssh) extra options")); 51193323Sed} 52193323Sed 53198090Srdivacky/// RunProgramWithTimeout - This function provides an alternate interface 54198090Srdivacky/// to the sys::Program::ExecuteAndWait interface. 55207618Srdivacky/// @see sys::Program::ExecuteAndWait 56193323Sedstatic int RunProgramWithTimeout(const sys::Path &ProgramPath, 57193323Sed const char **Args, 58193323Sed const sys::Path &StdInFile, 59193323Sed const sys::Path &StdOutFile, 60193323Sed const sys::Path &StdErrFile, 61193323Sed unsigned NumSeconds = 0, 62218885Sdim unsigned MemoryLimit = 0, 63218885Sdim std::string *ErrMsg = 0) { 64193323Sed const sys::Path* redirects[3]; 65193323Sed redirects[0] = &StdInFile; 66193323Sed redirects[1] = &StdOutFile; 67193323Sed redirects[2] = &StdErrFile; 68198090Srdivacky 69198090Srdivacky#if 0 // For debug purposes 70198090Srdivacky { 71198090Srdivacky errs() << "RUN:"; 72193323Sed for (unsigned i = 0; Args[i]; ++i) 73198090Srdivacky errs() << " " << Args[i]; 74198090Srdivacky errs() << "\n"; 75193323Sed } 76198090Srdivacky#endif 77193323Sed 78193323Sed return 79193323Sed sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, 80218885Sdim NumSeconds, MemoryLimit, ErrMsg); 81193323Sed} 82193323Sed 83198090Srdivacky/// RunProgramRemotelyWithTimeout - This function runs the given program 84198090Srdivacky/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 85198090Srdivacky/// Returns the remote program exit code or reports a remote client error if it 86198090Srdivacky/// fails. Remote client is required to return 255 if it failed or program exit 87198090Srdivacky/// code otherwise. 88207618Srdivacky/// @see sys::Program::ExecuteAndWait 89198090Srdivackystatic int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, 90198090Srdivacky const char **Args, 91198090Srdivacky const sys::Path &StdInFile, 92198090Srdivacky const sys::Path &StdOutFile, 93198090Srdivacky const sys::Path &StdErrFile, 94198090Srdivacky unsigned NumSeconds = 0, 95198090Srdivacky unsigned MemoryLimit = 0) { 96198090Srdivacky const sys::Path* redirects[3]; 97198090Srdivacky redirects[0] = &StdInFile; 98198090Srdivacky redirects[1] = &StdOutFile; 99198090Srdivacky redirects[2] = &StdErrFile; 100193323Sed 101198090Srdivacky#if 0 // For debug purposes 102198090Srdivacky { 103198090Srdivacky errs() << "RUN:"; 104198090Srdivacky for (unsigned i = 0; Args[i]; ++i) 105198090Srdivacky errs() << " " << Args[i]; 106198090Srdivacky errs() << "\n"; 107198090Srdivacky } 108198090Srdivacky#endif 109193323Sed 110198090Srdivacky // Run the program remotely with the remote client 111198090Srdivacky int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, 112198090Srdivacky 0, redirects, NumSeconds, MemoryLimit); 113198090Srdivacky 114198090Srdivacky // Has the remote client fail? 115198090Srdivacky if (255 == ReturnCode) { 116198090Srdivacky std::ostringstream OS; 117198090Srdivacky OS << "\nError running remote client:\n "; 118198090Srdivacky for (const char **Arg = Args; *Arg; ++Arg) 119198090Srdivacky OS << " " << *Arg; 120198090Srdivacky OS << "\n"; 121198090Srdivacky 122198090Srdivacky // The error message is in the output file, let's print it out from there. 123198090Srdivacky std::ifstream ErrorFile(StdOutFile.c_str()); 124198090Srdivacky if (ErrorFile) { 125198090Srdivacky std::copy(std::istreambuf_iterator<char>(ErrorFile), 126198090Srdivacky std::istreambuf_iterator<char>(), 127198090Srdivacky std::ostreambuf_iterator<char>(OS)); 128198090Srdivacky ErrorFile.close(); 129198090Srdivacky } 130198090Srdivacky 131236386Sdim errs() << OS.str(); 132198090Srdivacky } 133198090Srdivacky 134198090Srdivacky return ReturnCode; 135198090Srdivacky} 136198090Srdivacky 137208599Srdivackystatic std::string ProcessFailure(sys::Path ProgPath, const char** Args, 138208599Srdivacky unsigned Timeout = 0, 139208599Srdivacky unsigned MemoryLimit = 0) { 140193323Sed std::ostringstream OS; 141193323Sed OS << "\nError running tool:\n "; 142193323Sed for (const char **Arg = Args; *Arg; ++Arg) 143193323Sed OS << " " << *Arg; 144193323Sed OS << "\n"; 145218885Sdim 146193323Sed // Rerun the compiler, capturing any error messages to print them. 147193323Sed sys::Path ErrorFilename("bugpoint.program_error_messages"); 148193323Sed std::string ErrMsg; 149193323Sed if (ErrorFilename.makeUnique(true, &ErrMsg)) { 150198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 151193323Sed exit(1); 152193323Sed } 153193323Sed RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, 154208599Srdivacky ErrorFilename, Timeout, MemoryLimit); 155208599Srdivacky // FIXME: check return code ? 156193323Sed 157193323Sed // Print out the error messages generated by GCC if possible... 158193323Sed std::ifstream ErrorFile(ErrorFilename.c_str()); 159193323Sed if (ErrorFile) { 160193323Sed std::copy(std::istreambuf_iterator<char>(ErrorFile), 161193323Sed std::istreambuf_iterator<char>(), 162193323Sed std::ostreambuf_iterator<char>(OS)); 163193323Sed ErrorFile.close(); 164193323Sed } 165193323Sed 166193323Sed ErrorFilename.eraseFromDisk(); 167207618Srdivacky return OS.str(); 168193323Sed} 169193323Sed 170193323Sed//===---------------------------------------------------------------------===// 171193323Sed// LLI Implementation of AbstractIntepreter interface 172193323Sed// 173193323Sednamespace { 174193323Sed class LLI : public AbstractInterpreter { 175193323Sed std::string LLIPath; // The path to the LLI executable 176193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 177193323Sed public: 178193323Sed LLI(const std::string &Path, const std::vector<std::string> *Args) 179193323Sed : LLIPath(Path) { 180193323Sed ToolArgs.clear (); 181193323Sed if (Args) { ToolArgs = *Args; } 182193323Sed } 183193323Sed 184193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 185193323Sed const std::vector<std::string> &Args, 186193323Sed const std::string &InputFile, 187193323Sed const std::string &OutputFile, 188207618Srdivacky std::string *Error, 189193323Sed const std::vector<std::string> &GCCArgs, 190193323Sed const std::vector<std::string> &SharedLibs = 191193323Sed std::vector<std::string>(), 192193323Sed unsigned Timeout = 0, 193193323Sed unsigned MemoryLimit = 0); 194193323Sed }; 195193323Sed} 196193323Sed 197193323Sedint LLI::ExecuteProgram(const std::string &Bitcode, 198193323Sed const std::vector<std::string> &Args, 199193323Sed const std::string &InputFile, 200193323Sed const std::string &OutputFile, 201207618Srdivacky std::string *Error, 202193323Sed const std::vector<std::string> &GCCArgs, 203193323Sed const std::vector<std::string> &SharedLibs, 204193323Sed unsigned Timeout, 205193323Sed unsigned MemoryLimit) { 206193323Sed std::vector<const char*> LLIArgs; 207193323Sed LLIArgs.push_back(LLIPath.c_str()); 208193323Sed LLIArgs.push_back("-force-interpreter=true"); 209193323Sed 210218885Sdim for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), 211218885Sdim e = SharedLibs.end(); i != e; ++i) { 212199481Srdivacky LLIArgs.push_back("-load"); 213199481Srdivacky LLIArgs.push_back((*i).c_str()); 214199481Srdivacky } 215199481Srdivacky 216193323Sed // Add any extra LLI args. 217193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 218193323Sed LLIArgs.push_back(ToolArgs[i].c_str()); 219193323Sed 220193323Sed LLIArgs.push_back(Bitcode.c_str()); 221193323Sed // Add optional parameters to the running program from Argv 222193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 223193323Sed LLIArgs.push_back(Args[i].c_str()); 224193323Sed LLIArgs.push_back(0); 225193323Sed 226198090Srdivacky outs() << "<lli>"; outs().flush(); 227198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 228193323Sed for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) 229198090Srdivacky errs() << " " << LLIArgs[i]; 230198090Srdivacky errs() << "\n"; 231193323Sed ); 232193323Sed return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], 233193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 234218885Sdim Timeout, MemoryLimit, Error); 235193323Sed} 236193323Sed 237234353Sdimvoid AbstractInterpreter::anchor() { } 238234353Sdim 239193323Sed// LLI create method - Try to find the LLI executable 240198090SrdivackyAbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, 241193323Sed std::string &Message, 242193323Sed const std::vector<std::string> *ToolArgs) { 243198090Srdivacky std::string LLIPath = 244218885Sdim PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI).str(); 245193323Sed if (!LLIPath.empty()) { 246193323Sed Message = "Found lli: " + LLIPath + "\n"; 247193323Sed return new LLI(LLIPath, ToolArgs); 248193323Sed } 249193323Sed 250218885Sdim Message = "Cannot find `lli' in executable directory!\n"; 251193323Sed return 0; 252193323Sed} 253193323Sed 254193323Sed//===---------------------------------------------------------------------===// 255218885Sdim// Custom compiler command implementation of AbstractIntepreter interface 256218885Sdim// 257218885Sdim// Allows using a custom command for compiling the bitcode, thus allows, for 258218885Sdim// example, to compile a bitcode fragment without linking or executing, then 259218885Sdim// using a custom wrapper script to check for compiler errors. 260218885Sdimnamespace { 261218885Sdim class CustomCompiler : public AbstractInterpreter { 262218885Sdim std::string CompilerCommand; 263218885Sdim std::vector<std::string> CompilerArgs; 264218885Sdim public: 265218885Sdim CustomCompiler( 266218885Sdim const std::string &CompilerCmd, std::vector<std::string> CompArgs) : 267218885Sdim CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {} 268218885Sdim 269218885Sdim virtual void compileProgram(const std::string &Bitcode, 270218885Sdim std::string *Error, 271218885Sdim unsigned Timeout = 0, 272218885Sdim unsigned MemoryLimit = 0); 273218885Sdim 274218885Sdim virtual int ExecuteProgram(const std::string &Bitcode, 275218885Sdim const std::vector<std::string> &Args, 276218885Sdim const std::string &InputFile, 277218885Sdim const std::string &OutputFile, 278218885Sdim std::string *Error, 279218885Sdim const std::vector<std::string> &GCCArgs = 280218885Sdim std::vector<std::string>(), 281218885Sdim const std::vector<std::string> &SharedLibs = 282218885Sdim std::vector<std::string>(), 283218885Sdim unsigned Timeout = 0, 284218885Sdim unsigned MemoryLimit = 0) { 285218885Sdim *Error = "Execution not supported with -compile-custom"; 286218885Sdim return -1; 287218885Sdim } 288218885Sdim }; 289218885Sdim} 290218885Sdim 291218885Sdimvoid CustomCompiler::compileProgram(const std::string &Bitcode, 292218885Sdim std::string *Error, 293218885Sdim unsigned Timeout, 294218885Sdim unsigned MemoryLimit) { 295218885Sdim 296218885Sdim std::vector<const char*> ProgramArgs; 297218885Sdim ProgramArgs.push_back(CompilerCommand.c_str()); 298218885Sdim 299218885Sdim for (std::size_t i = 0; i < CompilerArgs.size(); ++i) 300218885Sdim ProgramArgs.push_back(CompilerArgs.at(i).c_str()); 301218885Sdim ProgramArgs.push_back(Bitcode.c_str()); 302218885Sdim ProgramArgs.push_back(0); 303218885Sdim 304218885Sdim // Add optional parameters to the running program from Argv 305218885Sdim for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) 306218885Sdim ProgramArgs.push_back(CompilerArgs[i].c_str()); 307218885Sdim 308218885Sdim if (RunProgramWithTimeout( sys::Path(CompilerCommand), &ProgramArgs[0], 309218885Sdim sys::Path(), sys::Path(), sys::Path(), 310218885Sdim Timeout, MemoryLimit, Error)) 311218885Sdim *Error = ProcessFailure(sys::Path(CompilerCommand), &ProgramArgs[0], 312218885Sdim Timeout, MemoryLimit); 313218885Sdim} 314218885Sdim 315218885Sdim//===---------------------------------------------------------------------===// 316193323Sed// Custom execution command implementation of AbstractIntepreter interface 317193323Sed// 318193323Sed// Allows using a custom command for executing the bitcode, thus allows, 319218885Sdim// for example, to invoke a cross compiler for code generation followed by 320193323Sed// a simulator that executes the generated binary. 321193323Sednamespace { 322193323Sed class CustomExecutor : public AbstractInterpreter { 323193323Sed std::string ExecutionCommand; 324193323Sed std::vector<std::string> ExecutorArgs; 325193323Sed public: 326193323Sed CustomExecutor( 327193323Sed const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : 328193323Sed ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} 329193323Sed 330193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 331193323Sed const std::vector<std::string> &Args, 332193323Sed const std::string &InputFile, 333193323Sed const std::string &OutputFile, 334207618Srdivacky std::string *Error, 335193323Sed const std::vector<std::string> &GCCArgs, 336193323Sed const std::vector<std::string> &SharedLibs = 337207618Srdivacky std::vector<std::string>(), 338193323Sed unsigned Timeout = 0, 339193323Sed unsigned MemoryLimit = 0); 340193323Sed }; 341193323Sed} 342193323Sed 343193323Sedint CustomExecutor::ExecuteProgram(const std::string &Bitcode, 344193323Sed const std::vector<std::string> &Args, 345193323Sed const std::string &InputFile, 346193323Sed const std::string &OutputFile, 347207618Srdivacky std::string *Error, 348193323Sed const std::vector<std::string> &GCCArgs, 349193323Sed const std::vector<std::string> &SharedLibs, 350193323Sed unsigned Timeout, 351193323Sed unsigned MemoryLimit) { 352193323Sed 353193323Sed std::vector<const char*> ProgramArgs; 354193323Sed ProgramArgs.push_back(ExecutionCommand.c_str()); 355193323Sed 356193323Sed for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 357193323Sed ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); 358193323Sed ProgramArgs.push_back(Bitcode.c_str()); 359193323Sed ProgramArgs.push_back(0); 360193323Sed 361193323Sed // Add optional parameters to the running program from Argv 362207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 363193323Sed ProgramArgs.push_back(Args[i].c_str()); 364193323Sed 365193323Sed return RunProgramWithTimeout( 366193323Sed sys::Path(ExecutionCommand), 367218885Sdim &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 368218885Sdim sys::Path(OutputFile), Timeout, MemoryLimit, Error); 369193323Sed} 370193323Sed 371218885Sdim// Tokenize the CommandLine to the command and the args to allow 372218885Sdim// defining a full command line as the command instead of just the 373218885Sdim// executed program. We cannot just pass the whole string after the command 374218885Sdim// as a single argument because then program sees only a single 375218885Sdim// command line argument (with spaces in it: "foo bar" instead 376218885Sdim// of "foo" and "bar"). 377218885Sdim// 378218885Sdim// code borrowed from: 379218885Sdim// http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html 380218885Sdimstatic void lexCommand(std::string &Message, const std::string &CommandLine, 381218885Sdim std::string &CmdPath, std::vector<std::string> Args) { 382193323Sed 383193323Sed std::string Command = ""; 384193323Sed std::string delimiters = " "; 385193323Sed 386218885Sdim std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0); 387218885Sdim std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos); 388193323Sed 389193323Sed while (std::string::npos != pos || std::string::npos != lastPos) { 390218885Sdim std::string token = CommandLine.substr(lastPos, pos - lastPos); 391193323Sed if (Command == "") 392193323Sed Command = token; 393193323Sed else 394193323Sed Args.push_back(token); 395193323Sed // Skip delimiters. Note the "not_of" 396218885Sdim lastPos = CommandLine.find_first_not_of(delimiters, pos); 397193323Sed // Find next "non-delimiter" 398218885Sdim pos = CommandLine.find_first_of(delimiters, lastPos); 399193323Sed } 400193323Sed 401218885Sdim CmdPath = sys::Program::FindProgramByName(Command).str(); 402193323Sed if (CmdPath.empty()) { 403218885Sdim Message = 404218885Sdim std::string("Cannot find '") + Command + 405218885Sdim "' in PATH!\n"; 406218885Sdim return; 407193323Sed } 408193323Sed 409193323Sed Message = "Found command in: " + CmdPath + "\n"; 410218885Sdim} 411193323Sed 412218885Sdim// Custom execution environment create method, takes the execution command 413218885Sdim// as arguments 414218885SdimAbstractInterpreter *AbstractInterpreter::createCustomCompiler( 415218885Sdim std::string &Message, 416218885Sdim const std::string &CompileCommandLine) { 417218885Sdim 418218885Sdim std::string CmdPath; 419218885Sdim std::vector<std::string> Args; 420218885Sdim lexCommand(Message, CompileCommandLine, CmdPath, Args); 421218885Sdim if (CmdPath.empty()) 422218885Sdim return 0; 423218885Sdim 424218885Sdim return new CustomCompiler(CmdPath, Args); 425218885Sdim} 426218885Sdim 427218885Sdim// Custom execution environment create method, takes the execution command 428218885Sdim// as arguments 429218885SdimAbstractInterpreter *AbstractInterpreter::createCustomExecutor( 430218885Sdim std::string &Message, 431218885Sdim const std::string &ExecCommandLine) { 432218885Sdim 433218885Sdim 434218885Sdim std::string CmdPath; 435218885Sdim std::vector<std::string> Args; 436218885Sdim lexCommand(Message, ExecCommandLine, CmdPath, Args); 437218885Sdim if (CmdPath.empty()) 438218885Sdim return 0; 439218885Sdim 440193323Sed return new CustomExecutor(CmdPath, Args); 441193323Sed} 442193323Sed 443193323Sed//===----------------------------------------------------------------------===// 444193323Sed// LLC Implementation of AbstractIntepreter interface 445193323Sed// 446218885SdimGCC::FileType LLC::OutputCode(const std::string &Bitcode, 447208599Srdivacky sys::Path &OutputAsmFile, std::string &Error, 448208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 449205218Srdivacky const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); 450205218Srdivacky sys::Path uniqueFile(Bitcode + Suffix); 451193323Sed std::string ErrMsg; 452193323Sed if (uniqueFile.makeUnique(true, &ErrMsg)) { 453198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 454193323Sed exit(1); 455193323Sed } 456193323Sed OutputAsmFile = uniqueFile; 457193323Sed std::vector<const char *> LLCArgs; 458205218Srdivacky LLCArgs.push_back(LLCPath.c_str()); 459193323Sed 460193323Sed // Add any extra LLC args. 461193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 462193323Sed LLCArgs.push_back(ToolArgs[i].c_str()); 463193323Sed 464205218Srdivacky LLCArgs.push_back("-o"); 465205218Srdivacky LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file 466205218Srdivacky LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 467218885Sdim 468205218Srdivacky if (UseIntegratedAssembler) 469205218Srdivacky LLCArgs.push_back("-filetype=obj"); 470218885Sdim 471193323Sed LLCArgs.push_back (0); 472193323Sed 473205218Srdivacky outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); 474205218Srdivacky outs().flush(); 475198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 476207618Srdivacky for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 477198090Srdivacky errs() << " " << LLCArgs[i]; 478198090Srdivacky errs() << "\n"; 479193323Sed ); 480193323Sed if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], 481208599Srdivacky sys::Path(), sys::Path(), sys::Path(), 482208599Srdivacky Timeout, MemoryLimit)) 483208599Srdivacky Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0], 484208599Srdivacky Timeout, MemoryLimit); 485218885Sdim return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; 486193323Sed} 487193323Sed 488208599Srdivackyvoid LLC::compileProgram(const std::string &Bitcode, std::string *Error, 489208599Srdivacky unsigned Timeout, unsigned MemoryLimit) { 490193323Sed sys::Path OutputAsmFile; 491208599Srdivacky OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); 492193323Sed OutputAsmFile.eraseFromDisk(); 493193323Sed} 494193323Sed 495193323Sedint LLC::ExecuteProgram(const std::string &Bitcode, 496193323Sed const std::vector<std::string> &Args, 497193323Sed const std::string &InputFile, 498193323Sed const std::string &OutputFile, 499207618Srdivacky std::string *Error, 500193323Sed const std::vector<std::string> &ArgsForGCC, 501193323Sed const std::vector<std::string> &SharedLibs, 502193323Sed unsigned Timeout, 503193323Sed unsigned MemoryLimit) { 504193323Sed 505193323Sed sys::Path OutputAsmFile; 506208599Srdivacky GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, 507208599Srdivacky MemoryLimit); 508221337Sdim FileRemover OutFileRemover(OutputAsmFile.str(), !SaveTemps); 509193323Sed 510193323Sed std::vector<std::string> GCCArgs(ArgsForGCC); 511193323Sed GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 512193323Sed 513193323Sed // Assuming LLC worked, compile the result with GCC and run it. 514205218Srdivacky return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind, 515207618Srdivacky InputFile, OutputFile, Error, GCCArgs, 516193323Sed Timeout, MemoryLimit); 517193323Sed} 518193323Sed 519193323Sed/// createLLC - Try to find the LLC executable 520193323Sed/// 521198090SrdivackyLLC *AbstractInterpreter::createLLC(const char *Argv0, 522193323Sed std::string &Message, 523208599Srdivacky const std::string &GCCBinary, 524193323Sed const std::vector<std::string> *Args, 525205218Srdivacky const std::vector<std::string> *GCCArgs, 526205218Srdivacky bool UseIntegratedAssembler) { 527198090Srdivacky std::string LLCPath = 528218885Sdim PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC).str(); 529193323Sed if (LLCPath.empty()) { 530218885Sdim Message = "Cannot find `llc' in executable directory!\n"; 531193323Sed return 0; 532193323Sed } 533193323Sed 534208599Srdivacky GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); 535193323Sed if (!gcc) { 536198090Srdivacky errs() << Message << "\n"; 537193323Sed exit(1); 538193323Sed } 539249423Sdim Message = "Found llc: " + LLCPath + "\n"; 540208599Srdivacky return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler); 541193323Sed} 542193323Sed 543193323Sed//===---------------------------------------------------------------------===// 544193323Sed// JIT Implementation of AbstractIntepreter interface 545193323Sed// 546193323Sednamespace { 547193323Sed class JIT : public AbstractInterpreter { 548193323Sed std::string LLIPath; // The path to the LLI executable 549193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 550193323Sed public: 551193323Sed JIT(const std::string &Path, const std::vector<std::string> *Args) 552193323Sed : LLIPath(Path) { 553193323Sed ToolArgs.clear (); 554193323Sed if (Args) { ToolArgs = *Args; } 555193323Sed } 556193323Sed 557193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 558193323Sed const std::vector<std::string> &Args, 559193323Sed const std::string &InputFile, 560193323Sed const std::string &OutputFile, 561207618Srdivacky std::string *Error, 562193323Sed const std::vector<std::string> &GCCArgs = 563193323Sed std::vector<std::string>(), 564193323Sed const std::vector<std::string> &SharedLibs = 565218885Sdim std::vector<std::string>(), 566207618Srdivacky unsigned Timeout = 0, 567207618Srdivacky unsigned MemoryLimit = 0); 568193323Sed }; 569193323Sed} 570193323Sed 571193323Sedint JIT::ExecuteProgram(const std::string &Bitcode, 572193323Sed const std::vector<std::string> &Args, 573193323Sed const std::string &InputFile, 574193323Sed const std::string &OutputFile, 575207618Srdivacky std::string *Error, 576193323Sed const std::vector<std::string> &GCCArgs, 577193323Sed const std::vector<std::string> &SharedLibs, 578193323Sed unsigned Timeout, 579193323Sed unsigned MemoryLimit) { 580193323Sed // Construct a vector of parameters, incorporating those from the command-line 581193323Sed std::vector<const char*> JITArgs; 582193323Sed JITArgs.push_back(LLIPath.c_str()); 583193323Sed JITArgs.push_back("-force-interpreter=false"); 584193323Sed 585193323Sed // Add any extra LLI args. 586193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 587193323Sed JITArgs.push_back(ToolArgs[i].c_str()); 588193323Sed 589193323Sed for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 590193323Sed JITArgs.push_back("-load"); 591193323Sed JITArgs.push_back(SharedLibs[i].c_str()); 592193323Sed } 593193323Sed JITArgs.push_back(Bitcode.c_str()); 594193323Sed // Add optional parameters to the running program from Argv 595193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 596193323Sed JITArgs.push_back(Args[i].c_str()); 597193323Sed JITArgs.push_back(0); 598193323Sed 599198090Srdivacky outs() << "<jit>"; outs().flush(); 600198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 601193323Sed for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) 602198090Srdivacky errs() << " " << JITArgs[i]; 603198090Srdivacky errs() << "\n"; 604193323Sed ); 605198090Srdivacky DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 606193323Sed return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], 607193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 608218885Sdim Timeout, MemoryLimit, Error); 609193323Sed} 610193323Sed 611193323Sed/// createJIT - Try to find the LLI executable 612193323Sed/// 613198090SrdivackyAbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, 614193323Sed std::string &Message, const std::vector<std::string> *Args) { 615198090Srdivacky std::string LLIPath = 616218885Sdim PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT).str(); 617193323Sed if (!LLIPath.empty()) { 618193323Sed Message = "Found lli: " + LLIPath + "\n"; 619193323Sed return new JIT(LLIPath, Args); 620193323Sed } 621193323Sed 622218885Sdim Message = "Cannot find `lli' in executable directory!\n"; 623193323Sed return 0; 624193323Sed} 625193323Sed 626193323Sed//===---------------------------------------------------------------------===// 627193323Sed// GCC abstraction 628193323Sed// 629198090Srdivacky 630212793Sdimstatic bool IsARMArchitecture(std::vector<const char*> Args) { 631212793Sdim for (std::vector<const char*>::const_iterator 632198090Srdivacky I = Args.begin(), E = Args.end(); I != E; ++I) { 633208599Srdivacky if (StringRef(*I).equals_lower("-arch")) { 634198090Srdivacky ++I; 635208599Srdivacky if (I != E && StringRef(*I).substr(0, strlen("arm")).equals_lower("arm")) 636198090Srdivacky return true; 637198090Srdivacky } 638198090Srdivacky } 639198090Srdivacky 640198090Srdivacky return false; 641198090Srdivacky} 642198090Srdivacky 643193323Sedint GCC::ExecuteProgram(const std::string &ProgramFile, 644193323Sed const std::vector<std::string> &Args, 645193323Sed FileType fileType, 646193323Sed const std::string &InputFile, 647193323Sed const std::string &OutputFile, 648207618Srdivacky std::string *Error, 649193323Sed const std::vector<std::string> &ArgsForGCC, 650193323Sed unsigned Timeout, 651193323Sed unsigned MemoryLimit) { 652193323Sed std::vector<const char*> GCCArgs; 653193323Sed 654193323Sed GCCArgs.push_back(GCCPath.c_str()); 655193323Sed 656205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 657205218Srdivacky GCCArgs.push_back("-m32"); 658205218Srdivacky 659193323Sed for (std::vector<std::string>::const_iterator 660193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 661193323Sed GCCArgs.push_back(I->c_str()); 662193323Sed 663193323Sed // Specify -x explicitly in case the extension is wonky 664205218Srdivacky if (fileType != ObjectFile) { 665205218Srdivacky GCCArgs.push_back("-x"); 666205218Srdivacky if (fileType == CFile) { 667205218Srdivacky GCCArgs.push_back("c"); 668205218Srdivacky GCCArgs.push_back("-fno-strict-aliasing"); 669205218Srdivacky } else { 670205218Srdivacky GCCArgs.push_back("assembler"); 671198090Srdivacky 672205218Srdivacky // For ARM architectures we don't want this flag. bugpoint isn't 673205218Srdivacky // explicitly told what architecture it is working on, so we get 674205218Srdivacky // it from gcc flags 675221337Sdim if (TargetTriple.isOSDarwin() && !IsARMArchitecture(GCCArgs)) 676205218Srdivacky GCCArgs.push_back("-force_cpusubtype_ALL"); 677205218Srdivacky } 678193323Sed } 679218885Sdim 680205218Srdivacky GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. 681218885Sdim 682193323Sed GCCArgs.push_back("-x"); 683193323Sed GCCArgs.push_back("none"); 684193323Sed GCCArgs.push_back("-o"); 685193323Sed sys::Path OutputBinary (ProgramFile+".gcc.exe"); 686193323Sed std::string ErrMsg; 687193323Sed if (OutputBinary.makeUnique(true, &ErrMsg)) { 688198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 689193323Sed exit(1); 690193323Sed } 691193323Sed GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 692193323Sed 693193323Sed // Add any arguments intended for GCC. We locate them here because this is 694193323Sed // most likely -L and -l options that need to come before other libraries but 695193323Sed // after the source. Other options won't be sensitive to placement on the 696193323Sed // command line, so this should be safe. 697193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 698193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 699193323Sed 700193323Sed GCCArgs.push_back("-lm"); // Hard-code the math library... 701193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit... 702193323Sed#if defined (HAVE_LINK_R) 703193323Sed GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files 704193323Sed#endif 705198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 706198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 707193323Sed GCCArgs.push_back(0); // NULL terminator 708193323Sed 709198090Srdivacky outs() << "<gcc>"; outs().flush(); 710198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 711207618Srdivacky for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 712198090Srdivacky errs() << " " << GCCArgs[i]; 713198090Srdivacky errs() << "\n"; 714193323Sed ); 715193323Sed if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 716193323Sed sys::Path())) { 717207618Srdivacky *Error = ProcessFailure(GCCPath, &GCCArgs[0]); 718207618Srdivacky return -1; 719193323Sed } 720193323Sed 721193323Sed std::vector<const char*> ProgramArgs; 722193323Sed 723212793Sdim // Declared here so that the destructor only runs after 724212793Sdim // ProgramArgs is used. 725212793Sdim std::string Exec; 726212793Sdim 727193323Sed if (RemoteClientPath.isEmpty()) 728193323Sed ProgramArgs.push_back(OutputBinary.c_str()); 729193323Sed else { 730193323Sed ProgramArgs.push_back(RemoteClientPath.c_str()); 731193323Sed ProgramArgs.push_back(RemoteHost.c_str()); 732198090Srdivacky if (!RemoteUser.empty()) { 733198090Srdivacky ProgramArgs.push_back("-l"); 734198090Srdivacky ProgramArgs.push_back(RemoteUser.c_str()); 735198090Srdivacky } 736198090Srdivacky if (!RemotePort.empty()) { 737198090Srdivacky ProgramArgs.push_back("-p"); 738198090Srdivacky ProgramArgs.push_back(RemotePort.c_str()); 739198090Srdivacky } 740193323Sed if (!RemoteExtra.empty()) { 741193323Sed ProgramArgs.push_back(RemoteExtra.c_str()); 742193323Sed } 743193323Sed 744198090Srdivacky // Full path to the binary. We need to cd to the exec directory because 745198090Srdivacky // there is a dylib there that the exec expects to find in the CWD 746193323Sed char* env_pwd = getenv("PWD"); 747212793Sdim Exec = "cd "; 748193323Sed Exec += env_pwd; 749193323Sed Exec += "; ./"; 750193323Sed Exec += OutputBinary.c_str(); 751193323Sed ProgramArgs.push_back(Exec.c_str()); 752193323Sed } 753193323Sed 754193323Sed // Add optional parameters to the running program from Argv 755207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 756193323Sed ProgramArgs.push_back(Args[i].c_str()); 757193323Sed ProgramArgs.push_back(0); // NULL terminator 758193323Sed 759193323Sed // Now that we have a binary, run it! 760198090Srdivacky outs() << "<program>"; outs().flush(); 761198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 762207618Srdivacky for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) 763198090Srdivacky errs() << " " << ProgramArgs[i]; 764198090Srdivacky errs() << "\n"; 765193323Sed ); 766193323Sed 767221337Sdim FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); 768193323Sed 769198090Srdivacky if (RemoteClientPath.isEmpty()) { 770207618Srdivacky DEBUG(errs() << "<run locally>"); 771223013Sdim int ExitCode = RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], 772193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 773218885Sdim Timeout, MemoryLimit, Error); 774223013Sdim // Treat a signal (usually SIGSEGV) or timeout as part of the program output 775223013Sdim // so that crash-causing miscompilation is handled seamlessly. 776223013Sdim if (ExitCode < -1) { 777223013Sdim std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 778223013Sdim outFile << *Error << '\n'; 779223013Sdim outFile.close(); 780223013Sdim Error->clear(); 781223013Sdim } 782223013Sdim return ExitCode; 783198090Srdivacky } else { 784198090Srdivacky outs() << "<run remotely>"; outs().flush(); 785198090Srdivacky return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), 786198090Srdivacky &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 787198090Srdivacky sys::Path(OutputFile), Timeout, MemoryLimit); 788198090Srdivacky } 789193323Sed} 790193323Sed 791193323Sedint GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 792193323Sed std::string &OutputFile, 793207618Srdivacky const std::vector<std::string> &ArgsForGCC, 794207618Srdivacky std::string &Error) { 795193323Sed sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); 796193323Sed std::string ErrMsg; 797193323Sed if (uniqueFilename.makeUnique(true, &ErrMsg)) { 798198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 799193323Sed exit(1); 800193323Sed } 801198090Srdivacky OutputFile = uniqueFilename.str(); 802193323Sed 803193323Sed std::vector<const char*> GCCArgs; 804218885Sdim 805193323Sed GCCArgs.push_back(GCCPath.c_str()); 806193323Sed 807205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 808205218Srdivacky GCCArgs.push_back("-m32"); 809205218Srdivacky 810193323Sed for (std::vector<std::string>::const_iterator 811193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 812193323Sed GCCArgs.push_back(I->c_str()); 813193323Sed 814193323Sed // Compile the C/asm file into a shared object 815205218Srdivacky if (fileType != ObjectFile) { 816205218Srdivacky GCCArgs.push_back("-x"); 817205218Srdivacky GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 818205218Srdivacky } 819193323Sed GCCArgs.push_back("-fno-strict-aliasing"); 820193323Sed GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. 821193323Sed GCCArgs.push_back("-x"); 822193323Sed GCCArgs.push_back("none"); 823198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 824198090Srdivacky GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 825221337Sdim else if (TargetTriple.isOSDarwin()) { 826198090Srdivacky // link all source files into a single module in data segment, rather than 827218885Sdim // generating blocks. dynamic_lookup requires that you set 828198090Srdivacky // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 829198090Srdivacky // bugpoint to just pass that in the environment of GCC. 830198090Srdivacky GCCArgs.push_back("-single_module"); 831198090Srdivacky GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 832198090Srdivacky GCCArgs.push_back("-undefined"); 833198090Srdivacky GCCArgs.push_back("dynamic_lookup"); 834198090Srdivacky } else 835198090Srdivacky GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 836193323Sed 837234353Sdim if (TargetTriple.getArch() == Triple::x86_64) 838198090Srdivacky GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 839198090Srdivacky 840198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 841198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 842198090Srdivacky 843193323Sed GCCArgs.push_back("-o"); 844193323Sed GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 845193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit. 846193323Sed 847218885Sdim 848218885Sdim 849193323Sed // Add any arguments intended for GCC. We locate them here because this is 850193323Sed // most likely -L and -l options that need to come before other libraries but 851193323Sed // after the source. Other options won't be sensitive to placement on the 852193323Sed // command line, so this should be safe. 853193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 854193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 855193323Sed GCCArgs.push_back(0); // NULL terminator 856193323Sed 857193323Sed 858218885Sdim 859198090Srdivacky outs() << "<gcc>"; outs().flush(); 860198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 861207618Srdivacky for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 862198090Srdivacky errs() << " " << GCCArgs[i]; 863198090Srdivacky errs() << "\n"; 864193323Sed ); 865193323Sed if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 866193323Sed sys::Path())) { 867207618Srdivacky Error = ProcessFailure(GCCPath, &GCCArgs[0]); 868193323Sed return 1; 869193323Sed } 870193323Sed return 0; 871193323Sed} 872193323Sed 873193323Sed/// create - Try to find the `gcc' executable 874193323Sed/// 875198090SrdivackyGCC *GCC::create(std::string &Message, 876208599Srdivacky const std::string &GCCBinary, 877193323Sed const std::vector<std::string> *Args) { 878208599Srdivacky sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary); 879193323Sed if (GCCPath.isEmpty()) { 880218885Sdim Message = "Cannot find `"+ GCCBinary +"' in PATH!\n"; 881193323Sed return 0; 882193323Sed } 883193323Sed 884193323Sed sys::Path RemoteClientPath; 885193323Sed if (!RemoteClient.empty()) 886198090Srdivacky RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); 887193323Sed 888198090Srdivacky Message = "Found gcc: " + GCCPath.str() + "\n"; 889193323Sed return new GCC(GCCPath, RemoteClientPath, Args); 890193323Sed} 891