ToolRunner.cpp revision 341825
1//===-- ToolRunner.cpp ----------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the interfaces described in the ToolRunner.h file. 11// 12//===----------------------------------------------------------------------===// 13 14#include "ToolRunner.h" 15#include "llvm/Config/config.h" 16#include "llvm/Support/CommandLine.h" 17#include "llvm/Support/Debug.h" 18#include "llvm/Support/FileSystem.h" 19#include "llvm/Support/FileUtilities.h" 20#include "llvm/Support/Program.h" 21#include "llvm/Support/raw_ostream.h" 22#include <fstream> 23#include <sstream> 24#include <utility> 25using namespace llvm; 26 27#define DEBUG_TYPE "toolrunner" 28 29namespace llvm { 30cl::opt<bool> SaveTemps("save-temps", cl::init(false), 31 cl::desc("Save temporary files")); 32} 33 34namespace { 35cl::opt<std::string> 36 RemoteClient("remote-client", 37 cl::desc("Remote execution client (rsh/ssh)")); 38 39cl::opt<std::string> RemoteHost("remote-host", 40 cl::desc("Remote execution (rsh/ssh) host")); 41 42cl::opt<std::string> RemotePort("remote-port", 43 cl::desc("Remote execution (rsh/ssh) port")); 44 45cl::opt<std::string> RemoteUser("remote-user", 46 cl::desc("Remote execution (rsh/ssh) user id")); 47 48cl::opt<std::string> 49 RemoteExtra("remote-extra-options", 50 cl::desc("Remote execution (rsh/ssh) extra options")); 51} 52 53/// RunProgramWithTimeout - This function provides an alternate interface 54/// to the sys::Program::ExecuteAndWait interface. 55/// @see sys::Program::ExecuteAndWait 56static int RunProgramWithTimeout(StringRef ProgramPath, 57 ArrayRef<StringRef> Args, StringRef StdInFile, 58 StringRef StdOutFile, StringRef StdErrFile, 59 unsigned NumSeconds = 0, 60 unsigned MemoryLimit = 0, 61 std::string *ErrMsg = nullptr) { 62 Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile}; 63 return sys::ExecuteAndWait(ProgramPath, Args, None, Redirects, NumSeconds, 64 MemoryLimit, ErrMsg); 65} 66 67/// RunProgramRemotelyWithTimeout - This function runs the given program 68/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 69/// Returns the remote program exit code or reports a remote client error if it 70/// fails. Remote client is required to return 255 if it failed or program exit 71/// code otherwise. 72/// @see sys::Program::ExecuteAndWait 73static int RunProgramRemotelyWithTimeout( 74 StringRef RemoteClientPath, ArrayRef<StringRef> Args, StringRef StdInFile, 75 StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0, 76 unsigned MemoryLimit = 0) { 77 Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile}; 78 79 // Run the program remotely with the remote client 80 int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, None, Redirects, 81 NumSeconds, MemoryLimit); 82 83 // Has the remote client fail? 84 if (255 == ReturnCode) { 85 std::ostringstream OS; 86 OS << "\nError running remote client:\n "; 87 for (StringRef Arg : Args) 88 OS << " " << Arg.str(); 89 OS << "\n"; 90 91 // The error message is in the output file, let's print it out from there. 92 std::string StdOutFileName = StdOutFile.str(); 93 std::ifstream ErrorFile(StdOutFileName.c_str()); 94 if (ErrorFile) { 95 std::copy(std::istreambuf_iterator<char>(ErrorFile), 96 std::istreambuf_iterator<char>(), 97 std::ostreambuf_iterator<char>(OS)); 98 ErrorFile.close(); 99 } 100 101 errs() << OS.str(); 102 } 103 104 return ReturnCode; 105} 106 107static Error ProcessFailure(StringRef ProgPath, ArrayRef<StringRef> Args, 108 unsigned Timeout = 0, unsigned MemoryLimit = 0) { 109 std::ostringstream OS; 110 OS << "\nError running tool:\n "; 111 for (StringRef Arg : Args) 112 OS << " " << Arg.str(); 113 OS << "\n"; 114 115 // Rerun the compiler, capturing any error messages to print them. 116 SmallString<128> ErrorFilename; 117 std::error_code EC = sys::fs::createTemporaryFile( 118 "bugpoint.program_error_messages", "", ErrorFilename); 119 if (EC) { 120 errs() << "Error making unique filename: " << EC.message() << "\n"; 121 exit(1); 122 } 123 124 RunProgramWithTimeout(ProgPath, Args, "", ErrorFilename.str(), 125 ErrorFilename.str(), Timeout, MemoryLimit); 126 // FIXME: check return code ? 127 128 // Print out the error messages generated by CC if possible... 129 std::ifstream ErrorFile(ErrorFilename.c_str()); 130 if (ErrorFile) { 131 std::copy(std::istreambuf_iterator<char>(ErrorFile), 132 std::istreambuf_iterator<char>(), 133 std::ostreambuf_iterator<char>(OS)); 134 ErrorFile.close(); 135 } 136 137 sys::fs::remove(ErrorFilename.c_str()); 138 return make_error<StringError>(OS.str(), inconvertibleErrorCode()); 139} 140 141//===---------------------------------------------------------------------===// 142// LLI Implementation of AbstractIntepreter interface 143// 144namespace { 145class LLI : public AbstractInterpreter { 146 std::string LLIPath; // The path to the LLI executable 147 std::vector<std::string> ToolArgs; // Args to pass to LLI 148public: 149 LLI(const std::string &Path, const std::vector<std::string> *Args) 150 : LLIPath(Path) { 151 ToolArgs.clear(); 152 if (Args) { 153 ToolArgs = *Args; 154 } 155 } 156 157 Expected<int> ExecuteProgram( 158 const std::string &Bitcode, const std::vector<std::string> &Args, 159 const std::string &InputFile, const std::string &OutputFile, 160 const std::vector<std::string> &CCArgs, 161 const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 162 unsigned Timeout = 0, unsigned MemoryLimit = 0) override; 163}; 164} 165 166Expected<int> LLI::ExecuteProgram(const std::string &Bitcode, 167 const std::vector<std::string> &Args, 168 const std::string &InputFile, 169 const std::string &OutputFile, 170 const std::vector<std::string> &CCArgs, 171 const std::vector<std::string> &SharedLibs, 172 unsigned Timeout, unsigned MemoryLimit) { 173 std::vector<StringRef> LLIArgs; 174 LLIArgs.push_back(LLIPath.c_str()); 175 LLIArgs.push_back("-force-interpreter=true"); 176 177 for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), 178 e = SharedLibs.end(); 179 i != e; ++i) { 180 LLIArgs.push_back("-load"); 181 LLIArgs.push_back(*i); 182 } 183 184 // Add any extra LLI args. 185 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 186 LLIArgs.push_back(ToolArgs[i]); 187 188 LLIArgs.push_back(Bitcode); 189 // Add optional parameters to the running program from Argv 190 for (unsigned i = 0, e = Args.size(); i != e; ++i) 191 LLIArgs.push_back(Args[i]); 192 193 outs() << "<lli>"; 194 outs().flush(); 195 LLVM_DEBUG(errs() << "\nAbout to run:\t"; 196 for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs() 197 << " " << LLIArgs[i]; 198 errs() << "\n";); 199 return RunProgramWithTimeout(LLIPath, LLIArgs, InputFile, OutputFile, 200 OutputFile, Timeout, MemoryLimit); 201} 202 203void AbstractInterpreter::anchor() {} 204 205#if defined(LLVM_ON_UNIX) 206const char EXESuffix[] = ""; 207#elif defined(_WIN32) 208const char EXESuffix[] = "exe"; 209#endif 210 211/// Prepend the path to the program being executed 212/// to \p ExeName, given the value of argv[0] and the address of main() 213/// itself. This allows us to find another LLVM tool if it is built in the same 214/// directory. An empty string is returned on error; note that this function 215/// just mainpulates the path and doesn't check for executability. 216/// Find a named executable. 217static std::string PrependMainExecutablePath(const std::string &ExeName, 218 const char *Argv0, 219 void *MainAddr) { 220 // Check the directory that the calling program is in. We can do 221 // this if ProgramPath contains at least one / character, indicating that it 222 // is a relative path to the executable itself. 223 std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr); 224 StringRef Result = sys::path::parent_path(Main); 225 226 if (!Result.empty()) { 227 SmallString<128> Storage = Result; 228 sys::path::append(Storage, ExeName); 229 sys::path::replace_extension(Storage, EXESuffix); 230 return Storage.str(); 231 } 232 233 return Result.str(); 234} 235 236// LLI create method - Try to find the LLI executable 237AbstractInterpreter * 238AbstractInterpreter::createLLI(const char *Argv0, std::string &Message, 239 const std::vector<std::string> *ToolArgs) { 240 std::string LLIPath = 241 PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI); 242 if (!LLIPath.empty()) { 243 Message = "Found lli: " + LLIPath + "\n"; 244 return new LLI(LLIPath, ToolArgs); 245 } 246 247 Message = "Cannot find `lli' in executable directory!\n"; 248 return nullptr; 249} 250 251//===---------------------------------------------------------------------===// 252// Custom compiler command implementation of AbstractIntepreter interface 253// 254// Allows using a custom command for compiling the bitcode, thus allows, for 255// example, to compile a bitcode fragment without linking or executing, then 256// using a custom wrapper script to check for compiler errors. 257namespace { 258class CustomCompiler : public AbstractInterpreter { 259 std::string CompilerCommand; 260 std::vector<std::string> CompilerArgs; 261 262public: 263 CustomCompiler(const std::string &CompilerCmd, 264 std::vector<std::string> CompArgs) 265 : CompilerCommand(CompilerCmd), CompilerArgs(std::move(CompArgs)) {} 266 267 Error compileProgram(const std::string &Bitcode, unsigned Timeout = 0, 268 unsigned MemoryLimit = 0) override; 269 270 Expected<int> ExecuteProgram( 271 const std::string &Bitcode, const std::vector<std::string> &Args, 272 const std::string &InputFile, const std::string &OutputFile, 273 const std::vector<std::string> &CCArgs = std::vector<std::string>(), 274 const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 275 unsigned Timeout = 0, unsigned MemoryLimit = 0) override { 276 return make_error<StringError>( 277 "Execution not supported with -compile-custom", 278 inconvertibleErrorCode()); 279 } 280}; 281} 282 283Error CustomCompiler::compileProgram(const std::string &Bitcode, 284 unsigned Timeout, unsigned MemoryLimit) { 285 286 std::vector<StringRef> ProgramArgs; 287 ProgramArgs.push_back(CompilerCommand.c_str()); 288 289 for (std::size_t i = 0; i < CompilerArgs.size(); ++i) 290 ProgramArgs.push_back(CompilerArgs.at(i).c_str()); 291 ProgramArgs.push_back(Bitcode); 292 293 // Add optional parameters to the running program from Argv 294 for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) 295 ProgramArgs.push_back(CompilerArgs[i].c_str()); 296 297 if (RunProgramWithTimeout(CompilerCommand, ProgramArgs, "", "", "", Timeout, 298 MemoryLimit)) 299 return ProcessFailure(CompilerCommand, ProgramArgs, Timeout, MemoryLimit); 300 return Error::success(); 301} 302 303//===---------------------------------------------------------------------===// 304// Custom execution command implementation of AbstractIntepreter interface 305// 306// Allows using a custom command for executing the bitcode, thus allows, 307// for example, to invoke a cross compiler for code generation followed by 308// a simulator that executes the generated binary. 309namespace { 310class CustomExecutor : public AbstractInterpreter { 311 std::string ExecutionCommand; 312 std::vector<std::string> ExecutorArgs; 313 314public: 315 CustomExecutor(const std::string &ExecutionCmd, 316 std::vector<std::string> ExecArgs) 317 : ExecutionCommand(ExecutionCmd), ExecutorArgs(std::move(ExecArgs)) {} 318 319 Expected<int> ExecuteProgram( 320 const std::string &Bitcode, const std::vector<std::string> &Args, 321 const std::string &InputFile, const std::string &OutputFile, 322 const std::vector<std::string> &CCArgs, 323 const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 324 unsigned Timeout = 0, unsigned MemoryLimit = 0) override; 325}; 326} 327 328Expected<int> CustomExecutor::ExecuteProgram( 329 const std::string &Bitcode, const std::vector<std::string> &Args, 330 const std::string &InputFile, const std::string &OutputFile, 331 const std::vector<std::string> &CCArgs, 332 const std::vector<std::string> &SharedLibs, unsigned Timeout, 333 unsigned MemoryLimit) { 334 335 std::vector<StringRef> ProgramArgs; 336 ProgramArgs.push_back(ExecutionCommand); 337 338 for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 339 ProgramArgs.push_back(ExecutorArgs[i]); 340 ProgramArgs.push_back(Bitcode); 341 342 // Add optional parameters to the running program from Argv 343 for (unsigned i = 0, e = Args.size(); i != e; ++i) 344 ProgramArgs.push_back(Args[i]); 345 346 return RunProgramWithTimeout(ExecutionCommand, ProgramArgs, InputFile, 347 OutputFile, OutputFile, Timeout, MemoryLimit); 348} 349 350// Tokenize the CommandLine to the command and the args to allow 351// defining a full command line as the command instead of just the 352// executed program. We cannot just pass the whole string after the command 353// as a single argument because then the program sees only a single 354// command line argument (with spaces in it: "foo bar" instead 355// of "foo" and "bar"). 356// 357// Spaces are used as a delimiter; however repeated, leading, and trailing 358// whitespace are ignored. Simple escaping is allowed via the '\' 359// character, as seen below: 360// 361// Two consecutive '\' evaluate to a single '\'. 362// A space after a '\' evaluates to a space that is not interpreted as a 363// delimiter. 364// Any other instances of the '\' character are removed. 365// 366// Example: 367// '\\' -> '\' 368// '\ ' -> ' ' 369// 'exa\mple' -> 'example' 370// 371static void lexCommand(std::string &Message, const std::string &CommandLine, 372 std::string &CmdPath, std::vector<std::string> &Args) { 373 374 std::string Token; 375 std::string Command; 376 bool FoundPath = false; 377 378 // first argument is the PATH. 379 // Skip repeated whitespace, leading whitespace and trailing whitespace. 380 for (std::size_t Pos = 0u; Pos <= CommandLine.size(); ++Pos) { 381 if ('\\' == CommandLine[Pos]) { 382 if (Pos + 1 < CommandLine.size()) 383 Token.push_back(CommandLine[++Pos]); 384 385 continue; 386 } 387 if (' ' == CommandLine[Pos] || CommandLine.size() == Pos) { 388 if (Token.empty()) 389 continue; 390 391 if (!FoundPath) { 392 Command = Token; 393 FoundPath = true; 394 Token.clear(); 395 continue; 396 } 397 398 Args.push_back(Token); 399 Token.clear(); 400 continue; 401 } 402 Token.push_back(CommandLine[Pos]); 403 } 404 405 auto Path = sys::findProgramByName(Command); 406 if (!Path) { 407 Message = std::string("Cannot find '") + Command + 408 "' in PATH: " + Path.getError().message() + "\n"; 409 return; 410 } 411 CmdPath = *Path; 412 413 Message = "Found command in: " + CmdPath + "\n"; 414} 415 416// Custom execution environment create method, takes the execution command 417// as arguments 418AbstractInterpreter *AbstractInterpreter::createCustomCompiler( 419 std::string &Message, const std::string &CompileCommandLine) { 420 421 std::string CmdPath; 422 std::vector<std::string> Args; 423 lexCommand(Message, CompileCommandLine, CmdPath, Args); 424 if (CmdPath.empty()) 425 return nullptr; 426 427 return new CustomCompiler(CmdPath, Args); 428} 429 430// Custom execution environment create method, takes the execution command 431// as arguments 432AbstractInterpreter * 433AbstractInterpreter::createCustomExecutor(std::string &Message, 434 const std::string &ExecCommandLine) { 435 436 std::string CmdPath; 437 std::vector<std::string> Args; 438 lexCommand(Message, ExecCommandLine, CmdPath, Args); 439 if (CmdPath.empty()) 440 return nullptr; 441 442 return new CustomExecutor(CmdPath, Args); 443} 444 445//===----------------------------------------------------------------------===// 446// LLC Implementation of AbstractIntepreter interface 447// 448Expected<CC::FileType> LLC::OutputCode(const std::string &Bitcode, 449 std::string &OutputAsmFile, 450 unsigned Timeout, unsigned MemoryLimit) { 451 const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); 452 453 SmallString<128> UniqueFile; 454 std::error_code EC = 455 sys::fs::createUniqueFile(Bitcode + "-%%%%%%%" + Suffix, UniqueFile); 456 if (EC) { 457 errs() << "Error making unique filename: " << EC.message() << "\n"; 458 exit(1); 459 } 460 OutputAsmFile = UniqueFile.str(); 461 std::vector<StringRef> LLCArgs; 462 LLCArgs.push_back(LLCPath); 463 464 // Add any extra LLC args. 465 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 466 LLCArgs.push_back(ToolArgs[i]); 467 468 LLCArgs.push_back("-o"); 469 LLCArgs.push_back(OutputAsmFile); // Output to the Asm file 470 LLCArgs.push_back(Bitcode); // This is the input bitcode 471 472 if (UseIntegratedAssembler) 473 LLCArgs.push_back("-filetype=obj"); 474 475 outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); 476 outs().flush(); 477 LLVM_DEBUG(errs() << "\nAbout to run:\t"; 478 for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs() 479 << " " << LLCArgs[i]; 480 errs() << "\n";); 481 if (RunProgramWithTimeout(LLCPath, LLCArgs, "", "", "", Timeout, MemoryLimit)) 482 return ProcessFailure(LLCPath, LLCArgs, Timeout, MemoryLimit); 483 return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile; 484} 485 486Error LLC::compileProgram(const std::string &Bitcode, unsigned Timeout, 487 unsigned MemoryLimit) { 488 std::string OutputAsmFile; 489 Expected<CC::FileType> Result = 490 OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit); 491 sys::fs::remove(OutputAsmFile); 492 if (Error E = Result.takeError()) 493 return E; 494 return Error::success(); 495} 496 497Expected<int> LLC::ExecuteProgram(const std::string &Bitcode, 498 const std::vector<std::string> &Args, 499 const std::string &InputFile, 500 const std::string &OutputFile, 501 const std::vector<std::string> &ArgsForCC, 502 const std::vector<std::string> &SharedLibs, 503 unsigned Timeout, unsigned MemoryLimit) { 504 505 std::string OutputAsmFile; 506 Expected<CC::FileType> FileKind = 507 OutputCode(Bitcode, OutputAsmFile, Timeout, MemoryLimit); 508 FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); 509 if (Error E = FileKind.takeError()) 510 return std::move(E); 511 512 std::vector<std::string> CCArgs(ArgsForCC); 513 CCArgs.insert(CCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 514 515 // Assuming LLC worked, compile the result with CC and run it. 516 return cc->ExecuteProgram(OutputAsmFile, Args, *FileKind, InputFile, 517 OutputFile, CCArgs, Timeout, MemoryLimit); 518} 519 520/// createLLC - Try to find the LLC executable 521/// 522LLC *AbstractInterpreter::createLLC(const char *Argv0, std::string &Message, 523 const std::string &CCBinary, 524 const std::vector<std::string> *Args, 525 const std::vector<std::string> *CCArgs, 526 bool UseIntegratedAssembler) { 527 std::string LLCPath = 528 PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC); 529 if (LLCPath.empty()) { 530 Message = "Cannot find `llc' in executable directory!\n"; 531 return nullptr; 532 } 533 534 CC *cc = CC::create(Message, CCBinary, CCArgs); 535 if (!cc) { 536 errs() << Message << "\n"; 537 exit(1); 538 } 539 Message = "Found llc: " + LLCPath + "\n"; 540 return new LLC(LLCPath, cc, Args, UseIntegratedAssembler); 541} 542 543//===---------------------------------------------------------------------===// 544// JIT Implementation of AbstractIntepreter interface 545// 546namespace { 547class JIT : public AbstractInterpreter { 548 std::string LLIPath; // The path to the LLI executable 549 std::vector<std::string> ToolArgs; // Args to pass to LLI 550public: 551 JIT(const std::string &Path, const std::vector<std::string> *Args) 552 : LLIPath(Path) { 553 ToolArgs.clear(); 554 if (Args) { 555 ToolArgs = *Args; 556 } 557 } 558 559 Expected<int> ExecuteProgram( 560 const std::string &Bitcode, const std::vector<std::string> &Args, 561 const std::string &InputFile, const std::string &OutputFile, 562 const std::vector<std::string> &CCArgs = std::vector<std::string>(), 563 const std::vector<std::string> &SharedLibs = std::vector<std::string>(), 564 unsigned Timeout = 0, unsigned MemoryLimit = 0) override; 565}; 566} 567 568Expected<int> JIT::ExecuteProgram(const std::string &Bitcode, 569 const std::vector<std::string> &Args, 570 const std::string &InputFile, 571 const std::string &OutputFile, 572 const std::vector<std::string> &CCArgs, 573 const std::vector<std::string> &SharedLibs, 574 unsigned Timeout, unsigned MemoryLimit) { 575 // Construct a vector of parameters, incorporating those from the command-line 576 std::vector<StringRef> JITArgs; 577 JITArgs.push_back(LLIPath.c_str()); 578 JITArgs.push_back("-force-interpreter=false"); 579 580 // Add any extra LLI args. 581 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 582 JITArgs.push_back(ToolArgs[i]); 583 584 for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 585 JITArgs.push_back("-load"); 586 JITArgs.push_back(SharedLibs[i]); 587 } 588 JITArgs.push_back(Bitcode.c_str()); 589 // Add optional parameters to the running program from Argv 590 for (unsigned i = 0, e = Args.size(); i != e; ++i) 591 JITArgs.push_back(Args[i]); 592 593 outs() << "<jit>"; 594 outs().flush(); 595 LLVM_DEBUG(errs() << "\nAbout to run:\t"; 596 for (unsigned i = 0, e = JITArgs.size() - 1; i != e; ++i) errs() 597 << " " << JITArgs[i]; 598 errs() << "\n";); 599 LLVM_DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 600 return RunProgramWithTimeout(LLIPath, JITArgs, InputFile, OutputFile, 601 OutputFile, Timeout, MemoryLimit); 602} 603 604/// createJIT - Try to find the LLI executable 605/// 606AbstractInterpreter * 607AbstractInterpreter::createJIT(const char *Argv0, std::string &Message, 608 const std::vector<std::string> *Args) { 609 std::string LLIPath = 610 PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT); 611 if (!LLIPath.empty()) { 612 Message = "Found lli: " + LLIPath + "\n"; 613 return new JIT(LLIPath, Args); 614 } 615 616 Message = "Cannot find `lli' in executable directory!\n"; 617 return nullptr; 618} 619 620//===---------------------------------------------------------------------===// 621// CC abstraction 622// 623 624static bool IsARMArchitecture(std::vector<StringRef> Args) { 625 for (size_t I = 0; I < Args.size(); ++I) { 626 if (!Args[I].equals_lower("-arch")) 627 continue; 628 ++I; 629 if (I == Args.size()) 630 break; 631 if (Args[I].startswith_lower("arm")) 632 return true; 633 } 634 635 return false; 636} 637 638Expected<int> CC::ExecuteProgram(const std::string &ProgramFile, 639 const std::vector<std::string> &Args, 640 FileType fileType, 641 const std::string &InputFile, 642 const std::string &OutputFile, 643 const std::vector<std::string> &ArgsForCC, 644 unsigned Timeout, unsigned MemoryLimit) { 645 std::vector<StringRef> CCArgs; 646 647 CCArgs.push_back(CCPath); 648 649 if (TargetTriple.getArch() == Triple::x86) 650 CCArgs.push_back("-m32"); 651 652 for (std::vector<std::string>::const_iterator I = ccArgs.begin(), 653 E = ccArgs.end(); 654 I != E; ++I) 655 CCArgs.push_back(*I); 656 657 // Specify -x explicitly in case the extension is wonky 658 if (fileType != ObjectFile) { 659 CCArgs.push_back("-x"); 660 if (fileType == CFile) { 661 CCArgs.push_back("c"); 662 CCArgs.push_back("-fno-strict-aliasing"); 663 } else { 664 CCArgs.push_back("assembler"); 665 666 // For ARM architectures we don't want this flag. bugpoint isn't 667 // explicitly told what architecture it is working on, so we get 668 // it from cc flags 669 if (TargetTriple.isOSDarwin() && !IsARMArchitecture(CCArgs)) 670 CCArgs.push_back("-force_cpusubtype_ALL"); 671 } 672 } 673 674 CCArgs.push_back(ProgramFile); // Specify the input filename. 675 676 CCArgs.push_back("-x"); 677 CCArgs.push_back("none"); 678 CCArgs.push_back("-o"); 679 680 SmallString<128> OutputBinary; 681 std::error_code EC = 682 sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.cc.exe", OutputBinary); 683 if (EC) { 684 errs() << "Error making unique filename: " << EC.message() << "\n"; 685 exit(1); 686 } 687 CCArgs.push_back(OutputBinary); // Output to the right file... 688 689 // Add any arguments intended for CC. We locate them here because this is 690 // most likely -L and -l options that need to come before other libraries but 691 // after the source. Other options won't be sensitive to placement on the 692 // command line, so this should be safe. 693 for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i) 694 CCArgs.push_back(ArgsForCC[i]); 695 696 CCArgs.push_back("-lm"); // Hard-code the math library... 697 CCArgs.push_back("-O2"); // Optimize the program a bit... 698 if (TargetTriple.getArch() == Triple::sparc) 699 CCArgs.push_back("-mcpu=v9"); 700 701 outs() << "<CC>"; 702 outs().flush(); 703 LLVM_DEBUG(errs() << "\nAbout to run:\t"; 704 for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs() 705 << " " << CCArgs[i]; 706 errs() << "\n";); 707 if (RunProgramWithTimeout(CCPath, CCArgs, "", "", "")) 708 return ProcessFailure(CCPath, CCArgs); 709 710 std::vector<StringRef> ProgramArgs; 711 712 // Declared here so that the destructor only runs after 713 // ProgramArgs is used. 714 std::string Exec; 715 716 if (RemoteClientPath.empty()) 717 ProgramArgs.push_back(OutputBinary); 718 else { 719 ProgramArgs.push_back(RemoteClientPath); 720 ProgramArgs.push_back(RemoteHost); 721 if (!RemoteUser.empty()) { 722 ProgramArgs.push_back("-l"); 723 ProgramArgs.push_back(RemoteUser); 724 } 725 if (!RemotePort.empty()) { 726 ProgramArgs.push_back("-p"); 727 ProgramArgs.push_back(RemotePort); 728 } 729 if (!RemoteExtra.empty()) { 730 ProgramArgs.push_back(RemoteExtra); 731 } 732 733 // Full path to the binary. We need to cd to the exec directory because 734 // there is a dylib there that the exec expects to find in the CWD 735 char *env_pwd = getenv("PWD"); 736 Exec = "cd "; 737 Exec += env_pwd; 738 Exec += "; ./"; 739 Exec += OutputBinary.c_str(); 740 ProgramArgs.push_back(Exec); 741 } 742 743 // Add optional parameters to the running program from Argv 744 for (unsigned i = 0, e = Args.size(); i != e; ++i) 745 ProgramArgs.push_back(Args[i]); 746 747 // Now that we have a binary, run it! 748 outs() << "<program>"; 749 outs().flush(); 750 LLVM_DEBUG( 751 errs() << "\nAbout to run:\t"; 752 for (unsigned i = 0, e = ProgramArgs.size() - 1; i != e; ++i) errs() 753 << " " << ProgramArgs[i]; 754 errs() << "\n";); 755 756 FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); 757 758 if (RemoteClientPath.empty()) { 759 LLVM_DEBUG(errs() << "<run locally>"); 760 std::string Error; 761 int ExitCode = RunProgramWithTimeout(OutputBinary.str(), ProgramArgs, 762 InputFile, OutputFile, OutputFile, 763 Timeout, MemoryLimit, &Error); 764 // Treat a signal (usually SIGSEGV) or timeout as part of the program output 765 // so that crash-causing miscompilation is handled seamlessly. 766 if (ExitCode < -1) { 767 std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 768 outFile << Error << '\n'; 769 outFile.close(); 770 } 771 return ExitCode; 772 } else { 773 outs() << "<run remotely>"; 774 outs().flush(); 775 return RunProgramRemotelyWithTimeout(RemoteClientPath, ProgramArgs, 776 InputFile, OutputFile, OutputFile, 777 Timeout, MemoryLimit); 778 } 779} 780 781Error CC::MakeSharedObject(const std::string &InputFile, FileType fileType, 782 std::string &OutputFile, 783 const std::vector<std::string> &ArgsForCC) { 784 SmallString<128> UniqueFilename; 785 std::error_code EC = sys::fs::createUniqueFile( 786 InputFile + "-%%%%%%%" + LTDL_SHLIB_EXT, UniqueFilename); 787 if (EC) { 788 errs() << "Error making unique filename: " << EC.message() << "\n"; 789 exit(1); 790 } 791 OutputFile = UniqueFilename.str(); 792 793 std::vector<StringRef> CCArgs; 794 795 CCArgs.push_back(CCPath); 796 797 if (TargetTriple.getArch() == Triple::x86) 798 CCArgs.push_back("-m32"); 799 800 for (std::vector<std::string>::const_iterator I = ccArgs.begin(), 801 E = ccArgs.end(); 802 I != E; ++I) 803 CCArgs.push_back(*I); 804 805 // Compile the C/asm file into a shared object 806 if (fileType != ObjectFile) { 807 CCArgs.push_back("-x"); 808 CCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 809 } 810 CCArgs.push_back("-fno-strict-aliasing"); 811 CCArgs.push_back(InputFile); // Specify the input filename. 812 CCArgs.push_back("-x"); 813 CCArgs.push_back("none"); 814 if (TargetTriple.getArch() == Triple::sparc) 815 CCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 816 else if (TargetTriple.isOSDarwin()) { 817 // link all source files into a single module in data segment, rather than 818 // generating blocks. dynamic_lookup requires that you set 819 // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 820 // bugpoint to just pass that in the environment of CC. 821 CCArgs.push_back("-single_module"); 822 CCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 823 CCArgs.push_back("-undefined"); 824 CCArgs.push_back("dynamic_lookup"); 825 } else 826 CCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 827 828 if (TargetTriple.getArch() == Triple::x86_64) 829 CCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 830 831 if (TargetTriple.getArch() == Triple::sparc) 832 CCArgs.push_back("-mcpu=v9"); 833 834 CCArgs.push_back("-o"); 835 CCArgs.push_back(OutputFile); // Output to the right filename. 836 CCArgs.push_back("-O2"); // Optimize the program a bit. 837 838 // Add any arguments intended for CC. We locate them here because this is 839 // most likely -L and -l options that need to come before other libraries but 840 // after the source. Other options won't be sensitive to placement on the 841 // command line, so this should be safe. 842 for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i) 843 CCArgs.push_back(ArgsForCC[i]); 844 845 outs() << "<CC>"; 846 outs().flush(); 847 LLVM_DEBUG(errs() << "\nAbout to run:\t"; 848 for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs() 849 << " " << CCArgs[i]; 850 errs() << "\n";); 851 if (RunProgramWithTimeout(CCPath, CCArgs, "", "", "")) 852 return ProcessFailure(CCPath, CCArgs); 853 return Error::success(); 854} 855 856/// create - Try to find the CC executable 857/// 858CC *CC::create(std::string &Message, const std::string &CCBinary, 859 const std::vector<std::string> *Args) { 860 auto CCPath = sys::findProgramByName(CCBinary); 861 if (!CCPath) { 862 Message = "Cannot find `" + CCBinary + "' in PATH: " + 863 CCPath.getError().message() + "\n"; 864 return nullptr; 865 } 866 867 std::string RemoteClientPath; 868 if (!RemoteClient.empty()) { 869 auto Path = sys::findProgramByName(RemoteClient); 870 if (!Path) { 871 Message = "Cannot find `" + RemoteClient + "' in PATH: " + 872 Path.getError().message() + "\n"; 873 return nullptr; 874 } 875 RemoteClientPath = *Path; 876 } 877 878 Message = "Found CC: " + *CCPath + "\n"; 879 return new CC(*CCPath, RemoteClientPath, Args); 880} 881