ExecutionDriver.cpp revision 9d679cbc6cb5c7dc8cca87a1e1548c480fb056b8
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 469d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman// Anything specified after the --args option are taken as arguments to the 479d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman// program being debugged. 489d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukmancl::list<std::string> 499d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha BrukmanInputArgv("args", cl::Positional, cl::desc("<program arguments>..."), 509d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman cl::ZeroOrMore); 519d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman 524a10645c70199c8d8567fbc46312158c419720abChris Lattner/// AbstractInterpreter Class - Subclasses of this class are used to execute 534a10645c70199c8d8567fbc46312158c419720abChris Lattner/// LLVM bytecode in a variety of ways. This abstract interface hides this 544a10645c70199c8d8567fbc46312158c419720abChris Lattner/// complexity behind a simple interface. 554a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 564a10645c70199c8d8567fbc46312158c419720abChris Lattnerstruct AbstractInterpreter { 574a10645c70199c8d8567fbc46312158c419720abChris Lattner 584a10645c70199c8d8567fbc46312158c419720abChris Lattner virtual ~AbstractInterpreter() {} 594a10645c70199c8d8567fbc46312158c419720abChris Lattner 604a10645c70199c8d8567fbc46312158c419720abChris Lattner /// ExecuteProgram - Run the specified bytecode file, emitting output to the 614a10645c70199c8d8567fbc46312158c419720abChris Lattner /// specified filename. This returns the exit code of the program. 624a10645c70199c8d8567fbc46312158c419720abChris Lattner /// 634a10645c70199c8d8567fbc46312158c419720abChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 645073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 655073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = "") = 0; 664a10645c70199c8d8567fbc46312158c419720abChris Lattner}; 674a10645c70199c8d8567fbc46312158c419720abChris Lattner 684a10645c70199c8d8567fbc46312158c419720abChris Lattner 694a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===// 704a10645c70199c8d8567fbc46312158c419720abChris Lattner// LLI Implementation of AbstractIntepreter interface 714a10645c70199c8d8567fbc46312158c419720abChris Lattner// 724a10645c70199c8d8567fbc46312158c419720abChris Lattnerclass LLI : public AbstractInterpreter { 734a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string LLIPath; // The path to the LLI executable 744a10645c70199c8d8567fbc46312158c419720abChris Lattnerpublic: 754a10645c70199c8d8567fbc46312158c419720abChris Lattner LLI(const std::string &Path) : LLIPath(Path) { } 764a10645c70199c8d8567fbc46312158c419720abChris Lattner 774a10645c70199c8d8567fbc46312158c419720abChris Lattner // LLI create method - Try to find the LLI executable 784a10645c70199c8d8567fbc46312158c419720abChris Lattner static LLI *create(BugDriver *BD, std::string &Message) { 794a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string LLIPath = FindExecutable("lli", BD->getToolName()); 804a10645c70199c8d8567fbc46312158c419720abChris Lattner if (!LLIPath.empty()) { 814a10645c70199c8d8567fbc46312158c419720abChris Lattner Message = "Found lli: " + LLIPath + "\n"; 824a10645c70199c8d8567fbc46312158c419720abChris Lattner return new LLI(LLIPath); 834a10645c70199c8d8567fbc46312158c419720abChris Lattner } 844a10645c70199c8d8567fbc46312158c419720abChris Lattner 855073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `lli' in bugpoint executable directory or PATH!\n"; 864a10645c70199c8d8567fbc46312158c419720abChris Lattner return 0; 874a10645c70199c8d8567fbc46312158c419720abChris Lattner } 884a10645c70199c8d8567fbc46312158c419720abChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 895073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 905073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 914a10645c70199c8d8567fbc46312158c419720abChris Lattner}; 924a10645c70199c8d8567fbc46312158c419720abChris Lattner 934a10645c70199c8d8567fbc46312158c419720abChris Lattnerint LLI::ExecuteProgram(const std::string &Bytecode, 945073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 955073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 96a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!SharedLib.empty()) { 975073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "LLI currently does not support loading shared libraries.\n" 985073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman << "Exiting.\n"; 995073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 1005073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1015073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1029d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman std::vector<const char*> LLIArgs; 1039d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman LLIArgs.push_back(LLIPath.c_str()); 1049d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman LLIArgs.push_back("-abort-on-exception"); 1059d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman LLIArgs.push_back("-quiet"); 1069d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman LLIArgs.push_back("-force-interpreter=true"); 1079d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman LLIArgs.push_back(Bytecode.c_str()); 1087835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman // Add optional parameters to the running program from Argv 1097835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman for (unsigned i=0, e = InputArgv.size(); i != e; ++i) 1109d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman LLIArgs.push_back(InputArgv[i].c_str()); 1119d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman LLIArgs.push_back(0); 1125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 11391eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman std::cout << "<lli>"; 1149d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman DEBUG(std::cerr << "About to run:\n\t"; 1159d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman for (unsigned i=0, e = LLIArgs.size(); i != e; ++i) 1169d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman std::cerr << " " << LLIArgs[i]; 1179d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman std::cerr << "\n"; 1189d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman ); 1199d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman return RunProgramWithTimeout(LLIPath, &LLIArgs[0], 1205073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman InputFile, OutputFile, OutputFile); 1215073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 1225073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1235073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman//===----------------------------------------------------------------------===// 12491eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman// GCC abstraction 1255073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// 1265073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// This is not a *real* AbstractInterpreter as it does not accept bytecode 1275073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// files, but only input acceptable to GCC, i.e. C, C++, and assembly files 1285073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// 129a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukmanclass GCC { 1305073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string GCCPath; // The path to the gcc executable 1315073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanpublic: 1325073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC(const std::string &gccPath) : GCCPath(gccPath) { } 133a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman virtual ~GCC() {} 1345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1355073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // GCC create method - Try to find the `gcc' executable 1365073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman static GCC *create(BugDriver *BD, std::string &Message) { 1375073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string GCCPath = FindExecutable("gcc", BD->getToolName()); 1385073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (GCCPath.empty()) { 1395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `gcc' in bugpoint executable directory or PATH!\n"; 1405073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 1415073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1425073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1435073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Found gcc: " + GCCPath + "\n"; 1445073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return new GCC(GCCPath); 1455073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1465073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1475073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman virtual int ExecuteProgram(const std::string &ProgramFile, 148a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman FileType fileType, 1495073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 1505073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 1515073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1525073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman int MakeSharedObject(const std::string &InputFile, 153a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman FileType fileType, 1545073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputFile); 1555073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1565073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman void ProcessFailure(const char **Args); 1575073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman}; 1585073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1595073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint GCC::ExecuteProgram(const std::string &ProgramFile, 160a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman FileType fileType, 1615073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 1625073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 16391eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman std::string OutputBinary = getUniqueFilename("bugpoint.gcc.exe"); 1647835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman std::vector<const char*> GCCArgs; 1657835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman 1667835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back(GCCPath.c_str()); 1677835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman if (!SharedLib.empty()) // Specify the shared library to link in... 1687835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back(SharedLib.c_str()); 1697835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back("-x"); 1707835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back((fileType == AsmFile) ? "assembler" : "c"); 1717835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename... 1727835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back("-o"); 1737835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 1747835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back("-lm"); // Hard-code the math library... 1757835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back("-O2"); // Optimize the program a bit... 1767835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman GCCArgs.push_back(0); // NULL terminator 1775073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1785073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "<gcc>"; 1797835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "/dev/null", "/dev/null", 180a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman "/dev/null")) { 1817835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman ProcessFailure(&GCCArgs[0]); 182a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman exit(1); 1835073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1845073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1857835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman std::vector<const char*> ProgramArgs; 1867835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman ProgramArgs.push_back(OutputBinary.c_str()); 1877835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman // Add optional parameters to the running program from Argv 1887835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman for (unsigned i=0, e = InputArgv.size(); i != e; ++i) 1897835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman ProgramArgs.push_back(InputArgv[i].c_str()); 1907835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman ProgramArgs.push_back(0); // NULL terminator 1915073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1925073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Now that we have a binary, run it! 19391eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman std::cout << "<program>"; 1949d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman DEBUG(std::cerr << "About to run:\n\t"; 1959d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman for (unsigned i=0, e = ProgramArgs.size(); i != e; ++i) 1969d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman std::cerr << " " << ProgramArgs[i]; 1979d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman std::cerr << "\n"; 1989d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman ); 1997835c852270da3da66d79d4d18cefda3c8e3019cMisha Brukman int ProgramResult = RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], 2005073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman InputFile, OutputFile, OutputFile); 2015073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "\n"; 2025073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(OutputBinary); 2035073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return ProgramResult; 2045073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 2055073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2065073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint GCC::MakeSharedObject(const std::string &InputFile, 207a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman FileType fileType, 2085073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputFile) { 20991eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman OutputFile = getUniqueFilename("./bugpoint.so"); 2105073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Compile the C/asm file into a shared object 2115073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const char* GCCArgs[] = { 2125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCCPath.c_str(), 213a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman "-x", (fileType == AsmFile) ? "assembler" : "c", 2145073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman InputFile.c_str(), // Specify the input filename... 2155073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#if defined(sparc) || defined(__sparc__) || defined(__sparcv9) 2165073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-G", // Compile a shared library, `-G' for Sparc 2175073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#else 2185073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-shared", // `-shared' for Linux/X86, maybe others 2195073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#endif 2205073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-o", OutputFile.c_str(), // Output to the right filename... 2215073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-O2", // Optimize the program a bit... 2225073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 0 2235073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman }; 2245073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2255073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "<gcc>"; 2265073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if(RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", "/dev/null", 2275073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "/dev/null")) { 2285073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ProcessFailure(GCCArgs); 2295073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 2305073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 2315073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 2325073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 2335073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanvoid GCC::ProcessFailure(const char** GCCArgs) { 2355073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "\n*** bugpoint error: invocation of the C compiler failed!\n"; 2365073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman for (const char **Arg = GCCArgs; *Arg; ++Arg) 2375073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << " " << *Arg; 2385073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "\n"; 2395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2405073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Rerun the compiler, capturing any error messages to print them. 2415073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string ErrorFilename = getUniqueFilename("bugpoint.gcc.errors"); 2425073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", ErrorFilename.c_str(), 2435073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ErrorFilename.c_str()); 2445073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2455073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Print out the error messages generated by GCC if possible... 2465073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::ifstream ErrorFile(ErrorFilename.c_str()); 2475073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (ErrorFile) { 2485073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::copy(std::istreambuf_iterator<char>(ErrorFile), 2495073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::istreambuf_iterator<char>(), 2505073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::ostreambuf_iterator<char>(std::cerr)); 2515073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ErrorFile.close(); 2525073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "\n"; 2535073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 2545073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2555073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(ErrorFilename); 2565073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 2575073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2585073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman//===----------------------------------------------------------------------===// 2595073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// LLC Implementation of AbstractIntepreter interface 2605073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// 2615073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanclass LLC : public AbstractInterpreter { 2625073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string LLCPath; // The path to the LLC executable 2635073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC *gcc; 2645073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanpublic: 2655073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman LLC(const std::string &llcPath, GCC *Gcc) 2665073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman : LLCPath(llcPath), gcc(Gcc) { } 2675073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ~LLC() { delete gcc; } 2685073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2695073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // LLC create method - Try to find the LLC executable 2705073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman static LLC *create(BugDriver *BD, std::string &Message) { 2715073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string LLCPath = FindExecutable("llc", BD->getToolName()); 2725073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (LLCPath.empty()) { 2735073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `llc' in bugpoint executable directory or PATH!\n"; 2745073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 2755073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 2765073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2775073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Found llc: " + LLCPath + "\n"; 2785073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC *gcc = GCC::create(BD, Message); 279a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!gcc) { 280a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman std::cerr << Message << "\n"; 281a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman exit(1); 282a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman } 2835073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return new LLC(LLCPath, gcc); 2845073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 2855073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2865073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman virtual int ExecuteProgram(const std::string &Bytecode, 2875073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 2885073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 2895073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2905073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman int OutputAsm(const std::string &Bytecode, 2915073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputAsmFile); 2925073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman}; 2935073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 2945073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint LLC::OutputAsm(const std::string &Bytecode, 2955073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputAsmFile) { 2965073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman OutputAsmFile = "bugpoint.llc.s"; 2975073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const char *LLCArgs[] = { 2985073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman LLCPath.c_str(), 2995073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-o", OutputAsmFile.c_str(), // Output to the Asm file 3005073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "-f", // Overwrite as necessary... 3015073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Bytecode.c_str(), // This is the input bytecode 3025073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 0 3035073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman }; 3045073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 3055073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "<llc>"; 3065073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (RunProgramWithTimeout(LLCPath, LLCArgs, "/dev/null", "/dev/null", 3075073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "/dev/null")) { 3085073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // If LLC failed on the bytecode, print error... 3095073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "bugpoint error: `llc' failed!\n"; 3105073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(OutputAsmFile); 3115073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 1; 3125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 3135073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 3145073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 3154a10645c70199c8d8567fbc46312158c419720abChris Lattner} 3164a10645c70199c8d8567fbc46312158c419720abChris Lattner 3175073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint LLC::ExecuteProgram(const std::string &Bytecode, 3185073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 3195073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 3205073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 3215073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string OutputAsmFile; 3225073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (OutputAsm(Bytecode, OutputAsmFile)) { 3235073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "Could not generate asm code with `llc', exiting.\n"; 3245073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 3255073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 3265073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 3275073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Assuming LLC worked, compile the result with GCC and run it. 328a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman int Result = gcc->ExecuteProgram(OutputAsmFile,AsmFile,OutputFile,SharedLib); 3295073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(OutputAsmFile); 3305073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return Result; 3315073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 3325073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 3335073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 334cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner//===----------------------------------------------------------------------===// 335cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner// JIT Implementation of AbstractIntepreter interface 336cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner// 337cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerclass JIT : public AbstractInterpreter { 338cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::string LLIPath; // The path to the LLI executable 339cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerpublic: 340cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner JIT(const std::string &Path) : LLIPath(Path) { } 341cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 342cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner // JIT create method - Try to find the LLI executable 343cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner static JIT *create(BugDriver *BD, std::string &Message) { 344cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::string LLIPath = FindExecutable("lli", BD->getToolName()); 345cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner if (!LLIPath.empty()) { 346cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner Message = "Found lli: " + LLIPath + "\n"; 347cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return new JIT(LLIPath); 348cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 349cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 3505073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `lli' in bugpoint executable directory or PATH!\n"; 351cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return 0; 352cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 353cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 3545073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 3555073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 356cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner}; 357cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 358cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerint JIT::ExecuteProgram(const std::string &Bytecode, 3595073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 3605073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 3619d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman // Construct a vector of parameters, incorporating those from the command-line 3629d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman std::vector<const char*> JITArgs; 3639d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman JITArgs.push_back(LLIPath.c_str()); 3649d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman JITArgs.push_back("-quiet"); 3659d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman JITArgs.push_back("-force-interpreter=false"); 3669d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman if (!SharedLib.empty()) { 3679d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman JITArgs.push_back("-load"); 3689d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman JITArgs.push_back(SharedLib.c_str()); 3699d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman } 3709d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman JITArgs.push_back(Bytecode.c_str()); 3719d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman // Add optional parameters to the running program from Argv 3729d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman for (unsigned i=0, e = InputArgv.size(); i != e; ++i) 3739d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman JITArgs.push_back(InputArgv[i].c_str()); 3749d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman JITArgs.push_back(0); 3759d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman 3769d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman std::cout << "<jit>\n"; 3779d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman DEBUG(std::cerr << "About to run:\n\t"; 3789d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman for (unsigned i=0, e = JITArgs.size(); i != e; ++i) 3799d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman std::cerr << " " << JITArgs[i]; 3809d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman std::cerr << "\n"; 3819d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman ); 38291eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n"); 3839d679cbc6cb5c7dc8cca87a1e1548c480fb056b8Misha Brukman return RunProgramWithTimeout(LLIPath, &JITArgs[0], 38491eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman InputFile, OutputFile, OutputFile); 385cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner} 386cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 387cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner//===----------------------------------------------------------------------===// 388cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner// CBE Implementation of AbstractIntepreter interface 389cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner// 390cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerclass CBE : public AbstractInterpreter { 391cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::string DISPath; // The path to the LLVM 'dis' executable 3925073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC *gcc; 393cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattnerpublic: 3945073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman CBE(const std::string &disPath, GCC *Gcc) : DISPath(disPath), gcc(Gcc) { } 3955073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ~CBE() { delete gcc; } 396cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 397cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner // CBE create method - Try to find the 'dis' executable 398cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner static CBE *create(BugDriver *BD, std::string &Message) { 399cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::string DISPath = FindExecutable("dis", BD->getToolName()); 400cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner if (DISPath.empty()) { 4015073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Message = "Cannot find `dis' in bugpoint executable directory or PATH!\n"; 402cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return 0; 403cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 404cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 405cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner Message = "Found dis: " + DISPath + "\n"; 406cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 4075073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman GCC *gcc = GCC::create(BD, Message); 408a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!gcc) { 409a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman std::cerr << Message << "\n"; 410a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman exit(1); 411a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman } 4125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return new CBE(DISPath, gcc); 413cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 4145073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 415cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner virtual int ExecuteProgram(const std::string &Bytecode, 4165073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 4175073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib = ""); 4185073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 4195073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Sometimes we just want to go half-way and only generate the C file, 4205073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // not necessarily compile it with GCC and run the program 4215073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman virtual int OutputC(const std::string &Bytecode, 4225073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputCFile); 4235073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 424cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner}; 425cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 4265073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint CBE::OutputC(const std::string &Bytecode, 4275073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &OutputCFile) { 4285073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman OutputCFile = "bugpoint.cbe.c"; 429cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner const char *DisArgs[] = { 430cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner DISPath.c_str(), 431cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner "-o", OutputCFile.c_str(), // Output to the C file 432cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner "-c", // Output to C 433cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner "-f", // Overwrite as necessary... 434cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner Bytecode.c_str(), // This is the input bytecode 435cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 0 436cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner }; 437cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 438cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner std::cout << "<cbe>"; 439cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner if (RunProgramWithTimeout(DISPath, DisArgs, "/dev/null", "/dev/null", 440cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner "/dev/null")) { 441cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner // If dis failed on the bytecode, print error... 4425073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "bugpoint error: `dis -c' failed!\n"; 443cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return 1; 444cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 445cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 4465073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 4475073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 448cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 449cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 4505073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint CBE::ExecuteProgram(const std::string &Bytecode, 4515073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &OutputFile, 4525073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedLib) { 4535073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string OutputCFile; 4545073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (OutputC(Bytecode, OutputCFile)) { 4555073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "Could not generate C code with `dis', exiting.\n"; 4565073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 457cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner } 458cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner 459a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman int Result = gcc->ExecuteProgram(OutputCFile, CFile, OutputFile, SharedLib); 460cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner removeFile(OutputCFile); 4615073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 462cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner return Result; 463cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner} 4644a10645c70199c8d8567fbc46312158c419720abChris Lattner 4655073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 4664a10645c70199c8d8567fbc46312158c419720abChris Lattner//===----------------------------------------------------------------------===// 4674a10645c70199c8d8567fbc46312158c419720abChris Lattner// BugDriver method implementation 4684a10645c70199c8d8567fbc46312158c419720abChris Lattner// 4694a10645c70199c8d8567fbc46312158c419720abChris Lattner 4704a10645c70199c8d8567fbc46312158c419720abChris Lattner/// initializeExecutionEnvironment - This method is used to set up the 4714a10645c70199c8d8567fbc46312158c419720abChris Lattner/// environment for executing LLVM programs. 4724a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 4734a10645c70199c8d8567fbc46312158c419720abChris Lattnerbool BugDriver::initializeExecutionEnvironment() { 4744a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cout << "Initializing execution environment: "; 4754a10645c70199c8d8567fbc46312158c419720abChris Lattner 4764a10645c70199c8d8567fbc46312158c419720abChris Lattner // FIXME: This should default to searching for the best interpreter to use on 4774a10645c70199c8d8567fbc46312158c419720abChris Lattner // this platform, which would be JIT, then LLC, then CBE, then LLI. 4784a10645c70199c8d8567fbc46312158c419720abChris Lattner 4794a10645c70199c8d8567fbc46312158c419720abChris Lattner // Create an instance of the AbstractInterpreter interface as specified on the 4804a10645c70199c8d8567fbc46312158c419720abChris Lattner // command line 4814a10645c70199c8d8567fbc46312158c419720abChris Lattner std::string Message; 482cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner switch (InterpreterSel) { 483cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner case RunLLI: Interpreter = LLI::create(this, Message); break; 4845073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman case RunLLC: Interpreter = LLC::create(this, Message); break; 485cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner case RunJIT: Interpreter = JIT::create(this, Message); break; 486cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner case RunCBE: Interpreter = CBE::create(this, Message); break; 487cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner default: 488cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner Message = " Sorry, this back-end is not supported by bugpoint right now!\n"; 489cc876a7421f6dbcca98446058d5f0637092c6e1aChris Lattner break; 4904a10645c70199c8d8567fbc46312158c419720abChris Lattner } 4914a10645c70199c8d8567fbc46312158c419720abChris Lattner 4924a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cout << Message; 4934a10645c70199c8d8567fbc46312158c419720abChris Lattner 494a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman // Initialize auxiliary tools for debugging 495a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman cbe = CBE::create(this, Message); 496a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!cbe) { std::cout << Message << "\nExiting.\n"; exit(1); } 497a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman gcc = GCC::create(this, Message); 498a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman if (!gcc) { std::cout << Message << "\nExiting.\n"; exit(1); } 499a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman 5004a10645c70199c8d8567fbc46312158c419720abChris Lattner // If there was an error creating the selected interpreter, quit with error. 5014a10645c70199c8d8567fbc46312158c419720abChris Lattner return Interpreter == 0; 5024a10645c70199c8d8567fbc46312158c419720abChris Lattner} 5034a10645c70199c8d8567fbc46312158c419720abChris Lattner 5044a10645c70199c8d8567fbc46312158c419720abChris Lattner 5054a10645c70199c8d8567fbc46312158c419720abChris Lattner/// executeProgram - This method runs "Program", capturing the output of the 5064a10645c70199c8d8567fbc46312158c419720abChris Lattner/// program to a file, returning the filename of the file. A recommended 5074a10645c70199c8d8567fbc46312158c419720abChris Lattner/// filename may be optionally specified. 5084a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 5094a10645c70199c8d8567fbc46312158c419720abChris Lattnerstd::string BugDriver::executeProgram(std::string OutputFile, 5105073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string BytecodeFile, 5115073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string SharedObject, 5125073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman AbstractInterpreter *AI) { 5135073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman assert((Interpreter || AI) &&"Interpreter should have been created already!"); 5144a10645c70199c8d8567fbc46312158c419720abChris Lattner bool CreatedBytecode = false; 5154a10645c70199c8d8567fbc46312158c419720abChris Lattner if (BytecodeFile.empty()) { 5164a10645c70199c8d8567fbc46312158c419720abChris Lattner // Emit the program to a bytecode file... 5174a10645c70199c8d8567fbc46312158c419720abChris Lattner BytecodeFile = getUniqueFilename("bugpoint-test-program.bc"); 5184a10645c70199c8d8567fbc46312158c419720abChris Lattner 5194a10645c70199c8d8567fbc46312158c419720abChris Lattner if (writeProgramToFile(BytecodeFile, Program)) { 5204a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cerr << ToolName << ": Error emitting bytecode to file '" 5215073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman << BytecodeFile << "'!\n"; 5224a10645c70199c8d8567fbc46312158c419720abChris Lattner exit(1); 5234a10645c70199c8d8567fbc46312158c419720abChris Lattner } 5244a10645c70199c8d8567fbc46312158c419720abChris Lattner CreatedBytecode = true; 5254a10645c70199c8d8567fbc46312158c419720abChris Lattner } 5264a10645c70199c8d8567fbc46312158c419720abChris Lattner 5274a10645c70199c8d8567fbc46312158c419720abChris Lattner if (OutputFile.empty()) OutputFile = "bugpoint-execution-output"; 5285073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5294a10645c70199c8d8567fbc46312158c419720abChris Lattner // Check to see if this is a valid output filename... 5304a10645c70199c8d8567fbc46312158c419720abChris Lattner OutputFile = getUniqueFilename(OutputFile); 5314a10645c70199c8d8567fbc46312158c419720abChris Lattner 5324a10645c70199c8d8567fbc46312158c419720abChris Lattner // Actually execute the program! 5335073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman int RetVal = (AI != 0) ? 5345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman AI->ExecuteProgram(BytecodeFile, OutputFile, SharedObject) : 5355073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Interpreter->ExecuteProgram(BytecodeFile, OutputFile, SharedObject); 5364a10645c70199c8d8567fbc46312158c419720abChris Lattner 5374a10645c70199c8d8567fbc46312158c419720abChris Lattner // Remove the temporary bytecode file. 5385073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (CreatedBytecode) removeFile(BytecodeFile); 5394a10645c70199c8d8567fbc46312158c419720abChris Lattner 5404a10645c70199c8d8567fbc46312158c419720abChris Lattner // Return the filename we captured the output to. 5414a10645c70199c8d8567fbc46312158c419720abChris Lattner return OutputFile; 5424a10645c70199c8d8567fbc46312158c419720abChris Lattner} 5434a10645c70199c8d8567fbc46312158c419720abChris Lattner 5445073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanstd::string BugDriver::executeProgramWithCBE(std::string OutputFile, 5455073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string BytecodeFile, 5465073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string SharedObject) { 547a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman return executeProgram(OutputFile, BytecodeFile, SharedObject, cbe); 5485073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 5495073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5505073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanint BugDriver::compileSharedObject(const std::string &BytecodeFile, 5515073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string &SharedObject) { 5525073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman assert(Interpreter && "Interpreter should have been created already!"); 5535073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string Message, OutputCFile; 5545073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5555073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Using CBE 5565073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman cbe->OutputC(BytecodeFile, OutputCFile); 5575073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5585073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#if 0 /* This is an alternative, as yet unimplemented */ 5595073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Using LLC 5605073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman LLC *llc = LLC::create(this, Message); 5615073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (llc->OutputAsm(BytecodeFile, OutputFile)) { 5625073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cerr << "Could not generate asm code with `llc', exiting.\n"; 5635073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman exit(1); 5645073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 5655073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#endif 5665073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 567a259c9be2acc9528ec7feb3cfd51dcde36d87bb3Misha Brukman gcc->MakeSharedObject(OutputCFile, CFile, SharedObject); 5685073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5695073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Remove the intermediate C file 5705073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman removeFile(OutputCFile); 5715073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5725073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return 0; 5735073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 5745073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5755073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 5764a10645c70199c8d8567fbc46312158c419720abChris Lattner/// diffProgram - This method executes the specified module and diffs the output 5774a10645c70199c8d8567fbc46312158c419720abChris Lattner/// against the file specified by ReferenceOutputFile. If the output is 5784a10645c70199c8d8567fbc46312158c419720abChris Lattner/// different, true is returned. 5794a10645c70199c8d8567fbc46312158c419720abChris Lattner/// 5805073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanbool BugDriver::diffProgram(const std::string &BytecodeFile, 5815073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman const std::string &SharedObject, 582640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner bool RemoveBytecode) { 5834a10645c70199c8d8567fbc46312158c419720abChris Lattner // Execute the program, generating an output file... 5845073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::string Output = executeProgram("", BytecodeFile, SharedObject); 5854a10645c70199c8d8567fbc46312158c419720abChris Lattner 5864a10645c70199c8d8567fbc46312158c419720abChris Lattner std::ifstream ReferenceFile(ReferenceOutputFile.c_str()); 5874a10645c70199c8d8567fbc46312158c419720abChris Lattner if (!ReferenceFile) { 5884a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cerr << "Couldn't open reference output file '" 5895073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman << ReferenceOutputFile << "'\n"; 5904a10645c70199c8d8567fbc46312158c419720abChris Lattner exit(1); 5914a10645c70199c8d8567fbc46312158c419720abChris Lattner } 5924a10645c70199c8d8567fbc46312158c419720abChris Lattner 5934a10645c70199c8d8567fbc46312158c419720abChris Lattner std::ifstream OutputFile(Output.c_str()); 5944a10645c70199c8d8567fbc46312158c419720abChris Lattner if (!OutputFile) { 5954a10645c70199c8d8567fbc46312158c419720abChris Lattner std::cerr << "Couldn't open output file: " << Output << "'!\n"; 5964a10645c70199c8d8567fbc46312158c419720abChris Lattner exit(1); 5974a10645c70199c8d8567fbc46312158c419720abChris Lattner } 5984a10645c70199c8d8567fbc46312158c419720abChris Lattner 5994a10645c70199c8d8567fbc46312158c419720abChris Lattner bool FilesDifferent = false; 6004a10645c70199c8d8567fbc46312158c419720abChris Lattner 6014a10645c70199c8d8567fbc46312158c419720abChris Lattner // Compare the two files... 6024a10645c70199c8d8567fbc46312158c419720abChris Lattner int C1, C2; 6034a10645c70199c8d8567fbc46312158c419720abChris Lattner do { 6044a10645c70199c8d8567fbc46312158c419720abChris Lattner C1 = ReferenceFile.get(); 6054a10645c70199c8d8567fbc46312158c419720abChris Lattner C2 = OutputFile.get(); 6064a10645c70199c8d8567fbc46312158c419720abChris Lattner if (C1 != C2) { FilesDifferent = true; break; } 6074a10645c70199c8d8567fbc46312158c419720abChris Lattner } while (C1 != EOF); 6084a10645c70199c8d8567fbc46312158c419720abChris Lattner 60991eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman //removeFile(Output); 610640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner if (RemoveBytecode) removeFile(BytecodeFile); 6114a10645c70199c8d8567fbc46312158c419720abChris Lattner return FilesDifferent; 6124a10645c70199c8d8567fbc46312158c419720abChris Lattner} 61391eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman 61491eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukmanbool BugDriver::isExecutingJIT() { 61591eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman return InterpreterSel == RunJIT; 61691eabc13d3a456cc4b387d3d7fdb041d976732c7Misha Brukman} 617