ExecutionDriver.cpp revision f73311bb646bf970806ba7caba220e6bffff7b49
1//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===// 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 contains code used to execute the program utilizing one of the 11// various ways of running LLVM bitcode. 12// 13//===----------------------------------------------------------------------===// 14 15#include "BugDriver.h" 16#include "ToolRunner.h" 17#include "llvm/Support/CommandLine.h" 18#include "llvm/Support/Debug.h" 19#include "llvm/Support/FileUtilities.h" 20#include "llvm/Support/SystemUtils.h" 21#include "llvm/Support/raw_ostream.h" 22#include <fstream> 23 24using namespace llvm; 25 26namespace { 27 // OutputType - Allow the user to specify the way code should be run, to test 28 // for miscompilation. 29 // 30 enum OutputType { 31 AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, RunCBE, CBE_bug, LLC_Safe, 32 CompileCustom, Custom 33 }; 34 35 cl::opt<double> 36 AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"), 37 cl::init(0.0)); 38 cl::opt<double> 39 RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"), 40 cl::init(0.0)); 41 42 cl::opt<OutputType> 43 InterpreterSel(cl::desc("Specify the \"test\" i.e. suspect back-end:"), 44 cl::values(clEnumValN(AutoPick, "auto", "Use best guess"), 45 clEnumValN(RunLLI, "run-int", 46 "Execute with the interpreter"), 47 clEnumValN(RunJIT, "run-jit", "Execute with JIT"), 48 clEnumValN(RunLLC, "run-llc", "Compile with LLC"), 49 clEnumValN(RunLLCIA, "run-llc-ia", 50 "Compile with LLC with integrated assembler"), 51 clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), 52 clEnumValN(CBE_bug,"cbe-bug", "Find CBE bugs"), 53 clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"), 54 clEnumValN(CompileCustom, "compile-custom", 55 "Use -compile-command to define a command to " 56 "compile the bitcode. Useful to avoid linking."), 57 clEnumValN(Custom, "run-custom", 58 "Use -exec-command to define a command to execute " 59 "the bitcode. Useful for cross-compilation."), 60 clEnumValEnd), 61 cl::init(AutoPick)); 62 63 cl::opt<OutputType> 64 SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"), 65 cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"), 66 clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"), 67 clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"), 68 clEnumValN(Custom, "safe-run-custom", 69 "Use -exec-command to define a command to execute " 70 "the bitcode. Useful for cross-compilation."), 71 clEnumValEnd), 72 cl::init(AutoPick)); 73 74 cl::opt<std::string> 75 SafeInterpreterPath("safe-path", 76 cl::desc("Specify the path to the \"safe\" backend program"), 77 cl::init("")); 78 79 cl::opt<bool> 80 AppendProgramExitCode("append-exit-code", 81 cl::desc("Append the exit code to the output so it gets diff'd too"), 82 cl::init(false)); 83 84 cl::opt<std::string> 85 InputFile("input", cl::init("/dev/null"), 86 cl::desc("Filename to pipe in as stdin (default: /dev/null)")); 87 88 cl::list<std::string> 89 AdditionalSOs("additional-so", 90 cl::desc("Additional shared objects to load " 91 "into executing programs")); 92 93 cl::list<std::string> 94 AdditionalLinkerArgs("Xlinker", 95 cl::desc("Additional arguments to pass to the linker")); 96 97 cl::opt<std::string> 98 CustomCompileCommand("compile-command", cl::init("llc"), 99 cl::desc("Command to compile the bitcode (use with -compile-custom) " 100 "(default: llc)")); 101 102 cl::opt<std::string> 103 CustomExecCommand("exec-command", cl::init("simulate"), 104 cl::desc("Command to execute the bitcode (use with -run-custom) " 105 "(default: simulate)")); 106} 107 108namespace llvm { 109 // Anything specified after the --args option are taken as arguments to the 110 // program being debugged. 111 cl::list<std::string> 112 InputArgv("args", cl::Positional, cl::desc("<program arguments>..."), 113 cl::ZeroOrMore, cl::PositionalEatsArgs); 114 115 cl::opt<std::string> 116 OutputPrefix("output-prefix", cl::init("bugpoint"), 117 cl::desc("Prefix to use for outputs (default: 'bugpoint')")); 118} 119 120namespace { 121 cl::list<std::string> 122 ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."), 123 cl::ZeroOrMore, cl::PositionalEatsArgs); 124 125 cl::list<std::string> 126 SafeToolArgv("safe-tool-args", cl::Positional, 127 cl::desc("<safe-tool arguments>..."), 128 cl::ZeroOrMore, cl::PositionalEatsArgs); 129 130 cl::opt<std::string> 131 GCCBinary("gcc", cl::init("gcc"), 132 cl::desc("The gcc binary to use. (default 'gcc')")); 133 134 cl::list<std::string> 135 GCCToolArgv("gcc-tool-args", cl::Positional, 136 cl::desc("<gcc-tool arguments>..."), 137 cl::ZeroOrMore, cl::PositionalEatsArgs); 138} 139 140//===----------------------------------------------------------------------===// 141// BugDriver method implementation 142// 143 144/// initializeExecutionEnvironment - This method is used to set up the 145/// environment for executing LLVM programs. 146/// 147bool BugDriver::initializeExecutionEnvironment() { 148 outs() << "Initializing execution environment: "; 149 150 // Create an instance of the AbstractInterpreter interface as specified on 151 // the command line 152 SafeInterpreter = 0; 153 std::string Message; 154 155 switch (InterpreterSel) { 156 case AutoPick: 157 InterpreterSel = RunCBE; 158 Interpreter = 159 AbstractInterpreter::createCBE(getToolName(), Message, GCCBinary, 160 &ToolArgv, &GCCToolArgv); 161 if (!Interpreter) { 162 InterpreterSel = RunJIT; 163 Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, 164 &ToolArgv); 165 } 166 if (!Interpreter) { 167 InterpreterSel = RunLLC; 168 Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, 169 GCCBinary, &ToolArgv, 170 &GCCToolArgv); 171 } 172 if (!Interpreter) { 173 InterpreterSel = RunLLI; 174 Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, 175 &ToolArgv); 176 } 177 if (!Interpreter) { 178 InterpreterSel = AutoPick; 179 Message = "Sorry, I can't automatically select an interpreter!\n"; 180 } 181 break; 182 case RunLLI: 183 Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, 184 &ToolArgv); 185 break; 186 case RunLLC: 187 case RunLLCIA: 188 case LLC_Safe: 189 Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, 190 GCCBinary, &ToolArgv, 191 &GCCToolArgv, 192 InterpreterSel == RunLLCIA); 193 break; 194 case RunJIT: 195 Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, 196 &ToolArgv); 197 break; 198 case RunCBE: 199 case CBE_bug: 200 Interpreter = AbstractInterpreter::createCBE(getToolName(), Message, 201 GCCBinary, &ToolArgv, 202 &GCCToolArgv); 203 break; 204 case CompileCustom: 205 Interpreter = 206 AbstractInterpreter::createCustomCompiler(Message, CustomCompileCommand); 207 break; 208 case Custom: 209 Interpreter = 210 AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); 211 break; 212 default: 213 Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; 214 break; 215 } 216 if (!Interpreter) 217 errs() << Message; 218 else // Display informational messages on stdout instead of stderr 219 outs() << Message; 220 221 std::string Path = SafeInterpreterPath; 222 if (Path.empty()) 223 Path = getToolName(); 224 std::vector<std::string> SafeToolArgs = SafeToolArgv; 225 switch (SafeInterpreterSel) { 226 case AutoPick: 227 // In "cbe-bug" mode, default to using LLC as the "safe" backend. 228 if (!SafeInterpreter && 229 InterpreterSel == CBE_bug) { 230 SafeInterpreterSel = RunLLC; 231 SafeToolArgs.push_back("--relocation-model=pic"); 232 SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, 233 GCCBinary, 234 &SafeToolArgs, 235 &GCCToolArgv); 236 } 237 238 // In "llc-safe" mode, default to using LLC as the "safe" backend. 239 if (!SafeInterpreter && 240 InterpreterSel == LLC_Safe) { 241 SafeInterpreterSel = RunLLC; 242 SafeToolArgs.push_back("--relocation-model=pic"); 243 SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, 244 GCCBinary, 245 &SafeToolArgs, 246 &GCCToolArgv); 247 } 248 249 // Pick a backend that's different from the test backend. The JIT and 250 // LLC backends share a lot of code, so prefer to use the CBE as the 251 // safe back-end when testing them. 252 if (!SafeInterpreter && 253 InterpreterSel != RunCBE) { 254 SafeInterpreterSel = RunCBE; 255 SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, 256 GCCBinary, 257 &SafeToolArgs, 258 &GCCToolArgv); 259 } 260 if (!SafeInterpreter && 261 InterpreterSel != RunLLC && 262 InterpreterSel != RunJIT) { 263 SafeInterpreterSel = RunLLC; 264 SafeToolArgs.push_back("--relocation-model=pic"); 265 SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, 266 GCCBinary, 267 &SafeToolArgs, 268 &GCCToolArgv); 269 } 270 if (!SafeInterpreter) { 271 SafeInterpreterSel = AutoPick; 272 Message = "Sorry, I can't automatically select an interpreter!\n"; 273 } 274 break; 275 case RunLLC: 276 case RunLLCIA: 277 SafeToolArgs.push_back("--relocation-model=pic"); 278 SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, 279 GCCBinary, &SafeToolArgs, 280 &GCCToolArgv, 281 SafeInterpreterSel == RunLLCIA); 282 break; 283 case RunCBE: 284 SafeInterpreter = AbstractInterpreter::createCBE(Path.c_str(), Message, 285 GCCBinary, &SafeToolArgs, 286 &GCCToolArgv); 287 break; 288 case Custom: 289 SafeInterpreter = 290 AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand); 291 break; 292 default: 293 Message = "Sorry, this back-end is not supported by bugpoint as the " 294 "\"safe\" backend right now!\n"; 295 break; 296 } 297 if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); } 298 299 gcc = GCC::create(Message, GCCBinary, &GCCToolArgv); 300 if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); } 301 302 // If there was an error creating the selected interpreter, quit with error. 303 return Interpreter == 0; 304} 305 306/// compileProgram - Try to compile the specified module, returning false and 307/// setting Error if an error occurs. This is used for code generation 308/// crash testing. 309/// 310void BugDriver::compileProgram(Module *M, std::string *Error) const { 311 // Emit the program to a bitcode file... 312 sys::Path BitcodeFile (OutputPrefix + "-test-program.bc"); 313 std::string ErrMsg; 314 if (BitcodeFile.makeUnique(true, &ErrMsg)) { 315 errs() << ToolName << ": Error making unique filename: " << ErrMsg 316 << "\n"; 317 exit(1); 318 } 319 if (writeProgramToFile(BitcodeFile.str(), M)) { 320 errs() << ToolName << ": Error emitting bitcode to file '" 321 << BitcodeFile.str() << "'!\n"; 322 exit(1); 323 } 324 325 // Remove the temporary bitcode file when we are done. 326 FileRemover BitcodeFileRemover(BitcodeFile, !SaveTemps); 327 328 // Actually compile the program! 329 Interpreter->compileProgram(BitcodeFile.str(), Error, Timeout, MemoryLimit); 330} 331 332 333/// executeProgram - This method runs "Program", capturing the output of the 334/// program to a file, returning the filename of the file. A recommended 335/// filename may be optionally specified. 336/// 337std::string BugDriver::executeProgram(const Module *Program, 338 std::string OutputFile, 339 std::string BitcodeFile, 340 const std::string &SharedObj, 341 AbstractInterpreter *AI, 342 std::string *Error) const { 343 if (AI == 0) AI = Interpreter; 344 assert(AI && "Interpreter should have been created already!"); 345 bool CreatedBitcode = false; 346 std::string ErrMsg; 347 if (BitcodeFile.empty()) { 348 // Emit the program to a bitcode file... 349 sys::Path uniqueFilename(OutputPrefix + "-test-program.bc"); 350 if (uniqueFilename.makeUnique(true, &ErrMsg)) { 351 errs() << ToolName << ": Error making unique filename: " 352 << ErrMsg << "!\n"; 353 exit(1); 354 } 355 BitcodeFile = uniqueFilename.str(); 356 357 if (writeProgramToFile(BitcodeFile, Program)) { 358 errs() << ToolName << ": Error emitting bitcode to file '" 359 << BitcodeFile << "'!\n"; 360 exit(1); 361 } 362 CreatedBitcode = true; 363 } 364 365 // Remove the temporary bitcode file when we are done. 366 sys::Path BitcodePath(BitcodeFile); 367 FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps); 368 369 if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output"; 370 371 // Check to see if this is a valid output filename... 372 sys::Path uniqueFile(OutputFile); 373 if (uniqueFile.makeUnique(true, &ErrMsg)) { 374 errs() << ToolName << ": Error making unique filename: " 375 << ErrMsg << "\n"; 376 exit(1); 377 } 378 OutputFile = uniqueFile.str(); 379 380 // Figure out which shared objects to run, if any. 381 std::vector<std::string> SharedObjs(AdditionalSOs); 382 if (!SharedObj.empty()) 383 SharedObjs.push_back(SharedObj); 384 385 int RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, OutputFile, 386 Error, AdditionalLinkerArgs, SharedObjs, 387 Timeout, MemoryLimit); 388 if (!Error->empty()) 389 return OutputFile; 390 391 if (RetVal == -1) { 392 errs() << "<timeout>"; 393 static bool FirstTimeout = true; 394 if (FirstTimeout) { 395 outs() << "\n" 396 "*** Program execution timed out! This mechanism is designed to handle\n" 397 " programs stuck in infinite loops gracefully. The -timeout option\n" 398 " can be used to change the timeout threshold or disable it completely\n" 399 " (with -timeout=0). This message is only displayed once.\n"; 400 FirstTimeout = false; 401 } 402 } 403 404 if (AppendProgramExitCode) { 405 std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 406 outFile << "exit " << RetVal << '\n'; 407 outFile.close(); 408 } 409 410 // Return the filename we captured the output to. 411 return OutputFile; 412} 413 414/// executeProgramSafely - Used to create reference output with the "safe" 415/// backend, if reference output is not provided. 416/// 417std::string BugDriver::executeProgramSafely(const Module *Program, 418 std::string OutputFile, 419 std::string *Error) const { 420 return executeProgram(Program, OutputFile, "", "", SafeInterpreter, Error); 421} 422 423std::string BugDriver::compileSharedObject(const std::string &BitcodeFile, 424 std::string &Error) { 425 assert(Interpreter && "Interpreter should have been created already!"); 426 sys::Path OutputFile; 427 428 // Using the known-good backend. 429 GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile, 430 Error); 431 if (!Error.empty()) 432 return ""; 433 434 std::string SharedObjectFile; 435 bool Failure = gcc->MakeSharedObject(OutputFile.str(), FT, SharedObjectFile, 436 AdditionalLinkerArgs, Error); 437 if (!Error.empty()) 438 return ""; 439 if (Failure) 440 exit(1); 441 442 // Remove the intermediate C file 443 OutputFile.eraseFromDisk(); 444 445 return "./" + SharedObjectFile; 446} 447 448/// createReferenceFile - calls compileProgram and then records the output 449/// into ReferenceOutputFile. Returns true if reference file created, false 450/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE 451/// this function. 452/// 453bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) { 454 std::string Error; 455 compileProgram(Program, &Error); 456 if (!Error.empty()) 457 return false; 458 459 ReferenceOutputFile = executeProgramSafely(Program, Filename, &Error); 460 if (!Error.empty()) { 461 errs() << Error; 462 if (Interpreter != SafeInterpreter) { 463 errs() << "*** There is a bug running the \"safe\" backend. Either" 464 << " debug it (for example with the -run-cbe bugpoint option," 465 << " if CBE is being used as the \"safe\" backend), or fix the" 466 << " error some other way.\n"; 467 } 468 return false; 469 } 470 outs() << "\nReference output is: " << ReferenceOutputFile << "\n\n"; 471 return true; 472} 473 474/// diffProgram - This method executes the specified module and diffs the 475/// output against the file specified by ReferenceOutputFile. If the output 476/// is different, 1 is returned. If there is a problem with the code 477/// generator (e.g., llc crashes), this will return -1 and set Error. 478/// 479bool BugDriver::diffProgram(const Module *Program, 480 const std::string &BitcodeFile, 481 const std::string &SharedObject, 482 bool RemoveBitcode, 483 std::string *ErrMsg) const { 484 // Execute the program, generating an output file... 485 sys::Path Output(executeProgram(Program, "", BitcodeFile, SharedObject, 0, 486 ErrMsg)); 487 if (!ErrMsg->empty()) 488 return false; 489 490 std::string Error; 491 bool FilesDifferent = false; 492 if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile), 493 sys::Path(Output.str()), 494 AbsTolerance, RelTolerance, &Error)) { 495 if (Diff == 2) { 496 errs() << "While diffing output: " << Error << '\n'; 497 exit(1); 498 } 499 FilesDifferent = true; 500 } 501 else { 502 // Remove the generated output if there are no differences. 503 Output.eraseFromDisk(); 504 } 505 506 // Remove the bitcode file if we are supposed to. 507 if (RemoveBitcode) 508 sys::Path(BitcodeFile).eraseFromDisk(); 509 return FilesDifferent; 510} 511 512bool BugDriver::isExecutingJIT() { 513 return InterpreterSel == RunJIT; 514} 515 516