1193323Sed//===-- ToolRunner.cpp ----------------------------------------------------===// 2193323Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193323Sed// 7193323Sed//===----------------------------------------------------------------------===// 8193323Sed// 9193323Sed// This file implements the interfaces described in the ToolRunner.h file. 10193323Sed// 11193323Sed//===----------------------------------------------------------------------===// 12193323Sed 13193323Sed#include "ToolRunner.h" 14314564Sdim#include "llvm/Config/config.h" 15193323Sed#include "llvm/Support/CommandLine.h" 16193323Sed#include "llvm/Support/Debug.h" 17261991Sdim#include "llvm/Support/FileSystem.h" 18193323Sed#include "llvm/Support/FileUtilities.h" 19249423Sdim#include "llvm/Support/Program.h" 20198090Srdivacky#include "llvm/Support/raw_ostream.h" 21193323Sed#include <fstream> 22193323Sed#include <sstream> 23309124Sdim#include <utility> 24193323Sedusing namespace llvm; 25193323Sed 26276479Sdim#define DEBUG_TYPE "toolrunner" 27276479Sdim 28198090Srdivackynamespace llvm { 29314564Sdimcl::opt<bool> SaveTemps("save-temps", cl::init(false), 30314564Sdim cl::desc("Save temporary files")); 31198090Srdivacky} 32198090Srdivacky 33193323Sednamespace { 34314564Sdimcl::opt<std::string> 35314564Sdim RemoteClient("remote-client", 36314564Sdim cl::desc("Remote execution client (rsh/ssh)")); 37193323Sed 38314564Sdimcl::opt<std::string> RemoteHost("remote-host", 39314564Sdim cl::desc("Remote execution (rsh/ssh) host")); 40193323Sed 41314564Sdimcl::opt<std::string> RemotePort("remote-port", 42314564Sdim cl::desc("Remote execution (rsh/ssh) port")); 43198090Srdivacky 44314564Sdimcl::opt<std::string> RemoteUser("remote-user", 45314564Sdim cl::desc("Remote execution (rsh/ssh) user id")); 46193323Sed 47314564Sdimcl::opt<std::string> 48314564Sdim RemoteExtra("remote-extra-options", 49314564Sdim cl::desc("Remote execution (rsh/ssh) extra options")); 50193323Sed} 51193323Sed 52198090Srdivacky/// RunProgramWithTimeout - This function provides an alternate interface 53198090Srdivacky/// to the sys::Program::ExecuteAndWait interface. 54207618Srdivacky/// @see sys::Program::ExecuteAndWait 55341825Sdimstatic int RunProgramWithTimeout(StringRef ProgramPath, 56341825Sdim ArrayRef<StringRef> Args, StringRef StdInFile, 57341825Sdim StringRef StdOutFile, StringRef StdErrFile, 58341825Sdim unsigned NumSeconds = 0, 59218885Sdim unsigned MemoryLimit = 0, 60276479Sdim std::string *ErrMsg = nullptr) { 61327952Sdim Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile}; 62341825Sdim return sys::ExecuteAndWait(ProgramPath, Args, None, Redirects, NumSeconds, 63314564Sdim MemoryLimit, ErrMsg); 64193323Sed} 65193323Sed 66198090Srdivacky/// RunProgramRemotelyWithTimeout - This function runs the given program 67198090Srdivacky/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 68198090Srdivacky/// Returns the remote program exit code or reports a remote client error if it 69198090Srdivacky/// fails. Remote client is required to return 255 if it failed or program exit 70198090Srdivacky/// code otherwise. 71207618Srdivacky/// @see sys::Program::ExecuteAndWait 72341825Sdimstatic int RunProgramRemotelyWithTimeout( 73341825Sdim StringRef RemoteClientPath, ArrayRef<StringRef> Args, StringRef StdInFile, 74341825Sdim StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0, 75341825Sdim unsigned MemoryLimit = 0) { 76327952Sdim Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile}; 77193323Sed 78198090Srdivacky // Run the program remotely with the remote client 79341825Sdim int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, None, Redirects, 80341825Sdim NumSeconds, MemoryLimit); 81198090Srdivacky 82198090Srdivacky // Has the remote client fail? 83198090Srdivacky if (255 == ReturnCode) { 84198090Srdivacky std::ostringstream OS; 85198090Srdivacky OS << "\nError running remote client:\n "; 86341825Sdim for (StringRef Arg : Args) 87341825Sdim OS << " " << Arg.str(); 88198090Srdivacky OS << "\n"; 89198090Srdivacky 90198090Srdivacky // The error message is in the output file, let's print it out from there. 91261991Sdim std::string StdOutFileName = StdOutFile.str(); 92261991Sdim std::ifstream ErrorFile(StdOutFileName.c_str()); 93198090Srdivacky if (ErrorFile) { 94198090Srdivacky std::copy(std::istreambuf_iterator<char>(ErrorFile), 95198090Srdivacky std::istreambuf_iterator<char>(), 96198090Srdivacky std::ostreambuf_iterator<char>(OS)); 97198090Srdivacky ErrorFile.close(); 98198090Srdivacky } 99198090Srdivacky 100236386Sdim errs() << OS.str(); 101198090Srdivacky } 102198090Srdivacky 103198090Srdivacky return ReturnCode; 104198090Srdivacky} 105198090Srdivacky 106341825Sdimstatic Error ProcessFailure(StringRef ProgPath, ArrayRef<StringRef> Args, 107314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) { 108193323Sed std::ostringstream OS; 109193323Sed OS << "\nError running tool:\n "; 110341825Sdim for (StringRef Arg : Args) 111341825Sdim OS << " " << Arg.str(); 112193323Sed OS << "\n"; 113218885Sdim 114193323Sed // Rerun the compiler, capturing any error messages to print them. 115261991Sdim SmallString<128> ErrorFilename; 116276479Sdim std::error_code EC = sys::fs::createTemporaryFile( 117280031Sdim "bugpoint.program_error_messages", "", ErrorFilename); 118261991Sdim if (EC) { 119261991Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 120193323Sed exit(1); 121193323Sed } 122276479Sdim 123261991Sdim RunProgramWithTimeout(ProgPath, Args, "", ErrorFilename.str(), 124261991Sdim ErrorFilename.str(), Timeout, MemoryLimit); 125208599Srdivacky // FIXME: check return code ? 126193323Sed 127296417Sdim // Print out the error messages generated by CC if possible... 128193323Sed std::ifstream ErrorFile(ErrorFilename.c_str()); 129193323Sed if (ErrorFile) { 130193323Sed std::copy(std::istreambuf_iterator<char>(ErrorFile), 131193323Sed std::istreambuf_iterator<char>(), 132193323Sed std::ostreambuf_iterator<char>(OS)); 133193323Sed ErrorFile.close(); 134193323Sed } 135193323Sed 136261991Sdim sys::fs::remove(ErrorFilename.c_str()); 137314564Sdim return make_error<StringError>(OS.str(), inconvertibleErrorCode()); 138193323Sed} 139193323Sed 140193323Sed//===---------------------------------------------------------------------===// 141193323Sed// LLI Implementation of AbstractIntepreter interface 142193323Sed// 143193323Sednamespace { 144314564Sdimclass LLI : public AbstractInterpreter { 145314564Sdim std::string LLIPath; // The path to the LLI executable 146314564Sdim std::vector<std::string> ToolArgs; // Args to pass to LLI 147314564Sdimpublic: 148314564Sdim LLI(const std::string &Path, const std::vector<std::string> *Args) 149193323Sed : LLIPath(Path) { 150314564Sdim ToolArgs.clear(); 151314564Sdim if (Args) { 152314564Sdim ToolArgs = *Args; 153193323Sed } 154314564Sdim } 155193323Sed 156314564Sdim Expected<int> ExecuteProgram( 157314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 158314564Sdim const std::string &InputFile, const std::string &OutputFile, 159314564Sdim const std::vector<std::string> &CCArgs, 160314564Sdim const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 161314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) override; 162314564Sdim}; 163193323Sed} 164193323Sed 165314564SdimExpected<int> LLI::ExecuteProgram(const std::string &Bitcode, 166314564Sdim const std::vector<std::string> &Args, 167314564Sdim const std::string &InputFile, 168314564Sdim const std::string &OutputFile, 169314564Sdim const std::vector<std::string> &CCArgs, 170314564Sdim const std::vector<std::string> &SharedLibs, 171314564Sdim unsigned Timeout, unsigned MemoryLimit) { 172341825Sdim std::vector<StringRef> LLIArgs; 173360784Sdim LLIArgs.push_back(LLIPath); 174193323Sed LLIArgs.push_back("-force-interpreter=true"); 175193323Sed 176218885Sdim for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), 177314564Sdim e = SharedLibs.end(); 178314564Sdim i != e; ++i) { 179199481Srdivacky LLIArgs.push_back("-load"); 180341825Sdim LLIArgs.push_back(*i); 181199481Srdivacky } 182199481Srdivacky 183193323Sed // Add any extra LLI args. 184193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 185341825Sdim LLIArgs.push_back(ToolArgs[i]); 186193323Sed 187341825Sdim LLIArgs.push_back(Bitcode); 188193323Sed // Add optional parameters to the running program from Argv 189314564Sdim for (unsigned i = 0, e = Args.size(); i != e; ++i) 190341825Sdim LLIArgs.push_back(Args[i]); 191193323Sed 192314564Sdim outs() << "<lli>"; 193314564Sdim outs().flush(); 194341825Sdim LLVM_DEBUG(errs() << "\nAbout to run:\t"; 195341825Sdim for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs() 196341825Sdim << " " << LLIArgs[i]; 197341825Sdim errs() << "\n";); 198341825Sdim return RunProgramWithTimeout(LLIPath, LLIArgs, InputFile, OutputFile, 199314564Sdim OutputFile, Timeout, MemoryLimit); 200193323Sed} 201193323Sed 202314564Sdimvoid AbstractInterpreter::anchor() {} 203234353Sdim 204344779SdimErrorOr<std::string> llvm::FindProgramByName(const std::string &ExeName, 205261991Sdim const char *Argv0, 206261991Sdim void *MainAddr) { 207261991Sdim // Check the directory that the calling program is in. We can do 208261991Sdim // this if ProgramPath contains at least one / character, indicating that it 209261991Sdim // is a relative path to the executable itself. 210261991Sdim std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr); 211261991Sdim StringRef Result = sys::path::parent_path(Main); 212344779Sdim if (ErrorOr<std::string> Path = sys::findProgramByName(ExeName, Result)) 213344779Sdim return *Path; 214261991Sdim 215344779Sdim // Check the user PATH. 216344779Sdim return sys::findProgramByName(ExeName); 217261991Sdim} 218261991Sdim 219193323Sed// LLI create method - Try to find the LLI executable 220314564SdimAbstractInterpreter * 221314564SdimAbstractInterpreter::createLLI(const char *Argv0, std::string &Message, 222314564Sdim const std::vector<std::string> *ToolArgs) { 223344779Sdim if (ErrorOr<std::string> LLIPath = 224344779Sdim FindProgramByName("lli", Argv0, (void *)(intptr_t)&createLLI)) { 225344779Sdim Message = "Found lli: " + *LLIPath + "\n"; 226344779Sdim return new LLI(*LLIPath, ToolArgs); 227344779Sdim } else { 228344779Sdim Message = LLIPath.getError().message() + "\n"; 229344779Sdim return nullptr; 230193323Sed } 231193323Sed} 232193323Sed 233193323Sed//===---------------------------------------------------------------------===// 234218885Sdim// Custom compiler command implementation of AbstractIntepreter interface 235218885Sdim// 236218885Sdim// Allows using a custom command for compiling the bitcode, thus allows, for 237218885Sdim// example, to compile a bitcode fragment without linking or executing, then 238218885Sdim// using a custom wrapper script to check for compiler errors. 239218885Sdimnamespace { 240314564Sdimclass CustomCompiler : public AbstractInterpreter { 241314564Sdim std::string CompilerCommand; 242314564Sdim std::vector<std::string> CompilerArgs; 243218885Sdim 244314564Sdimpublic: 245314564Sdim CustomCompiler(const std::string &CompilerCmd, 246314564Sdim std::vector<std::string> CompArgs) 247314564Sdim : CompilerCommand(CompilerCmd), CompilerArgs(std::move(CompArgs)) {} 248218885Sdim 249314564Sdim Error compileProgram(const std::string &Bitcode, unsigned Timeout = 0, 250314564Sdim unsigned MemoryLimit = 0) override; 251314564Sdim 252314564Sdim Expected<int> ExecuteProgram( 253314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 254314564Sdim const std::string &InputFile, const std::string &OutputFile, 255314564Sdim const std::vector<std::string> &CCArgs = std::vector<std::string>(), 256314564Sdim const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 257314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) override { 258314564Sdim return make_error<StringError>( 259314564Sdim "Execution not supported with -compile-custom", 260314564Sdim inconvertibleErrorCode()); 261314564Sdim } 262314564Sdim}; 263218885Sdim} 264218885Sdim 265314564SdimError CustomCompiler::compileProgram(const std::string &Bitcode, 266314564Sdim unsigned Timeout, unsigned MemoryLimit) { 267218885Sdim 268341825Sdim std::vector<StringRef> ProgramArgs; 269360784Sdim ProgramArgs.push_back(CompilerCommand); 270218885Sdim 271360784Sdim for (const auto &Arg : CompilerArgs) 272360784Sdim ProgramArgs.push_back(Arg); 273341825Sdim ProgramArgs.push_back(Bitcode); 274218885Sdim 275218885Sdim // Add optional parameters to the running program from Argv 276360784Sdim for (const auto &Arg : CompilerArgs) 277360784Sdim ProgramArgs.push_back(Arg); 278218885Sdim 279341825Sdim if (RunProgramWithTimeout(CompilerCommand, ProgramArgs, "", "", "", Timeout, 280341825Sdim MemoryLimit)) 281341825Sdim return ProcessFailure(CompilerCommand, ProgramArgs, Timeout, MemoryLimit); 282314564Sdim return Error::success(); 283218885Sdim} 284218885Sdim 285218885Sdim//===---------------------------------------------------------------------===// 286193323Sed// Custom execution command implementation of AbstractIntepreter interface 287193323Sed// 288193323Sed// Allows using a custom command for executing the bitcode, thus allows, 289218885Sdim// for example, to invoke a cross compiler for code generation followed by 290193323Sed// a simulator that executes the generated binary. 291193323Sednamespace { 292314564Sdimclass CustomExecutor : public AbstractInterpreter { 293314564Sdim std::string ExecutionCommand; 294314564Sdim std::vector<std::string> ExecutorArgs; 295193323Sed 296314564Sdimpublic: 297314564Sdim CustomExecutor(const std::string &ExecutionCmd, 298314564Sdim std::vector<std::string> ExecArgs) 299314564Sdim : ExecutionCommand(ExecutionCmd), ExecutorArgs(std::move(ExecArgs)) {} 300314564Sdim 301314564Sdim Expected<int> ExecuteProgram( 302314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 303314564Sdim const std::string &InputFile, const std::string &OutputFile, 304314564Sdim const std::vector<std::string> &CCArgs, 305314564Sdim const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 306314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) override; 307314564Sdim}; 308193323Sed} 309193323Sed 310314564SdimExpected<int> CustomExecutor::ExecuteProgram( 311314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 312314564Sdim const std::string &InputFile, const std::string &OutputFile, 313314564Sdim const std::vector<std::string> &CCArgs, 314314564Sdim const std::vector<std::string> &SharedLibs, unsigned Timeout, 315314564Sdim unsigned MemoryLimit) { 316193323Sed 317341825Sdim std::vector<StringRef> ProgramArgs; 318341825Sdim ProgramArgs.push_back(ExecutionCommand); 319193323Sed 320193323Sed for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 321341825Sdim ProgramArgs.push_back(ExecutorArgs[i]); 322341825Sdim ProgramArgs.push_back(Bitcode); 323193323Sed 324193323Sed // Add optional parameters to the running program from Argv 325207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 326341825Sdim ProgramArgs.push_back(Args[i]); 327193323Sed 328341825Sdim return RunProgramWithTimeout(ExecutionCommand, ProgramArgs, InputFile, 329314564Sdim OutputFile, OutputFile, Timeout, MemoryLimit); 330193323Sed} 331193323Sed 332218885Sdim// Tokenize the CommandLine to the command and the args to allow 333218885Sdim// defining a full command line as the command instead of just the 334218885Sdim// executed program. We cannot just pass the whole string after the command 335321369Sdim// as a single argument because then the program sees only a single 336218885Sdim// command line argument (with spaces in it: "foo bar" instead 337218885Sdim// of "foo" and "bar"). 338218885Sdim// 339321369Sdim// Spaces are used as a delimiter; however repeated, leading, and trailing 340321369Sdim// whitespace are ignored. Simple escaping is allowed via the '\' 341321369Sdim// character, as seen below: 342321369Sdim// 343321369Sdim// Two consecutive '\' evaluate to a single '\'. 344321369Sdim// A space after a '\' evaluates to a space that is not interpreted as a 345321369Sdim// delimiter. 346321369Sdim// Any other instances of the '\' character are removed. 347321369Sdim// 348321369Sdim// Example: 349321369Sdim// '\\' -> '\' 350321369Sdim// '\ ' -> ' ' 351321369Sdim// 'exa\mple' -> 'example' 352321369Sdim// 353344779Sdimstatic void lexCommand(const char *Argv0, std::string &Message, 354344779Sdim const std::string &CommandLine, std::string &CmdPath, 355344779Sdim std::vector<std::string> &Args) { 356193323Sed 357321369Sdim std::string Token; 358321369Sdim std::string Command; 359321369Sdim bool FoundPath = false; 360193323Sed 361321369Sdim // first argument is the PATH. 362321369Sdim // Skip repeated whitespace, leading whitespace and trailing whitespace. 363321369Sdim for (std::size_t Pos = 0u; Pos <= CommandLine.size(); ++Pos) { 364321369Sdim if ('\\' == CommandLine[Pos]) { 365321369Sdim if (Pos + 1 < CommandLine.size()) 366321369Sdim Token.push_back(CommandLine[++Pos]); 367193323Sed 368321369Sdim continue; 369321369Sdim } 370321369Sdim if (' ' == CommandLine[Pos] || CommandLine.size() == Pos) { 371321369Sdim if (Token.empty()) 372321369Sdim continue; 373321369Sdim 374321369Sdim if (!FoundPath) { 375321369Sdim Command = Token; 376321369Sdim FoundPath = true; 377321369Sdim Token.clear(); 378321369Sdim continue; 379321369Sdim } 380321369Sdim 381321369Sdim Args.push_back(Token); 382321369Sdim Token.clear(); 383321369Sdim continue; 384321369Sdim } 385321369Sdim Token.push_back(CommandLine[Pos]); 386193323Sed } 387193323Sed 388344779Sdim auto Path = FindProgramByName(Command, Argv0, (void *)(intptr_t)&lexCommand); 389280031Sdim if (!Path) { 390321369Sdim Message = std::string("Cannot find '") + Command + 391321369Sdim "' in PATH: " + Path.getError().message() + "\n"; 392218885Sdim return; 393193323Sed } 394280031Sdim CmdPath = *Path; 395193323Sed 396193323Sed Message = "Found command in: " + CmdPath + "\n"; 397218885Sdim} 398193323Sed 399218885Sdim// Custom execution environment create method, takes the execution command 400218885Sdim// as arguments 401218885SdimAbstractInterpreter *AbstractInterpreter::createCustomCompiler( 402344779Sdim const char *Argv0, std::string &Message, 403344779Sdim const std::string &CompileCommandLine) { 404218885Sdim 405218885Sdim std::string CmdPath; 406218885Sdim std::vector<std::string> Args; 407344779Sdim lexCommand(Argv0, Message, CompileCommandLine, CmdPath, Args); 408218885Sdim if (CmdPath.empty()) 409276479Sdim return nullptr; 410218885Sdim 411218885Sdim return new CustomCompiler(CmdPath, Args); 412218885Sdim} 413218885Sdim 414218885Sdim// Custom execution environment create method, takes the execution command 415218885Sdim// as arguments 416314564SdimAbstractInterpreter * 417344779SdimAbstractInterpreter::createCustomExecutor(const char *Argv0, 418344779Sdim std::string &Message, 419314564Sdim const std::string &ExecCommandLine) { 420218885Sdim 421218885Sdim std::string CmdPath; 422218885Sdim std::vector<std::string> Args; 423344779Sdim lexCommand(Argv0, Message, ExecCommandLine, CmdPath, Args); 424218885Sdim if (CmdPath.empty()) 425276479Sdim return nullptr; 426218885Sdim 427193323Sed return new CustomExecutor(CmdPath, Args); 428193323Sed} 429193323Sed 430193323Sed//===----------------------------------------------------------------------===// 431193323Sed// LLC Implementation of AbstractIntepreter interface 432193323Sed// 433314564SdimExpected<CC::FileType> LLC::OutputCode(const std::string &Bitcode, 434314564Sdim std::string &OutputAsmFile, 435314564Sdim unsigned Timeout, unsigned MemoryLimit) { 436205218Srdivacky const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); 437261991Sdim 438261991Sdim SmallString<128> UniqueFile; 439276479Sdim std::error_code EC = 440261991Sdim sys::fs::createUniqueFile(Bitcode + "-%%%%%%%" + Suffix, UniqueFile); 441261991Sdim if (EC) { 442261991Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 443193323Sed exit(1); 444193323Sed } 445261991Sdim OutputAsmFile = UniqueFile.str(); 446341825Sdim std::vector<StringRef> LLCArgs; 447341825Sdim LLCArgs.push_back(LLCPath); 448193323Sed 449193323Sed // Add any extra LLC args. 450193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 451341825Sdim LLCArgs.push_back(ToolArgs[i]); 452193323Sed 453205218Srdivacky LLCArgs.push_back("-o"); 454341825Sdim LLCArgs.push_back(OutputAsmFile); // Output to the Asm file 455341825Sdim LLCArgs.push_back(Bitcode); // This is the input bitcode 456218885Sdim 457205218Srdivacky if (UseIntegratedAssembler) 458205218Srdivacky LLCArgs.push_back("-filetype=obj"); 459218885Sdim 460205218Srdivacky outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); 461205218Srdivacky outs().flush(); 462341825Sdim LLVM_DEBUG(errs() << "\nAbout to run:\t"; 463341825Sdim for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs() 464341825Sdim << " " << LLCArgs[i]; 465341825Sdim errs() << "\n";); 466341825Sdim if (RunProgramWithTimeout(LLCPath, LLCArgs, "", "", "", Timeout, MemoryLimit)) 467341825Sdim return ProcessFailure(LLCPath, LLCArgs, Timeout, MemoryLimit); 468296417Sdim return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile; 469193323Sed} 470193323Sed 471314564SdimError LLC::compileProgram(const std::string &Bitcode, unsigned Timeout, 472314564Sdim unsigned MemoryLimit) { 473261991Sdim std::string OutputAsmFile; 474314564Sdim Expected<CC::FileType> Result = 475314564Sdim OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit); 476261991Sdim sys::fs::remove(OutputAsmFile); 477314564Sdim if (Error E = Result.takeError()) 478314564Sdim return E; 479314564Sdim return Error::success(); 480193323Sed} 481193323Sed 482314564SdimExpected<int> LLC::ExecuteProgram(const std::string &Bitcode, 483314564Sdim const std::vector<std::string> &Args, 484314564Sdim const std::string &InputFile, 485314564Sdim const std::string &OutputFile, 486314564Sdim const std::vector<std::string> &ArgsForCC, 487314564Sdim const std::vector<std::string> &SharedLibs, 488314564Sdim unsigned Timeout, unsigned MemoryLimit) { 489193323Sed 490261991Sdim std::string OutputAsmFile; 491314564Sdim Expected<CC::FileType> FileKind = 492314564Sdim OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit); 493261991Sdim FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); 494314564Sdim if (Error E = FileKind.takeError()) 495314564Sdim return std::move(E); 496193323Sed 497296417Sdim std::vector<std::string> CCArgs(ArgsForCC); 498296417Sdim CCArgs.insert(CCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 499193323Sed 500296417Sdim // Assuming LLC worked, compile the result with CC and run it. 501314564Sdim return cc->ExecuteProgram(OutputAsmFile, Args, *FileKind, InputFile, 502314564Sdim OutputFile, CCArgs, Timeout, MemoryLimit); 503193323Sed} 504193323Sed 505193323Sed/// createLLC - Try to find the LLC executable 506193323Sed/// 507314564SdimLLC *AbstractInterpreter::createLLC(const char *Argv0, std::string &Message, 508296417Sdim const std::string &CCBinary, 509193323Sed const std::vector<std::string> *Args, 510296417Sdim const std::vector<std::string> *CCArgs, 511205218Srdivacky bool UseIntegratedAssembler) { 512344779Sdim ErrorOr<std::string> LLCPath = 513344779Sdim FindProgramByName("llc", Argv0, (void *)(intptr_t)&createLLC); 514344779Sdim if (!LLCPath) { 515344779Sdim Message = LLCPath.getError().message() + "\n"; 516276479Sdim return nullptr; 517193323Sed } 518193323Sed 519344779Sdim CC *cc = CC::create(Argv0, Message, CCBinary, CCArgs); 520296417Sdim if (!cc) { 521198090Srdivacky errs() << Message << "\n"; 522193323Sed exit(1); 523193323Sed } 524344779Sdim Message = "Found llc: " + *LLCPath + "\n"; 525344779Sdim return new LLC(*LLCPath, cc, Args, UseIntegratedAssembler); 526193323Sed} 527193323Sed 528193323Sed//===---------------------------------------------------------------------===// 529193323Sed// JIT Implementation of AbstractIntepreter interface 530193323Sed// 531193323Sednamespace { 532314564Sdimclass JIT : public AbstractInterpreter { 533314564Sdim std::string LLIPath; // The path to the LLI executable 534314564Sdim std::vector<std::string> ToolArgs; // Args to pass to LLI 535314564Sdimpublic: 536314564Sdim JIT(const std::string &Path, const std::vector<std::string> *Args) 537193323Sed : LLIPath(Path) { 538314564Sdim ToolArgs.clear(); 539314564Sdim if (Args) { 540314564Sdim ToolArgs = *Args; 541193323Sed } 542314564Sdim } 543193323Sed 544314564Sdim Expected<int> ExecuteProgram( 545314564Sdim const std::string &Bitcode, const std::vector<std::string> &Args, 546314564Sdim const std::string &InputFile, const std::string &OutputFile, 547314564Sdim const std::vector<std::string> &CCArgs = std::vector<std::string>(), 548314564Sdim const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 549314564Sdim unsigned Timeout = 0, unsigned MemoryLimit = 0) override; 550314564Sdim}; 551193323Sed} 552193323Sed 553314564SdimExpected<int> JIT::ExecuteProgram(const std::string &Bitcode, 554314564Sdim const std::vector<std::string> &Args, 555314564Sdim const std::string &InputFile, 556314564Sdim const std::string &OutputFile, 557314564Sdim const std::vector<std::string> &CCArgs, 558314564Sdim const std::vector<std::string> &SharedLibs, 559314564Sdim unsigned Timeout, unsigned MemoryLimit) { 560193323Sed // Construct a vector of parameters, incorporating those from the command-line 561341825Sdim std::vector<StringRef> JITArgs; 562360784Sdim JITArgs.push_back(LLIPath); 563193323Sed JITArgs.push_back("-force-interpreter=false"); 564193323Sed 565193323Sed // Add any extra LLI args. 566193323Sed for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 567341825Sdim JITArgs.push_back(ToolArgs[i]); 568193323Sed 569193323Sed for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 570193323Sed JITArgs.push_back("-load"); 571341825Sdim JITArgs.push_back(SharedLibs[i]); 572193323Sed } 573360784Sdim JITArgs.push_back(Bitcode); 574193323Sed // Add optional parameters to the running program from Argv 575314564Sdim for (unsigned i = 0, e = Args.size(); i != e; ++i) 576341825Sdim JITArgs.push_back(Args[i]); 577193323Sed 578314564Sdim outs() << "<jit>"; 579314564Sdim outs().flush(); 580341825Sdim LLVM_DEBUG(errs() << "\nAbout to run:\t"; 581341825Sdim for (unsigned i = 0, e = JITArgs.size() - 1; i != e; ++i) errs() 582341825Sdim << " " << JITArgs[i]; 583341825Sdim errs() << "\n";); 584341825Sdim LLVM_DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 585341825Sdim return RunProgramWithTimeout(LLIPath, JITArgs, InputFile, OutputFile, 586314564Sdim OutputFile, Timeout, MemoryLimit); 587193323Sed} 588193323Sed 589193323Sed/// createJIT - Try to find the LLI executable 590193323Sed/// 591314564SdimAbstractInterpreter * 592314564SdimAbstractInterpreter::createJIT(const char *Argv0, std::string &Message, 593314564Sdim const std::vector<std::string> *Args) { 594344779Sdim if (ErrorOr<std::string> LLIPath = 595344779Sdim FindProgramByName("lli", Argv0, (void *)(intptr_t)&createJIT)) { 596344779Sdim Message = "Found lli: " + *LLIPath + "\n"; 597344779Sdim return new JIT(*LLIPath, Args); 598344779Sdim } else { 599344779Sdim Message = LLIPath.getError().message() + "\n"; 600344779Sdim return nullptr; 601193323Sed } 602193323Sed} 603193323Sed 604193323Sed//===---------------------------------------------------------------------===// 605296417Sdim// CC abstraction 606193323Sed// 607198090Srdivacky 608341825Sdimstatic bool IsARMArchitecture(std::vector<StringRef> Args) { 609341825Sdim for (size_t I = 0; I < Args.size(); ++I) { 610341825Sdim if (!Args[I].equals_lower("-arch")) 611341825Sdim continue; 612341825Sdim ++I; 613341825Sdim if (I == Args.size()) 614341825Sdim break; 615341825Sdim if (Args[I].startswith_lower("arm")) 616341825Sdim return true; 617198090Srdivacky } 618198090Srdivacky 619198090Srdivacky return false; 620198090Srdivacky} 621198090Srdivacky 622314564SdimExpected<int> CC::ExecuteProgram(const std::string &ProgramFile, 623314564Sdim const std::vector<std::string> &Args, 624314564Sdim FileType fileType, 625314564Sdim const std::string &InputFile, 626314564Sdim const std::string &OutputFile, 627314564Sdim const std::vector<std::string> &ArgsForCC, 628314564Sdim unsigned Timeout, unsigned MemoryLimit) { 629341825Sdim std::vector<StringRef> CCArgs; 630193323Sed 631341825Sdim CCArgs.push_back(CCPath); 632193323Sed 633205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 634296417Sdim CCArgs.push_back("-m32"); 635205218Srdivacky 636314564Sdim for (std::vector<std::string>::const_iterator I = ccArgs.begin(), 637314564Sdim E = ccArgs.end(); 638314564Sdim I != E; ++I) 639341825Sdim CCArgs.push_back(*I); 640193323Sed 641193323Sed // Specify -x explicitly in case the extension is wonky 642205218Srdivacky if (fileType != ObjectFile) { 643296417Sdim CCArgs.push_back("-x"); 644205218Srdivacky if (fileType == CFile) { 645296417Sdim CCArgs.push_back("c"); 646296417Sdim CCArgs.push_back("-fno-strict-aliasing"); 647205218Srdivacky } else { 648296417Sdim CCArgs.push_back("assembler"); 649198090Srdivacky 650205218Srdivacky // For ARM architectures we don't want this flag. bugpoint isn't 651205218Srdivacky // explicitly told what architecture it is working on, so we get 652296417Sdim // it from cc flags 653296417Sdim if (TargetTriple.isOSDarwin() && !IsARMArchitecture(CCArgs)) 654296417Sdim CCArgs.push_back("-force_cpusubtype_ALL"); 655205218Srdivacky } 656193323Sed } 657218885Sdim 658341825Sdim CCArgs.push_back(ProgramFile); // Specify the input filename. 659218885Sdim 660296417Sdim CCArgs.push_back("-x"); 661296417Sdim CCArgs.push_back("none"); 662296417Sdim CCArgs.push_back("-o"); 663261991Sdim 664261991Sdim SmallString<128> OutputBinary; 665276479Sdim std::error_code EC = 666296417Sdim sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.cc.exe", OutputBinary); 667261991Sdim if (EC) { 668261991Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 669193323Sed exit(1); 670193323Sed } 671341825Sdim CCArgs.push_back(OutputBinary); // Output to the right file... 672193323Sed 673296417Sdim // Add any arguments intended for CC. We locate them here because this is 674193323Sed // most likely -L and -l options that need to come before other libraries but 675193323Sed // after the source. Other options won't be sensitive to placement on the 676193323Sed // command line, so this should be safe. 677296417Sdim for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i) 678341825Sdim CCArgs.push_back(ArgsForCC[i]); 679193323Sed 680314564Sdim CCArgs.push_back("-lm"); // Hard-code the math library... 681314564Sdim CCArgs.push_back("-O2"); // Optimize the program a bit... 682198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 683296417Sdim CCArgs.push_back("-mcpu=v9"); 684193323Sed 685314564Sdim outs() << "<CC>"; 686314564Sdim outs().flush(); 687341825Sdim LLVM_DEBUG(errs() << "\nAbout to run:\t"; 688341825Sdim for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs() 689341825Sdim << " " << CCArgs[i]; 690341825Sdim errs() << "\n";); 691341825Sdim if (RunProgramWithTimeout(CCPath, CCArgs, "", "", "")) 692341825Sdim return ProcessFailure(CCPath, CCArgs); 693193323Sed 694341825Sdim std::vector<StringRef> ProgramArgs; 695193323Sed 696212793Sdim // Declared here so that the destructor only runs after 697212793Sdim // ProgramArgs is used. 698212793Sdim std::string Exec; 699212793Sdim 700261991Sdim if (RemoteClientPath.empty()) 701341825Sdim ProgramArgs.push_back(OutputBinary); 702193323Sed else { 703341825Sdim ProgramArgs.push_back(RemoteClientPath); 704341825Sdim ProgramArgs.push_back(RemoteHost); 705198090Srdivacky if (!RemoteUser.empty()) { 706198090Srdivacky ProgramArgs.push_back("-l"); 707341825Sdim ProgramArgs.push_back(RemoteUser); 708198090Srdivacky } 709198090Srdivacky if (!RemotePort.empty()) { 710198090Srdivacky ProgramArgs.push_back("-p"); 711341825Sdim ProgramArgs.push_back(RemotePort); 712198090Srdivacky } 713193323Sed if (!RemoteExtra.empty()) { 714341825Sdim ProgramArgs.push_back(RemoteExtra); 715193323Sed } 716193323Sed 717198090Srdivacky // Full path to the binary. We need to cd to the exec directory because 718198090Srdivacky // there is a dylib there that the exec expects to find in the CWD 719314564Sdim char *env_pwd = getenv("PWD"); 720212793Sdim Exec = "cd "; 721193323Sed Exec += env_pwd; 722193323Sed Exec += "; ./"; 723193323Sed Exec += OutputBinary.c_str(); 724341825Sdim ProgramArgs.push_back(Exec); 725193323Sed } 726193323Sed 727193323Sed // Add optional parameters to the running program from Argv 728207618Srdivacky for (unsigned i = 0, e = Args.size(); i != e; ++i) 729341825Sdim ProgramArgs.push_back(Args[i]); 730193323Sed 731193323Sed // Now that we have a binary, run it! 732314564Sdim outs() << "<program>"; 733314564Sdim outs().flush(); 734341825Sdim LLVM_DEBUG( 735341825Sdim errs() << "\nAbout to run:\t"; 736341825Sdim for (unsigned i = 0, e = ProgramArgs.size() - 1; i != e; ++i) errs() 737341825Sdim << " " << ProgramArgs[i]; 738341825Sdim errs() << "\n";); 739193323Sed 740221337Sdim FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); 741193323Sed 742261991Sdim if (RemoteClientPath.empty()) { 743341825Sdim LLVM_DEBUG(errs() << "<run locally>"); 744314564Sdim std::string Error; 745341825Sdim int ExitCode = RunProgramWithTimeout(OutputBinary.str(), ProgramArgs, 746261991Sdim InputFile, OutputFile, OutputFile, 747314564Sdim Timeout, MemoryLimit, &Error); 748223013Sdim // Treat a signal (usually SIGSEGV) or timeout as part of the program output 749223013Sdim // so that crash-causing miscompilation is handled seamlessly. 750223013Sdim if (ExitCode < -1) { 751223013Sdim std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 752314564Sdim outFile << Error << '\n'; 753223013Sdim outFile.close(); 754223013Sdim } 755223013Sdim return ExitCode; 756198090Srdivacky } else { 757314564Sdim outs() << "<run remotely>"; 758314564Sdim outs().flush(); 759341825Sdim return RunProgramRemotelyWithTimeout(RemoteClientPath, ProgramArgs, 760314564Sdim InputFile, OutputFile, OutputFile, 761314564Sdim Timeout, MemoryLimit); 762198090Srdivacky } 763193323Sed} 764193323Sed 765314564SdimError CC::MakeSharedObject(const std::string &InputFile, FileType fileType, 766314564Sdim std::string &OutputFile, 767314564Sdim const std::vector<std::string> &ArgsForCC) { 768261991Sdim SmallString<128> UniqueFilename; 769276479Sdim std::error_code EC = sys::fs::createUniqueFile( 770261991Sdim InputFile + "-%%%%%%%" + LTDL_SHLIB_EXT, UniqueFilename); 771261991Sdim if (EC) { 772261991Sdim errs() << "Error making unique filename: " << EC.message() << "\n"; 773193323Sed exit(1); 774193323Sed } 775261991Sdim OutputFile = UniqueFilename.str(); 776193323Sed 777341825Sdim std::vector<StringRef> CCArgs; 778218885Sdim 779341825Sdim CCArgs.push_back(CCPath); 780193323Sed 781205218Srdivacky if (TargetTriple.getArch() == Triple::x86) 782296417Sdim CCArgs.push_back("-m32"); 783205218Srdivacky 784314564Sdim for (std::vector<std::string>::const_iterator I = ccArgs.begin(), 785314564Sdim E = ccArgs.end(); 786314564Sdim I != E; ++I) 787341825Sdim CCArgs.push_back(*I); 788193323Sed 789193323Sed // Compile the C/asm file into a shared object 790205218Srdivacky if (fileType != ObjectFile) { 791296417Sdim CCArgs.push_back("-x"); 792296417Sdim CCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 793205218Srdivacky } 794296417Sdim CCArgs.push_back("-fno-strict-aliasing"); 795341825Sdim CCArgs.push_back(InputFile); // Specify the input filename. 796296417Sdim CCArgs.push_back("-x"); 797296417Sdim CCArgs.push_back("none"); 798198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 799314564Sdim CCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 800221337Sdim else if (TargetTriple.isOSDarwin()) { 801198090Srdivacky // link all source files into a single module in data segment, rather than 802218885Sdim // generating blocks. dynamic_lookup requires that you set 803198090Srdivacky // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 804296417Sdim // bugpoint to just pass that in the environment of CC. 805296417Sdim CCArgs.push_back("-single_module"); 806314564Sdim CCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 807296417Sdim CCArgs.push_back("-undefined"); 808296417Sdim CCArgs.push_back("dynamic_lookup"); 809198090Srdivacky } else 810314564Sdim CCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 811193323Sed 812234353Sdim if (TargetTriple.getArch() == Triple::x86_64) 813314564Sdim CCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 814198090Srdivacky 815198090Srdivacky if (TargetTriple.getArch() == Triple::sparc) 816296417Sdim CCArgs.push_back("-mcpu=v9"); 817198090Srdivacky 818296417Sdim CCArgs.push_back("-o"); 819341825Sdim CCArgs.push_back(OutputFile); // Output to the right filename. 820296417Sdim CCArgs.push_back("-O2"); // Optimize the program a bit. 821193323Sed 822296417Sdim // Add any arguments intended for CC. We locate them here because this is 823193323Sed // most likely -L and -l options that need to come before other libraries but 824193323Sed // after the source. Other options won't be sensitive to placement on the 825193323Sed // command line, so this should be safe. 826296417Sdim for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i) 827341825Sdim CCArgs.push_back(ArgsForCC[i]); 828193323Sed 829314564Sdim outs() << "<CC>"; 830314564Sdim outs().flush(); 831341825Sdim LLVM_DEBUG(errs() << "\nAbout to run:\t"; 832341825Sdim for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs() 833341825Sdim << " " << CCArgs[i]; 834341825Sdim errs() << "\n";); 835341825Sdim if (RunProgramWithTimeout(CCPath, CCArgs, "", "", "")) 836341825Sdim return ProcessFailure(CCPath, CCArgs); 837321369Sdim return Error::success(); 838193323Sed} 839193323Sed 840296417Sdim/// create - Try to find the CC executable 841193323Sed/// 842344779SdimCC *CC::create(const char *Argv0, std::string &Message, 843344779Sdim const std::string &CCBinary, 844314564Sdim const std::vector<std::string> *Args) { 845344779Sdim auto CCPath = FindProgramByName(CCBinary, Argv0, (void *)(intptr_t)&create); 846296417Sdim if (!CCPath) { 847296417Sdim Message = "Cannot find `" + CCBinary + "' in PATH: " + 848296417Sdim CCPath.getError().message() + "\n"; 849276479Sdim return nullptr; 850193323Sed } 851193323Sed 852261991Sdim std::string RemoteClientPath; 853280031Sdim if (!RemoteClient.empty()) { 854280031Sdim auto Path = sys::findProgramByName(RemoteClient); 855280031Sdim if (!Path) { 856280031Sdim Message = "Cannot find `" + RemoteClient + "' in PATH: " + 857280031Sdim Path.getError().message() + "\n"; 858280031Sdim return nullptr; 859280031Sdim } 860280031Sdim RemoteClientPath = *Path; 861280031Sdim } 862193323Sed 863296417Sdim Message = "Found CC: " + *CCPath + "\n"; 864296417Sdim return new CC(*CCPath, RemoteClientPath, Args); 865193323Sed} 866