ExecutionDriver.cpp revision 91eabc13d3a456cc4b387d3d7fdb041d976732c7
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 145073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman SingleSource directory, e.g. 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" 2091eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman#include "Support/Statistic.h" 214a10645c70199c8d8567fbc46312158c419720abChris Lattner#include <fstream> 22e1b52b765675015eee5ce9efdb1b81c6c3eaefb1Chris Lattner#include <iostream> 234a10645c70199c8d8567fbc46312158c419720abChris Lattner 244a10645c70199c8d8567fbc46312158c419720abChris Lattnernamespace { 254a10645c70199c8d8567fbc46312158c419720abChris Lattner // OutputType - Allow the user to specify the way code should be run, to test 264a10645c70199c8d8567fbc46312158c419720abChris Lattner // for miscompilation. 274a10645c70199c8d8567fbc46312158c419720abChris Lattner // 284a10645c70199c8d8567fbc46312158c419720abChris Lattner enum OutputType { 294a10645c70199c8d8567fbc46312158c419720abChris Lattner RunLLI, RunJIT, RunLLC, RunCBE 304a10645c70199c8d8567fbc46312158c419720abChris Lattner }; 314a10645c70199c8d8567fbc46312158c419720abChris Lattner cl::opt<OutputType> 324a10645c70199c8d8567fbc46312158c419720abChris Lattner InterpreterSel(cl::desc("Specify how LLVM code should be executed:"), 335073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman cl::values(clEnumValN(RunLLI, "run-lli", "Execute with LLI"), 345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman clEnumValN(RunJIT, "run-jit", "Execute with JIT"), 355073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman clEnumValN(RunLLC, "run-llc", "Compile with LLC"), 365073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman clEnumValN(RunCBE, "run-cbe", "Compile with CBE"), 375073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 0)); 383c053a0a98e19f5ac8905011ad4c8238b08d6aeaChris Lattner 393c053a0a98e19f5ac8905011ad4c8238b08d6aeaChris Lattner cl::opt<std::string> 403c053a0a98e19f5ac8905011ad4c8238b08d6aeaChris Lattner InputFile("input", cl::init("/dev/null"), 413c053a0a98e19f5ac8905011ad4c8238b08d6aeaChris Lattner cl::desc("Filename to pipe in as stdin (default: /dev/null)")); 42a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman 43a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman enum FileType { AsmFile, CFile }; 444a10645c70199c8d8567fbc46312158c419720abChris Lattner} 454a10645c70199c8d8567fbc46312158c419720abChris Lattner 464a10645c70199c8d8567fbc46312158c419720abChris Lattner/// AbstractInterpreter Class - Subclasses of this class are used to execute 474a10645c70199c8d8567fbc46312158c419720abChris Lattner/// LLVM bytecode in a variety of ways. This abstract interface hides this 484a10645c70199c8d8567fbc46312158c419720abChris Lattner/// complexity behind a simple interface. 494a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 504a10645c70199c8d8567fbc46312158c419720abChris Lattnerstruct AbstractInterpreter { 514a10645c70199c8d8567fbc46312158c419720abChris Lattner 524a10645c70199c8d8567fbc46312158c419720abChris Lattner virtual ~AbstractInterpreter() {} 534a10645c70199c8d8567fbc46312158c419720abChris Lattner 544a10645c70199c8d8567fbc46312158c419720abChris Lattner /// ExecuteProgram - Run the specified bytecode file, emitting output to the 554a10645c70199c8d8567fbc46312158c419720abChris Lattner /// specified filename. This returns the exit code of the program. 564a10645c70199c8d8567fbc46312158c419720abChris Lattner /// 574a10645c70199c8d8567fbc46312158c419720abChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 585073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 595073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = "") = 0; 604a10645c70199c8d8567fbc46312158c419720abChris Lattner}; 614a10645c70199c8d8567fbc46312158c419720abChris Lattner 624a10645c70199c8d8567fbc46312158c419720abChris Lattner 634a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===// 644a10645c70199c8d8567fbc46312158c419720abChris Lattner// LLI Implementation of AbstractIntepreter interface 654a10645c70199c8d8567fbc46312158c419720abChris Lattner// 664a10645c70199c8d8567fbc46312158c419720abChris Lattnerclass LLI : public AbstractInterpreter { 674a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string LLIPath; // The path to the LLI executable 684a10645c70199c8d8567fbc46312158c419720abChris Lattnerpublic: 694a10645c70199c8d8567fbc46312158c419720abChris Lattner LLI(const std::string &Path) : LLIPath(Path) { } 704a10645c70199c8d8567fbc46312158c419720abChris Lattner 714a10645c70199c8d8567fbc46312158c419720abChris Lattner // LLI create method - Try to find the LLI executable 724a10645c70199c8d8567fbc46312158c419720abChris Lattner static LLI *create(BugDriver *BD, std::string &Message) { 734a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string LLIPath = FindExecutable("lli", BD->getToolName()); 744a10645c70199c8d8567fbc46312158c419720abChris Lattner if (!LLIPath.empty()) { 754a10645c70199c8d8567fbc46312158c419720abChris Lattner Message = "Found lli: " + LLIPath + "\n"; 764a10645c70199c8d8567fbc46312158c419720abChris Lattner return new LLI(LLIPath); 774a10645c70199c8d8567fbc46312158c419720abChris Lattner } 784a10645c70199c8d8567fbc46312158c419720abChris Lattner 795073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `lli' in bugpoint executable directory or PATH!\n"; 804a10645c70199c8d8567fbc46312158c419720abChris Lattner return 0; 814a10645c70199c8d8567fbc46312158c419720abChris Lattner } 824a10645c70199c8d8567fbc46312158c419720abChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 835073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 845073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 854a10645c70199c8d8567fbc46312158c419720abChris Lattner}; 864a10645c70199c8d8567fbc46312158c419720abChris Lattner 874a10645c70199c8d8567fbc46312158c419720abChris Lattnerint LLI::ExecuteProgram(const std::string &Bytecode, 885073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 895073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 90a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!SharedLib.empty()) { 915073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "LLI currently does not support loading shared libraries.\n" 925073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman << "Exiting.\n"; 935073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 945073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 955073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 964a10645c70199c8d8567fbc46312158c419720abChris Lattner const char *Args[] = { 975073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman LLIPath.c_str(), 984a10645c70199c8d8567fbc46312158c419720abChris Lattner "-abort-on-exception", 994a10645c70199c8d8567fbc46312158c419720abChris Lattner "-quiet", 100cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner "-force-interpreter=true", 1014a10645c70199c8d8567fbc46312158c419720abChris Lattner Bytecode.c_str(), 1024a10645c70199c8d8567fbc46312158c419720abChris Lattner 0 1034a10645c70199c8d8567fbc46312158c419720abChris Lattner }; 1045073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 10591eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman std::cout << "<lli>"; 1064a10645c70199c8d8567fbc46312158c419720abChris Lattner return RunProgramWithTimeout(LLIPath, Args, 1075073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman InputFile, OutputFile, OutputFile); 1085073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 1095073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1105073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman//===----------------------------------------------------------------------===// 11191eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman// GCC abstraction 1125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// 1135073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// This is not a *real* AbstractInterpreter as it does not accept bytecode 1145073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// files, but only input acceptable to GCC, i.e. C, C++, and assembly files 1155073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// 116a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukmanclass GCC { 1175073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string GCCPath; // The path to the gcc executable 1185073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanpublic: 1195073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC(const std::string &gccPath) : GCCPath(gccPath) { } 120a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman virtual ~GCC() {} 1215073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1225073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // GCC create method - Try to find the `gcc' executable 1235073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman static GCC *create(BugDriver *BD, std::string &Message) { 1245073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string GCCPath = FindExecutable("gcc", BD->getToolName()); 1255073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (GCCPath.empty()) { 1265073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `gcc' in bugpoint executable directory or PATH!\n"; 1275073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 1285073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1295073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1305073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Found gcc: " + GCCPath + "\n"; 1315073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return new GCC(GCCPath); 1325073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1335073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman virtual int ExecuteProgram(const std::string &ProgramFile, 135a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman FileType fileType, 1365073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 1375073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 1385073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman int MakeSharedObject(const std::string &InputFile, 140a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman FileType fileType, 1415073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputFile); 1425073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1435073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman void ProcessFailure(const char **Args); 1445073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman}; 1455073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1465073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint GCC::ExecuteProgram(const std::string &ProgramFile, 147a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman FileType fileType, 1485073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 1495073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 15091eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman std::string OutputBinary = getUniqueFilename("bugpoint.gcc.exe"); 1515073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const char **GCCArgs; 1525073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1535073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const char *ArgsWithoutSO[] = { 1545073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCCPath.c_str(), 155a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman "-x", (fileType == AsmFile) ? "assembler" : "c", 1565073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ProgramFile.c_str(), // Specify the input filename... 1575073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-o", OutputBinary.c_str(), // Output to the right filename... 1585073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-lm", // Hard-code the math library... 1595073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-O2", // Optimize the program a bit... 1605073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 0 1615073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman }; 1625073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const char *ArgsWithSO[] = { 1635073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCCPath.c_str(), 16491eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman SharedLib.c_str(), // Specify the shared library to link in... 165a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman "-x", (fileType == AsmFile) ? "assembler" : "c", 1665073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ProgramFile.c_str(), // Specify the input filename... 1675073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-o", OutputBinary.c_str(), // Output to the right filename... 1685073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-lm", // Hard-code the math library... 1695073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-O2", // Optimize the program a bit... 1705073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 0 1715073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman }; 1725073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 173a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman GCCArgs = (SharedLib.empty()) ? ArgsWithoutSO : ArgsWithSO; 1745073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "<gcc>"; 175a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", "/dev/null", 176a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman "/dev/null")) { 1775073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ProcessFailure(GCCArgs); 178a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman exit(1); 1795073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1805073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1815073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const char *ProgramArgs[] = { 1825073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman OutputBinary.c_str(), 1835073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 0 1845073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman }; 1855073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1865073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Now that we have a binary, run it! 18791eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman std::cout << "<program>"; 1885073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman int ProgramResult = RunProgramWithTimeout(OutputBinary, ProgramArgs, 1895073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman InputFile, OutputFile, OutputFile); 1905073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "\n"; 1915073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(OutputBinary); 1925073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return ProgramResult; 1935073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 1945073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1955073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint GCC::MakeSharedObject(const std::string &InputFile, 196a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman FileType fileType, 1975073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputFile) { 19891eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman OutputFile = getUniqueFilename("./bugpoint.so"); 1995073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Compile the C/asm file into a shared object 2005073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const char* GCCArgs[] = { 2015073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCCPath.c_str(), 202a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman "-x", (fileType == AsmFile) ? "assembler" : "c", 2035073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman InputFile.c_str(), // Specify the input filename... 2045073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#if defined(sparc) || defined(__sparc__) || defined(__sparcv9) 2055073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-G", // Compile a shared library, `-G' for Sparc 2065073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#else 2075073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-shared", // `-shared' for Linux/X86, maybe others 2085073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#endif 2095073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-o", OutputFile.c_str(), // Output to the right filename... 2105073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-O2", // Optimize the program a bit... 2115073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 0 2125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman }; 2135073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2145073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "<gcc>"; 2155073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if(RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", "/dev/null", 2165073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "/dev/null")) { 2175073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ProcessFailure(GCCArgs); 2185073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 2195073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 2205073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 2215073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 2225073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2235073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanvoid GCC::ProcessFailure(const char** GCCArgs) { 2245073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "\n*** bugpoint error: invocation of the C compiler failed!\n"; 2255073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman for (const char **Arg = GCCArgs; *Arg; ++Arg) 2265073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << " " << *Arg; 2275073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "\n"; 2285073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2295073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Rerun the compiler, capturing any error messages to print them. 2305073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string ErrorFilename = getUniqueFilename("bugpoint.gcc.errors"); 2315073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", ErrorFilename.c_str(), 2325073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ErrorFilename.c_str()); 2335073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Print out the error messages generated by GCC if possible... 2355073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::ifstream ErrorFile(ErrorFilename.c_str()); 2365073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (ErrorFile) { 2375073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::copy(std::istreambuf_iterator<char>(ErrorFile), 2385073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::istreambuf_iterator<char>(), 2395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::ostreambuf_iterator<char>(std::cerr)); 2405073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ErrorFile.close(); 2415073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "\n"; 2425073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 2435073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2445073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(ErrorFilename); 2455073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 2465073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2475073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman//===----------------------------------------------------------------------===// 2485073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// LLC Implementation of AbstractIntepreter interface 2495073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// 2505073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanclass LLC : public AbstractInterpreter { 2515073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string LLCPath; // The path to the LLC executable 2525073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC *gcc; 2535073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanpublic: 2545073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman LLC(const std::string &llcPath, GCC *Gcc) 2555073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman : LLCPath(llcPath), gcc(Gcc) { } 2565073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ~LLC() { delete gcc; } 2575073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2585073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // LLC create method - Try to find the LLC executable 2595073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman static LLC *create(BugDriver *BD, std::string &Message) { 2605073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string LLCPath = FindExecutable("llc", BD->getToolName()); 2615073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (LLCPath.empty()) { 2625073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `llc' in bugpoint executable directory or PATH!\n"; 2635073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 2645073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 2655073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2665073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Found llc: " + LLCPath + "\n"; 2675073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC *gcc = GCC::create(BD, Message); 268a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!gcc) { 269a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman std::cerr << Message << "\n"; 270a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman exit(1); 271a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman } 2725073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return new LLC(LLCPath, gcc); 2735073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 2745073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2755073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman virtual int ExecuteProgram(const std::string &Bytecode, 2765073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 2775073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 2785073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2795073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman int OutputAsm(const std::string &Bytecode, 2805073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputAsmFile); 2815073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman}; 2825073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2835073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint LLC::OutputAsm(const std::string &Bytecode, 2845073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputAsmFile) { 2855073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman OutputAsmFile = "bugpoint.llc.s"; 2865073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const char *LLCArgs[] = { 2875073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman LLCPath.c_str(), 2885073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-o", OutputAsmFile.c_str(), // Output to the Asm file 2895073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-f", // Overwrite as necessary... 2905073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Bytecode.c_str(), // This is the input bytecode 2915073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 0 2925073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman }; 2935073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2945073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "<llc>"; 2955073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (RunProgramWithTimeout(LLCPath, LLCArgs, "/dev/null", "/dev/null", 2965073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "/dev/null")) { 2975073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // If LLC failed on the bytecode, print error... 2985073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "bugpoint error: `llc' failed!\n"; 2995073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(OutputAsmFile); 3005073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 1; 3015073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 3025073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 3035073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 3044a10645c70199c8d8567fbc46312158c419720abChris Lattner} 3054a10645c70199c8d8567fbc46312158c419720abChris Lattner 3065073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint LLC::ExecuteProgram(const std::string &Bytecode, 3075073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 3085073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 3095073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 3105073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string OutputAsmFile; 3115073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (OutputAsm(Bytecode, OutputAsmFile)) { 3125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "Could not generate asm code with `llc', exiting.\n"; 3135073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 3145073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 3155073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 3165073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Assuming LLC worked, compile the result with GCC and run it. 317a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman int Result = gcc->ExecuteProgram(OutputAsmFile,AsmFile,OutputFile,SharedLib); 3185073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(OutputAsmFile); 3195073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return Result; 3205073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 3215073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 3225073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 323cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner//===----------------------------------------------------------------------===// 324cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner// JIT Implementation of AbstractIntepreter interface 325cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner// 326cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerclass JIT : public AbstractInterpreter { 327cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::string LLIPath; // The path to the LLI executable 328cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerpublic: 329cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner JIT(const std::string &Path) : LLIPath(Path) { } 330cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 331cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner // JIT create method - Try to find the LLI executable 332cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner static JIT *create(BugDriver *BD, std::string &Message) { 333cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::string LLIPath = FindExecutable("lli", BD->getToolName()); 334cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner if (!LLIPath.empty()) { 335cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner Message = "Found lli: " + LLIPath + "\n"; 336cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return new JIT(LLIPath); 337cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 338cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 3395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `lli' in bugpoint executable directory or PATH!\n"; 340cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return 0; 341cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 342cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 3435073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 3445073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 345cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner}; 346cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 347cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerint JIT::ExecuteProgram(const std::string &Bytecode, 3485073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 3495073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 35091eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman const char* ArgsWithoutSO[] = { 35191eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman LLIPath.c_str(), "-quiet", "-force-interpreter=false", 35291eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman Bytecode.c_str(), 35391eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman 0 35491eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman }; 35591eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman 35691eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman const char* ArgsWithSO[] = { 35791eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman LLIPath.c_str(), "-quiet", "-force-interpreter=false", 35891eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman "-load", SharedLib.c_str(), 35991eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman Bytecode.c_str(), 36091eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman 0 36191eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman }; 36291eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman 36391eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman const char** JITArgs = SharedLib.empty() ? ArgsWithoutSO : ArgsWithSO; 36491eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman 36591eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman std::cout << "<jit>"; 36691eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n"); 36791eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman return RunProgramWithTimeout(LLIPath, JITArgs, 36891eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman InputFile, OutputFile, OutputFile); 369cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner} 370cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 371cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner//===----------------------------------------------------------------------===// 372cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner// CBE Implementation of AbstractIntepreter interface 373cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner// 374cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerclass CBE : public AbstractInterpreter { 375cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::string DISPath; // The path to the LLVM 'dis' executable 3765073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC *gcc; 377cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerpublic: 3785073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman CBE(const std::string &disPath, GCC *Gcc) : DISPath(disPath), gcc(Gcc) { } 3795073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ~CBE() { delete gcc; } 380cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 381cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner // CBE create method - Try to find the 'dis' executable 382cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner static CBE *create(BugDriver *BD, std::string &Message) { 383cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::string DISPath = FindExecutable("dis", BD->getToolName()); 384cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner if (DISPath.empty()) { 3855073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `dis' in bugpoint executable directory or PATH!\n"; 386cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return 0; 387cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 388cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 389cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner Message = "Found dis: " + DISPath + "\n"; 390cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 3915073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC *gcc = GCC::create(BD, Message); 392a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!gcc) { 393a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman std::cerr << Message << "\n"; 394a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman exit(1); 395a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman } 3965073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return new CBE(DISPath, gcc); 397cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 3985073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 399cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 4005073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 4015073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 4025073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 4035073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Sometimes we just want to go half-way and only generate the C file, 4045073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // not necessarily compile it with GCC and run the program 4055073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman virtual int OutputC(const std::string &Bytecode, 4065073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputCFile); 4075073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 408cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner}; 409cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 4105073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint CBE::OutputC(const std::string &Bytecode, 4115073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputCFile) { 4125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman OutputCFile = "bugpoint.cbe.c"; 413cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner const char *DisArgs[] = { 414cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner DISPath.c_str(), 415cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner "-o", OutputCFile.c_str(), // Output to the C file 416cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner "-c", // Output to C 417cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner "-f", // Overwrite as necessary... 418cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner Bytecode.c_str(), // This is the input bytecode 419cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 0 420cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner }; 421cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 422cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::cout << "<cbe>"; 423cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner if (RunProgramWithTimeout(DISPath, DisArgs, "/dev/null", "/dev/null", 424cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner "/dev/null")) { 425cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner // If dis failed on the bytecode, print error... 4265073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "bugpoint error: `dis -c' failed!\n"; 427cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return 1; 428cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 429cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 4305073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 4315073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 432cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 433cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 4345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint CBE::ExecuteProgram(const std::string &Bytecode, 4355073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 4365073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 4375073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string OutputCFile; 4385073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (OutputC(Bytecode, OutputCFile)) { 4395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "Could not generate C code with `dis', exiting.\n"; 4405073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 441cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 442cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 443a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman int Result = gcc->ExecuteProgram(OutputCFile, CFile, OutputFile, SharedLib); 444cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner removeFile(OutputCFile); 4455073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 446cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return Result; 447cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner} 4484a10645c70199c8d8567fbc46312158c419720abChris Lattner 4495073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 4504a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===// 4514a10645c70199c8d8567fbc46312158c419720abChris Lattner// BugDriver method implementation 4524a10645c70199c8d8567fbc46312158c419720abChris Lattner// 4534a10645c70199c8d8567fbc46312158c419720abChris Lattner 4544a10645c70199c8d8567fbc46312158c419720abChris Lattner/// initializeExecutionEnvironment - This method is used to set up the 4554a10645c70199c8d8567fbc46312158c419720abChris Lattner/// environment for executing LLVM programs. 4564a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 4574a10645c70199c8d8567fbc46312158c419720abChris Lattnerbool BugDriver::initializeExecutionEnvironment() { 4584a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cout << "Initializing execution environment: "; 4594a10645c70199c8d8567fbc46312158c419720abChris Lattner 4604a10645c70199c8d8567fbc46312158c419720abChris Lattner // FIXME: This should default to searching for the best interpreter to use on 4614a10645c70199c8d8567fbc46312158c419720abChris Lattner // this platform, which would be JIT, then LLC, then CBE, then LLI. 4624a10645c70199c8d8567fbc46312158c419720abChris Lattner 4634a10645c70199c8d8567fbc46312158c419720abChris Lattner // Create an instance of the AbstractInterpreter interface as specified on the 4644a10645c70199c8d8567fbc46312158c419720abChris Lattner // command line 4654a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string Message; 466cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner switch (InterpreterSel) { 467cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner case RunLLI: Interpreter = LLI::create(this, Message); break; 4685073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman case RunLLC: Interpreter = LLC::create(this, Message); break; 469cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner case RunJIT: Interpreter = JIT::create(this, Message); break; 470cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner case RunCBE: Interpreter = CBE::create(this, Message); break; 471cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner default: 472cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner Message = " Sorry, this back-end is not supported by bugpoint right now!\n"; 473cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner break; 4744a10645c70199c8d8567fbc46312158c419720abChris Lattner } 4754a10645c70199c8d8567fbc46312158c419720abChris Lattner 4764a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cout << Message; 4774a10645c70199c8d8567fbc46312158c419720abChris Lattner 478a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman // Initialize auxiliary tools for debugging 479a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman cbe = CBE::create(this, Message); 480a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!cbe) { std::cout << Message << "\nExiting.\n"; exit(1); } 481a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman gcc = GCC::create(this, Message); 482a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!gcc) { std::cout << Message << "\nExiting.\n"; exit(1); } 483a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman 4844a10645c70199c8d8567fbc46312158c419720abChris Lattner // If there was an error creating the selected interpreter, quit with error. 4854a10645c70199c8d8567fbc46312158c419720abChris Lattner return Interpreter == 0; 4864a10645c70199c8d8567fbc46312158c419720abChris Lattner} 4874a10645c70199c8d8567fbc46312158c419720abChris Lattner 4884a10645c70199c8d8567fbc46312158c419720abChris Lattner 4894a10645c70199c8d8567fbc46312158c419720abChris Lattner/// executeProgram - This method runs "Program", capturing the output of the 4904a10645c70199c8d8567fbc46312158c419720abChris Lattner/// program to a file, returning the filename of the file. A recommended 4914a10645c70199c8d8567fbc46312158c419720abChris Lattner/// filename may be optionally specified. 4924a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 4934a10645c70199c8d8567fbc46312158c419720abChris Lattnerstd::string BugDriver::executeProgram(std::string OutputFile, 4945073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string BytecodeFile, 4955073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string SharedObject, 4965073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman AbstractInterpreter *AI) { 4975073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman assert((Interpreter || AI) &&"Interpreter should have been created already!"); 4984a10645c70199c8d8567fbc46312158c419720abChris Lattner bool CreatedBytecode = false; 4994a10645c70199c8d8567fbc46312158c419720abChris Lattner if (BytecodeFile.empty()) { 5004a10645c70199c8d8567fbc46312158c419720abChris Lattner // Emit the program to a bytecode file... 5014a10645c70199c8d8567fbc46312158c419720abChris Lattner BytecodeFile = getUniqueFilename("bugpoint-test-program.bc"); 5024a10645c70199c8d8567fbc46312158c419720abChris Lattner 5034a10645c70199c8d8567fbc46312158c419720abChris Lattner if (writeProgramToFile(BytecodeFile, Program)) { 5044a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cerr << ToolName << ": Error emitting bytecode to file '" 5055073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman << BytecodeFile << "'!\n"; 5064a10645c70199c8d8567fbc46312158c419720abChris Lattner exit(1); 5074a10645c70199c8d8567fbc46312158c419720abChris Lattner } 5084a10645c70199c8d8567fbc46312158c419720abChris Lattner CreatedBytecode = true; 5094a10645c70199c8d8567fbc46312158c419720abChris Lattner } 5104a10645c70199c8d8567fbc46312158c419720abChris Lattner 5114a10645c70199c8d8567fbc46312158c419720abChris Lattner if (OutputFile.empty()) OutputFile = "bugpoint-execution-output"; 5125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5134a10645c70199c8d8567fbc46312158c419720abChris Lattner // Check to see if this is a valid output filename... 5144a10645c70199c8d8567fbc46312158c419720abChris Lattner OutputFile = getUniqueFilename(OutputFile); 5154a10645c70199c8d8567fbc46312158c419720abChris Lattner 5164a10645c70199c8d8567fbc46312158c419720abChris Lattner // Actually execute the program! 5175073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman int RetVal = (AI != 0) ? 5185073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman AI->ExecuteProgram(BytecodeFile, OutputFile, SharedObject) : 5195073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Interpreter->ExecuteProgram(BytecodeFile, OutputFile, SharedObject); 5204a10645c70199c8d8567fbc46312158c419720abChris Lattner 5214a10645c70199c8d8567fbc46312158c419720abChris Lattner // Remove the temporary bytecode file. 5225073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (CreatedBytecode) removeFile(BytecodeFile); 5234a10645c70199c8d8567fbc46312158c419720abChris Lattner 5244a10645c70199c8d8567fbc46312158c419720abChris Lattner // Return the filename we captured the output to. 5254a10645c70199c8d8567fbc46312158c419720abChris Lattner return OutputFile; 5264a10645c70199c8d8567fbc46312158c419720abChris Lattner} 5274a10645c70199c8d8567fbc46312158c419720abChris Lattner 5285073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanstd::string BugDriver::executeProgramWithCBE(std::string OutputFile, 5295073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string BytecodeFile, 5305073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string SharedObject) { 531a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman return executeProgram(OutputFile, BytecodeFile, SharedObject, cbe); 5325073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 5335073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint BugDriver::compileSharedObject(const std::string &BytecodeFile, 5355073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &SharedObject) { 5365073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman assert(Interpreter && "Interpreter should have been created already!"); 5375073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string Message, OutputCFile; 5385073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Using CBE 5405073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman cbe->OutputC(BytecodeFile, OutputCFile); 5415073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5425073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#if 0 /* This is an alternative, as yet unimplemented */ 5435073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Using LLC 5445073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman LLC *llc = LLC::create(this, Message); 5455073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (llc->OutputAsm(BytecodeFile, OutputFile)) { 5465073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "Could not generate asm code with `llc', exiting.\n"; 5475073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 5485073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 5495073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#endif 5505073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 551a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman gcc->MakeSharedObject(OutputCFile, CFile, SharedObject); 5525073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5535073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Remove the intermediate C file 5545073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(OutputCFile); 5555073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5565073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 5575073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 5585073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5595073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5604a10645c70199c8d8567fbc46312158c419720abChris Lattner/// diffProgram - This method executes the specified module and diffs the output 5614a10645c70199c8d8567fbc46312158c419720abChris Lattner/// against the file specified by ReferenceOutputFile. If the output is 5624a10645c70199c8d8567fbc46312158c419720abChris Lattner/// different, true is returned. 5634a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 5645073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanbool BugDriver::diffProgram(const std::string &BytecodeFile, 5655073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedObject, 566640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner bool RemoveBytecode) { 5674a10645c70199c8d8567fbc46312158c419720abChris Lattner // Execute the program, generating an output file... 5685073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string Output = executeProgram("", BytecodeFile, SharedObject); 5694a10645c70199c8d8567fbc46312158c419720abChris Lattner 5704a10645c70199c8d8567fbc46312158c419720abChris Lattner std::ifstream ReferenceFile(ReferenceOutputFile.c_str()); 5714a10645c70199c8d8567fbc46312158c419720abChris Lattner if (!ReferenceFile) { 5724a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cerr << "Couldn't open reference output file '" 5735073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman << ReferenceOutputFile << "'\n"; 5744a10645c70199c8d8567fbc46312158c419720abChris Lattner exit(1); 5754a10645c70199c8d8567fbc46312158c419720abChris Lattner } 5764a10645c70199c8d8567fbc46312158c419720abChris Lattner 5774a10645c70199c8d8567fbc46312158c419720abChris Lattner std::ifstream OutputFile(Output.c_str()); 5784a10645c70199c8d8567fbc46312158c419720abChris Lattner if (!OutputFile) { 5794a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cerr << "Couldn't open output file: " << Output << "'!\n"; 5804a10645c70199c8d8567fbc46312158c419720abChris Lattner exit(1); 5814a10645c70199c8d8567fbc46312158c419720abChris Lattner } 5824a10645c70199c8d8567fbc46312158c419720abChris Lattner 5834a10645c70199c8d8567fbc46312158c419720abChris Lattner bool FilesDifferent = false; 5844a10645c70199c8d8567fbc46312158c419720abChris Lattner 5854a10645c70199c8d8567fbc46312158c419720abChris Lattner // Compare the two files... 5864a10645c70199c8d8567fbc46312158c419720abChris Lattner int C1, C2; 5874a10645c70199c8d8567fbc46312158c419720abChris Lattner do { 5884a10645c70199c8d8567fbc46312158c419720abChris Lattner C1 = ReferenceFile.get(); 5894a10645c70199c8d8567fbc46312158c419720abChris Lattner C2 = OutputFile.get(); 5904a10645c70199c8d8567fbc46312158c419720abChris Lattner if (C1 != C2) { FilesDifferent = true; break; } 5914a10645c70199c8d8567fbc46312158c419720abChris Lattner } while (C1 != EOF); 5924a10645c70199c8d8567fbc46312158c419720abChris Lattner 59391eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman //removeFile(Output); 594640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner if (RemoveBytecode) removeFile(BytecodeFile); 5954a10645c70199c8d8567fbc46312158c419720abChris Lattner return FilesDifferent; 5964a10645c70199c8d8567fbc46312158c419720abChris Lattner} 59791eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman 59891eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukmanbool BugDriver::isExecutingJIT() { 59991eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman return InterpreterSel == RunJIT; 60091eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman} 601