//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
namespace {
cl::opt<std::string>
- RSHHost("rsh-host",
- cl::desc("Remote execution (rsh) host"));
+ RemoteClient("remote-client",
+ cl::desc("Remote execution client (rsh/ssh)"));
cl::opt<std::string>
- RSHUser("rsh-user",
- cl::desc("Remote execution (rsh) user id"));
+ RemoteHost("remote-host",
+ cl::desc("Remote execution (rsh/ssh) host"));
+
+ cl::opt<std::string>
+ RemoteUser("remote-user",
+ cl::desc("Remote execution (rsh/ssh) user id"));
+
+ cl::opt<std::string>
+ RemoteExtra("remote-extra-options",
+ cl::desc("Remote execution (rsh/ssh) extra options"));
}
ToolExecutionError::~ToolExecutionError() throw() { }
OS << "\n";
// Rerun the compiler, capturing any error messages to print them.
- sys::Path ErrorFilename("error_messages");
+ sys::Path ErrorFilename("bugpoint.program_error_messages");
std::string ErrMsg;
if (ErrorFilename.makeUnique(true, &ErrMsg)) {
std::cerr << "Error making unique filename: " << ErrMsg << "\n";
if (Args) { ToolArgs = *Args; }
}
- virtual int ExecuteProgram(const std::string &Bytecode,
+ virtual int ExecuteProgram(const std::string &Bitcode,
const std::vector<std::string> &Args,
const std::string &InputFile,
const std::string &OutputFile,
};
}
-int LLI::ExecuteProgram(const std::string &Bytecode,
+int LLI::ExecuteProgram(const std::string &Bitcode,
const std::vector<std::string> &Args,
const std::string &InputFile,
const std::string &OutputFile,
for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
LLIArgs.push_back(ToolArgs[i].c_str());
- LLIArgs.push_back(Bytecode.c_str());
+ LLIArgs.push_back(Bitcode.c_str());
// Add optional parameters to the running program from Argv
for (unsigned i=0, e = Args.size(); i != e; ++i)
LLIArgs.push_back(Args[i].c_str());
return 0;
}
+//===---------------------------------------------------------------------===//
+// Custom execution command implementation of AbstractIntepreter interface
+//
+// Allows using a custom command for executing the bitcode, thus allows,
+// for example, to invoke a cross compiler for code generation followed by
+// a simulator that executes the generated binary.
+namespace {
+ class CustomExecutor : public AbstractInterpreter {
+ std::string ExecutionCommand;
+ std::vector<std::string> ExecutorArgs;
+ public:
+ CustomExecutor(
+ const std::string &ExecutionCmd, std::vector<std::string> ExecArgs) :
+ ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {}
+
+ virtual int ExecuteProgram(const std::string &Bitcode,
+ const std::vector<std::string> &Args,
+ const std::string &InputFile,
+ const std::string &OutputFile,
+ const std::vector<std::string> &GCCArgs,
+ const std::vector<std::string> &SharedLibs =
+ std::vector<std::string>(),
+ unsigned Timeout = 0,
+ unsigned MemoryLimit = 0);
+ };
+}
+
+int CustomExecutor::ExecuteProgram(const std::string &Bitcode,
+ const std::vector<std::string> &Args,
+ const std::string &InputFile,
+ const std::string &OutputFile,
+ const std::vector<std::string> &GCCArgs,
+ const std::vector<std::string> &SharedLibs,
+ unsigned Timeout,
+ unsigned MemoryLimit) {
+
+ std::vector<const char*> ProgramArgs;
+ ProgramArgs.push_back(ExecutionCommand.c_str());
+
+ for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
+ ProgramArgs.push_back(ExecutorArgs.at(i).c_str());
+ ProgramArgs.push_back(Bitcode.c_str());
+ ProgramArgs.push_back(0);
+
+ // Add optional parameters to the running program from Argv
+ for (unsigned i=0, e = Args.size(); i != e; ++i)
+ ProgramArgs.push_back(Args[i].c_str());
+
+ return RunProgramWithTimeout(
+ sys::Path(ExecutionCommand),
+ &ProgramArgs[0], sys::Path(InputFile), sys::Path(OutputFile),
+ sys::Path(OutputFile), Timeout, MemoryLimit);
+}
+
+// Custom execution environment create method, takes the execution command
+// as arguments
+AbstractInterpreter *AbstractInterpreter::createCustom(
+ const std::string &ProgramPath,
+ std::string &Message,
+ const std::string &ExecCommandLine) {
+
+ std::string Command = "";
+ std::vector<std::string> Args;
+ std::string delimiters = " ";
+
+ // Tokenize the ExecCommandLine to the command and the args to allow
+ // defining a full command line as the command instead of just the
+ // executed program. We cannot just pass the whole string after the command
+ // as a single argument because then program sees only a single
+ // command line argument (with spaces in it: "foo bar" instead
+ // of "foo" and "bar").
+
+ // code borrowed from:
+ // http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
+ std::string::size_type lastPos =
+ ExecCommandLine.find_first_not_of(delimiters, 0);
+ std::string::size_type pos =
+ ExecCommandLine.find_first_of(delimiters, lastPos);
+
+ while (std::string::npos != pos || std::string::npos != lastPos) {
+ std::string token = ExecCommandLine.substr(lastPos, pos - lastPos);
+ if (Command == "")
+ Command = token;
+ else
+ Args.push_back(token);
+ // Skip delimiters. Note the "not_of"
+ lastPos = ExecCommandLine.find_first_not_of(delimiters, pos);
+ // Find next "non-delimiter"
+ pos = ExecCommandLine.find_first_of(delimiters, lastPos);
+ }
+
+ std::string CmdPath = FindExecutable(Command, ProgramPath).toString();
+ if (CmdPath.empty()) {
+ Message =
+ std::string("Cannot find '") + Command +
+ "' in executable directory or PATH!\n";
+ return 0;
+ }
+
+ Message = "Found command in: " + CmdPath + "\n";
+
+ return new CustomExecutor(CmdPath, Args);
+}
+
//===----------------------------------------------------------------------===//
// LLC Implementation of AbstractIntepreter interface
//
-GCC::FileType LLC::OutputCode(const std::string &Bytecode,
+GCC::FileType LLC::OutputCode(const std::string &Bitcode,
sys::Path &OutputAsmFile) {
- sys::Path uniqueFile(Bytecode+".llc.s");
+ sys::Path uniqueFile(Bitcode+".llc.s");
std::string ErrMsg;
if (uniqueFile.makeUnique(true, &ErrMsg)) {
std::cerr << "Error making unique filename: " << ErrMsg << "\n";
LLCArgs.push_back ("-o");
LLCArgs.push_back (OutputAsmFile.c_str()); // Output to the Asm file
LLCArgs.push_back ("-f"); // Overwrite as necessary...
- LLCArgs.push_back (Bytecode.c_str()); // This is the input bytecode
+ LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
LLCArgs.push_back (0);
std::cout << "<llc>" << std::flush;
return GCC::AsmFile;
}
-void LLC::compileProgram(const std::string &Bytecode) {
+void LLC::compileProgram(const std::string &Bitcode) {
sys::Path OutputAsmFile;
- OutputCode(Bytecode, OutputAsmFile);
+ OutputCode(Bitcode, OutputAsmFile);
OutputAsmFile.eraseFromDisk();
}
-int LLC::ExecuteProgram(const std::string &Bytecode,
+int LLC::ExecuteProgram(const std::string &Bitcode,
const std::vector<std::string> &Args,
const std::string &InputFile,
const std::string &OutputFile,
unsigned MemoryLimit) {
sys::Path OutputAsmFile;
- OutputCode(Bytecode, OutputAsmFile);
+ OutputCode(Bitcode, OutputAsmFile);
FileRemover OutFileRemover(OutputAsmFile);
std::vector<std::string> GCCArgs(ArgsForGCC);
if (Args) { ToolArgs = *Args; }
}
- virtual int ExecuteProgram(const std::string &Bytecode,
+ virtual int ExecuteProgram(const std::string &Bitcode,
const std::vector<std::string> &Args,
const std::string &InputFile,
const std::string &OutputFile,
};
}
-int JIT::ExecuteProgram(const std::string &Bytecode,
+int JIT::ExecuteProgram(const std::string &Bitcode,
const std::vector<std::string> &Args,
const std::string &InputFile,
const std::string &OutputFile,
JITArgs.push_back("-load");
JITArgs.push_back(SharedLibs[i].c_str());
}
- JITArgs.push_back(Bytecode.c_str());
+ JITArgs.push_back(Bitcode.c_str());
// Add optional parameters to the running program from Argv
for (unsigned i=0, e = Args.size(); i != e; ++i)
JITArgs.push_back(Args[i].c_str());
return 0;
}
-GCC::FileType CBE::OutputCode(const std::string &Bytecode,
+GCC::FileType CBE::OutputCode(const std::string &Bitcode,
sys::Path &OutputCFile) {
- sys::Path uniqueFile(Bytecode+".cbe.c");
+ sys::Path uniqueFile(Bitcode+".cbe.c");
std::string ErrMsg;
if (uniqueFile.makeUnique(true, &ErrMsg)) {
std::cerr << "Error making unique filename: " << ErrMsg << "\n";
LLCArgs.push_back (OutputCFile.c_str()); // Output to the C file
LLCArgs.push_back ("-march=c"); // Output C language
LLCArgs.push_back ("-f"); // Overwrite as necessary...
- LLCArgs.push_back (Bytecode.c_str()); // This is the input bytecode
+ LLCArgs.push_back (Bitcode.c_str()); // This is the input bitcode
LLCArgs.push_back (0);
std::cout << "<cbe>" << std::flush;
return GCC::CFile;
}
-void CBE::compileProgram(const std::string &Bytecode) {
+void CBE::compileProgram(const std::string &Bitcode) {
sys::Path OutputCFile;
- OutputCode(Bytecode, OutputCFile);
+ OutputCode(Bitcode, OutputCFile);
OutputCFile.eraseFromDisk();
}
-int CBE::ExecuteProgram(const std::string &Bytecode,
+int CBE::ExecuteProgram(const std::string &Bitcode,
const std::vector<std::string> &Args,
const std::string &InputFile,
const std::string &OutputFile,
unsigned Timeout,
unsigned MemoryLimit) {
sys::Path OutputCFile;
- OutputCode(Bytecode, OutputCFile);
+ OutputCode(Bitcode, OutputCFile);
FileRemover CFileRemove(OutputCFile);
std::vector<const char*> ProgramArgs;
- if (RSHPath.isEmpty())
+ if (RemoteClientPath.isEmpty())
ProgramArgs.push_back(OutputBinary.c_str());
else {
- ProgramArgs.push_back(RSHPath.c_str());
- ProgramArgs.push_back(RSHHost.c_str());
+ ProgramArgs.push_back(RemoteClientPath.c_str());
+ ProgramArgs.push_back(RemoteHost.c_str());
ProgramArgs.push_back("-l");
- ProgramArgs.push_back(RSHUser.c_str());
+ ProgramArgs.push_back(RemoteUser.c_str());
+ if (!RemoteExtra.empty()) {
+ ProgramArgs.push_back(RemoteExtra.c_str());
+ }
char* env_pwd = getenv("PWD");
std::string Exec = "cd ";
FileRemover OutputBinaryRemover(OutputBinary);
- if (RSHPath.isEmpty())
+ if (RemoteClientPath.isEmpty())
return RunProgramWithTimeout(OutputBinary, &ProgramArgs[0],
sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
Timeout, MemoryLimit);
else
- return RunProgramWithTimeout(sys::Path(RSHPath), &ProgramArgs[0],
+ return RunProgramWithTimeout(sys::Path(RemoteClientPath), &ProgramArgs[0],
sys::Path(InputFile), sys::Path(OutputFile), sys::Path(OutputFile),
Timeout, MemoryLimit);
}
GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
GCCArgs.push_back("-fno-strict-aliasing");
GCCArgs.push_back(InputFile.c_str()); // Specify the input filename.
+ GCCArgs.push_back("-x");
+ GCCArgs.push_back("none");
#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc
#elif defined(__APPLE__)
GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others
#endif
-#if defined(__ia64__) || defined(__alpha__)
+#if defined(__ia64__) || defined(__alpha__) || defined(__amd64__)
GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC
#endif
#ifdef __sparc__
return 0;
}
- sys::Path RSHPath;
- if (!RSHHost.empty())
- RSHPath = FindExecutable("rsh", ProgramPath);
+ sys::Path RemoteClientPath;
+ if (!RemoteClient.empty())
+ RemoteClientPath = FindExecutable(RemoteClient.c_str(), ProgramPath);
Message = "Found gcc: " + GCCPath.toString() + "\n";
- return new GCC(GCCPath, RSHPath);
+ return new GCC(GCCPath, RemoteClientPath);
}