summaryrefslogtreecommitdiff
path: root/tools/bugpoint
diff options
context:
space:
mode:
Diffstat (limited to 'tools/bugpoint')
-rw-r--r--tools/bugpoint/BugDriver.cpp3
-rw-r--r--tools/bugpoint/BugDriver.h10
-rw-r--r--tools/bugpoint/ExecutionDriver.cpp151
-rw-r--r--tools/bugpoint/Miscompilation.cpp18
4 files changed, 123 insertions, 59 deletions
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp
index acea37e1fe..19f9685677 100644
--- a/tools/bugpoint/BugDriver.cpp
+++ b/tools/bugpoint/BugDriver.cpp
@@ -65,7 +65,8 @@ std::string llvm::getPassesString(const std::vector<const PassInfo*> &Passes) {
BugDriver::BugDriver(const char *toolname, bool as_child, bool find_bugs,
unsigned timeout, unsigned memlimit)
: ToolName(toolname), ReferenceOutputFile(OutputFile),
- Program(0), Interpreter(0), cbe(0), gcc(0), run_as_child(as_child),
+ Program(0), Interpreter(0), SafeInterpreter(0), gcc(0),
+ run_as_child(as_child),
run_find_bugs(find_bugs), Timeout(timeout), MemoryLimit(memlimit) {}
diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h
index 2750575454..6a2105392f 100644
--- a/tools/bugpoint/BugDriver.h
+++ b/tools/bugpoint/BugDriver.h
@@ -45,7 +45,7 @@ class BugDriver {
Module *Program; // The raw program, linked together
std::vector<const PassInfo*> PassesToRun;
AbstractInterpreter *Interpreter; // How to run the program
- AbstractInterpreter *cbe;
+ AbstractInterpreter *SafeInterpreter; // To generate reference output, etc.
GCC *gcc;
bool run_as_child;
bool run_find_bugs;
@@ -140,9 +140,9 @@ public:
return OldProgram;
}
- AbstractInterpreter *switchToCBE() {
+ AbstractInterpreter *switchToSafeInterpreter() {
AbstractInterpreter *Old = Interpreter;
- Interpreter = (AbstractInterpreter*)cbe;
+ Interpreter = (AbstractInterpreter*)SafeInterpreter;
return Old;
}
@@ -172,11 +172,11 @@ public:
AbstractInterpreter *AI = 0,
bool *ProgramExitedNonzero = 0);
- /// executeProgramWithCBE - Used to create reference output with the C
+ /// executeProgramSafely - Used to create reference output with the "safe"
/// backend, if reference output is not provided. If there is a problem with
/// the code generator (e.g., llc crashes), this will throw an exception.
///
- std::string executeProgramWithCBE(std::string OutputFile = "");
+ std::string executeProgramSafely(std::string OutputFile = "");
/// createReferenceFile - calls compileProgram and then records the output
/// into ReferenceOutputFile. Returns true if reference file created, false
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp
index 821b842689..b3c802032d 100644
--- a/tools/bugpoint/ExecutionDriver.cpp
+++ b/tools/bugpoint/ExecutionDriver.cpp
@@ -39,7 +39,7 @@ namespace {
cl::init(0.0));
cl::opt<OutputType>
- InterpreterSel(cl::desc("Specify how LLVM code should be executed:"),
+ InterpreterSel(cl::desc("Specify the \"test\" i.e. suspect back-end:"),
cl::values(clEnumValN(AutoPick, "auto", "Use best guess"),
clEnumValN(RunLLI, "run-int",
"Execute with the interpreter"),
@@ -54,6 +54,22 @@ namespace {
clEnumValEnd),
cl::init(AutoPick));
+ cl::opt<OutputType>
+ SafeInterpreterSel(cl::desc("Specify \"safe\" i.e. known-good backend:"),
+ cl::values(clEnumValN(AutoPick, "safe-auto", "Use best guess"),
+ clEnumValN(RunLLC, "safe-run-llc", "Compile with LLC"),
+ clEnumValN(RunCBE, "safe-run-cbe", "Compile with CBE"),
+ clEnumValN(Custom, "safe-run-custom",
+ "Use -exec-command to define a command to execute "
+ "the bitcode. Useful for cross-compilation."),
+ clEnumValEnd),
+ cl::init(AutoPick));
+
+ cl::opt<std::string>
+ SafeInterpreterPath("safe-path",
+ cl::desc("Specify the path to the \"safe\" backend program"),
+ cl::init(""));
+
cl::opt<bool>
AppendProgramExitCode("append-exit-code",
cl::desc("Append the exit code to the output so it gets diff'd too"),
@@ -84,10 +100,17 @@ namespace llvm {
cl::list<std::string>
InputArgv("args", cl::Positional, cl::desc("<program arguments>..."),
cl::ZeroOrMore, cl::PositionalEatsArgs);
+}
+namespace {
cl::list<std::string>
ToolArgv("tool-args", cl::Positional, cl::desc("<tool arguments>..."),
cl::ZeroOrMore, cl::PositionalEatsArgs);
+
+ cl::list<std::string>
+ SafeToolArgv("safe-tool-args", cl::Positional,
+ cl::desc("<safe-tool arguments>..."),
+ cl::ZeroOrMore, cl::PositionalEatsArgs);
}
//===----------------------------------------------------------------------===//
@@ -102,14 +125,14 @@ bool BugDriver::initializeExecutionEnvironment() {
// Create an instance of the AbstractInterpreter interface as specified on
// the command line
- cbe = 0;
+ SafeInterpreter = 0;
std::string Message;
switch (InterpreterSel) {
case AutoPick:
InterpreterSel = RunCBE;
- Interpreter = cbe = AbstractInterpreter::createCBE(getToolName(), Message,
- &ToolArgv);
+ Interpreter =
+ AbstractInterpreter::createCBE(getToolName(), Message, &ToolArgv);
if (!Interpreter) {
InterpreterSel = RunJIT;
Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
@@ -135,6 +158,7 @@ bool BugDriver::initializeExecutionEnvironment() {
&ToolArgv);
break;
case RunLLC:
+ case LLC_Safe:
Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
&ToolArgv);
break;
@@ -142,10 +166,6 @@ bool BugDriver::initializeExecutionEnvironment() {
Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
&ToolArgv);
break;
- case LLC_Safe:
- Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
- &ToolArgv);
- break;
case RunCBE:
case CBE_bug:
Interpreter = AbstractInterpreter::createCBE(getToolName(), Message,
@@ -164,20 +184,71 @@ bool BugDriver::initializeExecutionEnvironment() {
else // Display informational messages on stdout instead of stderr
std::cout << Message;
- // Initialize auxiliary tools for debugging
- if (InterpreterSel == RunCBE) {
- // We already created a CBE, reuse it.
- cbe = Interpreter;
- } else if (InterpreterSel == CBE_bug || InterpreterSel == LLC_Safe) {
- // We want to debug the CBE itself or LLC is known-good. Use LLC as the
- // 'known-good' compiler.
- std::vector<std::string> ToolArgs;
- ToolArgs.push_back("--relocation-model=pic");
- cbe = AbstractInterpreter::createLLC(getToolName(), Message, &ToolArgs);
- } else {
- cbe = AbstractInterpreter::createCBE(getToolName(), Message, &ToolArgv);
+ std::string Path = SafeInterpreterPath;
+ if (Path.empty())
+ Path = getToolName();
+ std::vector<std::string> SafeToolArgs = SafeToolArgv;
+ switch (SafeInterpreterSel) {
+ case AutoPick:
+ // In "cbe-bug" mode, default to using LLC as the "safe" backend.
+ if (!SafeInterpreter &&
+ InterpreterSel == CBE_bug) {
+ SafeInterpreterSel = RunLLC;
+ SafeToolArgs.push_back("--relocation-model=pic");
+ SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ &SafeToolArgs);
+ }
+
+ // In "llc-safe" mode, default to using LLC as the "safe" backend.
+ if (!SafeInterpreter &&
+ InterpreterSel == LLC_Safe) {
+ SafeInterpreterSel = RunLLC;
+ SafeToolArgs.push_back("--relocation-model=pic");
+ SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ &SafeToolArgs);
+ }
+
+ // Pick a backend that's different from the test backend. The JIT and
+ // LLC backends share a lot of code, so prefer to use the CBE as the
+ // safe back-end when testing them.
+ if (!SafeInterpreter &&
+ InterpreterSel != RunCBE) {
+ SafeInterpreterSel = RunCBE;
+ SafeInterpreter = AbstractInterpreter::createCBE(Path, Message,
+ &SafeToolArgs);
+ }
+ if (!SafeInterpreter &&
+ InterpreterSel != RunLLC &&
+ InterpreterSel != RunJIT) {
+ SafeInterpreterSel = RunLLC;
+ SafeToolArgs.push_back("--relocation-model=pic");
+ SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ &SafeToolArgs);
+ }
+ if (!SafeInterpreter) {
+ SafeInterpreterSel = AutoPick;
+ Message = "Sorry, I can't automatically select an interpreter!\n";
+ }
+ break;
+ case RunLLC:
+ SafeToolArgs.push_back("--relocation-model=pic");
+ SafeInterpreter = AbstractInterpreter::createLLC(Path, Message,
+ &SafeToolArgs);
+ break;
+ case RunCBE:
+ SafeInterpreter = AbstractInterpreter::createCBE(Path, Message,
+ &SafeToolArgs);
+ break;
+ case Custom:
+ SafeInterpreter = AbstractInterpreter::createCustom(Path, Message,
+ CustomExecCommand);
+ break;
+ default:
+ Message = "Sorry, this back-end is not supported by bugpoint as the "
+ "\"safe\" backend right now!\n";
+ break;
}
- if (!cbe) { std::cout << Message << "\nExiting.\n"; exit(1); }
+ if (!SafeInterpreter) { std::cout << Message << "\nExiting.\n"; exit(1); }
gcc = GCC::create(getToolName(), Message);
if (!gcc) { std::cout << Message << "\nExiting.\n"; exit(1); }
@@ -264,20 +335,9 @@ std::string BugDriver::executeProgram(std::string OutputFile,
if (!SharedObj.empty())
SharedObjs.push_back(SharedObj);
-
- // If this is an LLC or CBE run, then the GCC compiler might get run to
- // compile the program. If so, we should pass the user's -Xlinker options
- // as the GCCArgs.
- int RetVal = 0;
- if (InterpreterSel == RunLLC || InterpreterSel == RunCBE ||
- InterpreterSel == CBE_bug || InterpreterSel == LLC_Safe)
- RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile,
- OutputFile, AdditionalLinkerArgs, SharedObjs,
- Timeout, MemoryLimit);
- else
- RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile,
- OutputFile, std::vector<std::string>(),
- SharedObjs, Timeout, MemoryLimit);
+ int RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile,
+ OutputFile, AdditionalLinkerArgs, SharedObjs,
+ Timeout, MemoryLimit);
if (RetVal == -1) {
std::cerr << "<timeout>";
@@ -305,12 +365,12 @@ std::string BugDriver::executeProgram(std::string OutputFile,
return OutputFile;
}
-/// executeProgramWithCBE - Used to create reference output with the C
+/// executeProgramSafely - Used to create reference output with the "safe"
/// backend, if reference output is not provided.
///
-std::string BugDriver::executeProgramWithCBE(std::string OutputFile) {
+std::string BugDriver::executeProgramSafely(std::string OutputFile) {
bool ProgramExitedNonzero;
- std::string outFN = executeProgram(OutputFile, "", "", cbe,
+ std::string outFN = executeProgram(OutputFile, "", "", SafeInterpreter,
&ProgramExitedNonzero);
return outFN;
}
@@ -319,8 +379,8 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile) {
assert(Interpreter && "Interpreter should have been created already!");
sys::Path OutputFile;
- // Using CBE
- GCC::FileType FT = cbe->OutputCode(BitcodeFile, OutputFile);
+ // Using the known-good backend.
+ GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile);
std::string SharedObjectFile;
if (gcc->MakeSharedObject(OutputFile.toString(), FT,
@@ -345,14 +405,15 @@ bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
return false;
}
try {
- ReferenceOutputFile = executeProgramWithCBE(Filename);
+ ReferenceOutputFile = executeProgramSafely(Filename);
std::cout << "Reference output is: " << ReferenceOutputFile << "\n\n";
} catch (ToolExecutionError &TEE) {
std::cerr << TEE.what();
- if (Interpreter != cbe) {
- std::cerr << "*** There is a bug running the C backend. Either debug"
- << " it (use the -run-cbe bugpoint option), or fix the error"
- << " some other way.\n";
+ if (Interpreter != SafeInterpreter) {
+ std::cerr << "*** There is a bug running the \"safe\" backend. Either"
+ << " debug it (for example with the -run-cbe bugpoint option,"
+ << " if CBE is being used as the \"safe\" backend), or fix the"
+ << " error some other way.\n";
}
return false;
}
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index d57e52b10b..6a0911bfb5 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -277,7 +277,7 @@ static bool ExtractLoops(BugDriver &BD,
// we're going to test the newly loop extracted program to make sure nothing
// has broken. If something broke, then we'll inform the user and stop
// extraction.
- AbstractInterpreter *AI = BD.switchToCBE();
+ AbstractInterpreter *AI = BD.switchToSafeInterpreter();
if (TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, false)) {
BD.switchToInterpreter(AI);
@@ -838,13 +838,15 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe) {
/// debugCodeGenerator - debug errors in LLC, LLI, or CBE.
///
bool BugDriver::debugCodeGenerator() {
- if ((void*)cbe == (void*)Interpreter) {
- std::string Result = executeProgramWithCBE("bugpoint.cbe.out");
- std::cout << "\n*** The C backend cannot match the reference diff, but it "
- << "is used as the\n 'known good' code generator, so I can't"
- << " debug it. Perhaps you have a\n front-end problem? As a"
- << " sanity check, I left the result of executing the\n "
- << "program with the C backend in this file for you: '"
+ if ((void*)SafeInterpreter == (void*)Interpreter) {
+ std::string Result = executeProgramSafely("bugpoint.safe.out");
+ std::cout << "\n*** The \"safe\" i.e. 'known good' backend cannot match "
+ << "the reference diff. This may be due to a\n front-end "
+ << "bug or a bug in the original program, but this can also "
+ << "happen if bugpoint isn't running the program with the "
+ << "right flags or input.\n I left the result of executing "
+ << "the program with the \"safe\" backend in this file for "
+ << "you: '"
<< Result << "'.\n";
return true;
}