ToolRunner.cpp revision 199481
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" 16193323Sed#include "llvm/System/Program.h" 17193323Sed#include "llvm/Support/CommandLine.h" 18193323Sed#include "llvm/Support/Debug.h" 19193323Sed#include "llvm/Support/FileUtilities.h" 20198090Srdivacky#include "llvm/Support/raw_ostream.h" 21198090Srdivacky#include "llvm/Config/config.h" // for HAVE_LINK_R 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 53193323SedToolExecutionError::~ToolExecutionError() throw() { } 54193323Sed 55198090Srdivacky/// RunProgramWithTimeout - This function provides an alternate interface 56198090Srdivacky/// to the sys::Program::ExecuteAndWait interface. 57193323Sed/// @see sys:Program::ExecuteAndWait 58193323Sedstatic int RunProgramWithTimeout(const sys::Path &ProgramPath, 59193323Sed const char **Args, 60193323Sed const sys::Path &StdInFile, 61193323Sed const sys::Path &StdOutFile, 62193323Sed const sys::Path &StdErrFile, 63193323Sed unsigned NumSeconds = 0, 64193323Sed unsigned MemoryLimit = 0) { 65193323Sed const sys::Path* redirects[3]; 66193323Sed redirects[0] = &StdInFile; 67193323Sed redirects[1] = &StdOutFile; 68193323Sed redirects[2] = &StdErrFile; 69198090Srdivacky 70198090Srdivacky#if 0 // For debug purposes 71198090Srdivacky { 72198090Srdivacky errs() << "RUN:"; 73193323Sed for (unsigned i = 0; Args[i]; ++i) 74198090Srdivacky errs() << " " << Args[i]; 75198090Srdivacky errs() << "\n"; 76193323Sed } 77198090Srdivacky#endif 78193323Sed 79193323Sed return 80193323Sed sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, 81193323Sed NumSeconds, MemoryLimit); 82193323Sed} 83193323Sed 84198090Srdivacky/// RunProgramRemotelyWithTimeout - This function runs the given program 85198090Srdivacky/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 86198090Srdivacky/// Returns the remote program exit code or reports a remote client error if it 87198090Srdivacky/// fails. Remote client is required to return 255 if it failed or program exit 88198090Srdivacky/// code otherwise. 89198090Srdivacky/// @see sys:Program::ExecuteAndWait 90198090Srdivackystatic int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, 91198090Srdivacky const char **Args, 92198090Srdivacky const sys::Path &StdInFile, 93198090Srdivacky const sys::Path &StdOutFile, 94198090Srdivacky const sys::Path &StdErrFile, 95198090Srdivacky unsigned NumSeconds = 0, 96198090Srdivacky unsigned MemoryLimit = 0) { 97198090Srdivacky const sys::Path* redirects[3]; 98198090Srdivacky redirects[0] = &StdInFile; 99198090Srdivacky redirects[1] = &StdOutFile; 100198090Srdivacky redirects[2] = &StdErrFile; 101193323Sed 102198090Srdivacky#if 0 // For debug purposes 103198090Srdivacky { 104198090Srdivacky errs() << "RUN:"; 105198090Srdivacky for (unsigned i = 0; Args[i]; ++i) 106198090Srdivacky errs() << " " << Args[i]; 107198090Srdivacky errs() << "\n"; 108198090Srdivacky } 109198090Srdivacky#endif 110193323Sed 111198090Srdivacky // Run the program remotely with the remote client 112198090Srdivacky int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, 113198090Srdivacky 0, redirects, NumSeconds, MemoryLimit); 114198090Srdivacky 115198090Srdivacky // Has the remote client fail? 116198090Srdivacky if (255 == ReturnCode) { 117198090Srdivacky std::ostringstream OS; 118198090Srdivacky OS << "\nError running remote client:\n "; 119198090Srdivacky for (const char **Arg = Args; *Arg; ++Arg) 120198090Srdivacky OS << " " << *Arg; 121198090Srdivacky OS << "\n"; 122198090Srdivacky 123198090Srdivacky // The error message is in the output file, let's print it out from there. 124198090Srdivacky std::ifstream ErrorFile(StdOutFile.c_str()); 125198090Srdivacky if (ErrorFile) { 126198090Srdivacky std::copy(std::istreambuf_iterator<char>(ErrorFile), 127198090Srdivacky std::istreambuf_iterator<char>(), 128198090Srdivacky std::ostreambuf_iterator<char>(OS)); 129198090Srdivacky ErrorFile.close(); 130198090Srdivacky } 131198090Srdivacky 132198090Srdivacky throw ToolExecutionError(OS.str()); 133198090Srdivacky } 134198090Srdivacky 135198090Srdivacky return ReturnCode; 136198090Srdivacky} 137198090Srdivacky 138193323Sedstatic void ProcessFailure(sys::Path ProgPath, const char** Args) { 139193323Sed std::ostringstream OS; 140193323Sed OS << "\nError running tool:\n "; 141193323Sed for (const char **Arg = Args; *Arg; ++Arg) 142193323Sed OS << " " << *Arg; 143193323Sed OS << "\n"; 144193323Sed 145193323Sed // Rerun the compiler, capturing any error messages to print them. 146193323Sed sys::Path ErrorFilename("bugpoint.program_error_messages"); 147193323Sed std::string ErrMsg; 148193323Sed if (ErrorFilename.makeUnique(true, &ErrMsg)) { 149198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 150193323Sed exit(1); 151193323Sed } 152193323Sed RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, 153193323Sed ErrorFilename); // FIXME: check return code ? 154193323Sed 155193323Sed // Print out the error messages generated by GCC if possible... 156193323Sed std::ifstream ErrorFile(ErrorFilename.c_str()); 157193323Sed if (ErrorFile) { 158193323Sed std::copy(std::istreambuf_iterator<char>(ErrorFile), 159193323Sed std::istreambuf_iterator<char>(), 160193323Sed std::ostreambuf_iterator<char>(OS)); 161193323Sed ErrorFile.close(); 162193323Sed } 163193323Sed 164193323Sed ErrorFilename.eraseFromDisk(); 165193323Sed throw ToolExecutionError(OS.str()); 166193323Sed} 167193323Sed 168193323Sed//===---------------------------------------------------------------------===// 169193323Sed// LLI Implementation of AbstractIntepreter interface 170193323Sed// 171193323Sednamespace { 172193323Sed class LLI : public AbstractInterpreter { 173193323Sed std::string LLIPath; // The path to the LLI executable 174193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 175193323Sed public: 176193323Sed LLI(const std::string &Path, const std::vector<std::string> *Args) 177193323Sed : LLIPath(Path) { 178193323Sed ToolArgs.clear (); 179193323Sed if (Args) { ToolArgs = *Args; } 180193323Sed } 181193323Sed 182193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 183193323Sed const std::vector<std::string> &Args, 184193323Sed const std::string &InputFile, 185193323Sed const std::string &OutputFile, 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, 198193323Sed const std::vector<std::string> &GCCArgs, 199193323Sed const std::vector<std::string> &SharedLibs, 200193323Sed unsigned Timeout, 201193323Sed unsigned MemoryLimit) { 202193323Sed std::vector<const char*> LLIArgs; 203193323Sed LLIArgs.push_back(LLIPath.c_str()); 204193323Sed LLIArgs.push_back("-force-interpreter=true"); 205193323Sed 206199481Srdivacky for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), e = SharedLibs.end(); i != e; ++i) { 207199481Srdivacky LLIArgs.push_back("-load"); 208199481Srdivacky LLIArgs.push_back((*i).c_str()); 209199481Srdivacky } 210199481Srdivacky 211193323Sed // Add any extra LLI args. 212193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 213193323Sed LLIArgs.push_back(ToolArgs[i].c_str()); 214193323Sed 215193323Sed LLIArgs.push_back(Bitcode.c_str()); 216193323Sed // Add optional parameters to the running program from Argv 217193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 218193323Sed LLIArgs.push_back(Args[i].c_str()); 219193323Sed LLIArgs.push_back(0); 220193323Sed 221198090Srdivacky outs() << "<lli>"; outs().flush(); 222198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 223193323Sed for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) 224198090Srdivacky errs() << " " << LLIArgs[i]; 225198090Srdivacky errs() << "\n"; 226193323Sed ); 227193323Sed return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], 228193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 229193323Sed Timeout, MemoryLimit); 230193323Sed} 231193323Sed 232193323Sed// LLI create method - Try to find the LLI executable 233198090SrdivackyAbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, 234193323Sed std::string &Message, 235193323Sed const std::vector<std::string> *ToolArgs) { 236198090Srdivacky std::string LLIPath = 237198090Srdivacky FindExecutable("lli", Argv0, (void *)(intptr_t)&createLLI).str(); 238193323Sed if (!LLIPath.empty()) { 239193323Sed Message = "Found lli: " + LLIPath + "\n"; 240193323Sed return new LLI(LLIPath, ToolArgs); 241193323Sed } 242193323Sed 243193323Sed Message = "Cannot find `lli' in executable directory or PATH!\n"; 244193323Sed return 0; 245193323Sed} 246193323Sed 247193323Sed//===---------------------------------------------------------------------===// 248193323Sed// Custom execution command implementation of AbstractIntepreter interface 249193323Sed// 250193323Sed// Allows using a custom command for executing the bitcode, thus allows, 251193323Sed// for example, to invoke a cross compiler for code generation followed by 252193323Sed// a simulator that executes the generated binary. 253193323Sednamespace { 254193323Sed class CustomExecutor : public AbstractInterpreter { 255193323Sed std::string ExecutionCommand; 256193323Sed std::vector<std::string> ExecutorArgs; 257193323Sed public: 258193323Sed CustomExecutor( 259193323Sed const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : 260193323Sed ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} 261193323Sed 262193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 263193323Sed const std::vector<std::string> &Args, 264193323Sed const std::string &InputFile, 265193323Sed const std::string &OutputFile, 266193323Sed const std::vector<std::string> &GCCArgs, 267193323Sed const std::vector<std::string> &SharedLibs = 268193323Sed std::vector<std::string>(), 269193323Sed unsigned Timeout = 0, 270193323Sed unsigned MemoryLimit = 0); 271193323Sed }; 272193323Sed} 273193323Sed 274193323Sedint CustomExecutor::ExecuteProgram(const std::string &Bitcode, 275193323Sed const std::vector<std::string> &Args, 276193323Sed const std::string &InputFile, 277193323Sed const std::string &OutputFile, 278193323Sed const std::vector<std::string> &GCCArgs, 279193323Sed const std::vector<std::string> &SharedLibs, 280193323Sed unsigned Timeout, 281193323Sed unsigned MemoryLimit) { 282193323Sed 283193323Sed std::vector<const char*> ProgramArgs; 284193323Sed ProgramArgs.push_back(ExecutionCommand.c_str()); 285193323Sed 286193323Sed for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 287193323Sed ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); 288193323Sed ProgramArgs.push_back(Bitcode.c_str()); 289193323Sed ProgramArgs.push_back(0); 290193323Sed 291193323Sed // Add optional parameters to the running program from Argv 292193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 293193323Sed ProgramArgs.push_back(Args[i].c_str()); 294193323Sed 295193323Sed return RunProgramWithTimeout( 296193323Sed sys::Path(ExecutionCommand), 297193323Sed &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 298193323Sed sys::Path(OutputFile), Timeout, MemoryLimit); 299193323Sed} 300193323Sed 301193323Sed// Custom execution environment create method, takes the execution command 302193323Sed// as arguments 303193323SedAbstractInterpreter *AbstractInterpreter::createCustom( 304193323Sed std::string &Message, 305193323Sed const std::string &ExecCommandLine) { 306193323Sed 307193323Sed std::string Command = ""; 308193323Sed std::vector<std::string> Args; 309193323Sed std::string delimiters = " "; 310193323Sed 311193323Sed // Tokenize the ExecCommandLine to the command and the args to allow 312193323Sed // defining a full command line as the command instead of just the 313193323Sed // executed program. We cannot just pass the whole string after the command 314193323Sed // as a single argument because then program sees only a single 315193323Sed // command line argument (with spaces in it: "foo bar" instead 316193323Sed // of "foo" and "bar"). 317193323Sed 318193323Sed // code borrowed from: 319193323Sed // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html 320193323Sed std::string::size_type lastPos = 321193323Sed ExecCommandLine.find_first_not_of(delimiters, 0); 322193323Sed std::string::size_type pos = 323193323Sed ExecCommandLine.find_first_of(delimiters, lastPos); 324193323Sed 325193323Sed while (std::string::npos != pos || std::string::npos != lastPos) { 326193323Sed std::string token = ExecCommandLine.substr(lastPos, pos - lastPos); 327193323Sed if (Command == "") 328193323Sed Command = token; 329193323Sed else 330193323Sed Args.push_back(token); 331193323Sed // Skip delimiters. Note the "not_of" 332193323Sed lastPos = ExecCommandLine.find_first_not_of(delimiters, pos); 333193323Sed // Find next "non-delimiter" 334193323Sed pos = ExecCommandLine.find_first_of(delimiters, lastPos); 335193323Sed } 336193323Sed 337198090Srdivacky std::string CmdPath = sys::Program::FindProgramByName(Command).str(); 338193323Sed if (CmdPath.empty()) { 339193323Sed Message = 340193323Sed std::string("Cannot find '") + Command + 341193323Sed "' in executable directory or PATH!\n"; 342193323Sed return 0; 343193323Sed } 344193323Sed 345193323Sed Message = "Found command in: " + CmdPath + "\n"; 346193323Sed 347193323Sed return new CustomExecutor(CmdPath, Args); 348193323Sed} 349193323Sed 350193323Sed//===----------------------------------------------------------------------===// 351193323Sed// LLC Implementation of AbstractIntepreter interface 352193323Sed// 353193323SedGCC::FileType LLC::OutputCode(const std::string &Bitcode, 354193323Sed sys::Path &OutputAsmFile) { 355193323Sed sys::Path uniqueFile(Bitcode+".llc.s"); 356193323Sed std::string ErrMsg; 357193323Sed if (uniqueFile.makeUnique(true, &ErrMsg)) { 358198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 359193323Sed exit(1); 360193323Sed } 361193323Sed OutputAsmFile = uniqueFile; 362193323Sed std::vector<const char *> LLCArgs; 363193323Sed LLCArgs.push_back (LLCPath.c_str()); 364193323Sed 365193323Sed // Add any extra LLC args. 366193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 367193323Sed LLCArgs.push_back(ToolArgs[i].c_str()); 368193323Sed 369193323Sed LLCArgs.push_back ("-o"); 370193323Sed LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file 371193323Sed LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode 372193323Sed LLCArgs.push_back (0); 373193323Sed 374198090Srdivacky outs() << "<llc>"; outs().flush(); 375198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 376193323Sed for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) 377198090Srdivacky errs() << " " << LLCArgs[i]; 378198090Srdivacky errs() << "\n"; 379193323Sed ); 380193323Sed if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], 381193323Sed sys::Path(), sys::Path(), sys::Path())) 382193323Sed ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]); 383193323Sed 384193323Sed return GCC::AsmFile; 385193323Sed} 386193323Sed 387193323Sedvoid LLC::compileProgram(const std::string &Bitcode) { 388193323Sed sys::Path OutputAsmFile; 389193323Sed OutputCode(Bitcode, OutputAsmFile); 390193323Sed OutputAsmFile.eraseFromDisk(); 391193323Sed} 392193323Sed 393193323Sedint LLC::ExecuteProgram(const std::string &Bitcode, 394193323Sed const std::vector<std::string> &Args, 395193323Sed const std::string &InputFile, 396193323Sed const std::string &OutputFile, 397193323Sed const std::vector<std::string> &ArgsForGCC, 398193323Sed const std::vector<std::string> &SharedLibs, 399193323Sed unsigned Timeout, 400193323Sed unsigned MemoryLimit) { 401193323Sed 402193323Sed sys::Path OutputAsmFile; 403193323Sed OutputCode(Bitcode, OutputAsmFile); 404198090Srdivacky FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); 405193323Sed 406193323Sed std::vector<std::string> GCCArgs(ArgsForGCC); 407193323Sed GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 408193323Sed GCCArgs.insert(GCCArgs.end(), gccArgs.begin(), gccArgs.end()); 409193323Sed 410193323Sed // Assuming LLC worked, compile the result with GCC and run it. 411198090Srdivacky return gcc->ExecuteProgram(OutputAsmFile.str(), Args, GCC::AsmFile, 412193323Sed InputFile, OutputFile, GCCArgs, 413193323Sed Timeout, MemoryLimit); 414193323Sed} 415193323Sed 416193323Sed/// createLLC - Try to find the LLC executable 417193323Sed/// 418198090SrdivackyLLC *AbstractInterpreter::createLLC(const char *Argv0, 419193323Sed std::string &Message, 420193323Sed const std::vector<std::string> *Args, 421193323Sed const std::vector<std::string> *GCCArgs) { 422198090Srdivacky std::string LLCPath = 423198090Srdivacky FindExecutable("llc", Argv0, (void *)(intptr_t)&createLLC).str(); 424193323Sed if (LLCPath.empty()) { 425193323Sed Message = "Cannot find `llc' in executable directory or PATH!\n"; 426193323Sed return 0; 427193323Sed } 428193323Sed 429193323Sed Message = "Found llc: " + LLCPath + "\n"; 430198090Srdivacky GCC *gcc = GCC::create(Message, GCCArgs); 431193323Sed if (!gcc) { 432198090Srdivacky errs() << Message << "\n"; 433193323Sed exit(1); 434193323Sed } 435193323Sed return new LLC(LLCPath, gcc, Args, GCCArgs); 436193323Sed} 437193323Sed 438193323Sed//===---------------------------------------------------------------------===// 439193323Sed// JIT Implementation of AbstractIntepreter interface 440193323Sed// 441193323Sednamespace { 442193323Sed class JIT : public AbstractInterpreter { 443193323Sed std::string LLIPath; // The path to the LLI executable 444193323Sed std::vector<std::string> ToolArgs; // Args to pass to LLI 445193323Sed public: 446193323Sed JIT(const std::string &Path, const std::vector<std::string> *Args) 447193323Sed : LLIPath(Path) { 448193323Sed ToolArgs.clear (); 449193323Sed if (Args) { ToolArgs = *Args; } 450193323Sed } 451193323Sed 452193323Sed virtual int ExecuteProgram(const std::string &Bitcode, 453193323Sed const std::vector<std::string> &Args, 454193323Sed const std::string &InputFile, 455193323Sed const std::string &OutputFile, 456193323Sed const std::vector<std::string> &GCCArgs = 457193323Sed std::vector<std::string>(), 458193323Sed const std::vector<std::string> &SharedLibs = 459193323Sed std::vector<std::string>(), 460193323Sed unsigned Timeout =0, 461193323Sed unsigned MemoryLimit =0); 462193323Sed }; 463193323Sed} 464193323Sed 465193323Sedint JIT::ExecuteProgram(const std::string &Bitcode, 466193323Sed const std::vector<std::string> &Args, 467193323Sed const std::string &InputFile, 468193323Sed const std::string &OutputFile, 469193323Sed const std::vector<std::string> &GCCArgs, 470193323Sed const std::vector<std::string> &SharedLibs, 471193323Sed unsigned Timeout, 472193323Sed unsigned MemoryLimit) { 473193323Sed // Construct a vector of parameters, incorporating those from the command-line 474193323Sed std::vector<const char*> JITArgs; 475193323Sed JITArgs.push_back(LLIPath.c_str()); 476193323Sed JITArgs.push_back("-force-interpreter=false"); 477193323Sed 478193323Sed // Add any extra LLI args. 479193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 480193323Sed JITArgs.push_back(ToolArgs[i].c_str()); 481193323Sed 482193323Sed for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 483193323Sed JITArgs.push_back("-load"); 484193323Sed JITArgs.push_back(SharedLibs[i].c_str()); 485193323Sed } 486193323Sed JITArgs.push_back(Bitcode.c_str()); 487193323Sed // Add optional parameters to the running program from Argv 488193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 489193323Sed JITArgs.push_back(Args[i].c_str()); 490193323Sed JITArgs.push_back(0); 491193323Sed 492198090Srdivacky outs() << "<jit>"; outs().flush(); 493198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 494193323Sed for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) 495198090Srdivacky errs() << " " << JITArgs[i]; 496198090Srdivacky errs() << "\n"; 497193323Sed ); 498198090Srdivacky DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 499193323Sed return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], 500193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 501193323Sed Timeout, MemoryLimit); 502193323Sed} 503193323Sed 504193323Sed/// createJIT - Try to find the LLI executable 505193323Sed/// 506198090SrdivackyAbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, 507193323Sed std::string &Message, const std::vector<std::string> *Args) { 508198090Srdivacky std::string LLIPath = 509198090Srdivacky FindExecutable("lli", Argv0, (void *)(intptr_t)&createJIT).str(); 510193323Sed if (!LLIPath.empty()) { 511193323Sed Message = "Found lli: " + LLIPath + "\n"; 512193323Sed return new JIT(LLIPath, Args); 513193323Sed } 514193323Sed 515193323Sed Message = "Cannot find `lli' in executable directory or PATH!\n"; 516193323Sed return 0; 517193323Sed} 518193323Sed 519193323SedGCC::FileType CBE::OutputCode(const std::string &Bitcode, 520193323Sed sys::Path &OutputCFile) { 521193323Sed sys::Path uniqueFile(Bitcode+".cbe.c"); 522193323Sed std::string ErrMsg; 523193323Sed if (uniqueFile.makeUnique(true, &ErrMsg)) { 524198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 525193323Sed exit(1); 526193323Sed } 527193323Sed OutputCFile = uniqueFile; 528193323Sed std::vector<const char *> LLCArgs; 529193323Sed LLCArgs.push_back (LLCPath.c_str()); 530193323Sed 531193323Sed // Add any extra LLC args. 532193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 533193323Sed LLCArgs.push_back(ToolArgs[i].c_str()); 534193323Sed 535193323Sed LLCArgs.push_back ("-o"); 536193323Sed LLCArgs.push_back (OutputCFile.c_str()); // Output to the C file 537193323Sed LLCArgs.push_back ("-march=c"); // Output C language 538193323Sed LLCArgs.push_back ("-f"); // Overwrite as necessary... 539193323Sed LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode 540193323Sed LLCArgs.push_back (0); 541193323Sed 542198090Srdivacky outs() << "<cbe>"; outs().flush(); 543198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 544193323Sed for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) 545198090Srdivacky errs() << " " << LLCArgs[i]; 546198090Srdivacky errs() << "\n"; 547193323Sed ); 548193323Sed if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), 549193323Sed sys::Path())) 550193323Sed ProcessFailure(LLCPath, &LLCArgs[0]); 551193323Sed return GCC::CFile; 552193323Sed} 553193323Sed 554193323Sedvoid CBE::compileProgram(const std::string &Bitcode) { 555193323Sed sys::Path OutputCFile; 556193323Sed OutputCode(Bitcode, OutputCFile); 557193323Sed OutputCFile.eraseFromDisk(); 558193323Sed} 559193323Sed 560193323Sedint CBE::ExecuteProgram(const std::string &Bitcode, 561193323Sed const std::vector<std::string> &Args, 562193323Sed const std::string &InputFile, 563193323Sed const std::string &OutputFile, 564193323Sed const std::vector<std::string> &ArgsForGCC, 565193323Sed const std::vector<std::string> &SharedLibs, 566193323Sed unsigned Timeout, 567193323Sed unsigned MemoryLimit) { 568193323Sed sys::Path OutputCFile; 569193323Sed OutputCode(Bitcode, OutputCFile); 570193323Sed 571198090Srdivacky FileRemover CFileRemove(OutputCFile, !SaveTemps); 572193323Sed 573193323Sed std::vector<std::string> GCCArgs(ArgsForGCC); 574193323Sed GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 575193323Sed 576198090Srdivacky return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, 577193323Sed InputFile, OutputFile, GCCArgs, 578193323Sed Timeout, MemoryLimit); 579193323Sed} 580193323Sed 581193323Sed/// createCBE - Try to find the 'llc' executable 582193323Sed/// 583198090SrdivackyCBE *AbstractInterpreter::createCBE(const char *Argv0, 584193323Sed std::string &Message, 585193323Sed const std::vector<std::string> *Args, 586193323Sed const std::vector<std::string> *GCCArgs) { 587198090Srdivacky sys::Path LLCPath = 588198090Srdivacky FindExecutable("llc", Argv0, (void *)(intptr_t)&createCBE); 589193323Sed if (LLCPath.isEmpty()) { 590193323Sed Message = 591193323Sed "Cannot find `llc' in executable directory or PATH!\n"; 592193323Sed return 0; 593193323Sed } 594193323Sed 595198090Srdivacky Message = "Found llc: " + LLCPath.str() + "\n"; 596198090Srdivacky GCC *gcc = GCC::create(Message, GCCArgs); 597193323Sed if (!gcc) { 598198090Srdivacky errs() << Message << "\n"; 599193323Sed exit(1); 600193323Sed } 601193323Sed return new CBE(LLCPath, gcc, Args); 602193323Sed} 603193323Sed 604193323Sed//===---------------------------------------------------------------------===// 605193323Sed// GCC abstraction 606193323Sed// 607198090Srdivacky 608198090Srdivackystatic bool 609198090SrdivackyIsARMArchitecture(std::vector<std::string> Args) 610198090Srdivacky{ 611198090Srdivacky for (std::vector<std::string>::const_iterator 612198090Srdivacky I = Args.begin(), E = Args.end(); I != E; ++I) { 613199481Srdivacky StringRef S(*I); 614199481Srdivacky if (!S.equals_lower("-arch")) { 615198090Srdivacky ++I; 616199481Srdivacky if (I != E && !S.substr(0, strlen("arm")).equals_lower("arm")) { 617198090Srdivacky return true; 618198090Srdivacky } 619198090Srdivacky } 620198090Srdivacky } 621198090Srdivacky 622198090Srdivacky return false; 623198090Srdivacky} 624198090Srdivacky 625193323Sedint GCC::ExecuteProgram(const std::string &ProgramFile, 626193323Sed const std::vector<std::string> &Args, 627193323Sed FileType fileType, 628193323Sed const std::string &InputFile, 629193323Sed const std::string &OutputFile, 630193323Sed const std::vector<std::string> &ArgsForGCC, 631193323Sed unsigned Timeout, 632193323Sed unsigned MemoryLimit) { 633193323Sed std::vector<const char*> GCCArgs; 634193323Sed 635193323Sed GCCArgs.push_back(GCCPath.c_str()); 636193323Sed 637193323Sed for (std::vector<std::string>::const_iterator 638193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 639193323Sed GCCArgs.push_back(I->c_str()); 640193323Sed 641193323Sed // Specify -x explicitly in case the extension is wonky 642193323Sed GCCArgs.push_back("-x"); 643193323Sed if (fileType == CFile) { 644193323Sed GCCArgs.push_back("c"); 645193323Sed GCCArgs.push_back("-fno-strict-aliasing"); 646193323Sed } else { 647193323Sed GCCArgs.push_back("assembler"); 648198090Srdivacky 649198090Srdivacky // For ARM architectures we don't want this flag. bugpoint isn't 650198090Srdivacky // explicitly told what architecture it is working on, so we get 651198090Srdivacky // it from gcc flags 652198090Srdivacky if ((TargetTriple.getOS() == Triple::Darwin) && 653198090Srdivacky !IsARMArchitecture(ArgsForGCC)) 654198090Srdivacky GCCArgs.push_back("-force_cpusubtype_ALL"); 655193323Sed } 656193323Sed GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename... 657193323Sed GCCArgs.push_back("-x"); 658193323Sed GCCArgs.push_back("none"); 659193323Sed GCCArgs.push_back("-o"); 660193323Sed sys::Path OutputBinary (ProgramFile+".gcc.exe"); 661193323Sed std::string ErrMsg; 662193323Sed if (OutputBinary.makeUnique(true, &ErrMsg)) { 663198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 664193323Sed exit(1); 665193323Sed } 666193323Sed GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 667193323Sed 668193323Sed // Add any arguments intended for GCC. We locate them here because this is 669193323Sed // most likely -L and -l options that need to come before other libraries but 670193323Sed // after the source. Other options won't be sensitive to placement on the 671193323Sed // command line, so this should be safe. 672193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 673193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 674193323Sed 675193323Sed GCCArgs.push_back("-lm"); // Hard-code the math library... 676193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit... 677193323Sed#if defined (HAVE_LINK_R) 678193323Sed GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files 679193323Sed#endif 680198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 681198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 682193323Sed GCCArgs.push_back(0); // NULL terminator 683193323Sed 684198090Srdivacky outs() << "<gcc>"; outs().flush(); 685198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 686193323Sed for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) 687198090Srdivacky errs() << " " << GCCArgs[i]; 688198090Srdivacky errs() << "\n"; 689193323Sed ); 690193323Sed if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 691193323Sed sys::Path())) { 692193323Sed ProcessFailure(GCCPath, &GCCArgs[0]); 693193323Sed exit(1); 694193323Sed } 695193323Sed 696193323Sed std::vector<const char*> ProgramArgs; 697193323Sed 698193323Sed if (RemoteClientPath.isEmpty()) 699193323Sed ProgramArgs.push_back(OutputBinary.c_str()); 700193323Sed else { 701193323Sed ProgramArgs.push_back(RemoteClientPath.c_str()); 702193323Sed ProgramArgs.push_back(RemoteHost.c_str()); 703198090Srdivacky if (!RemoteUser.empty()) { 704198090Srdivacky ProgramArgs.push_back("-l"); 705198090Srdivacky ProgramArgs.push_back(RemoteUser.c_str()); 706198090Srdivacky } 707198090Srdivacky if (!RemotePort.empty()) { 708198090Srdivacky ProgramArgs.push_back("-p"); 709198090Srdivacky ProgramArgs.push_back(RemotePort.c_str()); 710198090Srdivacky } 711193323Sed if (!RemoteExtra.empty()) { 712193323Sed ProgramArgs.push_back(RemoteExtra.c_str()); 713193323Sed } 714193323Sed 715198090Srdivacky // Full path to the binary. We need to cd to the exec directory because 716198090Srdivacky // there is a dylib there that the exec expects to find in the CWD 717193323Sed char* env_pwd = getenv("PWD"); 718193323Sed std::string Exec = "cd "; 719193323Sed Exec += env_pwd; 720193323Sed Exec += "; ./"; 721193323Sed Exec += OutputBinary.c_str(); 722193323Sed ProgramArgs.push_back(Exec.c_str()); 723193323Sed } 724193323Sed 725193323Sed // Add optional parameters to the running program from Argv 726193323Sed for (unsigned i=0, e = Args.size(); i != e; ++i) 727193323Sed ProgramArgs.push_back(Args[i].c_str()); 728193323Sed ProgramArgs.push_back(0); // NULL terminator 729193323Sed 730193323Sed // Now that we have a binary, run it! 731198090Srdivacky outs() << "<program>"; outs().flush(); 732198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 733193323Sed for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i) 734198090Srdivacky errs() << " " << ProgramArgs[i]; 735198090Srdivacky errs() << "\n"; 736193323Sed ); 737193323Sed 738198090Srdivacky FileRemover OutputBinaryRemover(OutputBinary, !SaveTemps); 739193323Sed 740198090Srdivacky if (RemoteClientPath.isEmpty()) { 741198090Srdivacky DEBUG(errs() << "<run locally>";); 742193323Sed return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], 743193323Sed sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 744193323Sed Timeout, MemoryLimit); 745198090Srdivacky } else { 746198090Srdivacky outs() << "<run remotely>"; outs().flush(); 747198090Srdivacky return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), 748198090Srdivacky &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 749198090Srdivacky sys::Path(OutputFile), Timeout, MemoryLimit); 750198090Srdivacky } 751193323Sed} 752193323Sed 753193323Sedint GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 754193323Sed std::string &OutputFile, 755193323Sed const std::vector<std::string> &ArgsForGCC) { 756193323Sed sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); 757193323Sed std::string ErrMsg; 758193323Sed if (uniqueFilename.makeUnique(true, &ErrMsg)) { 759198090Srdivacky errs() << "Error making unique filename: " << ErrMsg << "\n"; 760193323Sed exit(1); 761193323Sed } 762198090Srdivacky OutputFile = uniqueFilename.str(); 763193323Sed 764193323Sed std::vector<const char*> GCCArgs; 765193323Sed 766193323Sed GCCArgs.push_back(GCCPath.c_str()); 767193323Sed 768193323Sed for (std::vector<std::string>::const_iterator 769193323Sed I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 770193323Sed GCCArgs.push_back(I->c_str()); 771193323Sed 772193323Sed // Compile the C/asm file into a shared object 773193323Sed GCCArgs.push_back("-x"); 774193323Sed GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 775193323Sed GCCArgs.push_back("-fno-strict-aliasing"); 776193323Sed GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. 777193323Sed GCCArgs.push_back("-x"); 778193323Sed GCCArgs.push_back("none"); 779198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 780198090Srdivacky GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 781198090Srdivacky else if (TargetTriple.getOS() == Triple::Darwin) { 782198090Srdivacky // link all source files into a single module in data segment, rather than 783198090Srdivacky // generating blocks. dynamic_lookup requires that you set 784198090Srdivacky // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 785198090Srdivacky // bugpoint to just pass that in the environment of GCC. 786198090Srdivacky GCCArgs.push_back("-single_module"); 787198090Srdivacky GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 788198090Srdivacky GCCArgs.push_back("-undefined"); 789198090Srdivacky GCCArgs.push_back("dynamic_lookup"); 790198090Srdivacky } else 791198090Srdivacky GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 792193323Sed 793198090Srdivacky if ((TargetTriple.getArch() == Triple::alpha) || 794198090Srdivacky (TargetTriple.getArch() == Triple::x86_64)) 795198090Srdivacky GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 796198090Srdivacky 797198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 798198090Srdivacky GCCArgs.push_back("-mcpu=v9"); 799198090Srdivacky 800193323Sed GCCArgs.push_back("-o"); 801193323Sed GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 802193323Sed GCCArgs.push_back("-O2"); // Optimize the program a bit. 803193323Sed 804193323Sed 805193323Sed 806193323Sed // Add any arguments intended for GCC. We locate them here because this is 807193323Sed // most likely -L and -l options that need to come before other libraries but 808193323Sed // after the source. Other options won't be sensitive to placement on the 809193323Sed // command line, so this should be safe. 810193323Sed for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 811193323Sed GCCArgs.push_back(ArgsForGCC[i].c_str()); 812193323Sed GCCArgs.push_back(0); // NULL terminator 813193323Sed 814193323Sed 815193323Sed 816198090Srdivacky outs() << "<gcc>"; outs().flush(); 817198090Srdivacky DEBUG(errs() << "\nAbout to run:\t"; 818193323Sed for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) 819198090Srdivacky errs() << " " << GCCArgs[i]; 820198090Srdivacky errs() << "\n"; 821193323Sed ); 822193323Sed if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 823193323Sed sys::Path())) { 824193323Sed ProcessFailure(GCCPath, &GCCArgs[0]); 825193323Sed return 1; 826193323Sed } 827193323Sed return 0; 828193323Sed} 829193323Sed 830193323Sed/// create - Try to find the `gcc' executable 831193323Sed/// 832198090SrdivackyGCC *GCC::create(std::string &Message, 833193323Sed const std::vector<std::string> *Args) { 834198090Srdivacky sys::Path GCCPath = sys::Program::FindProgramByName("gcc"); 835193323Sed if (GCCPath.isEmpty()) { 836193323Sed Message = "Cannot find `gcc' in executable directory or PATH!\n"; 837193323Sed return 0; 838193323Sed } 839193323Sed 840193323Sed sys::Path RemoteClientPath; 841193323Sed if (!RemoteClient.empty()) 842198090Srdivacky RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); 843193323Sed 844198090Srdivacky Message = "Found gcc: " + GCCPath.str() + "\n"; 845193323Sed return new GCC(GCCPath, RemoteClientPath, Args); 846193323Sed} 847