1193323Sed//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file contains code used to execute the program utilizing one of the 11193323Sed// various ways of running LLVM bitcode. 12193323Sed// 13193323Sed//===----------------------------------------------------------------------===// 14193323Sed 15193323Sed#include "BugDriver.h" 16193323Sed#include "ToolRunner.h" 17193323Sed#include "llvm/Support/CommandLine.h" 18193323Sed#include "llvm/Support/Debug.h" 19193323Sed#include "llvm/Support/FileUtilities.h" 20193323Sed#include "llvm/Support/SystemUtils.h" 21198090Srdivacky#include "llvm/Support/raw_ostream.h" 22193323Sed#include <fstream> 23193323Sed 24193323Sedusing namespace llvm; 25193323Sed 26193323Sednamespace { 27193323Sed // OutputType - Allow the user to specify the way code should be run, to test 28193323Sed // for miscompilation. 29193323Sed // 30193323Sed enum OutputType { 31234353Sdim AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, LLC_Safe, CompileCustom, Custom 32193323Sed }; 33193323Sed 34193323Sed cl::opt<double> 35193323Sed AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"), 36193323Sed cl::init(0.0)); 37193323Sed cl::opt<double> 38193323Sed RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"), 39193323Sed cl::init(0.0)); 40193323Sed 41193323Sed cl::opt<OutputType> 42193323Sed InterpreterSel(cl::desc("Specify the \"test\" i.e. suspect back-end:"), 43193323Sed cl::values(clEnumValN(AutoPick, "auto", "Use best guess"), 44193323Sed clEnumValN(RunLLI, "run-int", 45193323Sed "Execute with the interpreter"), 46193323Sed clEnumValN(RunJIT, "run-jit", "Execute with JIT"), 47193323Sed clEnumValN(RunLLC, "run-llc", "Compile with LLC"), 48205218Srdivacky clEnumValN(RunLLCIA, "run-llc-ia", 49205218Srdivacky "Compile with LLC with integrated assembler"), 50193323Sed clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"), 51218885Sdim clEnumValN(CompileCustom, "compile-custom", 52218885Sdim "Use -compile-command to define a command to " 53218885Sdim "compile the bitcode. Useful to avoid linking."), 54193323Sed clEnumValN(Custom, "run-custom", 55193323Sed "Use -exec-command to define a command to execute " 56193323Sed "the bitcode. Useful for cross-compilation."), 57193323Sed clEnumValEnd), 58193323Sed cl::init(AutoPick)); 59193323Sed 60193323Sed cl::opt<OutputType> 61193323Sed SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"), 62198090Srdivacky cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"), 63198090Srdivacky clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"), 64198090Srdivacky clEnumValN(Custom, "safe-run-custom", 65198090Srdivacky "Use -exec-command to define a command to execute " 66198090Srdivacky "the bitcode. Useful for cross-compilation."), 67198090Srdivacky clEnumValEnd), 68193323Sed cl::init(AutoPick)); 69193323Sed 70193323Sed cl::opt<std::string> 71193323Sed SafeInterpreterPath("safe-path", 72198090Srdivacky cl::desc("Specify the path to the \"safe\" backend program"), 73198090Srdivacky cl::init("")); 74193323Sed 75193323Sed cl::opt<bool> 76193323Sed AppendProgramExitCode("append-exit-code", 77193323Sed cl::desc("Append the exit code to the output so it gets diff'd too"), 78193323Sed cl::init(false)); 79193323Sed 80193323Sed cl::opt<std::string> 81193323Sed InputFile("input", cl::init("/dev/null"), 82193323Sed cl::desc("Filename to pipe in as stdin (default: /dev/null)")); 83193323Sed 84193323Sed cl::list<std::string> 85193323Sed AdditionalSOs("additional-so", 86193323Sed cl::desc("Additional shared objects to load " 87193323Sed "into executing programs")); 88193323Sed 89193323Sed cl::list<std::string> 90218885Sdim AdditionalLinkerArgs("Xlinker", 91193323Sed cl::desc("Additional arguments to pass to the linker")); 92193323Sed 93193323Sed cl::opt<std::string> 94218885Sdim CustomCompileCommand("compile-command", cl::init("llc"), 95218885Sdim cl::desc("Command to compile the bitcode (use with -compile-custom) " 96218885Sdim "(default: llc)")); 97218885Sdim 98218885Sdim cl::opt<std::string> 99193323Sed CustomExecCommand("exec-command", cl::init("simulate"), 100193323Sed cl::desc("Command to execute the bitcode (use with -run-custom) " 101193323Sed "(default: simulate)")); 102193323Sed} 103193323Sed 104193323Sednamespace llvm { 105193323Sed // Anything specified after the --args option are taken as arguments to the 106193323Sed // program being debugged. 107193323Sed cl::list<std::string> 108193323Sed InputArgv("args", cl::Positional, cl::desc("<program arguments>..."), 109193323Sed cl::ZeroOrMore, cl::PositionalEatsArgs); 110198090Srdivacky 111198090Srdivacky cl::opt<std::string> 112198090Srdivacky OutputPrefix("output-prefix", cl::init("bugpoint"), 113198090Srdivacky cl::desc("Prefix to use for outputs (default: 'bugpoint')")); 114193323Sed} 115193323Sed 116193323Sednamespace { 117193323Sed cl::list<std::string> 118193323Sed ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."), 119193323Sed cl::ZeroOrMore, cl::PositionalEatsArgs); 120193323Sed 121193323Sed cl::list<std::string> 122193323Sed SafeToolArgv("safe-tool-args", cl::Positional, 123193323Sed cl::desc("<safe-tool arguments>..."), 124193323Sed cl::ZeroOrMore, cl::PositionalEatsArgs); 125193323Sed 126208599Srdivacky cl::opt<std::string> 127218885Sdim GCCBinary("gcc", cl::init("gcc"), 128208599Srdivacky cl::desc("The gcc binary to use. (default 'gcc')")); 129208599Srdivacky 130193323Sed cl::list<std::string> 131193323Sed GCCToolArgv("gcc-tool-args", cl::Positional, 132193323Sed cl::desc("<gcc-tool arguments>..."), 133193323Sed cl::ZeroOrMore, cl::PositionalEatsArgs); 134193323Sed} 135193323Sed 136193323Sed//===----------------------------------------------------------------------===// 137193323Sed// BugDriver method implementation 138193323Sed// 139193323Sed 140193323Sed/// initializeExecutionEnvironment - This method is used to set up the 141193323Sed/// environment for executing LLVM programs. 142193323Sed/// 143193323Sedbool BugDriver::initializeExecutionEnvironment() { 144198090Srdivacky outs() << "Initializing execution environment: "; 145193323Sed 146193323Sed // Create an instance of the AbstractInterpreter interface as specified on 147193323Sed // the command line 148193323Sed SafeInterpreter = 0; 149193323Sed std::string Message; 150193323Sed 151193323Sed switch (InterpreterSel) { 152193323Sed case AutoPick: 153193323Sed if (!Interpreter) { 154193323Sed InterpreterSel = RunJIT; 155193323Sed Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, 156193323Sed &ToolArgv); 157193323Sed } 158193323Sed if (!Interpreter) { 159193323Sed InterpreterSel = RunLLC; 160193323Sed Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, 161218885Sdim GCCBinary, &ToolArgv, 162208599Srdivacky &GCCToolArgv); 163193323Sed } 164193323Sed if (!Interpreter) { 165193323Sed InterpreterSel = RunLLI; 166193323Sed Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, 167193323Sed &ToolArgv); 168193323Sed } 169193323Sed if (!Interpreter) { 170193323Sed InterpreterSel = AutoPick; 171193323Sed Message = "Sorry, I can't automatically select an interpreter!\n"; 172193323Sed } 173193323Sed break; 174193323Sed case RunLLI: 175193323Sed Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, 176193323Sed &ToolArgv); 177193323Sed break; 178193323Sed case RunLLC: 179205218Srdivacky case RunLLCIA: 180193323Sed case LLC_Safe: 181193323Sed Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, 182218885Sdim GCCBinary, &ToolArgv, 183208599Srdivacky &GCCToolArgv, 184205218Srdivacky InterpreterSel == RunLLCIA); 185193323Sed break; 186193323Sed case RunJIT: 187193323Sed Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, 188193323Sed &ToolArgv); 189193323Sed break; 190218885Sdim case CompileCustom: 191218885Sdim Interpreter = 192218885Sdim AbstractInterpreter::createCustomCompiler(Message, CustomCompileCommand); 193218885Sdim break; 194193323Sed case Custom: 195218885Sdim Interpreter = 196218885Sdim AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); 197193323Sed break; 198193323Sed } 199193323Sed if (!Interpreter) 200198090Srdivacky errs() << Message; 201193323Sed else // Display informational messages on stdout instead of stderr 202198090Srdivacky outs() << Message; 203193323Sed 204193323Sed std::string Path = SafeInterpreterPath; 205193323Sed if (Path.empty()) 206193323Sed Path = getToolName(); 207193323Sed std::vector<std::string> SafeToolArgs = SafeToolArgv; 208193323Sed switch (SafeInterpreterSel) { 209193323Sed case AutoPick: 210193323Sed // In "llc-safe" mode, default to using LLC as the "safe" backend. 211193323Sed if (!SafeInterpreter && 212193323Sed InterpreterSel == LLC_Safe) { 213193323Sed SafeInterpreterSel = RunLLC; 214193323Sed SafeToolArgs.push_back("--relocation-model=pic"); 215198090Srdivacky SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, 216218885Sdim GCCBinary, 217193323Sed &SafeToolArgs, 218193323Sed &GCCToolArgv); 219193323Sed } 220193323Sed 221193323Sed if (!SafeInterpreter && 222193323Sed InterpreterSel != RunLLC && 223193323Sed InterpreterSel != RunJIT) { 224193323Sed SafeInterpreterSel = RunLLC; 225193323Sed SafeToolArgs.push_back("--relocation-model=pic"); 226198090Srdivacky SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, 227218885Sdim GCCBinary, 228193323Sed &SafeToolArgs, 229193323Sed &GCCToolArgv); 230193323Sed } 231193323Sed if (!SafeInterpreter) { 232193323Sed SafeInterpreterSel = AutoPick; 233249423Sdim Message = "Sorry, I can't automatically select a safe interpreter!\n"; 234193323Sed } 235193323Sed break; 236193323Sed case RunLLC: 237205218Srdivacky case RunLLCIA: 238193323Sed SafeToolArgs.push_back("--relocation-model=pic"); 239198090Srdivacky SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, 240208599Srdivacky GCCBinary, &SafeToolArgs, 241205218Srdivacky &GCCToolArgv, 242205218Srdivacky SafeInterpreterSel == RunLLCIA); 243193323Sed break; 244193323Sed case Custom: 245218885Sdim SafeInterpreter = 246218885Sdim AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); 247193323Sed break; 248193323Sed default: 249193323Sed Message = "Sorry, this back-end is not supported by bugpoint as the " 250193323Sed "\"safe\" backend right now!\n"; 251193323Sed break; 252193323Sed } 253198090Srdivacky if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); } 254218885Sdim 255208599Srdivacky gcc = GCC::create(Message, GCCBinary, &GCCToolArgv); 256198090Srdivacky if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); } 257193323Sed 258193323Sed // If there was an error creating the selected interpreter, quit with error. 259193323Sed return Interpreter == 0; 260193323Sed} 261193323Sed 262207618Srdivacky/// compileProgram - Try to compile the specified module, returning false and 263207618Srdivacky/// setting Error if an error occurs. This is used for code generation 264207618Srdivacky/// crash testing. 265193323Sed/// 266212793Sdimvoid BugDriver::compileProgram(Module *M, std::string *Error) const { 267193323Sed // Emit the program to a bitcode file... 268263508Sdim SmallString<128> BitcodeFile; 269263508Sdim int BitcodeFD; 270263508Sdim error_code EC = sys::fs::createUniqueFile( 271263508Sdim OutputPrefix + "-test-program-%%%%%%%.bc", BitcodeFD, BitcodeFile); 272263508Sdim if (EC) { 273263508Sdim errs() << ToolName << ": Error making unique filename: " << EC.message() 274198090Srdivacky << "\n"; 275193323Sed exit(1); 276193323Sed } 277263508Sdim if (writeProgramToFile(BitcodeFile.str(), BitcodeFD, M)) { 278263508Sdim errs() << ToolName << ": Error emitting bitcode to file '" << BitcodeFile 279263508Sdim << "'!\n"; 280193323Sed exit(1); 281193323Sed } 282193323Sed 283207618Srdivacky // Remove the temporary bitcode file when we are done. 284221337Sdim FileRemover BitcodeFileRemover(BitcodeFile.str(), !SaveTemps); 285193323Sed 286193323Sed // Actually compile the program! 287208599Srdivacky Interpreter->compileProgram(BitcodeFile.str(), Error, Timeout, MemoryLimit); 288193323Sed} 289193323Sed 290193323Sed 291193323Sed/// executeProgram - This method runs "Program", capturing the output of the 292193323Sed/// program to a file, returning the filename of the file. A recommended 293193323Sed/// filename may be optionally specified. 294193323Sed/// 295212793Sdimstd::string BugDriver::executeProgram(const Module *Program, 296212793Sdim std::string OutputFile, 297193323Sed std::string BitcodeFile, 298193323Sed const std::string &SharedObj, 299193323Sed AbstractInterpreter *AI, 300212793Sdim std::string *Error) const { 301193323Sed if (AI == 0) AI = Interpreter; 302193323Sed assert(AI && "Interpreter should have been created already!"); 303193323Sed bool CreatedBitcode = false; 304193323Sed if (BitcodeFile.empty()) { 305193323Sed // Emit the program to a bitcode file... 306263508Sdim SmallString<128> UniqueFilename; 307263508Sdim int UniqueFD; 308263508Sdim error_code EC = sys::fs::createUniqueFile( 309263508Sdim OutputPrefix + "-test-program-%%%%%%%.bc", UniqueFD, UniqueFilename); 310263508Sdim if (EC) { 311198090Srdivacky errs() << ToolName << ": Error making unique filename: " 312263508Sdim << EC.message() << "!\n"; 313193323Sed exit(1); 314193323Sed } 315263508Sdim BitcodeFile = UniqueFilename.str(); 316193323Sed 317263508Sdim if (writeProgramToFile(BitcodeFile, UniqueFD, Program)) { 318198090Srdivacky errs() << ToolName << ": Error emitting bitcode to file '" 319198090Srdivacky << BitcodeFile << "'!\n"; 320193323Sed exit(1); 321193323Sed } 322193323Sed CreatedBitcode = true; 323193323Sed } 324193323Sed 325193323Sed // Remove the temporary bitcode file when we are done. 326263508Sdim std::string BitcodePath(BitcodeFile); 327263508Sdim FileRemover BitcodeFileRemover(BitcodePath, 328221337Sdim CreatedBitcode && !SaveTemps); 329193323Sed 330263508Sdim if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output-%%%%%%%"; 331193323Sed 332193323Sed // Check to see if this is a valid output filename... 333263508Sdim SmallString<128> UniqueFile; 334263508Sdim error_code EC = sys::fs::createUniqueFile(OutputFile, UniqueFile); 335263508Sdim if (EC) { 336198090Srdivacky errs() << ToolName << ": Error making unique filename: " 337263508Sdim << EC.message() << "\n"; 338193323Sed exit(1); 339193323Sed } 340263508Sdim OutputFile = UniqueFile.str(); 341193323Sed 342193323Sed // Figure out which shared objects to run, if any. 343193323Sed std::vector<std::string> SharedObjs(AdditionalSOs); 344193323Sed if (!SharedObj.empty()) 345193323Sed SharedObjs.push_back(SharedObj); 346193323Sed 347207618Srdivacky int RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, OutputFile, 348207618Srdivacky Error, AdditionalLinkerArgs, SharedObjs, 349193323Sed Timeout, MemoryLimit); 350207618Srdivacky if (!Error->empty()) 351207618Srdivacky return OutputFile; 352193323Sed 353193323Sed if (RetVal == -1) { 354198090Srdivacky errs() << "<timeout>"; 355193323Sed static bool FirstTimeout = true; 356193323Sed if (FirstTimeout) { 357198090Srdivacky outs() << "\n" 358193323Sed "*** Program execution timed out! This mechanism is designed to handle\n" 359193323Sed " programs stuck in infinite loops gracefully. The -timeout option\n" 360193323Sed " can be used to change the timeout threshold or disable it completely\n" 361193323Sed " (with -timeout=0). This message is only displayed once.\n"; 362193323Sed FirstTimeout = false; 363193323Sed } 364193323Sed } 365193323Sed 366193323Sed if (AppendProgramExitCode) { 367193323Sed std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 368193323Sed outFile << "exit " << RetVal << '\n'; 369193323Sed outFile.close(); 370193323Sed } 371193323Sed 372193323Sed // Return the filename we captured the output to. 373193323Sed return OutputFile; 374193323Sed} 375193323Sed 376193323Sed/// executeProgramSafely - Used to create reference output with the "safe" 377193323Sed/// backend, if reference output is not provided. 378193323Sed/// 379212793Sdimstd::string BugDriver::executeProgramSafely(const Module *Program, 380212793Sdim std::string OutputFile, 381212793Sdim std::string *Error) const { 382212793Sdim return executeProgram(Program, OutputFile, "", "", SafeInterpreter, Error); 383193323Sed} 384193323Sed 385207618Srdivackystd::string BugDriver::compileSharedObject(const std::string &BitcodeFile, 386207618Srdivacky std::string &Error) { 387193323Sed assert(Interpreter && "Interpreter should have been created already!"); 388263508Sdim std::string OutputFile; 389193323Sed 390193323Sed // Using the known-good backend. 391207618Srdivacky GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile, 392207618Srdivacky Error); 393207618Srdivacky if (!Error.empty()) 394207618Srdivacky return ""; 395193323Sed 396193323Sed std::string SharedObjectFile; 397263508Sdim bool Failure = gcc->MakeSharedObject(OutputFile, FT, SharedObjectFile, 398207618Srdivacky AdditionalLinkerArgs, Error); 399207618Srdivacky if (!Error.empty()) 400207618Srdivacky return ""; 401207618Srdivacky if (Failure) 402193323Sed exit(1); 403193323Sed 404193323Sed // Remove the intermediate C file 405263508Sdim sys::fs::remove(OutputFile); 406193323Sed 407193323Sed return "./" + SharedObjectFile; 408193323Sed} 409193323Sed 410193323Sed/// createReferenceFile - calls compileProgram and then records the output 411218885Sdim/// into ReferenceOutputFile. Returns true if reference file created, false 412193323Sed/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE 413193323Sed/// this function. 414193323Sed/// 415193323Sedbool BugDriver::createReferenceFile(Module *M, const std::string &Filename) { 416207618Srdivacky std::string Error; 417207618Srdivacky compileProgram(Program, &Error); 418207618Srdivacky if (!Error.empty()) 419193323Sed return false; 420207618Srdivacky 421212793Sdim ReferenceOutputFile = executeProgramSafely(Program, Filename, &Error); 422207618Srdivacky if (!Error.empty()) { 423207618Srdivacky errs() << Error; 424193323Sed if (Interpreter != SafeInterpreter) { 425198090Srdivacky errs() << "*** There is a bug running the \"safe\" backend. Either" 426234353Sdim << " debug it (for example with the -run-jit bugpoint option," 427234353Sdim << " if JIT is being used as the \"safe\" backend), or fix the" 428198090Srdivacky << " error some other way.\n"; 429193323Sed } 430193323Sed return false; 431193323Sed } 432207618Srdivacky outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n"; 433193323Sed return true; 434193323Sed} 435193323Sed 436193323Sed/// diffProgram - This method executes the specified module and diffs the 437193323Sed/// output against the file specified by ReferenceOutputFile. If the output 438207618Srdivacky/// is different, 1 is returned. If there is a problem with the code 439223013Sdim/// generator (e.g., llc crashes), this will set ErrMsg. 440193323Sed/// 441212793Sdimbool BugDriver::diffProgram(const Module *Program, 442212793Sdim const std::string &BitcodeFile, 443193323Sed const std::string &SharedObject, 444207618Srdivacky bool RemoveBitcode, 445212793Sdim std::string *ErrMsg) const { 446193323Sed // Execute the program, generating an output file... 447263508Sdim std::string Output( 448263508Sdim executeProgram(Program, "", BitcodeFile, SharedObject, 0, ErrMsg)); 449207618Srdivacky if (!ErrMsg->empty()) 450207618Srdivacky return false; 451193323Sed 452193323Sed std::string Error; 453193323Sed bool FilesDifferent = false; 454263508Sdim if (int Diff = DiffFilesWithTolerance(ReferenceOutputFile, 455263508Sdim Output, 456193323Sed AbsTolerance, RelTolerance, &Error)) { 457193323Sed if (Diff == 2) { 458198090Srdivacky errs() << "While diffing output: " << Error << '\n'; 459193323Sed exit(1); 460193323Sed } 461193323Sed FilesDifferent = true; 462193323Sed } 463198090Srdivacky else { 464198090Srdivacky // Remove the generated output if there are no differences. 465263508Sdim sys::fs::remove(Output); 466198090Srdivacky } 467193323Sed 468193323Sed // Remove the bitcode file if we are supposed to. 469193323Sed if (RemoveBitcode) 470263508Sdim sys::fs::remove(BitcodeFile); 471193323Sed return FilesDifferent; 472193323Sed} 473193323Sed 474193323Sedbool BugDriver::isExecutingJIT() { 475193323Sed return InterpreterSel == RunJIT; 476193323Sed} 477193323Sed 478