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