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