ToolRunner.cpp revision 9ba8a76f8baaa1092d60ccfbc04e7efdc207c98f
1//===-- ToolRunner.cpp ----------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group and is distributed under 6// the University of Illinois Open Source 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/Debug.h" 19#include "llvm/Support/FileUtilities.h" 20#include <fstream> 21#include <sstream> 22#include <iostream> 23using namespace llvm; 24 25ToolExecutionError::~ToolExecutionError() throw() { } 26 27/// RunProgramWithTimeout - This function provides an alternate interface to the 28/// sys::Program::ExecuteAndWait interface. 29/// @see sys:Program::ExecuteAndWait 30static int RunProgramWithTimeout(const sys::Path &ProgramPath, 31 const char **Args, 32 const sys::Path &StdInFile, 33 const sys::Path &StdOutFile, 34 const sys::Path &StdErrFile, 35 unsigned NumSeconds = 0, 36 unsigned MemoryLimit = 0) { 37 const sys::Path* redirects[3]; 38 redirects[0] = &StdInFile; 39 redirects[1] = &StdOutFile; 40 redirects[2] = &StdErrFile; 41 42 if (0) { 43 std::cerr << "RUN:"; 44 for (unsigned i = 0; Args[i]; ++i) 45 std::cerr << " " << Args[i]; 46 std::cerr << "\n"; 47 } 48 49 return 50 sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, 51 NumSeconds, MemoryLimit); 52} 53 54 55 56static void ProcessFailure(sys::Path ProgPath, const char** Args) { 57 std::ostringstream OS; 58 OS << "\nError running tool:\n "; 59 for (const char **Arg = Args; *Arg; ++Arg) 60 OS << " " << *Arg; 61 OS << "\n"; 62 63 // Rerun the compiler, capturing any error messages to print them. 64 sys::Path ErrorFilename("error_messages"); 65 std::string ErrMsg; 66 if (ErrorFilename.makeUnique(true, &ErrMsg)) { 67 std::cerr << "Error making unique filename: " << ErrMsg << "\n"; 68 exit(1); 69 } 70 RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, 71 ErrorFilename); // FIXME: check return code ? 72 73 // Print out the error messages generated by GCC if possible... 74 std::ifstream ErrorFile(ErrorFilename.c_str()); 75 if (ErrorFile) { 76 std::copy(std::istreambuf_iterator<char>(ErrorFile), 77 std::istreambuf_iterator<char>(), 78 std::ostreambuf_iterator<char>(OS)); 79 ErrorFile.close(); 80 } 81 82 ErrorFilename.eraseFromDisk(); 83 throw ToolExecutionError(OS.str()); 84} 85 86//===---------------------------------------------------------------------===// 87// LLI Implementation of AbstractIntepreter interface 88// 89namespace { 90 class LLI : public AbstractInterpreter { 91 std::string LLIPath; // The path to the LLI executable 92 std::vector<std::string> ToolArgs; // Args to pass to LLI 93 public: 94 LLI(const std::string &Path, const std::vector<std::string> *Args) 95 : LLIPath(Path) { 96 ToolArgs.clear (); 97 if (Args) { ToolArgs = *Args; } 98 } 99 100 virtual int ExecuteProgram(const std::string &Bytecode, 101 const std::vector<std::string> &Args, 102 const std::string &InputFile, 103 const std::string &OutputFile, 104 const std::vector<std::string> &GCCArgs, 105 const std::vector<std::string> &SharedLibs = 106 std::vector<std::string>(), 107 unsigned Timeout = 0, 108 unsigned MemoryLimit = 0); 109 }; 110} 111 112int LLI::ExecuteProgram(const std::string &Bytecode, 113 const std::vector<std::string> &Args, 114 const std::string &InputFile, 115 const std::string &OutputFile, 116 const std::vector<std::string> &GCCArgs, 117 const std::vector<std::string> &SharedLibs, 118 unsigned Timeout, 119 unsigned MemoryLimit) { 120 if (!SharedLibs.empty()) 121 throw ToolExecutionError("LLI currently does not support " 122 "loading shared libraries."); 123 124 if (!GCCArgs.empty()) 125 throw ToolExecutionError("LLI currently does not support " 126 "GCC Arguments."); 127 std::vector<const char*> LLIArgs; 128 LLIArgs.push_back(LLIPath.c_str()); 129 LLIArgs.push_back("-force-interpreter=true"); 130 131 // Add any extra LLI args. 132 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 133 LLIArgs.push_back(ToolArgs[i].c_str()); 134 135 LLIArgs.push_back(Bytecode.c_str()); 136 // Add optional parameters to the running program from Argv 137 for (unsigned i=0, e = Args.size(); i != e; ++i) 138 LLIArgs.push_back(Args[i].c_str()); 139 LLIArgs.push_back(0); 140 141 std::cout << "<lli>" << std::flush; 142 DEBUG(std::cerr << "\nAbout to run:\t"; 143 for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) 144 std::cerr << " " << LLIArgs[i]; 145 std::cerr << "\n"; 146 ); 147 return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], 148 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 149 Timeout, MemoryLimit); 150} 151 152// LLI create method - Try to find the LLI executable 153AbstractInterpreter *AbstractInterpreter::createLLI(const std::string &ProgPath, 154 std::string &Message, 155 const std::vector<std::string> *ToolArgs) { 156 std::string LLIPath = FindExecutable("lli", ProgPath).toString(); 157 if (!LLIPath.empty()) { 158 Message = "Found lli: " + LLIPath + "\n"; 159 return new LLI(LLIPath, ToolArgs); 160 } 161 162 Message = "Cannot find `lli' in executable directory or PATH!\n"; 163 return 0; 164} 165 166//===----------------------------------------------------------------------===// 167// LLC Implementation of AbstractIntepreter interface 168// 169GCC::FileType LLC::OutputCode(const std::string &Bytecode, 170 sys::Path &OutputAsmFile) { 171 sys::Path uniqueFile(Bytecode+".llc.s"); 172 std::string ErrMsg; 173 if (uniqueFile.makeUnique(true, &ErrMsg)) { 174 std::cerr << "Error making unique filename: " << ErrMsg << "\n"; 175 exit(1); 176 } 177 OutputAsmFile = uniqueFile; 178 std::vector<const char *> LLCArgs; 179 LLCArgs.push_back (LLCPath.c_str()); 180 181 // Add any extra LLC args. 182 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 183 LLCArgs.push_back(ToolArgs[i].c_str()); 184 185 LLCArgs.push_back ("-o"); 186 LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file 187 LLCArgs.push_back ("-f"); // Overwrite as necessary... 188 LLCArgs.push_back (Bytecode.c_str()); // This is the input bytecode 189 LLCArgs.push_back (0); 190 191 std::cout << "<llc>" << std::flush; 192 DEBUG(std::cerr << "\nAbout to run:\t"; 193 for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) 194 std::cerr << " " << LLCArgs[i]; 195 std::cerr << "\n"; 196 ); 197 if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], 198 sys::Path(), sys::Path(), sys::Path())) 199 ProcessFailure(sys::Path(LLCPath), &LLCArgs[0]); 200 201 return GCC::AsmFile; 202} 203 204void LLC::compileProgram(const std::string &Bytecode) { 205 sys::Path OutputAsmFile; 206 OutputCode(Bytecode, OutputAsmFile); 207 OutputAsmFile.eraseFromDisk(); 208} 209 210int LLC::ExecuteProgram(const std::string &Bytecode, 211 const std::vector<std::string> &Args, 212 const std::string &InputFile, 213 const std::string &OutputFile, 214 const std::vector<std::string> &ArgsForGCC, 215 const std::vector<std::string> &SharedLibs, 216 unsigned Timeout, 217 unsigned MemoryLimit) { 218 219 sys::Path OutputAsmFile; 220 OutputCode(Bytecode, OutputAsmFile); 221 FileRemover OutFileRemover(OutputAsmFile); 222 223 std::vector<std::string> GCCArgs(ArgsForGCC); 224 GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end()); 225 226 // Assuming LLC worked, compile the result with GCC and run it. 227 return gcc->ExecuteProgram(OutputAsmFile.toString(), Args, GCC::AsmFile, 228 InputFile, OutputFile, GCCArgs, 229 Timeout, MemoryLimit); 230} 231 232/// createLLC - Try to find the LLC executable 233/// 234LLC *AbstractInterpreter::createLLC(const std::string &ProgramPath, 235 std::string &Message, 236 const std::vector<std::string> *Args) { 237 std::string LLCPath = FindExecutable("llc", ProgramPath).toString(); 238 if (LLCPath.empty()) { 239 Message = "Cannot find `llc' in executable directory or PATH!\n"; 240 return 0; 241 } 242 243 Message = "Found llc: " + LLCPath + "\n"; 244 GCC *gcc = GCC::create(ProgramPath, Message); 245 if (!gcc) { 246 std::cerr << Message << "\n"; 247 exit(1); 248 } 249 return new LLC(LLCPath, gcc, Args); 250} 251 252//===---------------------------------------------------------------------===// 253// JIT Implementation of AbstractIntepreter interface 254// 255namespace { 256 class JIT : public AbstractInterpreter { 257 std::string LLIPath; // The path to the LLI executable 258 std::vector<std::string> ToolArgs; // Args to pass to LLI 259 public: 260 JIT(const std::string &Path, const std::vector<std::string> *Args) 261 : LLIPath(Path) { 262 ToolArgs.clear (); 263 if (Args) { ToolArgs = *Args; } 264 } 265 266 virtual int ExecuteProgram(const std::string &Bytecode, 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 std::vector<std::string>(), 272 const std::vector<std::string> &SharedLibs = 273 std::vector<std::string>(), 274 unsigned Timeout =0, 275 unsigned MemoryLimit =0); 276 }; 277} 278 279int JIT::ExecuteProgram(const std::string &Bytecode, 280 const std::vector<std::string> &Args, 281 const std::string &InputFile, 282 const std::string &OutputFile, 283 const std::vector<std::string> &GCCArgs, 284 const std::vector<std::string> &SharedLibs, 285 unsigned Timeout, 286 unsigned MemoryLimit) { 287 if (!GCCArgs.empty()) 288 throw ToolExecutionError("JIT does not support GCC Arguments."); 289 // Construct a vector of parameters, incorporating those from the command-line 290 std::vector<const char*> JITArgs; 291 JITArgs.push_back(LLIPath.c_str()); 292 JITArgs.push_back("-force-interpreter=false"); 293 294 // Add any extra LLI args. 295 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 296 JITArgs.push_back(ToolArgs[i].c_str()); 297 298 for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 299 JITArgs.push_back("-load"); 300 JITArgs.push_back(SharedLibs[i].c_str()); 301 } 302 JITArgs.push_back(Bytecode.c_str()); 303 // Add optional parameters to the running program from Argv 304 for (unsigned i=0, e = Args.size(); i != e; ++i) 305 JITArgs.push_back(Args[i].c_str()); 306 JITArgs.push_back(0); 307 308 std::cout << "<jit>" << std::flush; 309 DEBUG(std::cerr << "\nAbout to run:\t"; 310 for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) 311 std::cerr << " " << JITArgs[i]; 312 std::cerr << "\n"; 313 ); 314 DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n"); 315 return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], 316 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 317 Timeout, MemoryLimit); 318} 319 320/// createJIT - Try to find the LLI executable 321/// 322AbstractInterpreter *AbstractInterpreter::createJIT(const std::string &ProgPath, 323 std::string &Message, const std::vector<std::string> *Args) { 324 std::string LLIPath = FindExecutable("lli", ProgPath).toString(); 325 if (!LLIPath.empty()) { 326 Message = "Found lli: " + LLIPath + "\n"; 327 return new JIT(LLIPath, Args); 328 } 329 330 Message = "Cannot find `lli' in executable directory or PATH!\n"; 331 return 0; 332} 333 334GCC::FileType CBE::OutputCode(const std::string &Bytecode, 335 sys::Path &OutputCFile) { 336 sys::Path uniqueFile(Bytecode+".cbe.c"); 337 std::string ErrMsg; 338 if (uniqueFile.makeUnique(true, &ErrMsg)) { 339 std::cerr << "Error making unique filename: " << ErrMsg << "\n"; 340 exit(1); 341 } 342 OutputCFile = uniqueFile; 343 std::vector<const char *> LLCArgs; 344 LLCArgs.push_back (LLCPath.c_str()); 345 346 // Add any extra LLC args. 347 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 348 LLCArgs.push_back(ToolArgs[i].c_str()); 349 350 LLCArgs.push_back ("-o"); 351 LLCArgs.push_back (OutputCFile.c_str()); // Output to the C file 352 LLCArgs.push_back ("-march=c"); // Output C language 353 LLCArgs.push_back ("-f"); // Overwrite as necessary... 354 LLCArgs.push_back (Bytecode.c_str()); // This is the input bytecode 355 LLCArgs.push_back (0); 356 357 std::cout << "<cbe>" << std::flush; 358 DEBUG(std::cerr << "\nAbout to run:\t"; 359 for (unsigned i=0, e = LLCArgs.size()-1; i != e; ++i) 360 std::cerr << " " << LLCArgs[i]; 361 std::cerr << "\n"; 362 ); 363 if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), 364 sys::Path())) 365 ProcessFailure(LLCPath, &LLCArgs[0]); 366 return GCC::CFile; 367} 368 369void CBE::compileProgram(const std::string &Bytecode) { 370 sys::Path OutputCFile; 371 OutputCode(Bytecode, OutputCFile); 372 OutputCFile.eraseFromDisk(); 373} 374 375int CBE::ExecuteProgram(const std::string &Bytecode, 376 const std::vector<std::string> &Args, 377 const std::string &InputFile, 378 const std::string &OutputFile, 379 const std::vector<std::string> &ArgsForGCC, 380 const std::vector<std::string> &SharedLibs, 381 unsigned Timeout, 382 unsigned MemoryLimit) { 383 sys::Path OutputCFile; 384 OutputCode(Bytecode, OutputCFile); 385 386 FileRemover CFileRemove(OutputCFile); 387 388 std::vector<std::string> GCCArgs(ArgsForGCC); 389 GCCArgs.insert(GCCArgs.end(),SharedLibs.begin(),SharedLibs.end()); 390 return gcc->ExecuteProgram(OutputCFile.toString(), Args, GCC::CFile, 391 InputFile, OutputFile, GCCArgs, 392 Timeout, MemoryLimit); 393} 394 395/// createCBE - Try to find the 'llc' executable 396/// 397CBE *AbstractInterpreter::createCBE(const std::string &ProgramPath, 398 std::string &Message, 399 const std::vector<std::string> *Args) { 400 sys::Path LLCPath = FindExecutable("llc", ProgramPath); 401 if (LLCPath.isEmpty()) { 402 Message = 403 "Cannot find `llc' in executable directory or PATH!\n"; 404 return 0; 405 } 406 407 Message = "Found llc: " + LLCPath.toString() + "\n"; 408 GCC *gcc = GCC::create(ProgramPath, Message); 409 if (!gcc) { 410 std::cerr << Message << "\n"; 411 exit(1); 412 } 413 return new CBE(LLCPath, gcc, Args); 414} 415 416//===---------------------------------------------------------------------===// 417// GCC abstraction 418// 419int GCC::ExecuteProgram(const std::string &ProgramFile, 420 const std::vector<std::string> &Args, 421 FileType fileType, 422 const std::string &InputFile, 423 const std::string &OutputFile, 424 const std::vector<std::string> &ArgsForGCC, 425 unsigned Timeout, 426 unsigned MemoryLimit) { 427 std::vector<const char*> GCCArgs; 428 429 GCCArgs.push_back(GCCPath.c_str()); 430 431 // Specify -x explicitly in case the extension is wonky 432 GCCArgs.push_back("-x"); 433 if (fileType == CFile) { 434 GCCArgs.push_back("c"); 435 GCCArgs.push_back("-fno-strict-aliasing"); 436 } else { 437 GCCArgs.push_back("assembler"); 438#ifdef __APPLE__ 439 GCCArgs.push_back("-force_cpusubtype_ALL"); 440#endif 441 } 442 GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename... 443 GCCArgs.push_back("-x"); 444 GCCArgs.push_back("none"); 445 GCCArgs.push_back("-o"); 446 sys::Path OutputBinary (ProgramFile+".gcc.exe"); 447 std::string ErrMsg; 448 if (OutputBinary.makeUnique(true, &ErrMsg)) { 449 std::cerr << "Error making unique filename: " << ErrMsg << "\n"; 450 exit(1); 451 } 452 GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 453 454 // Add any arguments intended for GCC. We locate them here because this is 455 // most likely -L and -l options that need to come before other libraries but 456 // after the source. Other options won't be sensitive to placement on the 457 // command line, so this should be safe. 458 for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 459 GCCArgs.push_back(ArgsForGCC[i].c_str()); 460 461 GCCArgs.push_back("-lm"); // Hard-code the math library... 462 GCCArgs.push_back("-O2"); // Optimize the program a bit... 463#if defined (HAVE_LINK_R) 464 GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files 465#endif 466#ifdef __sparc__ 467 GCCArgs.push_back("-mcpu=v9"); 468#endif 469 GCCArgs.push_back(0); // NULL terminator 470 471 std::cout << "<gcc>" << std::flush; 472 DEBUG(std::cerr << "\nAbout to run:\t"; 473 for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) 474 std::cerr << " " << GCCArgs[i]; 475 std::cerr << "\n"; 476 ); 477 if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 478 sys::Path())) { 479 ProcessFailure(GCCPath, &GCCArgs[0]); 480 exit(1); 481 } 482 483 std::vector<const char*> ProgramArgs; 484 485 ProgramArgs.push_back(OutputBinary.c_str()); 486 // Add optional parameters to the running program from Argv 487 for (unsigned i=0, e = Args.size(); i != e; ++i) 488 ProgramArgs.push_back(Args[i].c_str()); 489 ProgramArgs.push_back(0); // NULL terminator 490 491 // Now that we have a binary, run it! 492 std::cout << "<program>" << std::flush; 493 DEBUG(std::cerr << "\nAbout to run:\t"; 494 for (unsigned i=0, e = ProgramArgs.size()-1; i != e; ++i) 495 std::cerr << " " << ProgramArgs[i]; 496 std::cerr << "\n"; 497 ); 498 499 FileRemover OutputBinaryRemover(OutputBinary); 500 return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], 501 sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 502 Timeout, MemoryLimit); 503} 504 505int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 506 std::string &OutputFile, 507 const std::vector<std::string> &ArgsForGCC) { 508 sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); 509 std::string ErrMsg; 510 if (uniqueFilename.makeUnique(true, &ErrMsg)) { 511 std::cerr << "Error making unique filename: " << ErrMsg << "\n"; 512 exit(1); 513 } 514 OutputFile = uniqueFilename.toString(); 515 516 std::vector<const char*> GCCArgs; 517 518 GCCArgs.push_back(GCCPath.c_str()); 519 520 521 // Compile the C/asm file into a shared object 522 GCCArgs.push_back("-x"); 523 GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 524 GCCArgs.push_back("-fno-strict-aliasing"); 525 GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. 526#if defined(sparc) || defined(__sparc__) || defined(__sparcv9) 527 GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 528#elif defined(__APPLE__) 529 // link all source files into a single module in data segment, rather than 530 // generating blocks. dynamic_lookup requires that you set 531 // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 532 // bugpoint to just pass that in the environment of GCC. 533 GCCArgs.push_back("-single_module"); 534 GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 535 GCCArgs.push_back("-undefined"); 536 GCCArgs.push_back("dynamic_lookup"); 537#else 538 GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 539#endif 540 541#if defined(__ia64__) || defined(__alpha__) 542 GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 543#endif 544#ifdef __sparc__ 545 GCCArgs.push_back("-mcpu=v9"); 546#endif 547 GCCArgs.push_back("-o"); 548 GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 549 GCCArgs.push_back("-O2"); // Optimize the program a bit. 550 551 552 553 // Add any arguments intended for GCC. We locate them here because this is 554 // most likely -L and -l options that need to come before other libraries but 555 // after the source. Other options won't be sensitive to placement on the 556 // command line, so this should be safe. 557 for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 558 GCCArgs.push_back(ArgsForGCC[i].c_str()); 559 GCCArgs.push_back(0); // NULL terminator 560 561 562 563 std::cout << "<gcc>" << std::flush; 564 DEBUG(std::cerr << "\nAbout to run:\t"; 565 for (unsigned i=0, e = GCCArgs.size()-1; i != e; ++i) 566 std::cerr << " " << GCCArgs[i]; 567 std::cerr << "\n"; 568 ); 569 if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 570 sys::Path())) { 571 ProcessFailure(GCCPath, &GCCArgs[0]); 572 return 1; 573 } 574 return 0; 575} 576 577/// create - Try to find the `gcc' executable 578/// 579GCC *GCC::create(const std::string &ProgramPath, std::string &Message) { 580 sys::Path GCCPath = FindExecutable("gcc", ProgramPath); 581 if (GCCPath.isEmpty()) { 582 Message = "Cannot find `gcc' in executable directory or PATH!\n"; 583 return 0; 584 } 585 586 Message = "Found gcc: " + GCCPath.toString() + "\n"; 587 return new GCC(GCCPath); 588} 589