summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/bugpoint/BugDriver.cpp34
-rw-r--r--llvm/tools/bugpoint/BugDriver.h9
-rw-r--r--llvm/tools/bugpoint/OptimizerDriver.cpp110
-rw-r--r--llvm/tools/bugpoint/bugpoint.cpp9
4 files changed, 97 insertions, 65 deletions
diff --git a/llvm/tools/bugpoint/BugDriver.cpp b/llvm/tools/bugpoint/BugDriver.cpp
index 17e3374117a..bd558db6650 100644
--- a/llvm/tools/bugpoint/BugDriver.cpp
+++ b/llvm/tools/bugpoint/BugDriver.cpp
@@ -62,9 +62,9 @@ std::string llvm::getPassesString(const std::vector<const PassInfo*> &Passes) {
return Result;
}
-BugDriver::BugDriver(const char *toolname)
+BugDriver::BugDriver(const char *toolname, bool as_child)
: ToolName(toolname), ReferenceOutputFile(OutputFile),
- Program(0), Interpreter(0), cbe(0), gcc(0) {}
+ Program(0), Interpreter(0), cbe(0), gcc(0), run_as_child(as_child) {}
/// ParseInputFile - Given a bytecode or assembly input filename, parse and
@@ -97,13 +97,15 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
// Load the first input file...
Program = ParseInputFile(Filenames[0]);
if (Program == 0) return true;
- std::cout << "Read input file : '" << Filenames[0] << "'\n";
+ if (!run_as_child)
+ std::cout << "Read input file : '" << Filenames[0] << "'\n";
for (unsigned i = 1, e = Filenames.size(); i != e; ++i) {
std::auto_ptr<Module> M(ParseInputFile(Filenames[i]));
if (M.get() == 0) return true;
- std::cout << "Linking in input file: '" << Filenames[i] << "'\n";
+ if (!run_as_child)
+ std::cout << "Linking in input file: '" << Filenames[i] << "'\n";
std::string ErrorMessage;
if (Linker::LinkModules(Program, M.get(), &ErrorMessage)) {
std::cerr << ToolName << ": error linking in '" << Filenames[i] << "': "
@@ -112,7 +114,8 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
}
}
- std::cout << "*** All input ok\n";
+ if (!run_as_child)
+ std::cout << "*** All input ok\n";
// All input files read successfully!
return false;
@@ -124,12 +127,21 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
/// variables are set up from command line arguments.
///
bool BugDriver::run() {
- // The first thing that we must do is determine what the problem is. Does the
- // optimization series crash the compiler, or does it produce illegal code?
- // We make the top-level decision by trying to run all of the passes on the
- // the input program, which should generate a bytecode file. If it does
- // generate a bytecode file, then we know the compiler didn't crash, so try
- // to diagnose a miscompilation.
+ // The first thing to do is determine if we're running as a child. If we are,
+ // then what to do is very narrow. This form of invocation is only called
+ // from the runPasses method to actually run those passes in a child process.
+ if (run_as_child) {
+ // Execute the passes
+ return runPassesAsChild(PassesToRun);
+ }
+
+ // If we're not running as a child, the first thing that we must do is
+ // determine what the problem is. Does the optimization series crash the
+ // compiler, or does it produce illegal code? We make the top-level
+ // decision by trying to run all of the passes on the the input program,
+ // which should generate a bytecode file. If it does generate a bytecode
+ // file, then we know the compiler didn't crash, so try to diagnose a
+ // miscompilation.
if (!PassesToRun.empty()) {
std::cout << "Running selected passes on program to test for crash: ";
if (runPasses(PassesToRun))
diff --git a/llvm/tools/bugpoint/BugDriver.h b/llvm/tools/bugpoint/BugDriver.h
index 192ed527178..565a382d20a 100644
--- a/llvm/tools/bugpoint/BugDriver.h
+++ b/llvm/tools/bugpoint/BugDriver.h
@@ -47,13 +47,14 @@ class BugDriver {
AbstractInterpreter *Interpreter; // How to run the program
CBE *cbe;
GCC *gcc;
+ bool run_as_child;
// FIXME: sort out public/private distinctions...
friend class ReducePassList;
friend class ReduceMisCodegenFunctions;
public:
- BugDriver(const char *toolname);
+ BugDriver(const char *toolname, bool as_child);
const std::string &getToolName() const { return ToolName; }
@@ -71,7 +72,8 @@ public:
}
/// run - The top level method that is invoked after all of the instance
- /// variables are set up from command line arguments.
+ /// variables are set up from command line arguments. The \p as_child argument
+ /// indicates whether the driver is to run in parent mode or child mode.
///
bool run();
@@ -249,6 +251,9 @@ private:
return runPasses(PassesToRun, Filename, DeleteOutput);
}
+ /// runAsChild - The actual "runPasses" guts that runs in a child process.
+ int runPassesAsChild(const std::vector<const PassInfo*> &PassesToRun);
+
/// initializeExecutionEnvironment - This method is used to set up the
/// environment for executing LLVM programs.
///
diff --git a/llvm/tools/bugpoint/OptimizerDriver.cpp b/llvm/tools/bugpoint/OptimizerDriver.cpp
index 3a77e16d4ef..bac7f51de83 100644
--- a/llvm/tools/bugpoint/OptimizerDriver.cpp
+++ b/llvm/tools/bugpoint/OptimizerDriver.cpp
@@ -19,10 +19,6 @@
// independent code co-exist via conditional compilation until it is verified
// that the new code works correctly on Unix.
-#ifdef _MSC_VER
-#define PLATFORMINDEPENDENT
-#endif
-
#include "BugDriver.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
@@ -30,15 +26,18 @@
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/System/Path.h"
+#include "llvm/System/Program.h"
#include <fstream>
-#ifndef PLATFORMINDEPENDENT
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#endif
using namespace llvm;
+namespace {
+ // ChildOutput - This option captures the name of the child output file that
+ // is set up by the parent bugpoint process
+ cl::opt<std::string> ChildOutput("child-output", cl::ReallyHidden);
+}
+
/// writeProgramToFile - This writes the current "Program" to the named bytecode
/// file. If an error occurs, true is returned.
///
@@ -86,14 +85,14 @@ void BugDriver::EmitProgressBytecode(const std::string &ID, bool NoFlyer) {
std::cout << getPassesString(PassesToRun) << "\n";
}
-static void RunChild(Module *Program,const std::vector<const PassInfo*> &Passes,
- const std::string &OutFilename) {
+int BugDriver::runPassesAsChild(const std::vector<const PassInfo*> &Passes) {
+
std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
std::ios::binary;
- std::ofstream OutFile(OutFilename.c_str(), io_mode);
+ std::ofstream OutFile(ChildOutput.c_str(), io_mode);
if (!OutFile.good()) {
- std::cerr << "Error opening bytecode file: " << OutFilename << "\n";
- exit(1);
+ std::cerr << "Error opening bytecode file: " << ChildOutput << "\n";
+ return 1;
}
PassManager PM;
@@ -115,6 +114,8 @@ static void RunChild(Module *Program,const std::vector<const PassInfo*> &Passes,
// Run all queued passes.
PM.run(*Program);
+
+ return 0;
}
/// runPasses - Run the specified passes on Program, outputting a bytecode file
@@ -128,60 +129,67 @@ static void RunChild(Module *Program,const std::vector<const PassInfo*> &Passes,
bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
std::string &OutputFilename, bool DeleteOutput,
bool Quiet) const{
+ // setup the output file name
std::cout << std::flush;
sys::Path uniqueFilename("bugpoint-output.bc");
uniqueFilename.makeUnique();
OutputFilename = uniqueFilename.toString();
-#ifndef PLATFORMINDEPENDENT
- pid_t child_pid;
- switch (child_pid = fork()) {
- case -1: // Error occurred
- std::cerr << ToolName << ": Error forking!\n";
- exit(1);
- case 0: // Child process runs passes.
- RunChild(Program, Passes, OutputFilename);
- exit(0); // If we finish successfully, return 0!
- default: // Parent continues...
- break;
- }
-
- // Wait for the child process to get done.
- int Status;
- if (wait(&Status) != child_pid) {
- std::cerr << "Error waiting for child process!\n";
- exit(1);
+ // set up the input file name
+ sys::Path inputFilename("bugpoint-input.bc");
+ inputFilename.makeUnique();
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
+ std::ios::binary;
+ std::ofstream InFile(inputFilename.c_str(), io_mode);
+ if (!InFile.good()) {
+ std::cerr << "Error opening bytecode file: " << inputFilename << "\n";
+ return(1);
}
-
- bool ExitedOK = WIFEXITED(Status) && WEXITSTATUS(Status) == 0;
-#else
- bool ExitedOK = false;
-#endif
+ WriteBytecodeToFile(Program,InFile,false);
+ InFile.close();
+
+ // setup the child process' arguments
+ const char** args = (const char**)
+ alloca(sizeof(const char*)*(Passes.size()+10));
+ int n = 0;
+ args[n++] = ToolName.c_str();
+ args[n++] = "-as-child";
+ args[n++] = "-child-output";
+ args[n++] = OutputFilename.c_str();
+ std::vector<std::string> pass_args;
+ for (std::vector<const PassInfo*>::const_iterator I = Passes.begin(),
+ E = Passes.end(); I != E; ++I )
+ pass_args.push_back( std::string("-") + (*I)->getPassArgument() );
+ for (std::vector<std::string>::const_iterator I = pass_args.begin(),
+ E = pass_args.end(); I != E; ++I )
+ args[n++] = I->c_str();
+ args[n++] = inputFilename.c_str();
+ args[n++] = 0;
+
+ sys::Path prog(sys::Program::FindProgramByName(ToolName));
+ int result = sys::Program::ExecuteAndWait(prog,args);
// If we are supposed to delete the bytecode file or if the passes crashed,
// remove it now. This may fail if the file was never created, but that's ok.
- if (DeleteOutput || !ExitedOK)
+ if (DeleteOutput || result != 0)
sys::Path(OutputFilename).eraseFromDisk();
-#ifndef PLATFORMINDEPENDENT
+ // Remove the temporary input file as well
+ inputFilename.eraseFromDisk();
+
if (!Quiet) {
- if (ExitedOK)
+ if (result == 0)
std::cout << "Success!\n";
- else if (WIFEXITED(Status))
- std::cout << "Exited with error code '" << WEXITSTATUS(Status) << "'\n";
- else if (WIFSIGNALED(Status))
- std::cout << "Crashed with signal #" << WTERMSIG(Status) << "\n";
-#ifdef WCOREDUMP
- else if (WCOREDUMP(Status))
+ else if (result > 0)
+ std::cout << "Exited with error code '" << result << "'\n";
+ else if (result < 0)
+ std::cout << "Crashed with signal #" << abs(result) << "\n";
+ if (result & 0x01000000)
std::cout << "Dumped core\n";
-#endif
- else
- std::cout << "Failed for unknown reason!\n";
}
-#endif
// Was the child successful?
- return !ExitedOK;
+ return result != 0;
}
diff --git a/llvm/tools/bugpoint/bugpoint.cpp b/llvm/tools/bugpoint/bugpoint.cpp
index 0f25cf8a506..dde7286ae9f 100644
--- a/llvm/tools/bugpoint/bugpoint.cpp
+++ b/llvm/tools/bugpoint/bugpoint.cpp
@@ -24,6 +24,13 @@
#include "llvm/System/Signals.h"
using namespace llvm;
+// AsChild - Specifies that this invocation of bugpoint is being generated
+// from a parent process. It is not intended to be used by users so the
+// option is hidden.
+static cl::opt<bool>
+ AsChild("as-child", cl::desc("Run bugpoint as child process"),
+ cl::ReallyHidden);
+
static cl::list<std::string>
InputFilenames(cl::Positional, cl::OneOrMore,
cl::desc("<input llvm ll/bc files>"));
@@ -49,7 +56,7 @@ int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
sys::SetInterruptFunction(BugpointInterruptFunction);
- BugDriver D(argv[0]);
+ BugDriver D(argv[0],AsChild);
if (D.addSources(InputFilenames)) return 1;
D.addPasses(PassList.begin(), PassList.end());
OpenPOWER on IntegriCloud