This PR re-introduces LLVM's bugpoint tool from the LLVM 3.7 release which had previously been deleted in the DXC fork. This tool is extremely useful for reducing complex test cases to small reproductions.
I have not tested the tool to verify its degree of functionality, if we find it useful we may wish to invest in making it work better with the HLSL-specific changes in DXC's repository.
:warning: C/C++ code formatter, clang-format found issues in your code. :warning:
You can test this locally with the following command:
``````````bash
git-clang-format --diff 206133c9e7e182ba0f238d5f8792977ef5ce9280 ebcca5c841c60ca2baf5fe0184ee595ac729cb38 -- tools/bugpoint-passes/TestPasses.cpp tools/bugpoint/BugDriver.cpp tools/bugpoint/BugDriver.h tools/bugpoint/CrashDebugger.cpp tools/bugpoint/ExecutionDriver.cpp tools/bugpoint/ExtractFunction.cpp tools/bugpoint/FindBugs.cpp tools/bugpoint/ListReducer.h tools/bugpoint/Miscompilation.cpp tools/bugpoint/OptimizerDriver.cpp tools/bugpoint/ToolRunner.cpp tools/bugpoint/ToolRunner.h tools/bugpoint/bugpoint.cpp
``````````
View the diff from clang-format here.
``````````diff
diff --git a/tools/bugpoint-passes/TestPasses.cpp b/tools/bugpoint-passes/TestPasses.cpp
index 6979d034..8fac5231 100644
--- a/tools/bugpoint-passes/TestPasses.cpp
+++ b/tools/bugpoint-passes/TestPasses.cpp
@@ -22,78 +22,81 @@
using namespace llvm;
namespace {
- /// CrashOnCalls - This pass is used to test bugpoint. It intentionally
- /// crashes on any call instructions.
- class CrashOnCalls : public BasicBlockPass {
- public:
- static char ID; // Pass ID, replacement for typeid
- CrashOnCalls() : BasicBlockPass(ID) {}
- private:
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
+/// CrashOnCalls - This pass is used to test bugpoint. It intentionally
+/// crashes on any call instructions.
+class CrashOnCalls : public BasicBlockPass {
+public:
+ static char ID; // Pass ID, replacement for typeid
+ CrashOnCalls() : BasicBlockPass(ID) {}
- bool runOnBasicBlock(BasicBlock &BB) override {
- for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
- if (isa(*I))
- abort();
+private:
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
- return false;
- }
- };
-}
+ bool runOnBasicBlock(BasicBlock &BB) override {
+ for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
+ if (isa(*I))
+ abort();
+
+ return false;
+ }
+};
+} // namespace
char CrashOnCalls::ID = 0;
static RegisterPass
- X("bugpoint-crashcalls",
- "BugPoint Test Pass - Intentionally crash on CallInsts");
+ X("bugpoint-crashcalls",
+ "BugPoint Test Pass - Intentionally crash on CallInsts");
namespace {
- /// DeleteCalls - This pass is used to test bugpoint. It intentionally
- /// deletes some call instructions, "misoptimizing" the program.
- class DeleteCalls : public BasicBlockPass {
- public:
- static char ID; // Pass ID, replacement for typeid
- DeleteCalls() : BasicBlockPass(ID) {}
- private:
- bool runOnBasicBlock(BasicBlock &BB) override {
- for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
- if (CallInst *CI = dyn_cast(I)) {
- if (!CI->use_empty())
- CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
- CI->getParent()->getInstList().erase(CI);
- break;
- }
- return false;
- }
- };
-}
+/// DeleteCalls - This pass is used to test bugpoint. It intentionally
+/// deletes some call instructions, "misoptimizing" the program.
+class DeleteCalls : public BasicBlockPass {
+public:
+ static char ID; // Pass ID, replacement for typeid
+ DeleteCalls() : BasicBlockPass(ID) {}
+
+private:
+ bool runOnBasicBlock(BasicBlock &BB) override {
+ for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
+ if (CallInst *CI = dyn_cast(I)) {
+ if (!CI->use_empty())
+ CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
+ CI->getParent()->getInstList().erase(CI);
+ break;
+ }
+ return false;
+ }
+};
+} // namespace
char DeleteCalls::ID = 0;
static RegisterPass
- Y("bugpoint-deletecalls",
- "BugPoint Test Pass - Intentionally 'misoptimize' CallInsts");
+ Y("bugpoint-deletecalls",
+ "BugPoint Test Pass - Intentionally 'misoptimize' CallInsts");
namespace {
- /// CrashOnDeclFunc - This pass is used to test bugpoint. It intentionally
- /// crash if the module has an undefined function (ie a function that is
- /// defined in an external module).
- class CrashOnDeclFunc : public ModulePass {
- public:
- static char ID; // Pass ID, replacement for typeid
- CrashOnDeclFunc() : ModulePass(ID) {}
- private:
- bool runOnModule(Module &M) override {
- for (auto &F : M.functions()) {
- if (F.isDeclaration())
- abort();
- }
- return false;
+/// CrashOnDeclFunc - This pass is used to test bugpoint. It intentionally
+/// crash if the module has an undefined function (ie a function that is
+/// defined in an external module).
+class CrashOnDeclFunc : public ModulePass {
+public:
+ static char ID; // Pass ID, replacement for typeid
+ CrashOnDeclFunc() : ModulePass(ID) {}
+
+private:
+ bool runOnModule(Module &M) override {
+ for (auto &F : M.functions()) {
+ if (F.isDeclaration())
+ abort();
}
- };
-}
+ return false;
+ }
+};
+} // namespace
char CrashOnDeclFunc::ID = 0;
static RegisterPass
- Z("bugpoint-crash-decl-funcs",
- "BugPoint Test Pass - Intentionally crash on declared functions");
+ Z("bugpoint-crash-decl-funcs",
+ "BugPoint Test Pass - Intentionally crash on declared functions");
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp
index 43f4c296..a6699828 100644
--- a/tools/bugpoint/BugDriver.cpp
+++ b/tools/bugpoint/BugDriver.cpp
@@ -29,21 +29,21 @@
using namespace llvm;
namespace llvm {
- Triple TargetTriple;
+Triple TargetTriple;
}
// Anonymous namespace to define command line options for debugging.
//
namespace {
- // Output - The user can specify a file containing the expected output of the
- // program. If this filename is set, it is used as the reference diff source,
- // otherwise the raw input run through an interpreter is used as the reference
- // source.
- //
- cl::opt
- OutputFile("output", cl::desc("Specify a reference program output "
- "(for miscompilation detection)"));
-}
+// Output - The user can specify a file containing the expected output of the
+// program. If this filename is set, it is used as the reference diff source,
+// otherwise the raw input run through an interpreter is used as the reference
+// source.
+//
+cl::opt OutputFile("output",
+ cl::desc("Specify a reference program output "
+ "(for miscompilation detection)"));
+} // namespace
/// setNewProgram - If we reduce or update the program somehow, call this method
/// to update bugdriver with it. This deletes the old module and sets the
@@ -53,27 +53,26 @@ void BugDriver::setNewProgram(Module *M) {
Program = M;
}
-
/// getPassesString - Turn a list of passes into a string which indicates the
/// command line options that must be passed to add the passes.
///
std::string llvm::getPassesString(const std::vector &Passes) {
std::string Result;
for (unsigned i = 0, e = Passes.size(); i != e; ++i) {
- if (i) Result += " ";
+ if (i)
+ Result += " ";
Result += "-";
Result += Passes[i];
}
return Result;
}
-BugDriver::BugDriver(const char *toolname, bool find_bugs,
- unsigned timeout, unsigned memlimit, bool use_valgrind,
- LLVMContext& ctxt)
- : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile),
- Program(nullptr), Interpreter(nullptr), SafeInterpreter(nullptr),
- gcc(nullptr), run_find_bugs(find_bugs), Timeout(timeout),
- MemoryLimit(memlimit), UseValgrind(use_valgrind) {}
+BugDriver::BugDriver(const char *toolname, bool find_bugs, unsigned timeout,
+ unsigned memlimit, bool use_valgrind, LLVMContext &ctxt)
+ : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile),
+ Program(nullptr), Interpreter(nullptr), SafeInterpreter(nullptr),
+ gcc(nullptr), run_find_bugs(find_bugs), Timeout(timeout),
+ MemoryLimit(memlimit), UseValgrind(use_valgrind) {}
BugDriver::~BugDriver() {
delete Program;
@@ -123,13 +122,15 @@ bool BugDriver::addSources(const std::vector &Filenames) {
// Load the first input file.
Program = parseInputFile(Filenames[0], Context).release();
- if (!Program) return true;
+ if (!Program)
+ return true;
outs() << "Read input file : '" << Filenames[0] << "'\n";
for (unsigned i = 1, e = Filenames.size(); i != e; ++i) {
std::unique_ptr M = parseInputFile(Filenames[i], Context);
- if (!M.get()) return true;
+ if (!M.get())
+ return true;
outs() << "Linking in input file: '" << Filenames[i] << "'\n";
if (Linker::LinkModules(Program, M.get()))
@@ -142,8 +143,6 @@ bool BugDriver::addSources(const std::vector &Filenames) {
return false;
}
-
-
/// run - The top level method that is invoked after all of the instance
/// variables are set up from command line arguments.
///
@@ -168,7 +167,8 @@ bool BugDriver::run(std::string &ErrMsg) {
}
// Set up the execution environment, selecting a method to run LLVM bitcode.
- if (initializeExecutionEnvironment()) return true;
+ if (initializeExecutionEnvironment())
+ return true;
// Test to see if we have a code generator crash.
outs() << "Running the code generator to test for a crash: ";
@@ -227,9 +227,10 @@ bool BugDriver::run(std::string &ErrMsg) {
return Failure;
}
-void llvm::PrintFunctionList(const std::vector &Funcs) {
+void llvm::PrintFunctionList(const std::vector &Funcs) {
unsigned NumPrint = Funcs.size();
- if (NumPrint > 10) NumPrint = 10;
+ if (NumPrint > 10)
+ NumPrint = 10;
for (unsigned i = 0; i != NumPrint; ++i)
outs() << " " << Funcs[i]->getName();
if (NumPrint < Funcs.size())
@@ -237,9 +238,10 @@ void llvm::PrintFunctionList(const std::vector &Funcs) {
outs().flush();
}
-void llvm::PrintGlobalVariableList(const std::vector &GVs) {
+void llvm::PrintGlobalVariableList(const std::vector &GVs) {
unsigned NumPrint = GVs.size();
- if (NumPrint > 10) NumPrint = 10;
+ if (NumPrint > 10)
+ NumPrint = 10;
for (unsigned i = 0; i != NumPrint; ++i)
outs() << " " << GVs[i]->getName();
if (NumPrint < GVs.size())
diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h
index 57978124..68a73742 100644
--- a/tools/bugpoint/BugDriver.h
+++ b/tools/bugpoint/BugDriver.h
@@ -45,13 +45,13 @@ extern bool DisableSimplifyCFG;
extern bool BugpointIsInterrupted;
class BugDriver {
- LLVMContext& Context;
+ LLVMContext &Context;
const char *ToolName; // argv[0] of bugpoint
std::string ReferenceOutputFile; // Name of `good' output file
- Module *Program; // The raw program, linked together
+ Module *Program; // The raw program, linked together
std::vector PassesToRun;
- AbstractInterpreter *Interpreter; // How to run the program
- AbstractInterpreter *SafeInterpreter; // To generate reference output, etc.
+ AbstractInterpreter *Interpreter; // How to run the program
+ AbstractInterpreter *SafeInterpreter; // To generate reference output, etc.
GCC *gcc;
bool run_find_bugs;
unsigned Timeout;
@@ -63,14 +63,13 @@ class BugDriver {
friend class ReduceMisCodegenFunctions;
public:
- BugDriver(const char *toolname, bool find_bugs,
- unsigned timeout, unsigned memlimit, bool use_valgrind,
- LLVMContext& ctxt);
+ BugDriver(const char *toolname, bool find_bugs, unsigned timeout,
+ unsigned memlimit, bool use_valgrind, LLVMContext &ctxt);
~BugDriver();
const char *getToolName() const { return ToolName; }
- LLVMContext& getContext() const { return Context; }
+ LLVMContext &getContext() const { return Context; }
// Set up methods... these methods are used to copy information about the
// command line arguments into instance variables of BugDriver.
@@ -80,9 +79,7 @@ public:
void setPassesToRun(const std::vector &PTR) {
PassesToRun = PTR;
}
- const std::vector &getPassesToRun() const {
- return PassesToRun;
- }
+ const std::vector &getPassesToRun() const { return PassesToRun; }
/// run - The top level method that is invoked after all of the instance
/// variables are set up from command line arguments. The \p as_child argument
@@ -132,9 +129,7 @@ public:
/// runPasses - Run all of the passes in the "PassesToRun" list, discard the
/// output, and return true if any of the passes crashed.
- bool runPasses(Module *M) const {
- return runPasses(M, PassesToRun);
- }
+ bool runPasses(Module *M) const { return runPasses(M, PassesToRun); }
Module *getProgram() const { return Program; }
@@ -148,13 +143,11 @@ public:
AbstractInterpreter *switchToSafeInterpreter() {
AbstractInterpreter *Old = Interpreter;
- Interpreter = (AbstractInterpreter*)SafeInterpreter;
+ Interpreter = (AbstractInterpreter *)SafeInterpreter;
return Old;
}
- void switchToInterpreter(AbstractInterpreter *AI) {
- Interpreter = AI;
- }
+ void switchToInterpreter(AbstractInterpreter *AI) { Interpreter = AI; }
/// setNewProgram - If we reduce or update the program somehow, call this
/// method to update bugdriver with it. This deletes the old module and sets
@@ -170,12 +163,10 @@ public:
/// executeProgram - This method runs "Program", capturing the output of the
/// program to a file. A recommended filename may be optionally specified.
///
- std::string executeProgram(const Module *Program,
- std::string OutputFilename,
+ std::string executeProgram(const Module *Program, std::string OutputFilename,
std::string Bitcode,
const std::string &SharedObjects,
- AbstractInterpreter *AI,
- std::string *Error) const;
+ AbstractInterpreter *AI, std::string *Error) const;
/// executeProgramSafely - Used to create reference output with the "safe"
/// backend, if reference output is not provided. If there is a problem with
@@ -187,20 +178,19 @@ public:
std::string *Error) const;
/// createReferenceFile - calls compileProgram and then records the output
- /// into ReferenceOutputFile. Returns true if reference file created, false
+ /// into ReferenceOutputFile. Returns true if reference file created, false
/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE
/// this function.
///
- bool createReferenceFile(Module *M, const std::string &Filename
- = "bugpoint.reference.out-%%%%%%%");
+ bool createReferenceFile(Module *M, const std::string &Filename =
+ "bugpoint.reference.out-%%%%%%%");
/// diffProgram - This method executes the specified module and diffs the
/// output against the file specified by ReferenceOutputFile. If the output
/// is different, 1 is returned. If there is a problem with the code
/// generator (e.g., llc crashes), this will return -1 and set Error.
///
- bool diffProgram(const Module *Program,
- const std::string &BitcodeFile = "",
+ bool diffProgram(const Module *Program, const std::string &BitcodeFile = "",
const std::string &SharedObj = "",
bool RemoveBitcode = false,
std::string *Error = nullptr) const;
@@ -261,18 +251,18 @@ public:
/// or failed, unless Quiet is set. ExtraArgs specifies additional arguments
/// to pass to the child bugpoint instance.
///
- bool runPasses(Module *Program,
- const std::vector &PassesToRun,
+ bool runPasses(Module *Program, const std::vector &PassesToRun,
std::string &OutputFilename, bool DeleteOutput = false,
bool Quiet = false, unsigned NumExtraArgs = 0,
- const char * const *ExtraArgs = nullptr) const;
-
- /// runManyPasses - Take the specified pass list and create different
- /// combinations of passes to compile the program with. Compile the program with
- /// each set and mark test to see if it compiled correctly. If the passes
- /// compiled correctly output nothing and rearrange the passes into a new order.
- /// If the passes did not compile correctly, output the command required to
- /// recreate the failure. This returns true if a compiler error is found.
+ const char *const *ExtraArgs = nullptr) const;
+
+ /// runManyPasses - Take the specified pass list and create different
+ /// combinations of passes to compile the program with. Compile the program
+ /// with each set and mark test to see if it compiled correctly. If the passes
+ /// compiled correctly output nothing and rearrange the passes into a new
+ /// order. If the passes did not compile correctly, output the command
+ /// required to recreate the failure. This returns true if a compiler error is
+ /// found.
///
bool runManyPasses(const std::vector &AllPasses,
std::string &ErrMsg);
@@ -289,8 +279,7 @@ private:
/// false indicating whether or not the optimizer crashed on the specified
/// input (true = crashed).
///
- bool runPasses(Module *M,
- const std::vector &PassesToRun,
+ bool runPasses(Module *M, const std::vector &PassesToRun,
bool DeleteOutput = true) const {
std::string Filename;
return runPasses(M, PassesToRun, Filename, DeleteOutput);
@@ -315,11 +304,11 @@ std::string getPassesString(const std::vector &Passes);
/// PrintFunctionList - prints out list of problematic functions
///
-void PrintFunctionList(const std::vector &Funcs);
+void PrintFunctionList(const std::vector &Funcs);
/// PrintGlobalVariableList - prints out list of problematic global variables
///
-void PrintGlobalVariableList(const std::vector &GVs);
+void PrintGlobalVariableList(const std::vector &GVs);
// DeleteFunctionBody - "Remove" the function by deleting all of it's basic
// blocks, making it external.
@@ -329,9 +318,9 @@ void DeleteFunctionBody(Function *F);
/// SplitFunctionsOutOfModule - Given a module and a list of functions in the
/// module, split the functions OUT of the specified module, and place them in
/// the new module.
-Module *SplitFunctionsOutOfModule(Module *M, const std::vector &F,
+Module *SplitFunctionsOutOfModule(Module *M, const std::vector &F,
ValueToValueMapTy &VMap);
-} // End llvm namespace
+} // namespace llvm
#endif
diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp
index e2aaf6b0..954742f0 100644
--- a/tools/bugpoint/CrashDebugger.cpp
+++ b/tools/bugpoint/CrashDebugger.cpp
@@ -32,45 +32,42 @@
using namespace llvm;
namespace {
- cl::opt
- KeepMain("keep-main",
- cl::desc("Force function reduction to keep main"),
- cl::init(false));
- cl::opt
- NoGlobalRM ("disable-global-remove",
- cl::desc("Do not remove global variables"),
- cl::init(false));
-
- cl::opt
- ReplaceFuncsWithNull("replace-funcs-with-null",
- cl::desc("When stubbing functions, replace all uses will null"),
- cl::init(false));
- cl::opt
- DontReducePassList("disable-pass-list-reduction",
- cl::desc("Skip pass list reduction steps"),
- cl::init(false));
-}
+cl::opt KeepMain("keep-main",
+ cl::desc("Force function reduction to keep main"),
+ cl::init(false));
+cl::opt NoGlobalRM("disable-global-remove",
+ cl::desc("Do not remove global variables"),
+ cl::init(false));
+
+cl::opt ReplaceFuncsWithNull(
+ "replace-funcs-with-null",
+ cl::desc("When stubbing functions, replace all uses will null"),
+ cl::init(false));
+cl::opt DontReducePassList("disable-pass-list-reduction",
+ cl::desc("Skip pass list reduction steps"),
+ cl::init(false));
+} // namespace
namespace llvm {
- class ReducePassList : public ListReducer {
- BugDriver &BD;
- public:
- ReducePassList(BugDriver &bd) : BD(bd) {}
-
- // doTest - Return true iff running the "removed" passes succeeds, and
- // running the "Kept" passes fail when run on the output of the "removed"
- // passes. If we return true, we update the current module of bugpoint.
- //
- TestResult doTest(std::vector &Removed,
- std::vector &Kept,
- std::string &Error) override;
- };
-}
+class ReducePassList : public ListReducer {
+ BugDriver &BD;
+
+public:
+ ReducePassList(BugDriver &bd) : BD(bd) {}
+
+ // doTest - Return true iff running the "removed" passes succeeds, and
+ // running the "Kept" passes fail when run on the output of the "removed"
+ // passes. If we return true, we update the current module of bugpoint.
+ //
+ TestResult doTest(std::vector &Removed,
+ std::vector &Kept,
+ std::string &Error) override;
+};
+} // namespace llvm
ReducePassList::TestResult
ReducePassList::doTest(std::vector &Prefix,
- std::vector &Suffix,
- std::string &Error) {
+ std::vector &Suffix, std::string &Error) {
std::string PrefixOutput;
Module *OrigProgram = nullptr;
if (!Prefix.empty()) {
@@ -90,11 +87,11 @@ ReducePassList::doTest(std::vector &Prefix,
sys::fs::remove(PrefixOutput);
}
- outs() << "Checking to see if these passes crash: "
- << getPassesString(Suffix) << ": ";
+ outs() << "Checking to see if these passes crash: " << getPassesString(Suffix)
+ << ": ";
if (BD.runPasses(BD.getProgram(), Suffix)) {
- delete OrigProgram; // The suffix crashes alone...
+ delete OrigProgram; // The suffix crashes alone...
return KeepSuffix;
}
@@ -107,44 +104,44 @@ ReducePassList::doTest(std::vector &Prefix,
}
namespace {
- /// ReduceCrashingGlobalVariables - This works by removing the global
- /// variable's initializer and seeing if the program still crashes. If it
- /// does, then we keep that program and try again.
- ///
- class ReduceCrashingGlobalVariables : public ListReducer {
- BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
- public:
- ReduceCrashingGlobalVariables(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *))
+/// ReduceCrashingGlobalVariables - This works by removing the global
+/// variable's initializer and seeing if the program still crashes. If it
+/// does, then we keep that program and try again.
+///
+class ReduceCrashingGlobalVariables : public ListReducer {
+ BugDriver &BD;
+ bool (*TestFn)(const BugDriver &, Module *);
+
+public:
+ ReduceCrashingGlobalVariables(BugDriver &bd,
+ bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
- TestResult doTest(std::vector &Prefix,
- std::vector &Kept,
- std::string &Error) override {
- if (!Kept.empty() && TestGlobalVariables(Kept))
- return KeepSuffix;
- if (!Prefix.empty() && TestGlobalVariables(Prefix))
- return KeepPrefix;
- return NoFailure;
- }
+ TestResult doTest(std::vector &Prefix,
+ std::vector &Kept,
+ std::string &Error) override {
+ if (!Kept.empty() && TestGlobalVariables(Kept))
+ return KeepSuffix;
+ if (!Prefix.empty() && TestGlobalVariables(Prefix))
+ return KeepPrefix;
+ return NoFailure;
+ }
- bool TestGlobalVariables(std::vector &GVs);
- };
-}
+ bool TestGlobalVariables(std::vector &GVs);
+};
+} // namespace
-bool
-ReduceCrashingGlobalVariables::TestGlobalVariables(
- std::vector &GVs) {
+bool ReduceCrashingGlobalVariables::TestGlobalVariables(
+ std::vector &GVs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
Module *M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
- std::set GVSet;
+ std::set GVSet;
for (unsigned i = 0, e = GVs.size(); i != e; ++i) {
- GlobalVariable* CMGV = cast(VMap[GVs[i]]);
+ GlobalVariable *CMGV = cast(VMap[GVs[i]]);
assert(CMGV && "Global Variable not in module?!");
GVSet.insert(CMGV);
}
@@ -164,7 +161,7 @@ ReduceCrashingGlobalVariables::TestGlobalVariables(
// Try running the hacked up program...
if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ BD.setNewProgram(M); // It crashed, keep the trimmed version...
// Make sure to use global variable pointers that point into the now-current
// module.
@@ -177,45 +174,47 @@ ReduceCrashingGlobalVariables::TestGlobalVariables(
}
namespace {
- /// ReduceCrashingFunctions reducer - This works by removing functions and
- /// seeing if the program still crashes. If it does, then keep the newer,
- /// smaller program.
- ///
- class ReduceCrashingFunctions : public ListReducer {
- BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
- public:
- ReduceCrashingFunctions(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *))
+/// ReduceCrashingFunctions reducer - This works by removing functions and
+/// seeing if the program still crashes. If it does, then keep the newer,
+/// smaller program.
+///
+class ReduceCrashingFunctions : public ListReducer {
+ BugDriver &BD;
+ bool (*TestFn)(const BugDriver &, Module *);
+
+public:
+ ReduceCrashingFunctions(BugDriver &bd,
+ bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
- TestResult doTest(std::vector &Prefix,
- std::vector &Kept,
- std::string &Error) override {
- if (!Kept.empty() && TestFuncs(Kept))
- return KeepSuffix;
- if (!Prefix.empty() && TestFuncs(Prefix))
- return KeepPrefix;
- return NoFailure;
- }
+ TestResult doTest(std::vector &Prefix,
+ std::vector &Kept,
+ std::string &Error) override {
+ if (!Kept.empty() && TestFuncs(Kept))
+ return KeepSuffix;
+ if (!Prefix.empty() && TestFuncs(Prefix))
+ return KeepPrefix;
+ return NoFailure;
+ }
- bool TestFuncs(std::vector &Prefix);
- };
-}
+ bool TestFuncs(std::vector &Prefix);
+};
+} // namespace
-static void RemoveFunctionReferences(Module *M, const char* Name) {
+static void RemoveFunctionReferences(Module *M, const char *Name) {
auto *UsedVar = M->getGlobalVariable(Name, true);
- if (!UsedVar || !UsedVar->hasInitializer()) return;
+ if (!UsedVar || !UsedVar->hasInitializer())
+ return;
if (isa(UsedVar->getInitializer())) {
assert(UsedVar->use_empty());
UsedVar->eraseFromParent();
return;
}
auto *OldUsedVal = cast(UsedVar->getInitializer());
- std::vector Used;
- for(Value *V : OldUsedVal->operand_values()) {
+ std::vector Used;
+ for (Value *V : OldUsedVal->operand_values()) {
Constant *Op = cast(V->stripPointerCasts());
- if(!Op->isNullValue()) {
+ if (!Op->isNullValue()) {
Used.push_back(cast(V));
}
}
@@ -226,11 +225,11 @@ static void RemoveFunctionReferences(Module *M, const char* Name) {
UsedVar->setInitializer(NewUsedVal);
}
-bool ReduceCrashingFunctions::TestFuncs(std::vector &Funcs) {
+bool ReduceCrashingFunctions::TestFuncs(std::vector &Funcs) {
// If main isn't present, claim there is no problem.
- if (KeepMain && std::find(Funcs.begin(), Funcs.end(),
- BD.getProgram()->getFunction("main")) ==
- Funcs.end())
+ if (KeepMain &&
+ std::find(Funcs.begin(), Funcs.end(),
+ BD.getProgram()->getFunction("main")) == Funcs.end())
return false;
// Clone the program to try hacking it apart...
@@ -238,7 +237,7 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector &Funcs) {
Module *M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
- std::set Functions;
+ std::set Functions;
for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
Function *CMF = cast(VMap[Funcs[i]]);
assert(CMF && "Function not in module?!");
@@ -257,7 +256,7 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector &Funcs) {
if (!I->isDeclaration() && !Functions.count(I))
DeleteFunctionBody(I);
} else {
- std::vector ToRemove;
+ std::vector ToRemove;
// First, remove aliases to functions we're about to purge.
for (GlobalAlias &Alias : M->aliases()) {
Constant *Root = Alias.getAliasee()->stripPointerCasts();
@@ -299,7 +298,7 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector &Funcs) {
}
// Try running the hacked up program...
if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ BD.setNewProgram(M); // It crashed, keep the trimmed version...
// Make sure to use function pointers that point into the now-current
// module.
@@ -310,48 +309,49 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector &Funcs) {
return false;
}
-
namespace {
- /// ReduceCrashingBlocks reducer - This works by setting the terminators of
- /// all terminators except the specified basic blocks to a 'ret' instruction,
- /// then running the simplify-cfg pass. This has the effect of chopping up
- /// the CFG really fast which can reduce large functions quickly.
- ///
- class ReduceCrashingBlocks : public ListReducer {
- BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
- public:
- ReduceCrashingBlocks(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *))
+/// ReduceCrashingBlocks reducer - This works by setting the terminators of
+/// all terminators except the specified basic blocks to a 'ret' instruction,
+/// then running the simplify-cfg pass. This has the effect of chopping up
+/// the CFG really fast which can reduce large functions quickly.
+///
+class ReduceCrashingBlocks : public ListReducer {
+ BugDriver &BD;
+ bool (*TestFn)(const BugDriver &, Module *);
+
+public:
+ ReduceCrashingBlocks(BugDriver &bd,
+ bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
- TestResult doTest(std::vector &Prefix,
- std::vector &Kept,
- std::string &Error) override {
- if (!Kept.empty() && TestBlocks(Kept))
- return KeepSuffix;
- if (!Prefix.empty() && TestBlocks(Prefix))
- return KeepPrefix;
- return NoFailure;
- }
+ TestResult doTest(std::vector &Prefix,
+ std::vector &Kept,
+ std::string &Error) override {
+ if (!Kept.empty() && TestBlocks(Kept))
+ return KeepSuffix;
+ if (!Prefix.empty() && TestBlocks(Prefix))
+ return KeepPrefix;
+ return NoFailure;
+ }
- bool TestBlocks(std::vector &Prefix);
- };
-}
+ bool TestBlocks(std::vector &Prefix);
+};
+} // namespace
-bool ReduceCrashingBlocks::TestBlocks(std::vector &BBs) {
+bool ReduceCrashingBlocks::TestBlocks(std::vector &BBs) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
Module *M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
- SmallPtrSet Blocks;
+ SmallPtrSet Blocks;
for (unsigned i = 0, e = BBs.size(); i != e; ++i)
Blocks.insert(cast(VMap[BBs[i]]));
outs() << "Checking for crash with only these blocks:";
unsigned NumPrint = Blocks.size();
- if (NumPrint > 10) NumPrint = 10;
+ if (NumPrint > 10)
+ NumPrint = 10;
for (unsigned i = 0, e = NumPrint; i != e; ++i)
outs() << " " << BBs[i]->getName();
if (NumPrint < Blocks.size())
@@ -382,7 +382,7 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector &BBs) {
// a "persistent mapping" by turning basic blocks into pairs.
// This won't work well if blocks are unnamed, but that is just the risk we
// have to take.
- std::vector > BlockInfo;
+ std::vector> BlockInfo;
for (BasicBlock *BB : Blocks)
BlockInfo.emplace_back(BB->getParent()->getName(), BB->getName());
@@ -401,7 +401,7 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector &BBs) {
// Try running on the hacked up program...
if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ BD.setNewProgram(M); // It crashed, keep the trimmed version...
// Make sure to use basic block pointers that point into the now-current
// module, and that they don't include any deleted blocks.
@@ -410,50 +410,51 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector &BBs) {
for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
Function *F = cast(GST.lookup(BlockInfo[i].first));
ValueSymbolTable &ST = F->getValueSymbolTable();
- Value* V = ST.lookup(BlockInfo[i].second);
+ Value *V = ST.lookup(BlockInfo[i].second);
if (V && V->getType() == Type::getLabelTy(V->getContext()))
BBs.push_back(cast(V));
}
return true;
}
- delete M; // It didn't crash, try something else.
+ delete M; // It didn't crash, try something else.
return false;
}
namespace {
- /// ReduceCrashingInstructions reducer - This works by removing the specified
- /// non-terminator instructions and replacing them with undef.
- ///
- class ReduceCrashingInstructions : public ListReducer {
- BugDriver &BD;
- bool (*TestFn)(const BugDriver &, Module *);
- public:
- ReduceCrashingInstructions(BugDriver &bd,
- bool (*testFn)(const BugDriver &, Module *))
+/// ReduceCrashingInstructions reducer - This works by removing the specified
+/// non-terminator instructions and replacing them with undef.
+///
+class ReduceCrashingInstructions : public ListReducer {
+ BugDriver &BD;
+ bool (*TestFn)(const BugDriver &, Module *);
+
+public:
+ ReduceCrashingInstructions(BugDriver &bd,
+ bool (*testFn)(const BugDriver &, Module *))
: BD(bd), TestFn(testFn) {}
- TestResult doTest(std::vector &Prefix,
- std::vector &Kept,
- std::string &Error) override {
- if (!Kept.empty() && TestInsts(Kept))
- return KeepSuffix;
- if (!Prefix.empty() && TestInsts(Prefix))
- return KeepPrefix;
- return NoFailure;
- }
+ TestResult doTest(std::vector &Prefix,
+ std::vector &Kept,
+ std::string &Error) override {
+ if (!Kept.empty() && TestInsts(Kept))
+ return KeepSuffix;
+ if (!Prefix.empty() && TestInsts(Prefix))
+ return KeepPrefix;
+ return NoFailure;
+ }
- bool TestInsts(std::vector &Prefix);
- };
-}
+ bool TestInsts(std::vector &Prefix);
+};
+} // namespace
-bool ReduceCrashingInstructions::TestInsts(std::vector
- &Insts) {
+bool ReduceCrashingInstructions::TestInsts(
+ std::vector &Insts) {
// Clone the program to try hacking it apart...
ValueToValueMapTy VMap;
Module *M = CloneModule(BD.getProgram(), VMap);
// Convert list to set for fast lookup...
- SmallPtrSet Instructions;
+ SmallPtrSet Instructions;
for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
assert(!isa(Insts[i]));
Instructions.insert(cast(VMap[Insts[i]]));
@@ -484,7 +485,7 @@ bool ReduceCrashingInstructions::TestInsts(std::vector
// Try running on the hacked up program...
if (TestFn(BD, M)) {
- BD.setNewProgram(M); // It crashed, keep the trimmed version...
+ BD.setNewProgram(M); // It crashed, keep the trimmed version...
// Make sure to use instruction pointers that point into the now-current
// module, and that they don't include any deleted blocks.
@@ -493,7 +494,7 @@ bool ReduceCrashingInstructions::TestInsts(std::vector
Insts.push_back(Inst);
return true;
}
- delete M; // It didn't crash, try something else.
+ delete M; // It didn't crash, try something else.
return false;
}
@@ -521,28 +522,29 @@ static bool DebugACrash(BugDriver &BD,
}
if (!DeletedInit) {
- delete M; // No change made...
+ delete M; // No change made...
} else {
// See if the program still causes a crash...
outs() << "\nChecking to see if we can delete global inits: ";
- if (TestFn(BD, M)) { // Still crashes?
+ if (TestFn(BD, M)) { // Still crashes?
BD.setNewProgram(M);
outs() << "\n*** Able to remove all global initializers!\n";
- } else { // No longer crashes?
+ } else { // No longer crashes?
outs() << " - Removing all global inits hides problem!\n";
delete M;
- std::vector GVs;
+ std::vector GVs;
for (Module::global_iterator I = BD.getProgram()->global_begin(),
- E = BD.getProgram()->global_end(); I != E; ++I)
+ E = BD.getProgram()->global_end();
+ I != E; ++I)
if (I->hasInitializer())
GVs.push_back(I);
if (GVs.size() > 1 && !BugpointIsInterrupted) {
outs() << "\n*** Attempting to reduce the number of global "
- << "variables in the testcase\n";
+ << "variables in the testcase\n";
unsigned OldSize = GVs.size();
ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs, Error);
@@ -557,15 +559,16 @@ static bool DebugACrash(BugDriver &BD,
}
// Now try to reduce the number of functions in the module to something small.
- std::vector Functions;
+ std::vector Functions;
for (Module::iterator I = BD.getProgram()->begin(),
- E = BD.getProgram()->end(); I != E; ++I)
+ E = BD.getProgram()->end();
+ I != E; ++I)
if (!I->isDeclaration())
Functions.push_back(I);
if (Functions.size() > 1 && !BugpointIsInterrupted) {
outs() << "\n*** Attempting to reduce the number of functions "
- "in the testcase\n";
+ "in the testcase\n";
unsigned OldSize = Functions.size();
ReduceCrashingFunctions(BD, TestFn).reduceList(Functions, Error);
@@ -580,10 +583,12 @@ static bool DebugACrash(BugDriver &BD,
// shrinks the code dramatically quickly
//
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
- std::vector Blocks;
+ std::vector Blocks;
for (Module::const_iterator I = BD.getProgram()->begin(),
- E = BD.getProgram()->end(); I != E; ++I)
- for (Function::const_iterator FI = I->begin(), E = I->end(); FI !=E; ++FI)
+ E = BD.getProgram()->end();
+ I != E; ++I)
+ for (Function::const_iterator FI = I->begin(), E = I->end(); FI != E;
+ ++FI)
Blocks.push_back(FI);
unsigned OldSize = Blocks.size();
ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error);
@@ -594,13 +599,14 @@ static bool DebugACrash(BugDriver &BD,
// Attempt to delete instructions using bisection. This should help out nasty
// cases with large basic blocks where the problem is at one end.
if (!BugpointIsInterrupted) {
- std::vector Insts;
+ std::vector Insts;
for (Module::const_iterator MI = BD.getProgram()->begin(),
- ME = BD.getProgram()->end(); MI != ME; ++MI)
+ ME = BD.getProgram()->end();
+ MI != ME; ++MI)
for (Function::const_iterator FI = MI->begin(), FE = MI->end(); FI != FE;
++FI)
- for (BasicBlock::const_iterator I = FI->begin(), E = FI->end();
- I != E; ++I)
+ for (BasicBlock::const_iterator I = FI->begin(), E = FI->end(); I != E;
+ ++I)
if (!isa(I))
Insts.push_back(I);
@@ -611,7 +617,8 @@ static bool DebugACrash(BugDriver &BD,
// larger chunks of instructions at a time!
unsigned Simplification = 2;
do {
- if (BugpointIsInterrupted) break;
+ if (BugpointIsInterrupted)
+ break;
--Simplification;
outs() << "\n*** Attempting to reduce testcase by deleting instruc"
<< "tions: Simplification Level #" << Simplification << '\n';
@@ -631,7 +638,8 @@ static bool DebugACrash(BugDriver &BD,
// function, attempting to delete them.
unsigned CurInstructionNum = 0;
for (Module::const_iterator FI = BD.getProgram()->begin(),
- E = BD.getProgram()->end(); FI != E; ++FI)
+ E = BD.getProgram()->end();
+ FI != E; ++FI)
if (!FI->isDeclaration())
for (Function::const_iterator BI = FI->begin(), E = FI->end(); BI != E;
++BI)
@@ -640,7 +648,8 @@ static bool DebugACrash(BugDriver &BD,
if (InstructionsToSkipBeforeDeleting) {
--InstructionsToSkipBeforeDeleting;
} else {
- if (BugpointIsInterrupted) goto ExitLoops;
+ if (BugpointIsInterrupted)
+ goto ExitLoops;
if (isa(I))
continue;
@@ -655,7 +664,7 @@ static bool DebugACrash(BugDriver &BD,
// to reduce the testcase...
BD.setNewProgram(M.release());
InstructionsToSkipBeforeDeleting = CurInstructionNum;
- goto TryAgain; // I wish I had a multi-level break here!
+ goto TryAgain; // I wish I had a multi-level break here!
}
}
}
@@ -676,7 +685,7 @@ ExitLoops:
// Find out if the pass still crashes on the cleaned up program...
if (TestFn(BD, M)) {
- BD.setNewProgram(M); // Yup, it does, keep the reduced version...
+ BD.setNewProgram(M); // Yup, it does, keep the reduced version...
} else {
delete M;
}
@@ -720,7 +729,7 @@ static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) {
BD.compileProgram(M, &Error);
if (!Error.empty()) {
errs() << "\n";
- return true; // Tool is still crashing.
+ return true; // Tool is still crashing.
}
errs() << '\n';
return false;
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp
index 25813b34..eb5f8629 100644
--- a/tools/bugpoint/ExecutionDriver.cpp
+++ b/tools/bugpoint/ExecutionDriver.cpp
@@ -24,114 +24,115 @@
using namespace llvm;
namespace {
- // OutputType - Allow the user to specify the way code should be run, to test
- // for miscompilation.
- //
- enum OutputType {
- AutoPick, RunLLI, RunJIT, RunLLC, RunLLCIA, LLC_Safe, CompileCustom, Custom
- };
-
- cl::opt
- AbsTolerance("abs-tolerance", cl::desc("Absolute error tolerated"),
- cl::init(0.0));
- cl::opt
- RelTolerance("rel-tolerance", cl::desc("Relative error tolerated"),
- cl::init(0.0));
-
- cl::opt
- 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"),
- clEnumValN(RunJIT, "run-jit", "Execute with JIT"),
- clEnumValN(RunLLC, "run-llc", "Compile with LLC"),
- clEnumValN(RunLLCIA, "run-llc-ia",
- "Compile with LLC with integrated assembler"),
- clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"),
- clEnumValN(CompileCustom, "compile-custom",
- "Use -compile-command to define a command to "
- "compile the bitcode. Useful to avoid linking."),
- clEnumValN(Custom, "run-custom",
- "Use -exec-command to define a command to execute "
- "the bitcode. Useful for cross-compilation."),
- clEnumValEnd),
- cl::init(AutoPick));
-
- cl::opt
- 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(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
- SafeInterpreterPath("safe-path",
- cl::desc("Specify the path to the \"safe\" backend program"),
- cl::init(""));
-
- cl::opt
- AppendProgramExitCode("append-exit-code",
- cl::desc("Append the exit code to the output so it gets diff'd too"),
- cl::init(false));
-
- cl::opt
- InputFile("input", cl::init("/dev/null"),
- cl::desc("Filename to pipe in as stdin (default: /dev/null)"));
-
- cl::list
- AdditionalSOs("additional-so",
- cl::desc("Additional shared objects to load "
- "into executing programs"));
-
- cl::list
- AdditionalLinkerArgs("Xlinker",
- cl::desc("Additional arguments to pass to the linker"));
-
- cl::opt
- CustomCompileCommand("compile-command", cl::init("llc"),
- cl::desc("Command to compile the bitcode (use with -compile-custom) "
- "(default: llc)"));
-
- cl::opt
- CustomExecCommand("exec-command", cl::init("simulate"),
- cl::desc("Command to execute the bitcode (use with -run-custom) "
- "(default: simulate)"));
-}
+// OutputType - Allow the user to specify the way code should be run, to test
+// for miscompilation.
+//
+enum OutputType {
+ AutoPick,
+ RunLLI,
+ RunJIT,
+ RunLLC,
+ RunLLCIA,
+ LLC_Safe,
+ CompileCustom,
+ Custom
+};
+
+cl::opt AbsTolerance("abs-tolerance",
+ cl::desc("Absolute error tolerated"),
+ cl::init(0.0));
+cl::opt RelTolerance("rel-tolerance",
+ cl::desc("Relative error tolerated"),
+ cl::init(0.0));
+
+cl::opt 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"),
+ clEnumValN(RunJIT, "run-jit", "Execute with JIT"),
+ clEnumValN(RunLLC, "run-llc", "Compile with LLC"),
+ clEnumValN(RunLLCIA, "run-llc-ia",
+ "Compile with LLC with integrated assembler"),
+ clEnumValN(LLC_Safe, "llc-safe", "Use LLC for all"),
+ clEnumValN(CompileCustom, "compile-custom",
+ "Use -compile-command to define a command to "
+ "compile the bitcode. Useful to avoid linking."),
+ clEnumValN(Custom, "run-custom",
+ "Use -exec-command to define a command to execute "
+ "the bitcode. Useful for cross-compilation."),
+ clEnumValEnd),
+ cl::init(AutoPick));
+
+cl::opt 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(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 SafeInterpreterPath(
+ "safe-path", cl::desc("Specify the path to the \"safe\" backend program"),
+ cl::init(""));
+
+cl::opt AppendProgramExitCode(
+ "append-exit-code",
+ cl::desc("Append the exit code to the output so it gets diff'd too"),
+ cl::init(false));
+
+cl::opt
+ InputFile("input", cl::init("/dev/null"),
+ cl::desc("Filename to pipe in as stdin (default: /dev/null)"));
+
+cl::list
+ AdditionalSOs("additional-so", cl::desc("Additional shared objects to load "
+ "into executing programs"));
+
+cl::list AdditionalLinkerArgs(
+ "Xlinker", cl::desc("Additional arguments to pass to the linker"));
+
+cl::opt CustomCompileCommand(
+ "compile-command", cl::init("llc"),
+ cl::desc("Command to compile the bitcode (use with -compile-custom) "
+ "(default: llc)"));
+
+cl::opt CustomExecCommand(
+ "exec-command", cl::init("simulate"),
+ cl::desc("Command to execute the bitcode (use with -run-custom) "
+ "(default: simulate)"));
+} // namespace
namespace llvm {
- // Anything specified after the --args option are taken as arguments to the
- // program being debugged.
- cl::list
- InputArgv("args", cl::Positional, cl::desc("..."),
- cl::ZeroOrMore, cl::PositionalEatsArgs);
-
- cl::opt
- OutputPrefix("output-prefix", cl::init("bugpoint"),
- cl::desc("Prefix to use for outputs (default: 'bugpoint')"));
-}
+// Anything specified after the --args option are taken as arguments to the
+// program being debugged.
+cl::list InputArgv("args", cl::Positional,
+ cl::desc("..."),
+ cl::ZeroOrMore, cl::PositionalEatsArgs);
+
+cl::opt
+ OutputPrefix("output-prefix", cl::init("bugpoint"),
+ cl::desc("Prefix to use for outputs (default: 'bugpoint')"));
+} // namespace llvm
namespace {
- cl::list
- ToolArgv("tool-args", cl::Positional, cl::desc("..."),
- cl::ZeroOrMore, cl::PositionalEatsArgs);
+cl::list ToolArgv("tool-args", cl::Positional,
+ cl::desc("..."), cl::ZeroOrMore,
+ cl::PositionalEatsArgs);
- cl::list
- SafeToolArgv("safe-tool-args", cl::Positional,
- cl::desc("..."),
- cl::ZeroOrMore, cl::PositionalEatsArgs);
+cl::list SafeToolArgv("safe-tool-args", cl::Positional,
+ cl::desc("..."),
+ cl::ZeroOrMore, cl::PositionalEatsArgs);
- cl::opt
- GCCBinary("gcc", cl::init("gcc"),
+cl::opt
+ GCCBinary("gcc", cl::init("gcc"),
cl::desc("The gcc binary to use. (default 'gcc')"));
- cl::list
- GCCToolArgv("gcc-tool-args", cl::Positional,
- cl::desc("..."),
- cl::ZeroOrMore, cl::PositionalEatsArgs);
-}
+cl::list GCCToolArgv("gcc-tool-args", cl::Positional,
+ cl::desc("..."),
+ cl::ZeroOrMore, cl::PositionalEatsArgs);
+} // namespace
//===----------------------------------------------------------------------===//
// BugDriver method implementation
@@ -152,19 +153,18 @@ bool BugDriver::initializeExecutionEnvironment() {
case AutoPick:
if (!Interpreter) {
InterpreterSel = RunJIT;
- Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
- &ToolArgv);
+ Interpreter =
+ AbstractInterpreter::createJIT(getToolName(), Message, &ToolArgv);
}
if (!Interpreter) {
InterpreterSel = RunLLC;
- Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
- GCCBinary, &ToolArgv,
- &GCCToolArgv);
+ Interpreter = AbstractInterpreter::createLLC(
+ getToolName(), Message, GCCBinary, &ToolArgv, &GCCToolArgv);
}
if (!Interpreter) {
InterpreterSel = RunLLI;
- Interpreter = AbstractInterpreter::createLLI(getToolName(), Message,
- &ToolArgv);
+ Interpreter =
+ AbstractInterpreter::createLLI(getToolName(), Message, &ToolArgv);
}
if (!Interpreter) {
InterpreterSel = AutoPick;
@@ -172,28 +172,27 @@ bool BugDriver::initializeExecutionEnvironment() {
}
break;
case RunLLI:
- Interpreter = AbstractInterpreter::createLLI(getToolName(), Message,
- &ToolArgv);
+ Interpreter =
+ AbstractInterpreter::createLLI(getToolName(), Message, &ToolArgv);
break;
case RunLLC:
case RunLLCIA:
case LLC_Safe:
- Interpreter = AbstractInterpreter::createLLC(getToolName(), Message,
- GCCBinary, &ToolArgv,
- &GCCToolArgv,
- InterpreterSel == RunLLCIA);
+ Interpreter = AbstractInterpreter::createLLC(
+ getToolName(), Message, GCCBinary, &ToolArgv, &GCCToolArgv,
+ InterpreterSel == RunLLCIA);
break;
case RunJIT:
- Interpreter = AbstractInterpreter::createJIT(getToolName(), Message,
- &ToolArgv);
+ Interpreter =
+ AbstractInterpreter::createJIT(getToolName(), Message, &ToolArgv);
break;
case CompileCustom:
- Interpreter =
- AbstractInterpreter::createCustomCompiler(Message, CustomCompileCommand);
+ Interpreter = AbstractInterpreter::createCustomCompiler(
+ Message, CustomCompileCommand);
break;
case Custom:
Interpreter =
- AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand);
+ AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand);
break;
}
if (!Interpreter)
@@ -208,25 +207,19 @@ bool BugDriver::initializeExecutionEnvironment() {
switch (SafeInterpreterSel) {
case AutoPick:
// In "llc-safe" mode, default to using LLC as the "safe" backend.
- if (!SafeInterpreter &&
- InterpreterSel == LLC_Safe) {
+ if (!SafeInterpreter && InterpreterSel == LLC_Safe) {
SafeInterpreterSel = RunLLC;
SafeToolArgs.push_back("--relocation-model=pic");
- SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
- GCCBinary,
- &SafeToolArgs,
- &GCCToolArgv);
+ SafeInterpreter = AbstractInterpreter::createLLC(
+ Path.c_str(), Message, GCCBinary, &SafeToolArgs, &GCCToolArgv);
}
- if (!SafeInterpreter &&
- InterpreterSel != RunLLC &&
+ if (!SafeInterpreter && InterpreterSel != RunLLC &&
InterpreterSel != RunJIT) {
SafeInterpreterSel = RunLLC;
SafeToolArgs.push_back("--relocation-model=pic");
- SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
- GCCBinary,
- &SafeToolArgs,
- &GCCToolArgv);
+ SafeInterpreter = AbstractInterpreter::createLLC(
+ Path.c_str(), Message, GCCBinary, &SafeToolArgs, &GCCToolArgv);
}
if (!SafeInterpreter) {
SafeInterpreterSel = AutoPick;
@@ -236,24 +229,29 @@ bool BugDriver::initializeExecutionEnvironment() {
case RunLLC:
case RunLLCIA:
SafeToolArgs.push_back("--relocation-model=pic");
- SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message,
- GCCBinary, &SafeToolArgs,
- &GCCToolArgv,
- SafeInterpreterSel == RunLLCIA);
+ SafeInterpreter = AbstractInterpreter::createLLC(
+ Path.c_str(), Message, GCCBinary, &SafeToolArgs, &GCCToolArgv,
+ SafeInterpreterSel == RunLLCIA);
break;
case Custom:
SafeInterpreter =
- AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand);
+ AbstractInterpreter::createCustomExecutor(Message, CustomExecCommand);
break;
default:
Message = "Sorry, this back-end is not supported by bugpoint as the "
"\"safe\" backend right now!\n";
break;
}
- if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); }
+ if (!SafeInterpreter) {
+ outs() << Message << "\nExiting.\n";
+ exit(1);
+ }
gcc = GCC::create(Message, GCCBinary, &GCCToolArgv);
- if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); }
+ if (!gcc) {
+ outs() << Message << "\nExiting.\n";
+ exit(1);
+ }
// If there was an error creating the selected interpreter, quit with error.
return Interpreter == nullptr;
@@ -287,18 +285,16 @@ void BugDriver::compileProgram(Module *M, std::string *Error) const {
Interpreter->compileProgram(BitcodeFile.str(), Error, Timeout, MemoryLimit);
}
-
/// executeProgram - This method runs "Program", capturing the output of the
/// program to a file, returning the filename of the file. A recommended
/// filename may be optionally specified.
///
-std::string BugDriver::executeProgram(const Module *Program,
- std::string OutputFile,
- std::string BitcodeFile,
- const std::string &SharedObj,
- AbstractInterpreter *AI,
- std::string *Error) const {
- if (!AI) AI = Interpreter;
+std::string
+BugDriver::executeProgram(const Module *Program, std::string OutputFile,
+ std::string BitcodeFile, const std::string &SharedObj,
+ AbstractInterpreter *AI, std::string *Error) const {
+ if (!AI)
+ AI = Interpreter;
assert(AI && "Interpreter should have been created already!");
bool CreatedBitcode = false;
if (BitcodeFile.empty()) {
@@ -308,15 +304,15 @@ std::string BugDriver::executeProgram(const Module *Program,
std::error_code EC = sys::fs::createUniqueFile(
OutputPrefix + "-test-program-%%%%%%%.bc", UniqueFD, UniqueFilename);
if (EC) {
- errs() << ToolName << ": Error making unique filename: "
- << EC.message() << "!\n";
+ errs() << ToolName << ": Error making unique filename: " << EC.message()
+ << "!\n";
exit(1);
}
BitcodeFile = UniqueFilename.str();
if (writeProgramToFile(BitcodeFile, UniqueFD, Program)) {
- errs() << ToolName << ": Error emitting bitcode to file '"
- << BitcodeFile << "'!\n";
+ errs() << ToolName << ": Error emitting bitcode to file '" << BitcodeFile
+ << "'!\n";
exit(1);
}
CreatedBitcode = true;
@@ -324,17 +320,17 @@ std::string BugDriver::executeProgram(const Module *Program,
// Remove the temporary bitcode file when we are done.
std::string BitcodePath(BitcodeFile);
- FileRemover BitcodeFileRemover(BitcodePath,
- CreatedBitcode && !SaveTemps);
+ FileRemover BitcodeFileRemover(BitcodePath, CreatedBitcode && !SaveTemps);
- if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output-%%%%%%%";
+ if (OutputFile.empty())
+ OutputFile = OutputPrefix + "-execution-output-%%%%%%%";
// Check to see if this is a valid output filename...
SmallString<128> UniqueFile;
std::error_code EC = sys::fs::createUniqueFile(OutputFile, UniqueFile);
if (EC) {
- errs() << ToolName << ": Error making unique filename: "
- << EC.message() << "\n";
+ errs() << ToolName << ": Error making unique filename: " << EC.message()
+ << "\n";
exit(1);
}
OutputFile = UniqueFile.str();
@@ -354,11 +350,15 @@ std::string BugDriver::executeProgram(const Module *Program,
errs() << "";
static bool FirstTimeout = true;
if (FirstTimeout) {
- outs() << "\n"
- "*** Program execution timed out! This mechanism is designed to handle\n"
- " programs stuck in infinite loops gracefully. The -timeout option\n"
- " can be used to change the timeout threshold or disable it completely\n"
- " (with -timeout=0). This message is only displayed once.\n";
+ outs()
+ << "\n"
+ "*** Program execution timed out! This mechanism is designed to "
+ "handle\n"
+ " programs stuck in infinite loops gracefully. The -timeout "
+ "option\n"
+ " can be used to change the timeout threshold or disable it "
+ "completely\n"
+ " (with -timeout=0). This message is only displayed once.\n";
FirstTimeout = false;
}
}
@@ -388,8 +388,8 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile,
std::string OutputFile;
// Using the known-good backend.
- GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile,
- Error);
+ GCC::FileType FT =
+ SafeInterpreter->OutputCode(BitcodeFile, OutputFile, Error);
if (!Error.empty())
return "";
@@ -440,8 +440,7 @@ bool BugDriver::createReferenceFile(Module *M, const std::string &Filename) {
///
bool BugDriver::diffProgram(const Module *Program,
const std::string &BitcodeFile,
- const std::string &SharedObject,
- bool RemoveBitcode,
+ const std::string &SharedObject, bool RemoveBitcode,
std::string *ErrMsg) const {
// Execute the program, generating an output file...
std::string Output(
@@ -451,16 +450,14 @@ bool BugDriver::diffProgram(const Module *Program,
std::string Error;
bool FilesDifferent = false;
- if (int Diff = DiffFilesWithTolerance(ReferenceOutputFile,
- Output,
+ if (int Diff = DiffFilesWithTolerance(ReferenceOutputFile, Output,
AbsTolerance, RelTolerance, &Error)) {
if (Diff == 2) {
errs() << "While diffing output: " << Error << '\n';
exit(1);
}
FilesDifferent = true;
- }
- else {
+ } else {
// Remove the generated output if there are no differences.
sys::fs::remove(Output);
}
@@ -471,7 +468,4 @@ bool BugDriver::diffProgram(const Module *Program,
return FilesDifferent;
}
-bool BugDriver::isExecutingJIT() {
- return InterpreterSel == RunJIT;
-}
-
+bool BugDriver::isExecutingJIT() { return InterpreterSel == RunJIT; }
diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp
index 238cbbc7..28cb6ecb 100644
--- a/tools/bugpoint/ExtractFunction.cpp
+++ b/tools/bugpoint/ExtractFunction.cpp
@@ -37,50 +37,49 @@ using namespace llvm;
#define DEBUG_TYPE "bugpoint"
namespace llvm {
- bool DisableSimplifyCFG = false;
- extern cl::opt OutputPrefix;
-} // End llvm namespace
+bool DisableSimplifyCFG = false;
+extern cl::opt OutputPrefix;
+} // namespace llvm
namespace {
- cl::opt
- NoDCE ("disable-dce",
- cl::desc("Do not use the -dce pass to reduce testcases"));
- cl::opt
- NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG),
- cl::desc("Do not use the -simplifycfg pass to reduce testcases"));
-
- Function* globalInitUsesExternalBA(GlobalVariable* GV) {
- if (!GV->hasInitializer())
- return nullptr;
-
- Constant *I = GV->getInitializer();
-
- // walk the values used by the initializer
- // (and recurse into things like ConstantExpr)
- std::vector Todo;
- std::set Done;
- Todo.push_back(I);
-
- while (!Todo.empty()) {
- Constant* V = Todo.back();
- Todo.pop_back();
- Done.insert(V);
-
- if (BlockAddress *BA = dyn_cast(V)) {
- Function *F = BA->getFunction();
- if (F->isDeclaration())
- return F;
- }
+cl::opt NoDCE("disable-dce",
+ cl::desc("Do not use the -dce pass to reduce testcases"));
+cl::opt
+ NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG),
+ cl::desc("Do not use the -simplifycfg pass to reduce testcases"));
+
+Function *globalInitUsesExternalBA(GlobalVariable *GV) {
+ if (!GV->hasInitializer())
+ return nullptr;
- for (User::op_iterator i = V->op_begin(), e = V->op_end(); i != e; ++i) {
- Constant *C = dyn_cast(*i);
- if (C && !isa(C) && !Done.count(C))
- Todo.push_back(C);
- }
+ Constant *I = GV->getInitializer();
+
+ // walk the values used by the initializer
+ // (and recurse into things like ConstantExpr)
+ std::vector Todo;
+ std::set Done;
+ Todo.push_back(I);
+
+ while (!Todo.empty()) {
+ Constant *V = Todo.back();
+ Todo.pop_back();
+ Done.insert(V);
+
+ if (BlockAddress *BA = dyn_cast(V)) {
+ Function *F = BA->getFunction();
+ if (F->isDeclaration())
+ return F;
+ }
+
+ for (User::op_iterator i = V->op_begin(), e = V->op_end(); i != e; ++i) {
+ Constant *C = dyn_cast(*i);
+ if (C && !isa(C) && !Done.count(C))
+ Todo.push_back(C);
}
- return nullptr;
}
-} // end anonymous namespace
+ return nullptr;
+}
+} // end anonymous namespace
std::unique_ptr
BugDriver::deleteInstructionFromProgram(const Instruction *I,
@@ -92,15 +91,15 @@ BugDriver::deleteInstructionFromProgram(const Instruction *I,
const Function *PF = PBB->getParent();
Module::iterator RFI = Clone->begin(); // Get iterator to corresponding fn
- std::advance(RFI, std::distance(PF->getParent()->begin(),
- Module::const_iterator(PF)));
+ std::advance(
+ RFI, std::distance(PF->getParent()->begin(), Module::const_iterator(PF)));
- Function::iterator RBI = RFI->begin(); // Get iterator to corresponding BB
+ Function::iterator RBI = RFI->begin(); // Get iterator to corresponding BB
std::advance(RBI, std::distance(PF->begin(), Function::const_iterator(PBB)));
BasicBlock::iterator RI = RBI->begin(); // Get iterator to corresponding inst
std::advance(RI, std::distance(PBB->begin(), BasicBlock::const_iterator(I)));
- Instruction *TheInst = RI; // Got the corresponding instruction!
+ Instruction *TheInst = RI; // Got the corresponding instruction!
// If this instruction produces a value, replace any users with null values
if (!TheInst->getType()->isVoidTy())
@@ -116,7 +115,7 @@ BugDriver::deleteInstructionFromProgram(const Instruction *I,
if (Simplification > 1 && !NoDCE)
Passes.push_back("dce");
if (Simplification && !DisableSimplifyCFG)
- Passes.push_back("simplifycfg"); // Delete dead control flow
+ Passes.push_back("simplifycfg"); // Delete dead control flow
Passes.push_back("verify");
std::unique_ptr New = runPassesOn(Clone, Passes);
@@ -179,7 +178,6 @@ std::unique_ptr BugDriver::extractLoop(Module *M) {
return NewM;
}
-
// DeleteFunctionBody - "Remove" the function by deleting all of its basic
// blocks, making it external.
//
@@ -191,23 +189,20 @@ void llvm::DeleteFunctionBody(Function *F) {
/// GetTorInit - Given a list of entries for static ctors/dtors, return them
/// as a constant array.
-static Constant *GetTorInit(std::vector > &TorList) {
+static Constant *GetTorInit(std::vector> &TorList) {
assert(!TorList.empty() && "Don't create empty tor list!");
- std::vector ArrayElts;
+ std::vector ArrayElts;
Type *Int32Ty = Type::getInt32Ty(TorList[0].first->getContext());
StructType *STy =
StructType::get(Int32Ty, TorList[0].first->getType(), nullptr);
for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
- Constant *Elts[] = {
- ConstantInt::get(Int32Ty, TorList[i].second),
- TorList[i].first
- };
+ Constant *Elts[] = {ConstantInt::get(Int32Ty, TorList[i].second),
+ TorList[i].first};
ArrayElts.push_back(ConstantStruct::get(STy, Elts));
}
- return ConstantArray::get(ArrayType::get(ArrayElts[0]->getType(),
- ArrayElts.size()),
- ArrayElts);
+ return ConstantArray::get(
+ ArrayType::get(ArrayElts[0]->getType(), ArrayElts.size()), ArrayElts);
}
/// SplitStaticCtorDtor - A module was recently split into two parts, M1/M2, and
@@ -217,23 +212,26 @@ static Constant *GetTorInit(std::vector > &TorList) {
static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
ValueToValueMapTy &VMap) {
GlobalVariable *GV = M1->getNamedGlobal(GlobalName);
- if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() ||
- !GV->use_empty()) return;
-
- std::vector > M1Tors, M2Tors;
+ if (!GV || GV->isDeclaration() || GV->hasLocalLinkage() || !GV->use_empty())
+ return;
+
+ std::vector> M1Tors, M2Tors;
ConstantArray *InitList = dyn_cast(GV->getInitializer());
- if (!InitList) return;
-
+ if (!InitList)
+ return;
+
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
- if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){
- if (CS->getNumOperands() != 2) return; // Not array of 2-element structs.
-
+ if (ConstantStruct *CS =
+ dyn_cast(InitList->getOperand(i))) {
+ if (CS->getNumOperands() != 2)
+ return; // Not array of 2-element structs.
+
if (CS->getOperand(1)->isNullValue())
- break; // Found a null terminator, stop here.
-
+ break; // Found a null terminator, stop here.
+
ConstantInt *CI = dyn_cast(CS->getOperand(0));
int Priority = CI ? CI->getSExtValue() : 0;
-
+
Constant *FP = CS->getOperand(1);
if (ConstantExpr *CE = dyn_cast(FP))
if (CE->isCast())
@@ -249,13 +247,12 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
}
}
}
-
+
GV->eraseFromParent();
if (!M1Tors.empty()) {
Constant *M1Init = GetTorInit(M1Tors);
new GlobalVariable(*M1, M1Init->getType(), false,
- GlobalValue::AppendingLinkage,
- M1Init, GlobalName);
+ GlobalValue::AppendingLinkage, M1Init, GlobalName);
}
GV = M2->getNamedGlobal(GlobalName);
@@ -266,19 +263,16 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2,
if (!M2Tors.empty()) {
Constant *M2Init = GetTorInit(M2Tors);
new GlobalVariable(*M2, M2Init->getType(), false,
- GlobalValue::AppendingLinkage,
- M2Init, GlobalName);
+ GlobalValue::AppendingLinkage, M2Init, GlobalName);
}
}
-
/// SplitFunctionsOutOfModule - Given a module and a list of functions in the
/// module, split the functions OUT of the specified module, and place them in
/// the new module.
-Module *
-llvm::SplitFunctionsOutOfModule(Module *M,
- const std::vector &F,
- ValueToValueMapTy &VMap) {
+Module *llvm::SplitFunctionsOutOfModule(Module *M,
+ const std::vector &F,
+ ValueToValueMapTy &VMap) {
// Make sure functions & globals are all external so that linkage
// between the two modules will work.
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
@@ -301,15 +295,13 @@ llvm::SplitFunctionsOutOfModule(Module *M,
DEBUG(TNOF->printAsOperand(errs(), false));
DEBUG(errs() << "\n");
TestFunctions.insert(cast(NewVMap[TNOF]));
- DeleteFunctionBody(TNOF); // Function is now external in this module!
+ DeleteFunctionBody(TNOF); // Function is now external in this module!
}
-
// Remove the Safe functions from the Test module
for (Module::iterator I = New->begin(), E = New->end(); I != E; ++I)
if (!TestFunctions.count(I))
DeleteFunctionBody(I);
-
// Try to split the global initializers evenly
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
@@ -321,11 +313,12 @@ llvm::SplitFunctionsOutOfModule(Module *M,
"the global '";
GV->printAsOperand(errs(), false);
errs() << "' with an initializer that references blockaddresses "
- "from safe function '" << SafeFn->getName()
- << "' and from test function '" << TestFn->getName() << "'.\n";
+ "from safe function '"
+ << SafeFn->getName() << "' and from test function '"
+ << TestFn->getName() << "'.\n";
exit(1);
}
- I->setInitializer(nullptr); // Delete the initializer to make it external
+ I->setInitializer(nullptr); // Delete the initializer to make it external
} else {
// If we keep it in the safe module, then delete it in the test module
GV->setInitializer(nullptr);
@@ -336,7 +329,7 @@ llvm::SplitFunctionsOutOfModule(Module *M,
// module if they both have static ctor/dtor functions.
SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap);
SplitStaticCtorDtor("llvm.global_dtors", M, New, NewVMap);
-
+
return New;
}
@@ -360,14 +353,15 @@ BugDriver::extractMappedBlocksFromModule(const std::vector &BBs,
sys::RemoveFileOnSignal(Filename);
tool_output_file BlocksToNotExtractFile(Filename.c_str(), FD);
- for (std::vector::const_iterator I = BBs.begin(), E = BBs.end();
+ for (std::vector::const_iterator I = BBs.begin(), E = BBs.end();
I != E; ++I) {
BasicBlock *BB = *I;
// If the BB doesn't have a name, give it one so we have something to key
// off of.
- if (!BB->hasName()) BB->setName("tmpbb");
- BlocksToNotExtractFile.os() << BB->getParent()->getName() << " "
- << BB->getName() << "\n";
+ if (!BB->hasName())
+ BB->setName("tmpbb");
+ BlocksToNotExtractFile.os()
+ << BB->getParent()->getName() << " " << BB->getName() << "\n";
}
BlocksToNotExtractFile.os().close();
if (BlocksToNotExtractFile.os().has_error()) {
diff --git a/tools/bugpoint/FindBugs.cpp b/tools/bugpoint/FindBugs.cpp
index 22d42ae0..3811ae88 100644
--- a/tools/bugpoint/FindBugs.cpp
+++ b/tools/bugpoint/FindBugs.cpp
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines an interface that allows bugpoint to choose different
-// combinations of optimizations to run on the selected input. Bugpoint will
+// This file defines an interface that allows bugpoint to choose different
+// combinations of optimizations to run on the selected input. Bugpoint will
// run these optimizations and record the success/failure of each. This way
// we can hopefully spot bugs in the optimizations.
//
@@ -24,54 +24,55 @@
#include // HLSL Change - Updates for C++ 17
using namespace llvm;
-/// runManyPasses - Take the specified pass list and create different
+/// runManyPasses - Take the specified pass list and create different
/// combinations of passes to compile the program with. Compile the program with
-/// each set and mark test to see if it compiled correctly. If the passes
+/// each set and mark test to see if it compiled correctly. If the passes
/// compiled correctly output nothing and rearrange the passes into a new order.
-/// If the passes did not compile correctly, output the command required to
+/// If the passes did not compile correctly, output the command required to
/// recreate the failure. This returns true if a compiler error is found.
///
bool BugDriver::runManyPasses(const std::vector &AllPasses,
std::string &ErrMsg) {
setPassesToRun(AllPasses);
outs() << "Starting bug finding procedure...\n\n";
-
+
// Creating a reference output if necessary
- if (initializeExecutionEnvironment()) return false;
-
+ if (initializeExecutionEnvironment())
+ return false;
+
outs() << "\n";
if (ReferenceOutputFile.empty()) {
outs() << "Generating reference output from raw program: \n";
if (!createReferenceFile(Program))
return false;
}
-
+
srand(time(nullptr));
// HLSL Change Begin - C++ 17 Updates
std::random_device RD;
std::mt19937 Gen(RD());
// HLSL Change End
-
+
unsigned num = 1;
- while(1) {
+ while (1) {
//
// Step 1: Randomize the order of the optimizer passes.
//
// HLSL Change Begin - C++ 17 Updates
std::shuffle(PassesToRun.begin(), PassesToRun.end(), Gen);
// HLSL Change End
-
+
//
// Step 2: Run optimizer passes on the program and check for success.
//
outs() << "Running selected passes on program to test for crash: ";
- for(int i = 0, e = PassesToRun.size(); i != e; i++) {
+ for (int i = 0, e = PassesToRun.size(); i != e; i++) {
outs() << "-" << PassesToRun[i] << " ";
}
-
+
std::string Filename;
- if(runPasses(Program, PassesToRun, Filename, false)) {
+ if (runPasses(Program, PassesToRun, Filename, false)) {
outs() << "\n";
outs() << "Optimizer passes caused failure!\n\n";
debugOptimizerCrash();
@@ -79,7 +80,7 @@ bool BugDriver::runManyPasses(const std::vector &AllPasses,
} else {
outs() << "Combination " << num << " optimized successfully!\n";
}
-
+
//
// Step 3: Compile the optimized code.
//
@@ -92,9 +93,9 @@ bool BugDriver::runManyPasses(const std::vector &AllPasses,
return debugCodeGeneratorCrash(ErrMsg);
}
outs() << '\n';
-
+
//
- // Step 4: Run the program and compare its output to the reference
+ // Step 4: Run the program and compare its output to the reference
// output (created above).
//
outs() << "*** Checking if passes caused miscompliation:\n";
@@ -111,12 +112,12 @@ bool BugDriver::runManyPasses(const std::vector &AllPasses,
return true;
}
outs() << "\n*** diff'd output matches!\n";
-
+
sys::fs::remove(Filename);
-
+
outs() << "\n\n";
num++;
- } //end while
-
+ } // end while
+
// Unreachable.
}
diff --git a/tools/bugpoint/ListReducer.h b/tools/bugpoint/ListReducer.h
index edc384e4..e4df86ef 100644
--- a/tools/bugpoint/ListReducer.h
+++ b/tools/bugpoint/ListReducer.h
@@ -23,16 +23,15 @@
#include
namespace llvm {
-
- extern bool BugpointIsInterrupted;
-template
-struct ListReducer {
+extern bool BugpointIsInterrupted;
+
+template struct ListReducer {
enum TestResult {
- NoFailure, // No failure of the predicate was detected
- KeepSuffix, // The suffix alone satisfies the predicate
- KeepPrefix, // The prefix alone satisfies the predicate
- InternalError // Encountered an error trying to run the predicate
+ NoFailure, // No failure of the predicate was detected
+ KeepSuffix, // The suffix alone satisfies the predicate
+ KeepPrefix, // The prefix alone satisfies the predicate
+ InternalError // Encountered an error trying to run the predicate
};
virtual ~ListReducer() {}
@@ -42,8 +41,7 @@ struct ListReducer {
// if the Kept list still satisfies the property, but if it is going to check
// the prefix anyway, it can.
//
- virtual TestResult doTest(std::vector &Prefix,
- std::vector &Kept,
+ virtual TestResult doTest(std::vector &Prefix, std::vector &Kept,
std::string &Error) = 0;
// reduceList - This function attempts to reduce the length of the specified
@@ -78,7 +76,7 @@ struct ListReducer {
const unsigned MaxIterationsWithoutProgress = 3;
bool ShufflingEnabled = true;
-Backjump:
+ Backjump:
unsigned MidTop = TheList.size();
unsigned MaxIterations = MaxIterationsWithoutProgress;
unsigned NumOfIterationsWithoutProgress = 0;
@@ -96,8 +94,7 @@ Backjump:
// If the loop doesn't make satisfying progress, try shuffling.
// The purpose of shuffling is to avoid the heavy tails of the
// distribution (improving the speed of convergence).
- if (ShufflingEnabled &&
- NumOfIterationsWithoutProgress > MaxIterations) {
+ if (ShufflingEnabled && NumOfIterationsWithoutProgress > MaxIterations) {
std::vector ShuffledList(TheList);
// HLSL Change Begin - C++ 17 Update
std::shuffle(ShuffledList.begin(), ShuffledList.end(), Gen);
@@ -108,7 +105,7 @@ Backjump:
// If the bug is still here, use the shuffled list.
TheList.swap(ShuffledList);
MidTop = TheList.size();
- // Must increase the shuffling treshold to avoid the small
+ // Must increase the shuffling treshold to avoid the small
// probability of inifinite looping without making progress.
MaxIterations += 2;
errs() << "\n\n*** Shuffling does not hide the bug...\n\n";
@@ -118,10 +115,10 @@ Backjump:
}
NumOfIterationsWithoutProgress = 0;
}
-
+
unsigned Mid = MidTop / 2;
- std::vector Prefix(TheList.begin(), TheList.begin()+Mid);
- std::vector Suffix(TheList.begin()+Mid, TheList.end());
+ std::vector Prefix(TheList.begin(), TheList.begin() + Mid);
+ std::vector Suffix(TheList.begin() + Mid, TheList.end());
switch (doTest(Prefix, Suffix, Error)) {
case KeepSuffix:
@@ -148,7 +145,7 @@ Backjump:
NumOfIterationsWithoutProgress++;
break;
case InternalError:
- return true; // Error was set by doTest.
+ return true; // Error was set by doTest.
}
assert(Error.empty() && "doTest did not return InternalError for error");
}
@@ -158,36 +155,37 @@ Backjump:
const int BackjumpProbability = 10;
// Okay, we trimmed as much off the top and the bottom of the list as we
- // could. If there is more than two elements in the list, try deleting
+ // could. If there is more than two elements in the list, try deleting
// interior elements and testing that.
//
if (TheList.size() > 2) {
bool Changed = true;
std::vector EmptyList;
- while (Changed) { // Trimming loop.
+ while (Changed) { // Trimming loop.
Changed = false;
-
+
// If the binary split reduction loop made an unfortunate sequence of
// splits, the trimming loop might be left off with a huge number of
// remaining elements (large search space). Backjumping out of that
- // search space and attempting a different split can significantly
+ // search space and attempting a different split can significantly
// improve the convergence speed.
if (std::rand() % 100 < BackjumpProbability)
goto Backjump;
-
- for (unsigned i = 1; i < TheList.size()-1; ++i) { // Check interior elts
+
+ for (unsigned i = 1; i < TheList.size() - 1;
+ ++i) { // Check interior elts
if (BugpointIsInterrupted) {
errs() << "\n\n*** Reduction Interrupted, cleaning up...\n\n";
return true;
}
-
+
std::vector TestList(TheList);
- TestList.erase(TestList.begin()+i);
+ TestList.erase(TestList.begin() + i);
if (doTest(EmptyList, TestList, Error) == KeepSuffix) {
// We can trim down the list!
TheList.swap(TestList);
- --i; // Don't skip an element of the list
+ --i; // Don't skip an element of the list
Changed = true;
}
if (!Error.empty())
@@ -203,6 +201,6 @@ Backjump:
}
};
-} // End llvm namespace
+} // namespace llvm
#endif
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index fad16368..871b3fc9 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -15,7 +15,7 @@
#include "BugDriver.h"
#include "ListReducer.h"
#include "ToolRunner.h"
-#include "llvm/Config/config.h" // for HAVE_LINK_R
+#include "llvm/Config/config.h" // for HAVE_LINK_R
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
@@ -29,30 +29,31 @@
using namespace llvm;
namespace llvm {
- extern cl::opt OutputPrefix;
- extern cl::list InputArgv;
-}
+extern cl::opt OutputPrefix;
+extern cl::list InputArgv;
+} // namespace llvm
namespace {
- static llvm::cl::opt
- DisableLoopExtraction("disable-loop-extraction",
- cl::desc("Don't extract loops when searching for miscompilations"),
- cl::init(false));
- static llvm::cl::opt
- DisableBlockExtraction("disable-block-extraction",
- cl::desc("Don't extract blocks when searching for miscompilations"),
- cl::init(false));
-
- class ReduceMiscompilingPasses : public ListReducer {
- BugDriver &BD;
- public:
- ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
-
- TestResult doTest(std::vector &Prefix,
- std::vector &Suffix,
- std::string &Error) override;
- };
-}
+static llvm::cl::opt DisableLoopExtraction(
+ "disable-loop-extraction",
+ cl::desc("Don't extract loops when searching for miscompilations"),
+ cl::init(false));
+static llvm::cl::opt DisableBlockExtraction(
+ "disable-block-extraction",
+ cl::desc("Don't extract blocks when searching for miscompilations"),
+ cl::init(false));
+
+class ReduceMiscompilingPasses : public ListReducer {
+ BugDriver &BD;
+
+public:
+ ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {}
+
+ TestResult doTest(std::vector &Prefix,
+ std::vector
This PR re-introduces LLVM's bugpoint tool from the LLVM 3.7 release which had previously been deleted in the DXC fork. This tool is extremely useful for reducing complex test cases to small reproductions.
I have not tested the tool to verify its degree of functionality, if we find it useful we may wish to invest in making it work better with the HLSL-specific changes in DXC's repository.