ExecutionDriver.cpp revision 4a10645c70199c8d8567fbc46312158c419720ab
14a10645c70199c8d8567fbc46312158c419720abChris Lattner//===- ExecutionDriver.cpp - Allow execution of LLVM program --------------===// 24a10645c70199c8d8567fbc46312158c419720abChris Lattner// 34a10645c70199c8d8567fbc46312158c419720abChris Lattner// This file contains code used to execute the program utilizing one of the 44a10645c70199c8d8567fbc46312158c419720abChris Lattner// various ways of running LLVM bytecode. 54a10645c70199c8d8567fbc46312158c419720abChris Lattner// 64a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===// 74a10645c70199c8d8567fbc46312158c419720abChris Lattner 84a10645c70199c8d8567fbc46312158c419720abChris Lattner/* 94a10645c70199c8d8567fbc46312158c419720abChris LattnerBUGPOINT NOTES: 104a10645c70199c8d8567fbc46312158c419720abChris Lattner 114a10645c70199c8d8567fbc46312158c419720abChris Lattner1. Bugpoint should not leave any files behind if the program works properly 124a10645c70199c8d8567fbc46312158c419720abChris Lattner2. There should be an option to specify the program name, which specifies a 134a10645c70199c8d8567fbc46312158c419720abChris Lattner unique string to put into output files. This allows operation in the 144a10645c70199c8d8567fbc46312158c419720abChris Lattner SingleSource directory f.e. Default to the first input filename. 154a10645c70199c8d8567fbc46312158c419720abChris Lattner*/ 164a10645c70199c8d8567fbc46312158c419720abChris Lattner 174a10645c70199c8d8567fbc46312158c419720abChris Lattner#include "BugDriver.h" 184a10645c70199c8d8567fbc46312158c419720abChris Lattner#include "SystemUtils.h" 194a10645c70199c8d8567fbc46312158c419720abChris Lattner#include "Support/CommandLine.h" 204a10645c70199c8d8567fbc46312158c419720abChris Lattner#include <fstream> 214a10645c70199c8d8567fbc46312158c419720abChris Lattner 224a10645c70199c8d8567fbc46312158c419720abChris Lattnernamespace { 234a10645c70199c8d8567fbc46312158c419720abChris Lattner // OutputType - Allow the user to specify the way code should be run, to test 244a10645c70199c8d8567fbc46312158c419720abChris Lattner // for miscompilation. 254a10645c70199c8d8567fbc46312158c419720abChris Lattner // 264a10645c70199c8d8567fbc46312158c419720abChris Lattner enum OutputType { 274a10645c70199c8d8567fbc46312158c419720abChris Lattner RunLLI, RunJIT, RunLLC, RunCBE 284a10645c70199c8d8567fbc46312158c419720abChris Lattner }; 294a10645c70199c8d8567fbc46312158c419720abChris Lattner cl::opt<OutputType> 304a10645c70199c8d8567fbc46312158c419720abChris Lattner InterpreterSel(cl::desc("Specify how LLVM code should be executed:"), 314a10645c70199c8d8567fbc46312158c419720abChris Lattner cl::values(clEnumValN(RunLLI, "run-lli", "Execute with LLI"), 324a10645c70199c8d8567fbc46312158c419720abChris Lattner clEnumValN(RunJIT, "run-jit", "Execute with JIT"), 334a10645c70199c8d8567fbc46312158c419720abChris Lattner clEnumValN(RunLLC, "run-llc", "Compile with LLC"), 344a10645c70199c8d8567fbc46312158c419720abChris Lattner clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), 354a10645c70199c8d8567fbc46312158c419720abChris Lattner 0)); 364a10645c70199c8d8567fbc46312158c419720abChris Lattner} 374a10645c70199c8d8567fbc46312158c419720abChris Lattner 384a10645c70199c8d8567fbc46312158c419720abChris Lattner/// AbstractInterpreter Class - Subclasses of this class are used to execute 394a10645c70199c8d8567fbc46312158c419720abChris Lattner/// LLVM bytecode in a variety of ways. This abstract interface hides this 404a10645c70199c8d8567fbc46312158c419720abChris Lattner/// complexity behind a simple interface. 414a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 424a10645c70199c8d8567fbc46312158c419720abChris Lattnerstruct AbstractInterpreter { 434a10645c70199c8d8567fbc46312158c419720abChris Lattner 444a10645c70199c8d8567fbc46312158c419720abChris Lattner virtual ~AbstractInterpreter() {} 454a10645c70199c8d8567fbc46312158c419720abChris Lattner 464a10645c70199c8d8567fbc46312158c419720abChris Lattner /// ExecuteProgram - Run the specified bytecode file, emitting output to the 474a10645c70199c8d8567fbc46312158c419720abChris Lattner /// specified filename. This returns the exit code of the program. 484a10645c70199c8d8567fbc46312158c419720abChris Lattner /// 494a10645c70199c8d8567fbc46312158c419720abChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 504a10645c70199c8d8567fbc46312158c419720abChris Lattner const std::string &OutputFile) = 0; 514a10645c70199c8d8567fbc46312158c419720abChris Lattner 524a10645c70199c8d8567fbc46312158c419720abChris Lattner}; 534a10645c70199c8d8567fbc46312158c419720abChris Lattner 544a10645c70199c8d8567fbc46312158c419720abChris Lattner 554a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===// 564a10645c70199c8d8567fbc46312158c419720abChris Lattner// LLI Implementation of AbstractIntepreter interface 574a10645c70199c8d8567fbc46312158c419720abChris Lattner// 584a10645c70199c8d8567fbc46312158c419720abChris Lattnerclass LLI : public AbstractInterpreter { 594a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string LLIPath; // The path to the LLI executable 604a10645c70199c8d8567fbc46312158c419720abChris Lattnerpublic: 614a10645c70199c8d8567fbc46312158c419720abChris Lattner LLI(const std::string &Path) : LLIPath(Path) { } 624a10645c70199c8d8567fbc46312158c419720abChris Lattner 634a10645c70199c8d8567fbc46312158c419720abChris Lattner // LLI create method - Try to find the LLI executable 644a10645c70199c8d8567fbc46312158c419720abChris Lattner static LLI *create(BugDriver *BD, std::string &Message) { 654a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string LLIPath = FindExecutable("lli", BD->getToolName()); 664a10645c70199c8d8567fbc46312158c419720abChris Lattner if (!LLIPath.empty()) { 674a10645c70199c8d8567fbc46312158c419720abChris Lattner Message = "Found lli: " + LLIPath + "\n"; 684a10645c70199c8d8567fbc46312158c419720abChris Lattner return new LLI(LLIPath); 694a10645c70199c8d8567fbc46312158c419720abChris Lattner } 704a10645c70199c8d8567fbc46312158c419720abChris Lattner 714a10645c70199c8d8567fbc46312158c419720abChris Lattner Message = "Cannot find 'lli' in bugpoint executable directory or PATH!\n"; 724a10645c70199c8d8567fbc46312158c419720abChris Lattner return 0; 734a10645c70199c8d8567fbc46312158c419720abChris Lattner } 744a10645c70199c8d8567fbc46312158c419720abChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 754a10645c70199c8d8567fbc46312158c419720abChris Lattner const std::string &OutputFile); 764a10645c70199c8d8567fbc46312158c419720abChris Lattner}; 774a10645c70199c8d8567fbc46312158c419720abChris Lattner 784a10645c70199c8d8567fbc46312158c419720abChris Lattnerint LLI::ExecuteProgram(const std::string &Bytecode, 794a10645c70199c8d8567fbc46312158c419720abChris Lattner const std::string &OutputFile) { 804a10645c70199c8d8567fbc46312158c419720abChris Lattner const char *Args[] = { 814a10645c70199c8d8567fbc46312158c419720abChris Lattner "-abort-on-exception", 824a10645c70199c8d8567fbc46312158c419720abChris Lattner "-quiet", 834a10645c70199c8d8567fbc46312158c419720abChris Lattner Bytecode.c_str(), 844a10645c70199c8d8567fbc46312158c419720abChris Lattner 0 854a10645c70199c8d8567fbc46312158c419720abChris Lattner }; 864a10645c70199c8d8567fbc46312158c419720abChris Lattner 874a10645c70199c8d8567fbc46312158c419720abChris Lattner return RunProgramWithTimeout(LLIPath, Args, 884a10645c70199c8d8567fbc46312158c419720abChris Lattner "/dev/null", OutputFile, OutputFile); 894a10645c70199c8d8567fbc46312158c419720abChris Lattner} 904a10645c70199c8d8567fbc46312158c419720abChris Lattner 914a10645c70199c8d8567fbc46312158c419720abChris Lattner 924a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===// 934a10645c70199c8d8567fbc46312158c419720abChris Lattner// BugDriver method implementation 944a10645c70199c8d8567fbc46312158c419720abChris Lattner// 954a10645c70199c8d8567fbc46312158c419720abChris Lattner 964a10645c70199c8d8567fbc46312158c419720abChris Lattner/// initializeExecutionEnvironment - This method is used to set up the 974a10645c70199c8d8567fbc46312158c419720abChris Lattner/// environment for executing LLVM programs. 984a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 994a10645c70199c8d8567fbc46312158c419720abChris Lattnerbool BugDriver::initializeExecutionEnvironment() { 1004a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cout << "Initializing execution environment: "; 1014a10645c70199c8d8567fbc46312158c419720abChris Lattner 1024a10645c70199c8d8567fbc46312158c419720abChris Lattner // FIXME: This should default to searching for the best interpreter to use on 1034a10645c70199c8d8567fbc46312158c419720abChris Lattner // this platform, which would be JIT, then LLC, then CBE, then LLI. 1044a10645c70199c8d8567fbc46312158c419720abChris Lattner 1054a10645c70199c8d8567fbc46312158c419720abChris Lattner // Create an instance of the AbstractInterpreter interface as specified on the 1064a10645c70199c8d8567fbc46312158c419720abChris Lattner // command line 1074a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string Message; 1084a10645c70199c8d8567fbc46312158c419720abChris Lattner if (InterpreterSel == RunLLI) { 1094a10645c70199c8d8567fbc46312158c419720abChris Lattner Interpreter = LLI::create(this, Message); 1104a10645c70199c8d8567fbc46312158c419720abChris Lattner } else { 1114a10645c70199c8d8567fbc46312158c419720abChris Lattner Message = " Sorry, only LLI is supported right now!"; 1124a10645c70199c8d8567fbc46312158c419720abChris Lattner } 1134a10645c70199c8d8567fbc46312158c419720abChris Lattner 1144a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cout << Message; 1154a10645c70199c8d8567fbc46312158c419720abChris Lattner 1164a10645c70199c8d8567fbc46312158c419720abChris Lattner // If there was an error creating the selected interpreter, quit with error. 1174a10645c70199c8d8567fbc46312158c419720abChris Lattner return Interpreter == 0; 1184a10645c70199c8d8567fbc46312158c419720abChris Lattner} 1194a10645c70199c8d8567fbc46312158c419720abChris Lattner 1204a10645c70199c8d8567fbc46312158c419720abChris Lattner 1214a10645c70199c8d8567fbc46312158c419720abChris Lattner/// executeProgram - This method runs "Program", capturing the output of the 1224a10645c70199c8d8567fbc46312158c419720abChris Lattner/// program to a file, returning the filename of the file. A recommended 1234a10645c70199c8d8567fbc46312158c419720abChris Lattner/// filename may be optionally specified. 1244a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 1254a10645c70199c8d8567fbc46312158c419720abChris Lattnerstd::string BugDriver::executeProgram(std::string OutputFile, 1264a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string BytecodeFile) { 1274a10645c70199c8d8567fbc46312158c419720abChris Lattner assert(Interpreter && "Interpreter should have been created already!"); 1284a10645c70199c8d8567fbc46312158c419720abChris Lattner bool CreatedBytecode = false; 1294a10645c70199c8d8567fbc46312158c419720abChris Lattner if (BytecodeFile.empty()) { 1304a10645c70199c8d8567fbc46312158c419720abChris Lattner // Emit the program to a bytecode file... 1314a10645c70199c8d8567fbc46312158c419720abChris Lattner BytecodeFile = getUniqueFilename("bugpoint-test-program.bc"); 1324a10645c70199c8d8567fbc46312158c419720abChris Lattner 1334a10645c70199c8d8567fbc46312158c419720abChris Lattner if (writeProgramToFile(BytecodeFile, Program)) { 1344a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cerr << ToolName << ": Error emitting bytecode to file '" 1354a10645c70199c8d8567fbc46312158c419720abChris Lattner << BytecodeFile << "'!\n"; 1364a10645c70199c8d8567fbc46312158c419720abChris Lattner exit(1); 1374a10645c70199c8d8567fbc46312158c419720abChris Lattner } 1384a10645c70199c8d8567fbc46312158c419720abChris Lattner CreatedBytecode = true; 1394a10645c70199c8d8567fbc46312158c419720abChris Lattner } 1404a10645c70199c8d8567fbc46312158c419720abChris Lattner 1414a10645c70199c8d8567fbc46312158c419720abChris Lattner if (OutputFile.empty()) OutputFile = "bugpoint-execution-output"; 1424a10645c70199c8d8567fbc46312158c419720abChris Lattner 1434a10645c70199c8d8567fbc46312158c419720abChris Lattner // Check to see if this is a valid output filename... 1444a10645c70199c8d8567fbc46312158c419720abChris Lattner OutputFile = getUniqueFilename(OutputFile); 1454a10645c70199c8d8567fbc46312158c419720abChris Lattner 1464a10645c70199c8d8567fbc46312158c419720abChris Lattner // Actually execute the program! 1474a10645c70199c8d8567fbc46312158c419720abChris Lattner int RetVal = Interpreter->ExecuteProgram(BytecodeFile, OutputFile); 1484a10645c70199c8d8567fbc46312158c419720abChris Lattner 1494a10645c70199c8d8567fbc46312158c419720abChris Lattner // Remove the temporary bytecode file. 1504a10645c70199c8d8567fbc46312158c419720abChris Lattner if (CreatedBytecode) 1514a10645c70199c8d8567fbc46312158c419720abChris Lattner removeFile(BytecodeFile); 1524a10645c70199c8d8567fbc46312158c419720abChris Lattner 1534a10645c70199c8d8567fbc46312158c419720abChris Lattner // Return the filename we captured the output to. 1544a10645c70199c8d8567fbc46312158c419720abChris Lattner return OutputFile; 1554a10645c70199c8d8567fbc46312158c419720abChris Lattner} 1564a10645c70199c8d8567fbc46312158c419720abChris Lattner 1574a10645c70199c8d8567fbc46312158c419720abChris Lattner/// diffProgram - This method executes the specified module and diffs the output 1584a10645c70199c8d8567fbc46312158c419720abChris Lattner/// against the file specified by ReferenceOutputFile. If the output is 1594a10645c70199c8d8567fbc46312158c419720abChris Lattner/// different, true is returned. 1604a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 1614a10645c70199c8d8567fbc46312158c419720abChris Lattnerbool BugDriver::diffProgram(const std::string &ReferenceOutputFile, 1624a10645c70199c8d8567fbc46312158c419720abChris Lattner const std::string &BytecodeFile) { 1634a10645c70199c8d8567fbc46312158c419720abChris Lattner // Execute the program, generating an output file... 1644a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string Output = executeProgram("", BytecodeFile); 1654a10645c70199c8d8567fbc46312158c419720abChris Lattner 1664a10645c70199c8d8567fbc46312158c419720abChris Lattner std::ifstream ReferenceFile(ReferenceOutputFile.c_str()); 1674a10645c70199c8d8567fbc46312158c419720abChris Lattner if (!ReferenceFile) { 1684a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cerr << "Couldn't open reference output file '" 1694a10645c70199c8d8567fbc46312158c419720abChris Lattner << ReferenceOutputFile << "'\n"; 1704a10645c70199c8d8567fbc46312158c419720abChris Lattner exit(1); 1714a10645c70199c8d8567fbc46312158c419720abChris Lattner } 1724a10645c70199c8d8567fbc46312158c419720abChris Lattner 1734a10645c70199c8d8567fbc46312158c419720abChris Lattner std::ifstream OutputFile(Output.c_str()); 1744a10645c70199c8d8567fbc46312158c419720abChris Lattner if (!OutputFile) { 1754a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cerr << "Couldn't open output file: " << Output << "'!\n"; 1764a10645c70199c8d8567fbc46312158c419720abChris Lattner exit(1); 1774a10645c70199c8d8567fbc46312158c419720abChris Lattner } 1784a10645c70199c8d8567fbc46312158c419720abChris Lattner 1794a10645c70199c8d8567fbc46312158c419720abChris Lattner bool FilesDifferent = false; 1804a10645c70199c8d8567fbc46312158c419720abChris Lattner 1814a10645c70199c8d8567fbc46312158c419720abChris Lattner // Compare the two files... 1824a10645c70199c8d8567fbc46312158c419720abChris Lattner int C1, C2; 1834a10645c70199c8d8567fbc46312158c419720abChris Lattner do { 1844a10645c70199c8d8567fbc46312158c419720abChris Lattner C1 = ReferenceFile.get(); 1854a10645c70199c8d8567fbc46312158c419720abChris Lattner C2 = OutputFile.get(); 1864a10645c70199c8d8567fbc46312158c419720abChris Lattner if (C1 != C2) { FilesDifferent = true; break; } 1874a10645c70199c8d8567fbc46312158c419720abChris Lattner } while (C1 != EOF); 1884a10645c70199c8d8567fbc46312158c419720abChris Lattner 1894a10645c70199c8d8567fbc46312158c419720abChris Lattner removeFile(Output); 1904a10645c70199c8d8567fbc46312158c419720abChris Lattner return FilesDifferent; 1914a10645c70199c8d8567fbc46312158c419720abChris Lattner} 192