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