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 #define DEBUG_TYPE "toolrunner" 15 #include "ToolRunner.h" 16 #include "llvm/Config/config.h" // for HAVE_LINK_R 17 #include "llvm/System/Program.h" 18 #include "llvm/Support/CommandLine.h" 19 #include "llvm/Support/Debug.h" 20 #include "llvm/Support/FileUtilities.h" 21 #include <fstream> 22 #include <sstream> 23 using namespace llvm; 24 25 namespace { 26 cl::opt<std::string> 27 RemoteClient("remote-client", 28 cl::desc("Remote execution client (rsh/ssh)")); 29 30 cl::opt<std::string> 31 RemoteHost("remote-host", 32 cl::desc("Remote execution (rsh/ssh) host")); 33 34 cl::opt<std::string> 35 RemotePort("remote-port", 36 cl::desc("Remote execution (rsh/ssh) port")); 37 38 cl::opt<std::string> 39 RemoteUser("remote-user", 40 cl::desc("Remote execution (rsh/ssh) user id")); 41 42 cl::opt<std::string> 43 RemoteExtra("remote-extra-options", 44 cl::desc("Remote execution (rsh/ssh) extra options")); 45 } 46 47 ToolExecutionError::~ToolExecutionError() throw() { } 48 49 /// RunProgramWithTimeout - This function provides an alternate interface 50 /// to the sys::Program::ExecuteAndWait interface. 51 /// @see sys:Program::ExecuteAndWait 52 static int RunProgramWithTimeout(const sys::Path &ProgramPath, 53 const char **Args, 54 const sys::Path &StdInFile, 55 const sys::Path &StdOutFile, 56 const sys::Path &StdErrFile, 57 unsigned NumSeconds = 0, 58 unsigned MemoryLimit = 0) { 59 const sys::Path* redirects[3]; 60 redirects[0] = &StdInFile; 61 redirects[1] = &StdOutFile; 62 redirects[2] = &StdErrFile; 63 64 #if 0 // For debug purposes 65 { 66 errs() << "RUN:"; 67 for (unsigned i = 0; Args[i]; ++i) 68 errs() << " " << Args[i]; 69 errs() << "\n"; 70 } 71 #endif 72 73 return 74 sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, 75 NumSeconds, MemoryLimit); 76 } 77 78 /// RunProgramRemotelyWithTimeout - This function runs the given program 79 /// remotely using the given remote client and the sys::Program::ExecuteAndWait. 80 /// Returns the remote program exit code or reports a remote client error if it 81 /// fails. Remote client is required to return 255 if it failed or program exit 82 /// code otherwise. 83 /// @see sys:Program::ExecuteAndWait 84 static int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, 85 const char **Args, 86 const sys::Path &StdInFile, 87 const sys::Path &StdOutFile, 88 const sys::Path &StdErrFile, 89 unsigned NumSeconds = 0, 90 unsigned MemoryLimit = 0) { 91 const sys::Path* redirects[3]; 92 redirects[0] = &StdInFile; 93 redirects[1] = &StdOutFile; 94 redirects[2] = &StdErrFile; 95 96 #if 0 // For debug purposes 97 { 98 errs() << "RUN:"; 99 for (unsigned i = 0; Args[i]; ++i) 100 errs() << " " << Args[i]; 101 errs() << "\n"; 102 } 103 #endif 104 105 // Run the program remotely with the remote client 106 int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, 107 0, redirects, NumSeconds, MemoryLimit); 108 109 // Has the remote client fail? 110 if (255 == ReturnCode) { 111 std::ostringstream OS; 112 OS << "\nError running remote client:\n "; 113 for (const char **Arg = Args; *Arg; ++Arg) 114 OS << " " << *Arg; 115 OS << "\n"; 116 117 // The error message is in the output file, let's print it out from there. 118 std::ifstream ErrorFile(StdOutFile.c_str()); 119 if (ErrorFile) { 120 std::copy(std::istreambuf_iterator<char>(ErrorFile), 121 std::istreambuf_iterator<char>(), 122 std::ostreambuf_iterator<char>(OS)); 123 ErrorFile.close(); 124 } 125 126 throw ToolExecutionError(OS.str()); 127 } 128 129 return ReturnCode; 130 } 131 132 static void ProcessFailure(sys::Path ProgPath, const char** Args) { 133 std::ostringstream OS; 134 OS << "\nError running tool:\n "; 135 for (const char **Arg = Args; *Arg; ++Arg) 136 OS << " " << *Arg; 137 OS << "\n"; 138 139 // Rerun the compiler, capturing any error messages to print them. 140 sys::Path ErrorFilename("bugpoint.program_error_messages"); 141 std::string ErrMsg; 142 if (ErrorFilename.makeUnique(true, &ErrMsg)) { 143 errs() << "Error making unique filename: " << ErrMsg << "\n"; 144 exit(1); 145 } 146 RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, 147 ErrorFilename); // FIXME: check return code ? 148 149 // Print out the error messages generated by GCC if possible... 150 std::ifstream ErrorFile(ErrorFilename.c_str()); 151 if (ErrorFile) { 152 std::copy(std::istreambuf_iterator<char>(ErrorFile), 153 std::istreambuf_iterator<char>(), 154 std::ostreambuf_iterator<char>(OS)); 155 ErrorFile.close(); 156 } 157 158 ErrorFilename.eraseFromDisk(); 159 throw ToolExecutionError(OS.str()); 160 } 161 162 //===---------------------------------------------------------------------===// 163 // LLI Implementation of AbstractIntepreter interface 164 // 165 namespace { 166 class LLI : public AbstractInterpreter { 167 std::string LLIPath; // The path to the LLI executable 168 std::vector<std::string> ToolArgs; // Args to pass to LLI 169 public: 170 LLI(const std::string &Path, const std::vector<std::string> *Args) 171 : LLIPath(Path) { 172 ToolArgs.clear (); 173 if (Args) { ToolArgs = *Args; } 174 } 175 176 virtual int ExecuteProgram(const std::string &Bitcode, 177 const std::vector<std::string> &Args, 178 const std::string &InputFile, 179 const std::string &OutputFile, 180 const std::vector<std::string> &GCCArgs, 181 const std::vector<std::string> &SharedLibs = 182 std::vector<std::string>(), 183 unsigned Timeout = 0, 184 unsigned MemoryLimit = 0); 185 }; 186 } 187 188 int LLI::ExecuteProgram(const std::string &Bitcode, 189 const std::vector<std::string> &Args, 190 const std::string &InputFile, 191 const std::string &OutputFile, 192 const std::vector<std::string> &GCCArgs, 193 const std::vector<std::string> &SharedLibs, 194 unsigned Timeout, 195 unsigned MemoryLimit) { 196 if (!SharedLibs.empty()) 197 throw ToolExecutionError("LLI currently does not support " 198 "loading shared libraries."); 199 200 std::vector<const char*> LLIArgs; 201 LLIArgs.push_back(LLIPath.c_str()); 202 LLIArgs.push_back("-force-interpreter=true"); 203 204 // Add any extra LLI args. 205 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 206 LLIArgs.push_back(ToolArgs[i].c_str()); 207 208 LLIArgs.push_back(Bitcode.c_str()); 209 // Add optional parameters to the running program from Argv 210 for (unsigned i=0, e = Args.size(); i != e; ++i) 211 LLIArgs.push_back(Args[i].c_str()); 212 LLIArgs.push_back(0); 213 214 outs() << "<lli>"; outs().flush(); 215 DEBUG(errs() << "\nAbout to run:\t"; 216 for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) 217 errs() << " " << LLIArgs[i]; 218 errs() << "\n"; 219 ); 220 return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], 221 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 222 Timeout, MemoryLimit); 223 } 224 225 // LLI create method - Try to find the LLI executable 226 AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath, 227 std::string &Message, 228 const std::vector<std::string> *ToolArgs) { 229 std::string LLIPath = FindExecutable("lli", ProgPath).toString(); 230 if (!LLIPath.empty()) { 231 Message = "Found lli: " + LLIPath + "\n"; 232 return new LLI(LLIPath, ToolArgs); 233 } 234 235 Message = "Cannot find `lli' in executable directory or PATH!\n"; 236 return 0; 237 } 238 239 //===---------------------------------------------------------------------===// 240 // Custom execution command implementation of AbstractIntepreter interface 241 // 242 // Allows using a custom command for executing the bitcode, thus allows, 243 // for example, to invoke a cross compiler for code generation followed by 244 // a simulator that executes the generated binary. 245 namespace { 246 class CustomExecutor : public AbstractInterpreter { 247 std::string ExecutionCommand; 248 std::vector<std::string> ExecutorArgs; 249 public: 250 CustomExecutor( 251 const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : 252 ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} 253 254 virtual int ExecuteProgram(const std::string &Bitcode, 255 const std::vector<std::string> &Args, 256 const std::string &InputFile, 257 const std::string &OutputFile, 258 const std::vector<std::string> &GCCArgs, 259 const std::vector<std::string> &SharedLibs = 260 std::vector<std::string>(), 261 unsigned Timeout = 0, 262 unsigned MemoryLimit = 0); 263 }; 264 } 265 266 int CustomExecutor::ExecuteProgram(const std::string &Bitcode, 267 const std::vector<std::string> &Args, 268 const std::string &InputFile, 269 const std::string &OutputFile, 270 const std::vector<std::string> &GCCArgs, 271 const std::vector<std::string> &SharedLibs, 272 unsigned Timeout, 273 unsigned MemoryLimit) { 274 275 std::vector<const char*> ProgramArgs; 276 ProgramArgs.push_back(ExecutionCommand.c_str()); 277 278 for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 279 ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); 280 ProgramArgs.push_back(Bitcode.c_str()); 281 ProgramArgs.push_back(0); 282 283 // Add optional parameters to the running program from Argv 284 for (unsigned i=0, e = Args.size(); i != e; ++i) 285 ProgramArgs.push_back(Args[i].c_str()); 286 287 return RunProgramWithTimeout( 288 sys::Path(ExecutionCommand), 289 &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 290 sys::Path(OutputFile), Timeout, MemoryLimit); 291 } 292 293 // Custom execution environment create method, takes the execution command 294 // as arguments 295 AbstractInterpreter *AbstractInterpreter::createCustom( 296 const std::string &ProgramPath, 297 std::string &Message, 298 const std::string &ExecCommandLine) { 299 300 std::string Command = ""; 301 std::vector<std::string> Args; 302 std::string delimiters = " "; 303 304 // Tokenize the ExecCommandLine to the command and the args to allow 305 // defining a full command line as the command instead of just the 306 // executed program. We cannot just pass the whole string after the command 307 // as a single argument because then program sees only a single 308 // command line argument (with spaces in it: "foo bar" instead 309 // of "foo" and "bar"). 310 311 // code borrowed from: 312 // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html 313 std::string::size_type lastPos = 314 ExecCommandLine.find_first_not_of(delimiters, 0); 315 std::string::size_type pos = 316 ExecCommandLine.find_first_of(delimiters, lastPos); 317 318 while (std::string::npos != pos || std::string::npos != lastPos) { 319 std::string token = ExecCommandLine.substr(lastPos, pos - lastPos); 320 if (Command == "") 321 Command = token; 322 else 323 Args.push_back(token); 324 // Skip delimiters. Note the "not_of" 325 lastPos = ExecCommandLine.find_first_not_of(delimiters, pos); 326 // Find next "non-delimiter" 327 pos = ExecCommandLine.find_first_of(delimiters, lastPos); 328 } 329 330 std::string CmdPath = FindExecutable(Command, ProgramPath).toString(); 331 if (CmdPath.empty()) { 332 Message = 333 std::string("Cannot find '") + Command + 334 "' in executable directory or PATH!\n"; 335 return 0; 336 } 337 338 Message = "Found command in: " + CmdPath + "\n"; 339 340 return new CustomExecutor(CmdPath, Args); 341 } 342 343 //===----------------------------------------------------------------------===// 344 // LLC Implementation of AbstractIntepreter interface 345 // 346 GCC::FileType LLC::OutputCode(const std::string &Bitcode, 347 sys::Path &OutputAsmFile) { 348 sys::Path uniqueFile(Bitcode+".llc.s"); 349 std::string ErrMsg; 350 if (uniqueFile.makeUnique(true, &ErrMsg)) { 351 errs() << "Error making unique filename: " << ErrMsg << "\n"; 352 exit(1); 353 } 354 OutputAsmFile = uniqueFile; 355 std::vector<const char *> LLCArgs; 356 LLCArgs.push_back (LLCPath.c_str()); 357 358 // Add any extra LLC args. 359 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 360 LLCArgs.push_back(ToolArgs[i].c_str()); 361 362 LLCArgs.push_back ("-o"); 363 LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file 364 LLCArgs.push_back ("-f"); // Overwrite as necessary... 365 LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode 366 LLCArgs.push_back (0); 367 368 outs() << "<llc>"; outs().flush(); 369 DEBUG(errs() << "\nAbout to run:\t"; 370 for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) 371 errs() << " " << LLCArgs[i]; 372 errs() << "\n"; 373 ); 374 if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], 375 sys::Path(), sys::Path(), sys::Path())) 376 ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]); 377 378 return GCC::AsmFile; 379 } 380 381 void LLC::compileProgram(const std::string &Bitcode) { 382 sys::Path OutputAsmFile; 383 OutputCode(Bitcode, OutputAsmFile); 384 OutputAsmFile.eraseFromDisk(); 385 } 386 387 int LLC::ExecuteProgram(const std::string &Bitcode, 388 const std::vector<std::string> &Args, 389 const std::string &InputFile, 390 const std::string &OutputFile, 391 const std::vector<std::string> &ArgsForGCC, 392 const std::vector<std::string> &SharedLibs, 393 unsigned Timeout, 394 unsigned MemoryLimit) { 395 396 sys::Path OutputAsmFile; 397 OutputCode(Bitcode, OutputAsmFile); 398 FileRemover OutFileRemover(OutputAsmFile); 399 400 std::vector<std::string> GCCArgs(ArgsForGCC); 401 GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 402 GCCArgs.insert(GCCArgs.end(), gccArgs.begin(), gccArgs.end()); 403 404 // Assuming LLC worked, compile the result with GCC and run it. 405 return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile, 406 InputFile, OutputFile, GCCArgs, 407 Timeout, MemoryLimit); 408 } 409 410 /// createLLC - Try to find the LLC executable 411 /// 412 LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath, 413 std::string &Message, 414 const std::vector<std::string> *Args, 415 const std::vector<std::string> *GCCArgs) { 416 std::string LLCPath = FindExecutable("llc", ProgramPath).toString(); 417 if (LLCPath.empty()) { 418 Message = "Cannot find `llc' in executable directory or PATH!\n"; 419 return 0; 420 } 421 422 Message = "Found llc: " + LLCPath + "\n"; 423 GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs); 424 if (!gcc) { 425 errs() << Message << "\n"; 426 exit(1); 427 } 428 return new LLC(LLCPath, gcc, Args, GCCArgs); 429 } 430 431 //===---------------------------------------------------------------------===// 432 // JIT Implementation of AbstractIntepreter interface 433 // 434 namespace { 435 class JIT : public AbstractInterpreter { 436 std::string LLIPath; // The path to the LLI executable 437 std::vector<std::string> ToolArgs; // Args to pass to LLI 438 public: 439 JIT(const std::string &Path, const std::vector<std::string> *Args) 440 : LLIPath(Path) { 441 ToolArgs.clear (); 442 if (Args) { ToolArgs = *Args; } 443 } 444 445 virtual int ExecuteProgram(const std::string &Bitcode, 446 const std::vector<std::string> &Args, 447 const std::string &InputFile, 448 const std::string &OutputFile, 449 const std::vector<std::string> &GCCArgs = 450 std::vector<std::string>(), 451 const std::vector<std::string> &SharedLibs = 452 std::vector<std::string>(), 453 unsigned Timeout =0, 454 unsigned MemoryLimit =0); 455 }; 456 } 457 458 int JIT::ExecuteProgram(const std::string &Bitcode, 459 const std::vector<std::string> &Args, 460 const std::string &InputFile, 461 const std::string &OutputFile, 462 const std::vector<std::string> &GCCArgs, 463 const std::vector<std::string> &SharedLibs, 464 unsigned Timeout, 465 unsigned MemoryLimit) { 466 // Construct a vector of parameters, incorporating those from the command-line 467 std::vector<const char*> JITArgs; 468 JITArgs.push_back(LLIPath.c_str()); 469 JITArgs.push_back("-force-interpreter=false"); 470 471 // Add any extra LLI args. 472 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 473 JITArgs.push_back(ToolArgs[i].c_str()); 474 475 for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 476 JITArgs.push_back("-load"); 477 JITArgs.push_back(SharedLibs[i].c_str()); 478 } 479 JITArgs.push_back(Bitcode.c_str()); 480 // Add optional parameters to the running program from Argv 481 for (unsigned i=0, e = Args.size(); i != e; ++i) 482 JITArgs.push_back(Args[i].c_str()); 483 JITArgs.push_back(0); 484 485 outs() << "<jit>"; outs().flush(); 486 DEBUG(errs() << "\nAbout to run:\t"; 487 for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) 488 errs() << " " << JITArgs[i]; 489 errs() << "\n"; 490 ); 491 DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 492 return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], 493 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 494 Timeout, MemoryLimit); 495 } 496 497 /// createJIT - Try to find the LLI executable 498 /// 499 AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath, 500 std::string &Message, const std::vector<std::string> *Args) { 501 std::string LLIPath = FindExecutable("lli", ProgPath).toString(); 502 if (!LLIPath.empty()) { 503 Message = "Found lli: " + LLIPath + "\n"; 504 return new JIT(LLIPath, Args); 505 } 506 507 Message = "Cannot find `lli' in executable directory or PATH!\n"; 508 return 0; 509 } 510 511 GCC::FileType CBE::OutputCode(const std::string &Bitcode, 512 sys::Path &OutputCFile) { 513 sys::Path uniqueFile(Bitcode+".cbe.c"); 514 std::string ErrMsg; 515 if (uniqueFile.makeUnique(true, &ErrMsg)) { 516 errs() << "Error making unique filename: " << ErrMsg << "\n"; 517 exit(1); 518 } 519 OutputCFile = uniqueFile; 520 std::vector<const char *> LLCArgs; 521 LLCArgs.push_back (LLCPath.c_str()); 522 523 // Add any extra LLC args. 524 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 525 LLCArgs.push_back(ToolArgs[i].c_str()); 526 527 LLCArgs.push_back ("-o"); 528 LLCArgs.push_back (OutputCFile.c_str()); // Output to the C file 529 LLCArgs.push_back ("-march=c"); // Output C language 530 LLCArgs.push_back ("-f"); // Overwrite as necessary... 531 LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode 532 LLCArgs.push_back (0); 533 534 outs() << "<cbe>"; outs().flush(); 535 DEBUG(errs() << "\nAbout to run:\t"; 536 for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) 537 errs() << " " << LLCArgs[i]; 538 errs() << "\n"; 539 ); 540 if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), 541 sys::Path())) 542 ProcessFailure(LLCPath, &LLCArgs[0]); 543 return GCC::CFile; 544 } 545 546 void CBE::compileProgram(const std::string &Bitcode) { 547 sys::Path OutputCFile; 548 OutputCode(Bitcode, OutputCFile); 549 OutputCFile.eraseFromDisk(); 550 } 551 552 int CBE::ExecuteProgram(const std::string &Bitcode, 553 const std::vector<std::string> &Args, 554 const std::string &InputFile, 555 const std::string &OutputFile, 556 const std::vector<std::string> &ArgsForGCC, 557 const std::vector<std::string> &SharedLibs, 558 unsigned Timeout, 559 unsigned MemoryLimit) { 560 sys::Path OutputCFile; 561 OutputCode(Bitcode, OutputCFile); 562 563 FileRemover CFileRemove(OutputCFile); 564 565 std::vector<std::string> GCCArgs(ArgsForGCC); 566 GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 567 568 return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile, 569 InputFile, OutputFile, GCCArgs, 570 Timeout, MemoryLimit); 571 } 572 573 /// createCBE - Try to find the 'llc' executable 574 /// 575 CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath, 576 std::string &Message, 577 const std::vector<std::string> *Args, 578 const std::vector<std::string> *GCCArgs) { 579 sys::Path LLCPath = FindExecutable("llc", ProgramPath); 580 if (LLCPath.isEmpty()) { 581 Message = 582 "Cannot find `llc' in executable directory or PATH!\n"; 583 return 0; 584 } 585 586 Message = "Found llc: " + LLCPath.toString() + "\n"; 587 GCC *gcc = GCC::create(ProgramPath, Message, GCCArgs); 588 if (!gcc) { 589 errs() << Message << "\n"; 590 exit(1); 591 } 592 return new CBE(LLCPath, gcc, Args); 593 } 594 595 //===---------------------------------------------------------------------===// 596 // GCC abstraction 597 // 598 599 #ifdef __APPLE__ 600 static bool 601 IsARMArchitecture(std::vector<std::string> Args) 602 { 603 for (std::vector<std::string>::const_iterator 604 I = Args.begin(), E = Args.end(); I != E; ++I) { 605 if (!strcasecmp(I->c_str(), "-arch")) { 606 ++I; 607 if ((I != E) && !strncasecmp(I->c_str(), "arm", strlen("arm"))) { 608 return true; 609 } 610 } 611 } 612 613 return false; 614 } 615 #endif 616 617 int GCC::ExecuteProgram(const std::string &ProgramFile, 618 const std::vector<std::string> &Args, 619 FileType fileType, 620 const std::string &InputFile, 621 const std::string &OutputFile, 622 const std::vector<std::string> &ArgsForGCC, 623 unsigned Timeout, 624 unsigned MemoryLimit) { 625 std::vector<const char*> GCCArgs; 626 627 GCCArgs.push_back(GCCPath.c_str()); 628 629 for (std::vector<std::string>::const_iterator 630 I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 631 GCCArgs.push_back(I->c_str()); 632 633 // Specify -x explicitly in case the extension is wonky 634 GCCArgs.push_back("-x"); 635 if (fileType == CFile) { 636 GCCArgs.push_back("c"); 637 GCCArgs.push_back("-fno-strict-aliasing"); 638 } else { 639 GCCArgs.push_back("assembler"); 640 #ifdef __APPLE__ 641 // For ARM architectures we don't want this flag. bugpoint isn't 642 // explicitly told what architecture it is working on, so we get 643 // it from gcc flags 644 if (!IsARMArchitecture(ArgsForGCC)) 645 GCCArgs.push_back("-force_cpusubtype_ALL"); 646 #endif 647 } 648 GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename... 649 GCCArgs.push_back("-x"); 650 GCCArgs.push_back("none"); 651 GCCArgs.push_back("-o"); 652 sys::Path OutputBinary (ProgramFile+".gcc.exe"); 653 std::string ErrMsg; 654 if (OutputBinary.makeUnique(true, &ErrMsg)) { 655 errs() << "Error making unique filename: " << ErrMsg << "\n"; 656 exit(1); 657 } 658 GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 659 660 // Add any arguments intended for GCC. We locate them here because this is 661 // most likely -L and -l options that need to come before other libraries but 662 // after the source. Other options won't be sensitive to placement on the 663 // command line, so this should be safe. 664 for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 665 GCCArgs.push_back(ArgsForGCC[i].c_str()); 666 667 GCCArgs.push_back("-lm"); // Hard-code the math library... 668 GCCArgs.push_back("-O2"); // Optimize the program a bit... 669 #if defined (HAVE_LINK_R) 670 GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files 671 #endif 672 #ifdef __sparc__ 673 GCCArgs.push_back("-mcpu=v9"); 674 #endif 675 GCCArgs.push_back(0); // NULL terminator 676 677 outs() << "<gcc>"; outs().flush(); 678 DEBUG(errs() << "\nAbout to run:\t"; 679 for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) 680 errs() << " " << GCCArgs[i]; 681 errs() << "\n"; 682 ); 683 if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 684 sys::Path())) { 685 ProcessFailure(GCCPath, &GCCArgs[0]); 686 exit(1); 687 } 688 689 std::vector<const char*> ProgramArgs; 690 691 if (RemoteClientPath.isEmpty()) 692 ProgramArgs.push_back(OutputBinary.c_str()); 693 else { 694 ProgramArgs.push_back(RemoteClientPath.c_str()); 695 ProgramArgs.push_back(RemoteHost.c_str()); 696 ProgramArgs.push_back("-l"); 697 ProgramArgs.push_back(RemoteUser.c_str()); 698 if (!RemotePort.empty()) { 699 ProgramArgs.push_back("-p"); 700 ProgramArgs.push_back(RemotePort.c_str()); 701 } 702 if (!RemoteExtra.empty()) { 703 ProgramArgs.push_back(RemoteExtra.c_str()); 704 } 705 706 // Full path to the binary. We need to cd to the exec directory because 707 // there is a dylib there that the exec expects to find in the CWD 708 char* env_pwd = getenv("PWD"); 709 std::string Exec = "cd "; 710 Exec += env_pwd; 711 Exec += "; ./"; 712 Exec += OutputBinary.c_str(); 713 ProgramArgs.push_back(Exec.c_str()); 714 } 715 716 // Add optional parameters to the running program from Argv 717 for (unsigned i=0, e = Args.size(); i != e; ++i) 718 ProgramArgs.push_back(Args[i].c_str()); 719 ProgramArgs.push_back(0); // NULL terminator 720 721 // Now that we have a binary, run it! 722 outs() << "<program>"; outs().flush(); 723 DEBUG(errs() << "\nAbout to run:\t"; 724 for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i) 725 errs() << " " << ProgramArgs[i]; 726 errs() << "\n"; 727 ); 728 729 FileRemover OutputBinaryRemover(OutputBinary); 730 731 if (RemoteClientPath.isEmpty()) { 732 DEBUG(errs() << "<run locally>";); 733 return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], 734 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 735 Timeout, MemoryLimit); 736 } else { 737 outs() << "<run remotely>"; outs().flush(); 738 return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), 739 &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 740 sys::Path(OutputFile), Timeout, MemoryLimit); 741 } 742 } 743 744 int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 745 std::string &OutputFile, 746 const std::vector<std::string> &ArgsForGCC) { 747 sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); 748 std::string ErrMsg; 749 if (uniqueFilename.makeUnique(true, &ErrMsg)) { 750 errs() << "Error making unique filename: " << ErrMsg << "\n"; 751 exit(1); 752 } 753 OutputFile = uniqueFilename.toString(); 754 755 std::vector<const char*> GCCArgs; 756 757 GCCArgs.push_back(GCCPath.c_str()); 758 759 for (std::vector<std::string>::const_iterator 760 I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 761 GCCArgs.push_back(I->c_str()); 762 763 // Compile the C/asm file into a shared object 764 GCCArgs.push_back("-x"); 765 GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 766 GCCArgs.push_back("-fno-strict-aliasing"); 767 GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. 768 GCCArgs.push_back("-x"); 769 GCCArgs.push_back("none"); 770 #if defined(sparc) || defined(__sparc__) || defined(__sparcv9) 771 GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 772 #elif defined(__APPLE__) 773 // link all source files into a single module in data segment, rather than 774 // generating blocks. dynamic_lookup requires that you set 775 // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 776 // bugpoint to just pass that in the environment of GCC. 777 GCCArgs.push_back("-single_module"); 778 GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 779 GCCArgs.push_back("-undefined"); 780 GCCArgs.push_back("dynamic_lookup"); 781 #else 782 GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 783 #endif 784 785 #if defined(__ia64__) || defined(__alpha__) || defined(__amd64__) 786 GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 787 #endif 788 #ifdef __sparc__ 789 GCCArgs.push_back("-mcpu=v9"); 790 #endif 791 GCCArgs.push_back("-o"); 792 GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 793 GCCArgs.push_back("-O2"); // Optimize the program a bit. 794 795 796 797 // Add any arguments intended for GCC. We locate them here because this is 798 // most likely -L and -l options that need to come before other libraries but 799 // after the source. Other options won't be sensitive to placement on the 800 // command line, so this should be safe. 801 for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 802 GCCArgs.push_back(ArgsForGCC[i].c_str()); 803 GCCArgs.push_back(0); // NULL terminator 804 805 806 807 outs() << "<gcc>"; outs().flush(); 808 DEBUG(errs() << "\nAbout to run:\t"; 809 for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) 810 errs() << " " << GCCArgs[i]; 811 errs() << "\n"; 812 ); 813 if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 814 sys::Path())) { 815 ProcessFailure(GCCPath, &GCCArgs[0]); 816 return 1; 817 } 818 return 0; 819 } 820 821 /// create - Try to find the `gcc' executable 822 /// 823 GCC *GCC::create(const std::string &ProgramPath, std::string &Message, 824 const std::vector<std::string> *Args) { 825 sys::Path GCCPath = FindExecutable("gcc", ProgramPath); 826 if (GCCPath.isEmpty()) { 827 Message = "Cannot find `gcc' in executable directory or PATH!\n"; 828 return 0; 829 } 830 831 sys::Path RemoteClientPath; 832 if (!RemoteClient.empty()) 833 RemoteClientPath = FindExecutable(RemoteClient.c_str(), ProgramPath); 834 835 Message = "Found gcc: " + GCCPath.toString() + "\n"; 836 return new GCC(GCCPath, RemoteClientPath, Args); 837 } 838