166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===-- ToolRunner.cpp ----------------------------------------------------===// 266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// The LLVM Compiler Infrastructure 466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This file is distributed under the University of Illinois Open Source 666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// License. See LICENSE.TXT for details. 766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 1066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This file implements the interfaces described in the ToolRunner.h file. 1166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 1266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 1366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 1466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#define DEBUG_TYPE "toolrunner" 1566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "ToolRunner.h" 1666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/Program.h" 1766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/CommandLine.h" 1866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/Debug.h" 1966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/FileUtilities.h" 2066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/raw_ostream.h" 2166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Config/config.h" // for HAVE_LINK_R 2266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <fstream> 2366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include <sstream> 2466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanusing namespace llvm; 2566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 2666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace llvm { 2766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::opt<bool> 2866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); 2966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 3066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace { 3266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::opt<std::string> 3366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RemoteClient("remote-client", 3466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::desc("Remote execution client (rsh/ssh)")); 3566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::opt<std::string> 3766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RemoteHost("remote-host", 3866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::desc("Remote execution (rsh/ssh) host")); 3966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::opt<std::string> 4166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RemotePort("remote-port", 4266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::desc("Remote execution (rsh/ssh) port")); 4366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::opt<std::string> 4566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RemoteUser("remote-user", 4666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::desc("Remote execution (rsh/ssh) user id")); 4766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::opt<std::string> 4966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RemoteExtra("remote-extra-options", 5066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::desc("Remote execution (rsh/ssh) extra options")); 5166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 5266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 5366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// RunProgramWithTimeout - This function provides an alternate interface 5466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// to the sys::Program::ExecuteAndWait interface. 5566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// @see sys::Program::ExecuteAndWait 5666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic int RunProgramWithTimeout(const sys::Path &ProgramPath, 5766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const char **Args, 5866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::Path &StdInFile, 5966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::Path &StdOutFile, 6066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::Path &StdErrFile, 6166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned NumSeconds = 0, 6266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit = 0, 6366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *ErrMsg = 0) { 6466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::Path* redirects[3]; 6566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman redirects[0] = &StdInFile; 6666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman redirects[1] = &StdOutFile; 6766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman redirects[2] = &StdErrFile; 6866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 6966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#if 0 // For debug purposes 7066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman { 7166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "RUN:"; 7266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0; Args[i]; ++i) 7366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << " " << Args[i]; 7466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "\n"; 7566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 7666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#endif 7766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 7966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Program::ExecuteAndWait(ProgramPath, Args, 0, redirects, 8066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman NumSeconds, MemoryLimit, ErrMsg); 8166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 8266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// RunProgramRemotelyWithTimeout - This function runs the given program 8466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// remotely using the given remote client and the sys::Program::ExecuteAndWait. 8566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// Returns the remote program exit code or reports a remote client error if it 8666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// fails. Remote client is required to return 255 if it failed or program exit 8766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// code otherwise. 8866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// @see sys::Program::ExecuteAndWait 8966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic int RunProgramRemotelyWithTimeout(const sys::Path &RemoteClientPath, 9066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const char **Args, 9166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::Path &StdInFile, 9266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::Path &StdOutFile, 9366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::Path &StdErrFile, 9466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned NumSeconds = 0, 9566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit = 0) { 9666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const sys::Path* redirects[3]; 9766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman redirects[0] = &StdInFile; 9866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman redirects[1] = &StdOutFile; 9966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman redirects[2] = &StdErrFile; 10066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#if 0 // For debug purposes 10266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman { 10366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "RUN:"; 10466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0; Args[i]; ++i) 10566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << " " << Args[i]; 10666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "\n"; 10766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 10866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#endif 10966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 11066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Run the program remotely with the remote client 11166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman int ReturnCode = sys::Program::ExecuteAndWait(RemoteClientPath, Args, 11266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 0, redirects, NumSeconds, MemoryLimit); 11366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 11466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Has the remote client fail? 11566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (255 == ReturnCode) { 11666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ostringstream OS; 11766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OS << "\nError running remote client:\n "; 11866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (const char **Arg = Args; *Arg; ++Arg) 11966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OS << " " << *Arg; 12066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OS << "\n"; 12166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 12266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // The error message is in the output file, let's print it out from there. 12366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ifstream ErrorFile(StdOutFile.c_str()); 12466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ErrorFile) { 12566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::copy(std::istreambuf_iterator<char>(ErrorFile), 12666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::istreambuf_iterator<char>(), 12766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ostreambuf_iterator<char>(OS)); 12866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ErrorFile.close(); 12966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 13066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 13166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << OS; 13266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 13366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 13466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return ReturnCode; 13566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 13666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 13766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic std::string ProcessFailure(sys::Path ProgPath, const char** Args, 13866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout = 0, 13966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit = 0) { 14066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ostringstream OS; 14166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OS << "\nError running tool:\n "; 14266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (const char **Arg = Args; *Arg; ++Arg) 14366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OS << " " << *Arg; 14466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OS << "\n"; 14566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 14666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Rerun the compiler, capturing any error messages to print them. 14766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path ErrorFilename("bugpoint.program_error_messages"); 14866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string ErrMsg; 14966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ErrorFilename.makeUnique(true, &ErrMsg)) { 15066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "Error making unique filename: " << ErrMsg << "\n"; 15166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(1); 15266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 15366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RunProgramWithTimeout(ProgPath, Args, sys::Path(""), ErrorFilename, 15466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ErrorFilename, Timeout, MemoryLimit); 15566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // FIXME: check return code ? 15666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 15766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Print out the error messages generated by GCC if possible... 15866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ifstream ErrorFile(ErrorFilename.c_str()); 15966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ErrorFile) { 16066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::copy(std::istreambuf_iterator<char>(ErrorFile), 16166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::istreambuf_iterator<char>(), 16266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ostreambuf_iterator<char>(OS)); 16366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ErrorFile.close(); 16466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 16566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 16666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ErrorFilename.eraseFromDisk(); 16766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return OS.str(); 16866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 16966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 17066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===---------------------------------------------------------------------===// 17166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// LLI Implementation of AbstractIntepreter interface 17266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 17366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace { 17466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman class LLI : public AbstractInterpreter { 17566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string LLIPath; // The path to the LLI executable 17666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string> ToolArgs; // Args to pass to LLI 17766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman public: 17866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLI(const std::string &Path, const std::vector<std::string> *Args) 17966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman : LLIPath(Path) { 18066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ToolArgs.clear (); 18166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Args) { ToolArgs = *Args; } 18266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 18366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 18466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman virtual int ExecuteProgram(const std::string &Bitcode, 18566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 18666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 18766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 18866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 18966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &GCCArgs, 19066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &SharedLibs = 19166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string>(), 19266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout = 0, 19366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit = 0); 19466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman }; 19566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 19666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 19766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint LLI::ExecuteProgram(const std::string &Bitcode, 19866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 19966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 20066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 20166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 20266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &GCCArgs, 20366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &SharedLibs, 20466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, 20566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit) { 20666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<const char*> LLIArgs; 20766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLIArgs.push_back(LLIPath.c_str()); 20866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLIArgs.push_back("-force-interpreter=true"); 20966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 21066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::vector<std::string>::const_iterator i = SharedLibs.begin(), 21166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman e = SharedLibs.end(); i != e; ++i) { 21266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLIArgs.push_back("-load"); 21366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLIArgs.push_back((*i).c_str()); 21466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 21566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 21666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add any extra LLI args. 21766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 21866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLIArgs.push_back(ToolArgs[i].c_str()); 21966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 22066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLIArgs.push_back(Bitcode.c_str()); 22166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add optional parameters to the running program from Argv 22266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i=0, e = Args.size(); i != e; ++i) 22366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLIArgs.push_back(Args[i].c_str()); 22466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLIArgs.push_back(0); 22566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 22666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "<lli>"; outs().flush(); 22766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DEBUG(errs() << "\nAbout to run:\t"; 22866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) 22966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << " " << LLIArgs[i]; 23066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "\n"; 23166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ); 23266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return RunProgramWithTimeout(sys::Path(LLIPath), &LLIArgs[0], 23366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 23466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Timeout, MemoryLimit, Error); 23566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 23666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 23766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// LLI create method - Try to find the LLI executable 23866b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanAbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, 23966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string &Message, 24066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> *ToolArgs) { 24166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string LLIPath = 24266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI).str(); 24366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!LLIPath.empty()) { 24466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Found lli: " + LLIPath + "\n"; 24566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return new LLI(LLIPath, ToolArgs); 24666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 24766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 24866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Cannot find `lli' in executable directory!\n"; 24966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 0; 25066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 25166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 25266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===---------------------------------------------------------------------===// 25366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Custom compiler command implementation of AbstractIntepreter interface 25466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 25566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Allows using a custom command for compiling the bitcode, thus allows, for 25666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// example, to compile a bitcode fragment without linking or executing, then 25766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// using a custom wrapper script to check for compiler errors. 25866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace { 25966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman class CustomCompiler : public AbstractInterpreter { 26066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string CompilerCommand; 26166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string> CompilerArgs; 26266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman public: 26366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman CustomCompiler( 26466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &CompilerCmd, std::vector<std::string> CompArgs) : 26566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {} 26666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 26766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman virtual void compileProgram(const std::string &Bitcode, 26866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 26966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout = 0, 27066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit = 0); 27166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 27266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman virtual int ExecuteProgram(const std::string &Bitcode, 27366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 27466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 27566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 27666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 27766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &GCCArgs = 27866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string>(), 27966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &SharedLibs = 28066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string>(), 28166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout = 0, 28266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit = 0) { 28366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman *Error = "Execution not supported with -compile-custom"; 28466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return -1; 28566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 28666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman }; 28766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 28866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 28966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid CustomCompiler::compileProgram(const std::string &Bitcode, 29066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 29166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, 29266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit) { 29366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 29466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<const char*> ProgramArgs; 29566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(CompilerCommand.c_str()); 29666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 29766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::size_t i = 0; i < CompilerArgs.size(); ++i) 29866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(CompilerArgs.at(i).c_str()); 29966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(Bitcode.c_str()); 30066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(0); 30166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 30266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add optional parameters to the running program from Argv 30366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) 30466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(CompilerArgs[i].c_str()); 30566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 30666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RunProgramWithTimeout( sys::Path(CompilerCommand), &ProgramArgs[0], 30766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path(), sys::Path(), sys::Path(), 30866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Timeout, MemoryLimit, Error)) 30966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman *Error = ProcessFailure(sys::Path(CompilerCommand), &ProgramArgs[0], 31066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Timeout, MemoryLimit); 31166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 31266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 31366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===---------------------------------------------------------------------===// 31466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Custom execution command implementation of AbstractIntepreter interface 31566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 31666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Allows using a custom command for executing the bitcode, thus allows, 31766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// for example, to invoke a cross compiler for code generation followed by 31866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// a simulator that executes the generated binary. 31966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace { 32066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman class CustomExecutor : public AbstractInterpreter { 32166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string ExecutionCommand; 32266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string> ExecutorArgs; 32366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman public: 32466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman CustomExecutor( 32566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) : 32666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} 32766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 32866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman virtual int ExecuteProgram(const std::string &Bitcode, 32966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 33066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 33166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 33266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 33366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &GCCArgs, 33466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &SharedLibs = 33566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string>(), 33666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout = 0, 33766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit = 0); 33866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman }; 33966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 34066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 34166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint CustomExecutor::ExecuteProgram(const std::string &Bitcode, 34266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 34366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 34466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 34566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 34666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &GCCArgs, 34766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &SharedLibs, 34866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, 34966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit) { 35066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 35166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<const char*> ProgramArgs; 35266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(ExecutionCommand.c_str()); 35366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 35466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) 35566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(ExecutorArgs.at(i).c_str()); 35666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(Bitcode.c_str()); 35766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(0); 35866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 35966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add optional parameters to the running program from Argv 36066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = Args.size(); i != e; ++i) 36166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(Args[i].c_str()); 36266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 36366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return RunProgramWithTimeout( 36466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path(ExecutionCommand), 36566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 36666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path(OutputFile), Timeout, MemoryLimit, Error); 36766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 36866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 36966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Tokenize the CommandLine to the command and the args to allow 37066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// defining a full command line as the command instead of just the 37166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// executed program. We cannot just pass the whole string after the command 37266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// as a single argument because then program sees only a single 37366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// command line argument (with spaces in it: "foo bar" instead 37466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// of "foo" and "bar"). 37566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 37666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// code borrowed from: 37766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html 37866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic void lexCommand(std::string &Message, const std::string &CommandLine, 37966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string &CmdPath, std::vector<std::string> Args) { 38066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 38166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string Command = ""; 38266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string delimiters = " "; 38366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 38466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string::size_type lastPos = CommandLine.find_first_not_of(delimiters, 0); 38566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string::size_type pos = CommandLine.find_first_of(delimiters, lastPos); 38666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 38766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman while (std::string::npos != pos || std::string::npos != lastPos) { 38866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string token = CommandLine.substr(lastPos, pos - lastPos); 38966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Command == "") 39066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Command = token; 39166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else 39266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Args.push_back(token); 39366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Skip delimiters. Note the "not_of" 39466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman lastPos = CommandLine.find_first_not_of(delimiters, pos); 39566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Find next "non-delimiter" 39666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman pos = CommandLine.find_first_of(delimiters, lastPos); 39766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 39866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 39966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman CmdPath = sys::Program::FindProgramByName(Command).str(); 40066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (CmdPath.empty()) { 40166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = 40266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string("Cannot find '") + Command + 40366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman "' in PATH!\n"; 40466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return; 40566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 40666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 40766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Found command in: " + CmdPath + "\n"; 40866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 40966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 41066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Custom execution environment create method, takes the execution command 41166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// as arguments 41266b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanAbstractInterpreter *AbstractInterpreter::createCustomCompiler( 41366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string &Message, 41466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &CompileCommandLine) { 41566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 41666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string CmdPath; 41766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string> Args; 41866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman lexCommand(Message, CompileCommandLine, CmdPath, Args); 41966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (CmdPath.empty()) 42066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 0; 42166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 42266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return new CustomCompiler(CmdPath, Args); 42366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 42466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 42566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Custom execution environment create method, takes the execution command 42666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// as arguments 42766b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanAbstractInterpreter *AbstractInterpreter::createCustomExecutor( 42866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string &Message, 42966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &ExecCommandLine) { 43066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 43166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 43266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string CmdPath; 43366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string> Args; 43466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman lexCommand(Message, ExecCommandLine, CmdPath, Args); 43566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (CmdPath.empty()) 43666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 0; 43766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 43866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return new CustomExecutor(CmdPath, Args); 43966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 44066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 44166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 44266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// LLC Implementation of AbstractIntepreter interface 44366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 44466b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanGCC::FileType LLC::OutputCode(const std::string &Bitcode, 44566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path &OutputAsmFile, std::string &Error, 44666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, unsigned MemoryLimit) { 44766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); 44866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path uniqueFile(Bitcode + Suffix); 44966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string ErrMsg; 45066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (uniqueFile.makeUnique(true, &ErrMsg)) { 45166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "Error making unique filename: " << ErrMsg << "\n"; 45266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(1); 45366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 45466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputAsmFile = uniqueFile; 45566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<const char *> LLCArgs; 45666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back(LLCPath.c_str()); 45766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 45866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add any extra LLC args. 45966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 46066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back(ToolArgs[i].c_str()); 46166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 46266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back("-o"); 46366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file 46466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 46566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 46666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (UseIntegratedAssembler) 46766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back("-filetype=obj"); 46866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 46966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back (0); 47066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 47166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << (UseIntegratedAssembler ? "<llc-ia>" : "<llc>"); 47266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs().flush(); 47366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DEBUG(errs() << "\nAbout to run:\t"; 47466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 47566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << " " << LLCArgs[i]; 47666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "\n"; 47766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ); 47866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RunProgramWithTimeout(sys::Path(LLCPath), &LLCArgs[0], 47966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path(), sys::Path(), sys::Path(), 48066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Timeout, MemoryLimit)) 48166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Error = ProcessFailure(sys::Path(LLCPath), &LLCArgs[0], 48266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Timeout, MemoryLimit); 48366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; 48466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 48566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 48666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid LLC::compileProgram(const std::string &Bitcode, std::string *Error, 48766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, unsigned MemoryLimit) { 48866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path OutputAsmFile; 48966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); 49066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputAsmFile.eraseFromDisk(); 49166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 49266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 49366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint LLC::ExecuteProgram(const std::string &Bitcode, 49466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 49566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 49666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 49766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 49866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &ArgsForGCC, 49966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &SharedLibs, 50066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, 50166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit) { 50266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 50366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path OutputAsmFile; 50466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, 50566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman MemoryLimit); 50666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman FileRemover OutFileRemover(OutputAsmFile.str(), !SaveTemps); 50766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 50866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string> GCCArgs(ArgsForGCC); 50966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 51066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 51166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Assuming LLC worked, compile the result with GCC and run it. 51266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return gcc->ExecuteProgram(OutputAsmFile.str(), Args, FileKind, 51366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman InputFile, OutputFile, Error, GCCArgs, 51466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Timeout, MemoryLimit); 51566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 51666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 51766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// createLLC - Try to find the LLC executable 51866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// 51966b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanLLC *AbstractInterpreter::createLLC(const char *Argv0, 52066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string &Message, 52166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &GCCBinary, 52266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> *Args, 52366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> *GCCArgs, 52466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman bool UseIntegratedAssembler) { 52566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string LLCPath = 52666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC).str(); 52766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (LLCPath.empty()) { 52866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Cannot find `llc' in executable directory!\n"; 52966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 0; 53066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 53166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 53266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Found llc: " + LLCPath + "\n"; 53366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); 53466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!gcc) { 53566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << Message << "\n"; 53666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(1); 53766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 53866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler); 53966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 54066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 54166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===---------------------------------------------------------------------===// 54266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// JIT Implementation of AbstractIntepreter interface 54366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 54466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace { 54566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman class JIT : public AbstractInterpreter { 54666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string LLIPath; // The path to the LLI executable 54766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string> ToolArgs; // Args to pass to LLI 54866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman public: 54966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman JIT(const std::string &Path, const std::vector<std::string> *Args) 55066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman : LLIPath(Path) { 55166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ToolArgs.clear (); 55266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Args) { ToolArgs = *Args; } 55366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 55466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 55566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman virtual int ExecuteProgram(const std::string &Bitcode, 55666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 55766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 55866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 55966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 56066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &GCCArgs = 56166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string>(), 56266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &SharedLibs = 56366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string>(), 56466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout = 0, 56566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit = 0); 56666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman }; 56766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 56866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 56966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint JIT::ExecuteProgram(const std::string &Bitcode, 57066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 57166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 57266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 57366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 57466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &GCCArgs, 57566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &SharedLibs, 57666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, 57766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit) { 57866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Construct a vector of parameters, incorporating those from the command-line 57966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<const char*> JITArgs; 58066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman JITArgs.push_back(LLIPath.c_str()); 58166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman JITArgs.push_back("-force-interpreter=false"); 58266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 58366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add any extra LLI args. 58466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 58566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman JITArgs.push_back(ToolArgs[i].c_str()); 58666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 58766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) { 58866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman JITArgs.push_back("-load"); 58966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman JITArgs.push_back(SharedLibs[i].c_str()); 59066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 59166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman JITArgs.push_back(Bitcode.c_str()); 59266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add optional parameters to the running program from Argv 59366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i=0, e = Args.size(); i != e; ++i) 59466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman JITArgs.push_back(Args[i].c_str()); 59566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman JITArgs.push_back(0); 59666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 59766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "<jit>"; outs().flush(); 59866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DEBUG(errs() << "\nAbout to run:\t"; 59966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) 60066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << " " << JITArgs[i]; 60166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "\n"; 60266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ); 60366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); 60466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return RunProgramWithTimeout(sys::Path(LLIPath), &JITArgs[0], 60566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 60666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Timeout, MemoryLimit, Error); 60766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 60866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 60966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// createJIT - Try to find the LLI executable 61066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// 61166b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanAbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, 61266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string &Message, const std::vector<std::string> *Args) { 61366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string LLIPath = 61466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT).str(); 61566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!LLIPath.empty()) { 61666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Found lli: " + LLIPath + "\n"; 61766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return new JIT(LLIPath, Args); 61866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 61966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 62066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Cannot find `lli' in executable directory!\n"; 62166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 0; 62266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 62366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 62466b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanGCC::FileType CBE::OutputCode(const std::string &Bitcode, 62566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path &OutputCFile, std::string &Error, 62666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, unsigned MemoryLimit) { 62766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path uniqueFile(Bitcode+".cbe.c"); 62866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string ErrMsg; 62966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (uniqueFile.makeUnique(true, &ErrMsg)) { 63066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "Error making unique filename: " << ErrMsg << "\n"; 63166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(1); 63266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 63366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputCFile = uniqueFile; 63466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<const char *> LLCArgs; 63566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back(LLCPath.c_str()); 63666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 63766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add any extra LLC args. 63866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i) 63966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back(ToolArgs[i].c_str()); 64066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 64166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back("-o"); 64266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back(OutputCFile.c_str()); // Output to the C file 64366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back("-march=c"); // Output C language 64466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode 64566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman LLCArgs.push_back(0); 64666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 64766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "<cbe>"; outs().flush(); 64866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DEBUG(errs() << "\nAbout to run:\t"; 64966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) 65066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << " " << LLCArgs[i]; 65166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "\n"; 65266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ); 65366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], sys::Path(), sys::Path(), 65466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path(), Timeout, MemoryLimit)) 65566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); 65666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return GCC::CFile; 65766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 65866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 65966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid CBE::compileProgram(const std::string &Bitcode, std::string *Error, 66066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, unsigned MemoryLimit) { 66166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path OutputCFile; 66266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); 66366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputCFile.eraseFromDisk(); 66466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 66566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 66666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint CBE::ExecuteProgram(const std::string &Bitcode, 66766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 66866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 66966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 67066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 67166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &ArgsForGCC, 67266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &SharedLibs, 67366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, 67466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit) { 67566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path OutputCFile; 67666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputCode(Bitcode, OutputCFile, *Error, Timeout, MemoryLimit); 67766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 67866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman FileRemover CFileRemove(OutputCFile.str(), !SaveTemps); 67966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 68066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<std::string> GCCArgs(ArgsForGCC); 68166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); 68266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 68366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return gcc->ExecuteProgram(OutputCFile.str(), Args, GCC::CFile, 68466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman InputFile, OutputFile, Error, GCCArgs, 68566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Timeout, MemoryLimit); 68666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 68766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 68866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// createCBE - Try to find the 'llc' executable 68966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// 69066b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanCBE *AbstractInterpreter::createCBE(const char *Argv0, 69166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string &Message, 69266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &GCCBinary, 69366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> *Args, 69466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> *GCCArgs) { 69566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path LLCPath = 69666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createCBE); 69766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (LLCPath.isEmpty()) { 69866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = 69966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman "Cannot find `llc' in executable directory!\n"; 70066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 0; 70166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 70266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 70366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Found llc: " + LLCPath.str() + "\n"; 70466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); 70566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!gcc) { 70666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << Message << "\n"; 70766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(1); 70866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 70966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return new CBE(LLCPath, gcc, Args); 71066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 71166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 71266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===---------------------------------------------------------------------===// 71366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// GCC abstraction 71466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 71566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 71666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic bool IsARMArchitecture(std::vector<const char*> Args) { 71766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::vector<const char*>::const_iterator 71866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I = Args.begin(), E = Args.end(); I != E; ++I) { 71966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (StringRef(*I).equals_lower("-arch")) { 72066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ++I; 72166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (I != E && StringRef(*I).substr(0, strlen("arm")).equals_lower("arm")) 72266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return true; 72366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 72466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 72566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 72666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 72766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 72866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 72966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint GCC::ExecuteProgram(const std::string &ProgramFile, 73066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &Args, 73166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman FileType fileType, 73266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &InputFile, 73366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &OutputFile, 73466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string *Error, 73566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &ArgsForGCC, 73666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned Timeout, 73766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman unsigned MemoryLimit) { 73866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<const char*> GCCArgs; 73966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 74066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(GCCPath.c_str()); 74166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 74266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TargetTriple.getArch() == Triple::x86) 74366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-m32"); 74466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 74566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::vector<std::string>::const_iterator 74666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 74766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(I->c_str()); 74866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 74966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Specify -x explicitly in case the extension is wonky 75066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (fileType != ObjectFile) { 75166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-x"); 75266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (fileType == CFile) { 75366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("c"); 75466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-fno-strict-aliasing"); 75566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 75666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("assembler"); 75766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 75866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // For ARM architectures we don't want this flag. bugpoint isn't 75966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // explicitly told what architecture it is working on, so we get 76066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // it from gcc flags 76166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TargetTriple.isOSDarwin() && !IsARMArchitecture(GCCArgs)) 76266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-force_cpusubtype_ALL"); 76366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 76466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 76566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 76666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. 76766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 76866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-x"); 76966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("none"); 77066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-o"); 77166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path OutputBinary (ProgramFile+".gcc.exe"); 77266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string ErrMsg; 77366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (OutputBinary.makeUnique(true, &ErrMsg)) { 77466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "Error making unique filename: " << ErrMsg << "\n"; 77566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(1); 77666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 77766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... 77866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 77966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add any arguments intended for GCC. We locate them here because this is 78066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // most likely -L and -l options that need to come before other libraries but 78166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // after the source. Other options won't be sensitive to placement on the 78266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // command line, so this should be safe. 78366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 78466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(ArgsForGCC[i].c_str()); 78566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 78666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-lm"); // Hard-code the math library... 78766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-O2"); // Optimize the program a bit... 78866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#if defined (HAVE_LINK_R) 78966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files 79066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#endif 79166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TargetTriple.getArch() == Triple::sparc) 79266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-mcpu=v9"); 79366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(0); // NULL terminator 79466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 79566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "<gcc>"; outs().flush(); 79666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DEBUG(errs() << "\nAbout to run:\t"; 79766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 79866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << " " << GCCArgs[i]; 79966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "\n"; 80066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ); 80166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 80266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path())) { 80366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman *Error = ProcessFailure(GCCPath, &GCCArgs[0]); 80466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return -1; 80566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 80666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 80766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<const char*> ProgramArgs; 80866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 80966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Declared here so that the destructor only runs after 81066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // ProgramArgs is used. 81166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string Exec; 81266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 81366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RemoteClientPath.isEmpty()) 81466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(OutputBinary.c_str()); 81566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else { 81666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(RemoteClientPath.c_str()); 81766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(RemoteHost.c_str()); 81866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!RemoteUser.empty()) { 81966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back("-l"); 82066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(RemoteUser.c_str()); 82166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 82266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!RemotePort.empty()) { 82366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back("-p"); 82466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(RemotePort.c_str()); 82566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 82666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!RemoteExtra.empty()) { 82766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(RemoteExtra.c_str()); 82866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 82966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 83066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Full path to the binary. We need to cd to the exec directory because 83166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // there is a dylib there that the exec expects to find in the CWD 83266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman char* env_pwd = getenv("PWD"); 83366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Exec = "cd "; 83466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Exec += env_pwd; 83566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Exec += "; ./"; 83666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Exec += OutputBinary.c_str(); 83766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(Exec.c_str()); 83866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 83966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 84066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add optional parameters to the running program from Argv 84166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = Args.size(); i != e; ++i) 84266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(Args[i].c_str()); 84366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramArgs.push_back(0); // NULL terminator 84466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 84566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Now that we have a binary, run it! 84666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "<program>"; outs().flush(); 84766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DEBUG(errs() << "\nAbout to run:\t"; 84866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) 84966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << " " << ProgramArgs[i]; 85066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "\n"; 85166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ); 85266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 85366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); 85466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 85566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RemoteClientPath.isEmpty()) { 85666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DEBUG(errs() << "<run locally>"); 85766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman int ExitCode = RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], 85866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile), 85966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Timeout, MemoryLimit, Error); 86066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Treat a signal (usually SIGSEGV) or timeout as part of the program output 86166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // so that crash-causing miscompilation is handled seamlessly. 86266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ExitCode < -1) { 86366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); 86466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outFile << *Error << '\n'; 86566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outFile.close(); 86666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Error->clear(); 86766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 86866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return ExitCode; 86966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else { 87066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "<run remotely>"; outs().flush(); 87166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return RunProgramRemotelyWithTimeout(sys::Path(RemoteClientPath), 87266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile), 87366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path(OutputFile), Timeout, MemoryLimit); 87466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 87566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 87666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 87766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, 87866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string &OutputFile, 87966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> &ArgsForGCC, 88066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string &Error) { 88166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path uniqueFilename(InputFile+LTDL_SHLIB_EXT); 88266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string ErrMsg; 88366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (uniqueFilename.makeUnique(true, &ErrMsg)) { 88466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "Error making unique filename: " << ErrMsg << "\n"; 88566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman exit(1); 88666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 88766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OutputFile = uniqueFilename.str(); 88866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 88966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::vector<const char*> GCCArgs; 89066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 89166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(GCCPath.c_str()); 89266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 89366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TargetTriple.getArch() == Triple::x86) 89466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-m32"); 89566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 89666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (std::vector<std::string>::const_iterator 89766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) 89866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(I->c_str()); 89966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 90066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Compile the C/asm file into a shared object 90166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (fileType != ObjectFile) { 90266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-x"); 90366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); 90466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 90566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-fno-strict-aliasing"); 90666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. 90766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-x"); 90866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("none"); 90966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TargetTriple.getArch() == Triple::sparc) 91066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc 91166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman else if (TargetTriple.isOSDarwin()) { 91266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // link all source files into a single module in data segment, rather than 91366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // generating blocks. dynamic_lookup requires that you set 91466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for 91566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // bugpoint to just pass that in the environment of GCC. 91666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-single_module"); 91766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC 91866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-undefined"); 91966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("dynamic_lookup"); 92066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } else 92166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others 92266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 92366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if ((TargetTriple.getArch() == Triple::alpha) || 92466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (TargetTriple.getArch() == Triple::x86_64)) 92566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC 92666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 92766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (TargetTriple.getArch() == Triple::sparc) 92866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-mcpu=v9"); 92966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 93066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-o"); 93166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. 93266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back("-O2"); // Optimize the program a bit. 93366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 93466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 93566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 93666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Add any arguments intended for GCC. We locate them here because this is 93766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // most likely -L and -l options that need to come before other libraries but 93866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // after the source. Other options won't be sensitive to placement on the 93966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // command line, so this should be safe. 94066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) 94166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(ArgsForGCC[i].c_str()); 94266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman GCCArgs.push_back(0); // NULL terminator 94366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 94466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 94566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 94666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman outs() << "<gcc>"; outs().flush(); 94766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DEBUG(errs() << "\nAbout to run:\t"; 94866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) 94966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << " " << GCCArgs[i]; 95066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "\n"; 95166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ); 95266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], sys::Path(), sys::Path(), 95366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path())) { 95466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Error = ProcessFailure(GCCPath, &GCCArgs[0]); 95566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 1; 95666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 95766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 0; 95866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 95966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 96066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// create - Try to find the `gcc' executable 96166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/// 96266b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanGCC *GCC::create(std::string &Message, 96366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::string &GCCBinary, 96466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const std::vector<std::string> *Args) { 96566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path GCCPath = sys::Program::FindProgramByName(GCCBinary); 96666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (GCCPath.isEmpty()) { 96766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Cannot find `"+ GCCBinary +"' in PATH!\n"; 96866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 0; 96966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 97066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 97166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Path RemoteClientPath; 97266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!RemoteClient.empty()) 97366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RemoteClientPath = sys::Program::FindProgramByName(RemoteClient); 97466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 97566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message = "Found gcc: " + GCCPath.str() + "\n"; 97666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return new GCC(GCCPath, RemoteClientPath, Args); 97766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 978