ExecutionDriver.cpp revision 51c5a286bae5ad27ddc49602f44b7ea7253a4cc9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file was developed by the LLVM research group and is distributed under 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the University of Illinois Open Source License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)// This file contains code used to execute the program utilizing one of the 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// various ways of running LLVM bytecode. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "BugDriver.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ToolRunner.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "llvm/Support/CommandLine.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "llvm/Support/Debug.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "llvm/Support/FileUtilities.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/Support/SystemUtils.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fstream> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iostream> 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace llvm; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OutputType - Allow the user to specify the way code should be run, to test 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for miscompilation. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum OutputType { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoPick, RunLLI, RunJIT, RunLLC, RunCBE 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<double> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"), 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::init(0.0)); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<double> 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::init(0.0)); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<OutputType> 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InterpreterSel(cl::desc("Specify how LLVM code should be executed:"), 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cl::values(clEnumValN(AutoPick, "auto", "Use best guess"), 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) clEnumValN(RunLLI, "run-int", 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Execute with the interpreter"), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clEnumValN(RunJIT, "run-jit", "Execute with JIT"), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clEnumValN(RunLLC, "run-llc", "Compile with LLC"), 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clEnumValEnd), 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cl::init(AutoPick)); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<bool> 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckProgramExitCode("check-exit-code", 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::desc("Assume nonzero exit code is failure (default on)"), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::init(true)); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::opt<std::string> 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InputFile("input", cl::init("/dev/null"), 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cl::desc("Filename to pipe in as stdin (default: /dev/null)")); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cl::list<std::string> 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AdditionalSOs("additional-so", 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cl::desc("Additional shared objects to load " 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "into executing programs")); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cl::list<std::string> 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AdditionalLinkerArgs("Xlinker", 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::desc("Additional arguments to pass to the linker")); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace llvm { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Anything specified after the --args option are taken as arguments to the 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // program being debugged. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::list<std::string> 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InputArgv("args", cl::Positional, cl::desc("<program arguments>..."), 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::ZeroOrMore, cl::PositionalEatsArgs); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::list<std::string> 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."), 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::ZeroOrMore, cl::PositionalEatsArgs); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BugDriver method implementation 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// initializeExecutionEnvironment - This method is used to set up the 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// environment for executing LLVM programs. 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool BugDriver::initializeExecutionEnvironment() { 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::cout << "Initializing execution environment: "; 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Create an instance of the AbstractInterpreter interface as specified on 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the command line 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cbe = 0; 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string Message; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (InterpreterSel) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case AutoPick: 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterpreterSel = RunCBE; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = cbe = AbstractInterpreter::createCBE(getToolName(), Message, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Interpreter) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterpreterSel = RunJIT; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &ToolArgv); 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!Interpreter) { 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) InterpreterSel = RunLLC; 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &ToolArgv); 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!Interpreter) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterpreterSel = RunLLI; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Interpreter) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterpreterSel = AutoPick; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Message = "Sorry, I can't automatically select an interpreter!\n"; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RunLLI: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Interpreter = AbstractInterpreter::createLLI(getToolName(), Message, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RunLLC: 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RunJIT: 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Interpreter = AbstractInterpreter::createJIT(getToolName(), Message, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RunCBE: 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Interpreter = cbe = AbstractInterpreter::createCBE(getToolName(), Message, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ToolArgv); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Message = "Sorry, this back-end is not supported by bugpoint right now!\n"; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << Message; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize auxiliary tools for debugging 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cbe) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cbe = AbstractInterpreter::createCBE(getToolName(), Message, &ToolArgv); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cbe) { std::cout << Message << "\nExiting.\n"; exit(1); } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gcc = GCC::create(getToolName(), Message); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gcc) { std::cout << Message << "\nExiting.\n"; exit(1); } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there was an error creating the selected interpreter, quit with error. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Interpreter == 0; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// compileProgram - Try to compile the specified module, throwing an exception 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// if an error occurs, or returning normally if not. This is used for code 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// generation crash testing. 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void BugDriver::compileProgram(Module *M) { 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Emit the program to a bytecode file... 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sys::Path BytecodeFile ("bugpoint-test-program.bc"); 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string ErrMsg; 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (BytecodeFile.makeUnique(true,&ErrMsg)) { 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::cerr << ToolName << ": Error making unique filename: " << ErrMsg 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n"; 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch exit(1); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (writeProgramToFile(BytecodeFile.toString(), M)) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << ToolName << ": Error emitting bytecode to file '" 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << BytecodeFile << "'!\n"; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit(1); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Remove the temporary bytecode file when we are done. 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FileRemover BytecodeFileRemover(BytecodeFile); 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Actually compile the program! 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Interpreter->compileProgram(BytecodeFile.toString()); 181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// executeProgram - This method runs "Program", capturing the output of the 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/// program to a file, returning the filename of the file. A recommended 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// filename may be optionally specified. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string BugDriver::executeProgram(std::string OutputFile, 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string BytecodeFile, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string &SharedObj, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AbstractInterpreter *AI, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool *ProgramExitedNonzero) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (AI == 0) AI = Interpreter; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(AI && "Interpreter should have been created already!"); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool CreatedBytecode = false; 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string ErrMsg; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (BytecodeFile.empty()) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Emit the program to a bytecode file... 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sys::Path uniqueFilename("bugpoint-test-program.bc"); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (uniqueFilename.makeUnique(true, &ErrMsg)) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << ToolName << ": Error making unique filename: " 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ErrMsg << "!\n"; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit(1); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BytecodeFile = uniqueFilename.toString(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (writeProgramToFile(BytecodeFile, Program)) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << ToolName << ": Error emitting bytecode to file '" 209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << BytecodeFile << "'!\n"; 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) exit(1); 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CreatedBytecode = true; 213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Remove the temporary bytecode file when we are done. 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sys::Path BytecodePath (BytecodeFile); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileRemover BytecodeFileRemover(BytecodePath, CreatedBytecode); 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (OutputFile.empty()) OutputFile = "bugpoint-execution-output"; 220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Check to see if this is a valid output filename... 222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sys::Path uniqueFile(OutputFile); 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (uniqueFile.makeUnique(true, &ErrMsg)) { 224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::cerr << ToolName << ": Error making unique filename: " 225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << ErrMsg << "\n"; 226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) exit(1); 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch OutputFile = uniqueFile.toString(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Figure out which shared objects to run, if any. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> SharedObjs(AdditionalSOs); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SharedObj.empty()) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SharedObjs.push_back(SharedObj); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is an LLC or CBE run, then the GCC compiler might get run to 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compile the program. If so, we should pass the user's -Xlinker options 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as the GCCArgs. 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int RetVal = 0; 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (InterpreterSel == RunLLC || InterpreterSel == RunCBE) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutputFile, AdditionalLinkerArgs, SharedObjs, 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Timeout); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutputFile, std::vector<std::string>(), 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SharedObjs, Timeout); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (RetVal == -1) { 250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::cerr << "<timeout>"; 251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static bool FirstTimeout = true; 252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (FirstTimeout) { 253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::cout << "\n" 254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "*** Program execution timed out! This mechanism is designed to handle\n" 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) " programs stuck in infinite loops gracefully. The -timeout option\n" 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) " can be used to change the timeout threshold or disable it completely\n" 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " (with -timeout=0). This message is only displayed once.\n"; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FirstTimeout = false; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ProgramExitedNonzero != 0) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ProgramExitedNonzero = (RetVal != 0); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return the filename we captured the output to. 266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return OutputFile; 267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// executeProgramWithCBE - Used to create reference output with the C 270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// backend, if reference output is not provided. 271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// 272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::string BugDriver::executeProgramWithCBE(std::string OutputFile) { 273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool ProgramExitedNonzero; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string outFN = executeProgram(OutputFile, "", "", 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (AbstractInterpreter*)cbe, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ProgramExitedNonzero); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ProgramExitedNonzero) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Warning: While generating reference output, program exited with\n" 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "non-zero exit code. This will NOT be treated as a failure.\n"; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckProgramExitCode = false; 2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return outFN; 2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::string BugDriver::compileSharedObject(const std::string &BytecodeFile) { 2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) assert(Interpreter && "Interpreter should have been created already!"); 2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sys::Path OutputCFile; 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Using CBE 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cbe->OutputC(BytecodeFile, OutputCFile); 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 /* This is an alternative, as yet unimplemented */ 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Using LLC 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string Message; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LLC *llc = createLLCtool(Message); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (llc->OutputAsm(BytecodeFile, OutputFile)) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << "Could not generate asm code with `llc', exiting.\n"; 299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) exit(1); 300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string SharedObjectFile; 304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (gcc->MakeSharedObject(OutputCFile.toString(), GCC::CFile, 305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SharedObjectFile, AdditionalLinkerArgs)) 306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) exit(1); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Remove the intermediate C file 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutputCFile.eraseFromDisk(); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "./" + SharedObjectFile; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// createReferenceFile - calls compileProgram and then records the output 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// into ReferenceOutputFile. Returns true if reference file created, false 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// this function. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BugDriver::createReferenceFile(Module *M, const std::string &Filename){ 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try { 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compileProgram(Program); 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } catch (ToolExecutionError &TEE) { 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReferenceOutputFile = executeProgramWithCBE(Filename); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cout << "Reference output is: " << ReferenceOutputFile << "\n\n"; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } catch (ToolExecutionError &TEE) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << TEE.what(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Interpreter != cbe) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << "*** There is a bug running the C backend. Either debug" 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " it (use the -run-cbe bugpoint option), or fix the error" 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " some other way.\n"; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// diffProgram - This method executes the specified module and diffs the 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// output against the file specified by ReferenceOutputFile. If the output 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// is different, true is returned. If there is a problem with the code 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// generator (e.g., llc crashes), this will throw an exception. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BugDriver::diffProgram(const std::string &BytecodeFile, 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string &SharedObject, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool RemoveBytecode) { 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool ProgramExitedNonzero; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Execute the program, generating an output file... 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys::Path Output(executeProgram("", BytecodeFile, SharedObject, 0, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ProgramExitedNonzero)); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we're checking the program exit code, assume anything nonzero is bad. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CheckProgramExitCode && ProgramExitedNonzero) { 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Output.eraseFromDisk(); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (RemoveBytecode) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys::Path(BytecodeFile).eraseFromDisk(); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string Error; 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool FilesDifferent = false; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (int Diff = DiffFilesWithTolerance(sys::Path(ReferenceOutputFile), 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sys::Path(Output.toString()), 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AbsTolerance, RelTolerance, &Error)) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Diff == 2) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << "While diffing output: " << Error << '\n'; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit(1); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilesDifferent = true; 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the generated output. 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Output.eraseFromDisk(); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove the bytecode file if we are supposed to. 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (RemoveBytecode) 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sys::Path(BytecodeFile).eraseFromDisk(); 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FilesDifferent; 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BugDriver::isExecutingJIT() { 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return InterpreterSel == RunJIT; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)