microsoft / DirectXShaderCompiler

This repo hosts the source for the DirectX Shader Compiler which is based on LLVM/Clang.
Other
3.06k stars 677 forks source link

Reintroduce bugpoint from LLVM 3.7 #6731

Closed llvm-beanz closed 3 months ago

llvm-beanz commented 3 months ago

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.

github-actions[bot] commented 3 months ago

: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 &Suffix, + std::string &Error) override; +}; +} // namespace /// TestResult - After passes have been split into a test group and a control /// group, see if they still break the program. @@ -67,12 +68,12 @@ ReduceMiscompilingPasses::doTest(std::vector &Prefix, << "' compiles correctly: "; std::string BitcodeResult; - if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/, - true/*quiet*/)) { + if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false /*delete*/, + true /*quiet*/)) { errs() << " Error running this sequence of passes" << " on the input program!\n"; BD.setPassesToRun(Suffix); - BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); + BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); exit(BD.debugOptimizerCrash()); } @@ -88,11 +89,12 @@ ReduceMiscompilingPasses::doTest(std::vector &Prefix, << "no passes are run, nondeterministic program?\n"; exit(1); } - return KeepSuffix; // Miscompilation detected! + return KeepSuffix; // Miscompilation detected! } - outs() << " yup.\n"; // No miscompilation! + outs() << " yup.\n"; // No miscompilation! - if (Prefix.empty()) return NoFailure; + if (Prefix.empty()) + return NoFailure; // Next, see if the program is broken if we run the "prefix" passes first, // then separately run the "kept" passes. @@ -105,12 +107,12 @@ ReduceMiscompilingPasses::doTest(std::vector &Prefix, // kept passes, we can update our bitcode file to include the result of the // prefix passes, then discard the prefix passes. // - if (BD.runPasses(BD.getProgram(), Prefix, BitcodeResult, false/*delete*/, - true/*quiet*/)) { + if (BD.runPasses(BD.getProgram(), Prefix, BitcodeResult, false /*delete*/, + true /*quiet*/)) { errs() << " Error running this sequence of passes" << " on the input program!\n"; BD.setPassesToRun(Prefix); - BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); + BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); exit(BD.debugOptimizerCrash()); } @@ -123,7 +125,7 @@ ReduceMiscompilingPasses::doTest(std::vector &Prefix, sys::fs::remove(BitcodeResult); return KeepPrefix; } - outs() << " yup.\n"; // No miscompilation! + outs() << " yup.\n"; // No miscompilation! // Ok, so now we know that the prefix passes work, try running the suffix // passes on the result of the prefix passes. @@ -142,17 +144,17 @@ ReduceMiscompilingPasses::doTest(std::vector &Prefix, return NoFailure; outs() << "Checking to see if '" << getPassesString(Suffix) - << "' passes compile correctly after the '" - << getPassesString(Prefix) << "' passes: "; + << "' passes compile correctly after the '" << getPassesString(Prefix) + << "' passes: "; std::unique_ptr OriginalInput( BD.swapProgramIn(PrefixOutput.release())); - if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false/*delete*/, - true/*quiet*/)) { + if (BD.runPasses(BD.getProgram(), Suffix, BitcodeResult, false /*delete*/, + true /*quiet*/)) { errs() << " Error running this sequence of passes" << " on the input program!\n"; BD.setPassesToRun(Suffix); - BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); + BD.EmitProgressBitcode(BD.getProgram(), "pass-error", false); exit(BD.debugOptimizerCrash()); } @@ -167,45 +169,45 @@ ReduceMiscompilingPasses::doTest(std::vector &Prefix, } // Otherwise, we must not be running the bad pass anymore. - outs() << " yup.\n"; // No miscompilation! + outs() << " yup.\n"; // No miscompilation! // Restore orig program & free test. delete BD.swapProgramIn(OriginalInput.release()); return NoFailure; } namespace { - class ReduceMiscompilingFunctions : public ListReducer { - BugDriver &BD; - bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); - public: - ReduceMiscompilingFunctions(BugDriver &bd, - bool (*F)(BugDriver &, Module *, Module *, - std::string &)) +class ReduceMiscompilingFunctions : public ListReducer { + BugDriver &BD; + bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); + +public: + ReduceMiscompilingFunctions(BugDriver &bd, bool (*F)(BugDriver &, Module *, + Module *, std::string &)) : BD(bd), TestFn(F) {} - TestResult doTest(std::vector &Prefix, - std::vector &Suffix, - std::string &Error) override { - if (!Suffix.empty()) { - bool Ret = TestFuncs(Suffix, Error); - if (!Error.empty()) - return InternalError; - if (Ret) - return KeepSuffix; - } - if (!Prefix.empty()) { - bool Ret = TestFuncs(Prefix, Error); - if (!Error.empty()) - return InternalError; - if (Ret) - return KeepPrefix; - } - return NoFailure; + TestResult doTest(std::vector &Prefix, + std::vector &Suffix, + std::string &Error) override { + if (!Suffix.empty()) { + bool Ret = TestFuncs(Suffix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepSuffix; + } + if (!Prefix.empty()) { + bool Ret = TestFuncs(Prefix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepPrefix; } + return NoFailure; + } - bool TestFuncs(const std::vector &Prefix, std::string &Error); - }; -} + bool TestFuncs(const std::vector &Prefix, std::string &Error); +}; +} // namespace /// TestMergedProgram - Given two modules, link them together and run the /// program, checking to see if the program matches the diff. If there is @@ -224,7 +226,7 @@ static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2, } if (Linker::LinkModules(M1, M2)) exit(1); - delete M2; // We are done with this module. + delete M2; // We are done with this module. // Execute the program. Broken = BD.diffProgram(M1, "", "", false, &Error); @@ -240,12 +242,12 @@ static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2, /// under consideration for miscompilation vs. those that are not, and test /// accordingly. Each group of functions becomes a separate Module. /// -bool ReduceMiscompilingFunctions::TestFuncs(const std::vector &Funcs, - std::string &Error) { +bool ReduceMiscompilingFunctions::TestFuncs( + const std::vector &Funcs, std::string &Error) { // Test to see if the function is misoptimized if we ONLY run it on the // functions listed in Funcs. outs() << "Checking to see if the program is misoptimized when " - << (Funcs.size()==1 ? "this function is" : "these functions are") + << (Funcs.size() == 1 ? "this function is" : "these functions are") << " run through the pass" << (BD.getPassesToRun().size() == 1 ? "" : "es") << ":"; PrintFunctionList(Funcs); @@ -262,7 +264,7 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector &Funcs, Module *Clone = CloneModule(BD.getProgram(), VMap); Module *Orig = BD.swapProgramIn(Clone); - std::vector FuncsOnClone; + std::vector FuncsOnClone; for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { Function *F = cast(VMap[Funcs[i]]); FuncsOnClone.push_back(F); @@ -271,8 +273,8 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector &Funcs, // Split the module into the two halves of the program we want. VMap.clear(); Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone, - VMap); + Module *ToOptimize = + SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone, VMap); // Run the predicate, note that the predicate will delete both input modules. bool Broken = TestFn(BD, ToOptimize, ToNotOptimize, Error); @@ -301,17 +303,17 @@ static void DisambiguateGlobalSymbols(Module *M) { static bool ExtractLoops(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *, Module *, std::string &), - std::vector &MiscompiledFunctions, + std::vector &MiscompiledFunctions, std::string &Error) { bool MadeChange = false; while (1) { - if (BugpointIsInterrupted) return MadeChange; + if (BugpointIsInterrupted) + return MadeChange; ValueToValueMapTy VMap; Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, - MiscompiledFunctions, - VMap); + Module *ToOptimize = + SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, VMap); Module *ToOptimizeLoopExtracted = BD.extractLoop(ToOptimize).release(); if (!ToOptimizeLoopExtracted) { // If the loop extractor crashed or if there were no extractible loops, @@ -330,8 +332,8 @@ static bool ExtractLoops(BugDriver &BD, // extraction. AbstractInterpreter *AI = BD.switchToSafeInterpreter(); bool Failure; - Module *New = TestMergedProgram(BD, ToOptimizeLoopExtracted, - ToNotOptimize, false, Error, Failure); + Module *New = TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, + false, Error, Failure); if (!New) return false; @@ -356,8 +358,8 @@ static bool ExtractLoops(BugDriver &BD, BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc", ToOptimizeLoopExtracted); - errs() << "Please submit the " - << OutputPrefix << "-loop-extract-fail-*.bc files.\n"; + errs() << "Please submit the " << OutputPrefix + << "-loop-extract-fail-*.bc files.\n"; delete ToOptimize; delete ToNotOptimize; return MadeChange; @@ -368,7 +370,7 @@ static bool ExtractLoops(BugDriver &BD, outs() << " Testing after loop extraction:\n"; // Clone modules, the tester function will free them. Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted, VMap); - Module *TNOBackup = CloneModule(ToNotOptimize, VMap); + Module *TNOBackup = CloneModule(ToNotOptimize, VMap); for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) MiscompiledFunctions[i] = cast(VMap[MiscompiledFunctions[i]]); @@ -385,7 +387,7 @@ static bool ExtractLoops(BugDriver &BD, // If the program is not still broken, then loop extraction did something // that masked the error. Stop loop extraction now. - std::vector > MisCompFunctions; + std::vector> MisCompFunctions; for (Function *F : MiscompiledFunctions) { MisCompFunctions.emplace_back(F->getName(), F->getFunctionType()); } @@ -408,9 +410,10 @@ static bool ExtractLoops(BugDriver &BD, outs() << "*** Loop extraction successful!\n"; - std::vector > MisCompFunctions; + std::vector> MisCompFunctions; for (Module::iterator I = ToOptimizeLoopExtracted->begin(), - E = ToOptimizeLoopExtracted->end(); I != E; ++I) + E = ToOptimizeLoopExtracted->end(); + I != E; ++I) if (!I->isDeclaration()) MisCompFunctions.emplace_back(I->getName(), I->getFunctionType()); @@ -440,45 +443,46 @@ static bool ExtractLoops(BugDriver &BD, } namespace { - class ReduceMiscompiledBlocks : public ListReducer { - BugDriver &BD; - bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); - std::vector FunctionsBeingTested; - public: - ReduceMiscompiledBlocks(BugDriver &bd, - bool (*F)(BugDriver &, Module *, Module *, - std::string &), - const std::vector &Fns) +class ReduceMiscompiledBlocks : public ListReducer { + BugDriver &BD; + bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); + std::vector FunctionsBeingTested; + +public: + ReduceMiscompiledBlocks(BugDriver &bd, + bool (*F)(BugDriver &, Module *, Module *, + std::string &), + const std::vector &Fns) : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {} - TestResult doTest(std::vector &Prefix, - std::vector &Suffix, - std::string &Error) override { - if (!Suffix.empty()) { - bool Ret = TestFuncs(Suffix, Error); - if (!Error.empty()) - return InternalError; - if (Ret) - return KeepSuffix; - } - if (!Prefix.empty()) { - bool Ret = TestFuncs(Prefix, Error); - if (!Error.empty()) - return InternalError; - if (Ret) - return KeepPrefix; - } - return NoFailure; + TestResult doTest(std::vector &Prefix, + std::vector &Suffix, + std::string &Error) override { + if (!Suffix.empty()) { + bool Ret = TestFuncs(Suffix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepSuffix; } + if (!Prefix.empty()) { + bool Ret = TestFuncs(Prefix, Error); + if (!Error.empty()) + return InternalError; + if (Ret) + return KeepPrefix; + } + return NoFailure; + } - bool TestFuncs(const std::vector &BBs, std::string &Error); - }; -} + bool TestFuncs(const std::vector &BBs, std::string &Error); +}; +} // namespace /// TestFuncs - Extract all blocks for the miscompiled functions except for the /// specified blocks. If the problem still exists, return true. /// -bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs, +bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs, std::string &Error) { // Test to see if the function is misoptimized if we ONLY run it on the // functions listed in Funcs. @@ -487,7 +491,8 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs, outs() << "but these " << BBs.size() << " blocks are extracted: "; for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i) outs() << BBs[i]->getName() << " "; - if (BBs.size() > 10) outs() << "..."; + if (BBs.size() > 10) + outs() << "..."; } else { outs() << "blocks are extracted."; } @@ -497,8 +502,8 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs, ValueToValueMapTy VMap; Module *Clone = CloneModule(BD.getProgram(), VMap); Module *Orig = BD.swapProgramIn(Clone); - std::vector FuncsOnClone; - std::vector BBsOnClone; + std::vector FuncsOnClone; + std::vector BBsOnClone; for (unsigned i = 0, e = FunctionsBeingTested.size(); i != e; ++i) { Function *F = cast(VMap[FunctionsBeingTested[i]]); FuncsOnClone.push_back(F); @@ -510,9 +515,8 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs, VMap.clear(); Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, - FuncsOnClone, - VMap); + Module *ToOptimize = + SplitFunctionsOutOfModule(ToNotOptimize, FuncsOnClone, VMap); // Try the extraction. If it doesn't work, then the block extractor crashed // or something, in which case bugpoint can't chase down this possibility. @@ -531,7 +535,6 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs, return false; } - /// ExtractBlocks - Given a reduced list of functions that still expose the bug, /// extract as many basic blocks from the region as possible without obscuring /// the bug. @@ -539,14 +542,16 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs, static bool ExtractBlocks(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *, Module *, std::string &), - std::vector &MiscompiledFunctions, + std::vector &MiscompiledFunctions, std::string &Error) { - if (BugpointIsInterrupted) return false; + if (BugpointIsInterrupted) + return false; - std::vector Blocks; + std::vector Blocks; for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) for (Function::iterator I = MiscompiledFunctions[i]->begin(), - E = MiscompiledFunctions[i]->end(); I != E; ++I) + E = MiscompiledFunctions[i]->end(); + I != E; ++I) Blocks.push_back(I); // Use the list reducer to identify blocks that can be extracted without @@ -556,14 +561,14 @@ static bool ExtractBlocks(BugDriver &BD, // Check to see if all blocks are extractible first. bool Ret = ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions) - .TestFuncs(std::vector(), Error); + .TestFuncs(std::vector(), Error); if (!Error.empty()) return false; if (Ret) { Blocks.clear(); } else { - ReduceMiscompiledBlocks(BD, TestFn, - MiscompiledFunctions).reduceList(Blocks, Error); + ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions) + .reduceList(Blocks, Error); if (!Error.empty()) return false; if (Blocks.size() == OldSize) @@ -572,9 +577,8 @@ static bool ExtractBlocks(BugDriver &BD, ValueToValueMapTy VMap; Module *ProgClone = CloneModule(BD.getProgram(), VMap); - Module *ToExtract = SplitFunctionsOutOfModule(ProgClone, - MiscompiledFunctions, - VMap); + Module *ToExtract = + SplitFunctionsOutOfModule(ProgClone, MiscompiledFunctions, VMap); std::unique_ptr Extracted = BD.extractMappedBlocksFromModule(Blocks, ToExtract); if (!Extracted) { @@ -589,9 +593,9 @@ static bool ExtractBlocks(BugDriver &BD, // together. delete ToExtract; - std::vector > MisCompFunctions; - for (Module::iterator I = Extracted->begin(), E = Extracted->end(); - I != E; ++I) + std::vector> MisCompFunctions; + for (Module::iterator I = Extracted->begin(), E = Extracted->end(); I != E; + ++I) if (!I->isDeclaration()) MisCompFunctions.emplace_back(I->getName(), I->getFunctionType()); @@ -613,20 +617,18 @@ static bool ExtractBlocks(BugDriver &BD, return true; } - /// DebugAMiscompilation - This is a generic driver to narrow down /// miscompilations, either in an optimization or a code generator. /// -static std::vector -DebugAMiscompilation(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *, - std::string &), - std::string &Error) { +static std::vector DebugAMiscompilation( + BugDriver &BD, + bool (*TestFn)(BugDriver &, Module *, Module *, std::string &), + std::string &Error) { // Okay, now that we have reduced the list of passes which are causing the // failure, see if we can pin down which functions are being // miscompiled... first build a list of all of the non-external functions in // the program. - std::vector MiscompiledFunctions; + std::vector MiscompiledFunctions; Module *Prog = BD.getProgram(); for (Module::iterator I = Prog->begin(), E = Prog->end(); I != E; ++I) if (!I->isDeclaration()) @@ -634,8 +636,8 @@ DebugAMiscompilation(BugDriver &BD, // Do the reduction... if (!BugpointIsInterrupted) - ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, - Error); + ReduceMiscompilingFunctions(BD, TestFn) + .reduceList(MiscompiledFunctions, Error); if (!Error.empty()) { errs() << "\n***Cannot reduce functions: "; return MiscompiledFunctions; @@ -660,8 +662,8 @@ DebugAMiscompilation(BugDriver &BD, // Do the reduction... if (!BugpointIsInterrupted) - ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, - Error); + ReduceMiscompilingFunctions(BD, TestFn) + .reduceList(MiscompiledFunctions, Error); if (!Error.empty()) return MiscompiledFunctions; @@ -683,8 +685,8 @@ DebugAMiscompilation(BugDriver &BD, DisambiguateGlobalSymbols(BD.getProgram()); // Do the reduction... - ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions, - Error); + ReduceMiscompilingFunctions(BD, TestFn) + .reduceList(MiscompiledFunctions, Error); if (!Error.empty()) return MiscompiledFunctions; @@ -725,7 +727,6 @@ static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe, return Broken; } - /// debugMiscompilation - This method is used when the passes selected are not /// crashing, but the generated output is semantically different from the /// input. @@ -746,7 +747,7 @@ void BugDriver::debugMiscompilation(std::string *Error) { EmitProgressBitcode(Program, "passinput"); std::vector MiscompiledFunctions = - DebugAMiscompilation(*this, TestOptimizer, *Error); + DebugAMiscompilation(*this, TestOptimizer, *Error); if (!Error->empty()) return; @@ -754,17 +755,16 @@ void BugDriver::debugMiscompilation(std::string *Error) { outs() << "Outputting reduced bitcode files which expose the problem:\n"; ValueToValueMapTy VMap; Module *ToNotOptimize = CloneModule(getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, - MiscompiledFunctions, - VMap); + Module *ToOptimize = + SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, VMap); outs() << " Non-optimized portion: "; EmitProgressBitcode(ToNotOptimize, "tonotoptimize", true); - delete ToNotOptimize; // Delete hacked module. + delete ToNotOptimize; // Delete hacked module. outs() << " Portion that is input to optimizer: "; EmitProgressBitcode(ToOptimize, "tooptimize"); - delete ToOptimize; // Delete hacked module. + delete ToOptimize; // Delete hacked module. return; } @@ -778,7 +778,8 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, Test = BD.performFinalCleanups(Test).release(); // If we are executing the JIT, we have several nasty issues to take care of. - if (!BD.isExecutingJIT()) return; + if (!BD.isExecutingJIT()) + return; // First, if the main function is in the Safe module, we must add a stub to // the Test module to call into it. Thus, we create a new function `main' @@ -788,20 +789,21 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Rename it oldMain->setName("llvm_bugpoint_old_main"); // Create a NEW `main' function with same type in the test module. - Function *newMain = Function::Create(oldMain->getFunctionType(), - GlobalValue::ExternalLinkage, - "main", Test); + Function *newMain = + Function::Create(oldMain->getFunctionType(), + GlobalValue::ExternalLinkage, "main", Test); // Create an `oldmain' prototype in the test module, which will // corresponds to the real main function in the same module. Function *oldMainProto = Function::Create(oldMain->getFunctionType(), GlobalValue::ExternalLinkage, oldMain->getName(), Test); // Set up and remember the argument list for the main function. - std::vector args; - for (Function::arg_iterator - I = newMain->arg_begin(), E = newMain->arg_end(), - OI = oldMain->arg_begin(); I != E; ++I, ++OI) { - I->setName(OI->getName()); // Copy argument names from oldMain + std::vector args; + for (Function::arg_iterator I = newMain->arg_begin(), + E = newMain->arg_end(), + OI = oldMain->arg_begin(); + I != E; ++I, ++OI) { + I->setName(OI->getName()); // Copy argument names from oldMain args.push_back(I); } @@ -820,11 +822,9 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Add the resolver to the Safe module. // Prototype: void *getPointerToNamedFunction(const char* Name) - Constant *resolverFunc = - Safe->getOrInsertFunction("getPointerToNamedFunction", - Type::getInt8PtrTy(Safe->getContext()), - Type::getInt8PtrTy(Safe->getContext()), - (Type *)nullptr); + Constant *resolverFunc = Safe->getOrInsertFunction( + "getPointerToNamedFunction", Type::getInt8PtrTy(Safe->getContext()), + Type::getInt8PtrTy(Safe->getContext()), (Type *)nullptr); // Use the function we just added to get addresses of functions we need. for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { @@ -836,21 +836,20 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, if (TestFn && !TestFn->isDeclaration()) { // 1. Add a string constant with its name to the global file Constant *InitArray = - ConstantDataArray::getString(F->getContext(), F->getName()); - GlobalVariable *funcName = - new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/, - GlobalValue::InternalLinkage, InitArray, - F->getName() + "_name"); + ConstantDataArray::getString(F->getContext(), F->getName()); + GlobalVariable *funcName = new GlobalVariable( + *Safe, InitArray->getType(), true /*isConstant*/, + GlobalValue::InternalLinkage, InitArray, F->getName() + "_name"); // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an // sbyte* so it matches the signature of the resolver function. // GetElementPtr *funcName, ulong 0, ulong 0 - std::vector GEPargs(2, - Constant::getNullValue(Type::getInt32Ty(F->getContext()))); + std::vector GEPargs( + 2, Constant::getNullValue(Type::getInt32Ty(F->getContext()))); Value *GEP = ConstantExpr::getGetElementPtr(InitArray->getType(), funcName, GEPargs); - std::vector ResolverArgs; + std::vector ResolverArgs; ResolverArgs.push_back(GEP); // Rewrite uses of F in global initializers, etc. to uses of a wrapper @@ -858,23 +857,21 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, if (!F->use_empty()) { // Create a new global to hold the cached function pointer. Constant *NullPtr = ConstantPointerNull::get(F->getType()); - GlobalVariable *Cache = - new GlobalVariable(*F->getParent(), F->getType(), - false, GlobalValue::InternalLinkage, - NullPtr,F->getName()+".fpcache"); + GlobalVariable *Cache = new GlobalVariable( + *F->getParent(), F->getType(), false, + GlobalValue::InternalLinkage, NullPtr, F->getName() + ".fpcache"); // Construct a new stub function that will re-route calls to F FunctionType *FuncTy = F->getFunctionType(); - Function *FuncWrapper = Function::Create(FuncTy, - GlobalValue::InternalLinkage, - F->getName() + "_wrapper", - F->getParent()); - BasicBlock *EntryBB = BasicBlock::Create(F->getContext(), - "entry", FuncWrapper); - BasicBlock *DoCallBB = BasicBlock::Create(F->getContext(), - "usecache", FuncWrapper); - BasicBlock *LookupBB = BasicBlock::Create(F->getContext(), - "lookupfp", FuncWrapper); + Function *FuncWrapper = + Function::Create(FuncTy, GlobalValue::InternalLinkage, + F->getName() + "_wrapper", F->getParent()); + BasicBlock *EntryBB = + BasicBlock::Create(F->getContext(), "entry", FuncWrapper); + BasicBlock *DoCallBB = + BasicBlock::Create(F->getContext(), "usecache", FuncWrapper); + BasicBlock *LookupBB = + BasicBlock::Create(F->getContext(), "lookupfp", FuncWrapper); // Check to see if we already looked up the value. Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB); @@ -885,28 +882,28 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Resolve the call to function F via the JIT API: // // call resolver(GetElementPtr...) - CallInst *Resolver = - CallInst::Create(resolverFunc, ResolverArgs, "resolver", LookupBB); + CallInst *Resolver = CallInst::Create(resolverFunc, ResolverArgs, + "resolver", LookupBB); // Cast the result from the resolver to correctly-typed function. - CastInst *CastedResolver = - new BitCastInst(Resolver, - PointerType::getUnqual(F->getFunctionType()), - "resolverCast", LookupBB); + CastInst *CastedResolver = new BitCastInst( + Resolver, PointerType::getUnqual(F->getFunctionType()), + "resolverCast", LookupBB); // Save the value in our cache. new StoreInst(CastedResolver, Cache, LookupBB); BranchInst::Create(DoCallBB, LookupBB); - PHINode *FuncPtr = PHINode::Create(NullPtr->getType(), 2, - "fp", DoCallBB); + PHINode *FuncPtr = + PHINode::Create(NullPtr->getType(), 2, "fp", DoCallBB); FuncPtr->addIncoming(CastedResolver, LookupBB); FuncPtr->addIncoming(CachedVal, EntryBB); // Save the argument list. - std::vector Args; + std::vector Args; for (Function::arg_iterator i = FuncWrapper->arg_begin(), - e = FuncWrapper->arg_end(); i != e; ++i) + e = FuncWrapper->arg_end(); + i != e; ++i) Args.push_back(i); // Pass on the arguments to the real function, return its result @@ -914,9 +911,9 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, CallInst::Create(FuncPtr, Args, "", DoCallBB); ReturnInst::Create(F->getContext(), DoCallBB); } else { - CallInst *Call = CallInst::Create(FuncPtr, Args, - "retval", DoCallBB); - ReturnInst::Create(F->getContext(),Call, DoCallBB); + CallInst *Call = + CallInst::Create(FuncPtr, Args, "retval", DoCallBB); + ReturnInst::Create(F->getContext(), Call, DoCallBB); } // Use the wrapper function instead of the old function @@ -932,8 +929,6 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, } } - - /// TestCodeGenerator - This is the predicate function used to check to see if /// the "Test" portion of the program is miscompiled by the code generator under /// test. If so, return true. In any case, both module arguments are deleted. @@ -947,8 +942,8 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, std::error_code EC = sys::fs::createTemporaryFile("bugpoint.test", "bc", TestModuleFD, TestModuleBC); if (EC) { - errs() << BD.getToolName() << "Error making unique filename: " - << EC.message() << "\n"; + errs() << BD.getToolName() + << "Error making unique filename: " << EC.message() << "\n"; exit(1); } if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test)) { @@ -966,14 +961,13 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD, SafeModuleBC); if (EC) { - errs() << BD.getToolName() << "Error making unique filename: " - << EC.message() << "\n"; + errs() << BD.getToolName() + << "Error making unique filename: " << EC.message() << "\n"; exit(1); } if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe)) { - errs() << "Error writing bitcode to `" << SafeModuleBC - << "'\nExiting."; + errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting."; exit(1); } @@ -1001,13 +995,12 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, return Result; } - /// debugCodeGenerator - debug errors in LLC, LLI, or CBE. /// bool BugDriver::debugCodeGenerator(std::string *Error) { - if ((void*)SafeInterpreter == (void*)Interpreter) { - std::string Result = executeProgramSafely(Program, "bugpoint.safe.out", - Error); + if ((void *)SafeInterpreter == (void *)Interpreter) { + std::string Result = + executeProgramSafely(Program, "bugpoint.safe.out", Error); if (Error->empty()) { outs() << "\n*** The \"safe\" i.e. 'known good' backend cannot match " << "the reference diff. This may be due to a\n front-end " @@ -1015,16 +1008,15 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { << "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"; + << "you: '" << Result << "'.\n"; } return true; } DisambiguateGlobalSymbols(Program); - std::vector Funcs = DebugAMiscompilation(*this, TestCodeGenerator, - *Error); + std::vector Funcs = + DebugAMiscompilation(*this, TestCodeGenerator, *Error); if (!Error->empty()) return true; @@ -1041,14 +1033,13 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { std::error_code EC = sys::fs::createTemporaryFile("bugpoint.test", "bc", TestModuleFD, TestModuleBC); if (EC) { - errs() << getToolName() << "Error making unique filename: " - << EC.message() << "\n"; + errs() << getToolName() << "Error making unique filename: " << EC.message() + << "\n"; exit(1); } if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen)) { - errs() << "Error writing bitcode to `" << TestModuleBC - << "'\nExiting."; + errs() << "Error writing bitcode to `" << TestModuleBC << "'\nExiting."; exit(1); } delete ToCodeGen; @@ -1059,14 +1050,13 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { EC = sys::fs::createTemporaryFile("bugpoint.safe", "bc", SafeModuleFD, SafeModuleBC); if (EC) { - errs() << getToolName() << "Error making unique filename: " - << EC.message() << "\n"; + errs() << getToolName() << "Error making unique filename: " << EC.message() + << "\n"; exit(1); } if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, ToNotCodeGen)) { - errs() << "Error writing bitcode to `" << SafeModuleBC - << "'\nExiting."; + errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting."; exit(1); } std::string SharedObject = compileSharedObject(SafeModuleBC.str(), *Error); @@ -1078,11 +1068,10 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { if (isExecutingJIT()) { outs() << " lli -load " << SharedObject << " " << TestModuleBC; } else { - outs() << " llc " << TestModuleBC << " -o " << TestModuleBC - << ".s\n"; - outs() << " gcc " << SharedObject << " " << TestModuleBC.str() - << ".s -o " << TestModuleBC << ".exe"; -#if defined (HAVE_LINK_R) + outs() << " llc " << TestModuleBC << " -o " << TestModuleBC << ".s\n"; + outs() << " gcc " << SharedObject << " " << TestModuleBC.str() << ".s -o " + << TestModuleBC << ".exe"; +#if defined(HAVE_LINK_R) outs() << " -Wl,-R."; #endif outs() << "\n"; @@ -1095,9 +1084,9 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { << SafeModuleBC.str() << " -o temporary.c\n" << " gcc -xc temporary.c -O2 -o " << SharedObject; if (TargetTriple.getArch() == Triple::sparc) - outs() << " -G"; // Compile a shared library, `-G' for Sparc + outs() << " -G"; // Compile a shared library, `-G' for Sparc else - outs() << " -fPIC -shared"; // `-shared' for Linux/X86, maybe others + outs() << " -fPIC -shared"; // `-shared' for Linux/X86, maybe others outs() << " -fno-strict-aliasing\n"; diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index 4caba463..49c75a2d 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -39,7 +39,7 @@ using namespace llvm; #define DEBUG_TYPE "bugpoint" namespace llvm { - extern cl::opt OutputPrefix; +extern cl::opt OutputPrefix; } static cl::opt PreserveBitcodeUseListOrder( @@ -48,13 +48,13 @@ static cl::opt PreserveBitcodeUseListOrder( cl::init(true), cl::Hidden); namespace { - // ChildOutput - This option captures the name of the child output file that - // is set up by the parent bugpoint process - cl::opt ChildOutput("child-output", cl::ReallyHidden); - cl::opt OptCmd("opt-command", cl::init(""), - cl::desc("Path to opt. (default: search path " - "for 'opt'.)")); -} +// ChildOutput - This option captures the name of the child output file that +// is set up by the parent bugpoint process +cl::opt ChildOutput("child-output", cl::ReallyHidden); +cl::opt OptCmd("opt-command", cl::init(""), + cl::desc("Path to opt. (default: search path " + "for 'opt'.)")); +} // namespace /// writeProgramToFile - This writes the current "Program" to the named bitcode /// file. If an error occurs, true is returned. @@ -84,26 +84,26 @@ bool BugDriver::writeProgramToFile(const std::string &Filename, return true; } - /// EmitProgressBitcode - This function is used to output the current Program /// to a file named "bugpoint-ID.bc". /// -void BugDriver::EmitProgressBitcode(const Module *M, - const std::string &ID, - bool NoFlyer) const { +void BugDriver::EmitProgressBitcode(const Module *M, const std::string &ID, + bool NoFlyer) const { // Output the input to the current pass to a bitcode file, emit a message // telling the user how to reproduce it: opt -foo blah.bc // std::string Filename = OutputPrefix + "-" + ID + ".bc"; if (writeProgramToFile(Filename, M)) { - errs() << "Error opening file '" << Filename << "' for writing!\n"; + errs() << "Error opening file '" << Filename << "' for writing!\n"; return; } outs() << "Emitted bitcode to '" << Filename << "'\n"; - if (NoFlyer || PassesToRun.empty()) return; + if (NoFlyer || PassesToRun.empty()) + return; outs() << "\n*** You can reproduce the problem with: "; - if (UseValgrind) outs() << "valgrind "; + if (UseValgrind) + outs() << "valgrind "; outs() << "opt " << Filename; #if 0 // HLSL Change - HLSL disabled plugin loading for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { @@ -113,8 +113,9 @@ void BugDriver::EmitProgressBitcode(const Module *M, outs() << " " << getPassesString(PassesToRun) << "\n"; } -cl::opt SilencePasses("silence-passes", - cl::desc("Suppress output of running passes (both stdout and stderr)")); +cl::opt SilencePasses( + "silence-passes", + cl::desc("Suppress output of running passes (both stdout and stderr)")); static cl::list OptArgs("opt-args", cl::Positional, cl::desc("..."), @@ -132,15 +133,15 @@ bool BugDriver::runPasses(Module *Program, const std::vector &Passes, std::string &OutputFilename, bool DeleteOutput, bool Quiet, unsigned NumExtraArgs, - const char * const *ExtraArgs) const { + const char *const *ExtraArgs) const { // setup the output file name outs().flush(); SmallString<128> UniqueFilename; std::error_code EC = sys::fs::createUniqueFile( OutputPrefix + "-output-%%%%%%%.bc", UniqueFilename); if (EC) { - errs() << getToolName() << ": Error making unique filename: " - << EC.message() << "\n"; + errs() << getToolName() + << ": Error making unique filename: " << EC.message() << "\n"; return 1; } OutputFilename = UniqueFilename.str(); @@ -151,8 +152,8 @@ bool BugDriver::runPasses(Module *Program, EC = sys::fs::createUniqueFile(OutputPrefix + "-input-%%%%%%%.bc", InputFD, InputFilename); if (EC) { - errs() << getToolName() << ": Error making unique filename: " - << EC.message() << "\n"; + errs() << getToolName() + << ": Error making unique filename: " << EC.message() << "\n"; return 1; } @@ -195,7 +196,7 @@ bool BugDriver::runPasses(Module *Program, InFile.keep(); // setup the child process' arguments - SmallVector Args; + SmallVector Args; if (UseValgrind) { Args.push_back("valgrind"); Args.push_back("--error-exitcode=1"); @@ -216,10 +217,12 @@ bool BugDriver::runPasses(Module *Program, } #endif for (std::vector::const_iterator I = Passes.begin(), - E = Passes.end(); I != E; ++I ) - pass_args.push_back( std::string("-") + (*I) ); + E = Passes.end(); + I != E; ++I) + pass_args.push_back(std::string("-") + (*I)); for (std::vector::const_iterator I = pass_args.begin(), - E = pass_args.end(); I != E; ++I ) + E = pass_args.end(); + I != E; ++I) Args.push_back(I->c_str()); Args.push_back(InputFilename.c_str()); for (unsigned i = 0; i < NumExtraArgs; ++i) @@ -227,10 +230,9 @@ bool BugDriver::runPasses(Module *Program, Args.push_back(nullptr); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = Args.size()-1; i != e; ++i) - errs() << " " << Args[i]; - errs() << "\n"; - ); + for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) errs() + << " " << Args[i]; + errs() << "\n";); // Redirect stdout and stderr to nowhere if SilencePasses is given StringRef Nowhere; @@ -268,19 +270,18 @@ bool BugDriver::runPasses(Module *Program, return result != 0; } - std::unique_ptr BugDriver::runPassesOn(Module *M, const std::vector &Passes, bool AutoDebugCrashes, unsigned NumExtraArgs, const char *const *ExtraArgs) { std::string BitcodeResult; - if (runPasses(M, Passes, BitcodeResult, false/*delete*/, true/*quiet*/, + if (runPasses(M, Passes, BitcodeResult, false /*delete*/, true /*quiet*/, NumExtraArgs, ExtraArgs)) { if (AutoDebugCrashes) { errs() << " Error running this sequence of passes" << " on the input program!\n"; delete swapProgramIn(M); - EmitProgressBitcode(M, "pass-error", false); + EmitProgressBitcode(M, "pass-error", false); exit(debugOptimizerCrash()); } return nullptr; @@ -288,8 +289,8 @@ BugDriver::runPassesOn(Module *M, const std::vector &Passes, std::unique_ptr Ret = parseInputFile(BitcodeResult, Context); if (!Ret) { - errs() << getToolName() << ": Error reading bitcode file '" - << BitcodeResult << "'!\n"; + errs() << getToolName() << ": Error reading bitcode file '" << BitcodeResult + << "'!\n"; exit(1); } sys::fs::remove(BitcodeResult); diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp index 51091e29..8efb2bea 100644 --- a/tools/bugpoint/ToolRunner.cpp +++ b/tools/bugpoint/ToolRunner.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "ToolRunner.h" -#include "llvm/Config/config.h" // for HAVE_LINK_R +#include "llvm/Config/config.h" // for HAVE_LINK_R #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -26,44 +26,38 @@ using namespace llvm; #define DEBUG_TYPE "toolrunner" namespace llvm { - cl::opt - SaveTemps("save-temps", cl::init(false), cl::desc("Save temporary files")); +cl::opt SaveTemps("save-temps", cl::init(false), + cl::desc("Save temporary files")); } namespace { - cl::opt - RemoteClient("remote-client", - cl::desc("Remote execution client (rsh/ssh)")); +cl::opt + RemoteClient("remote-client", + cl::desc("Remote execution client (rsh/ssh)")); - cl::opt - RemoteHost("remote-host", - cl::desc("Remote execution (rsh/ssh) host")); +cl::opt RemoteHost("remote-host", + cl::desc("Remote execution (rsh/ssh) host")); - cl::opt - RemotePort("remote-port", - cl::desc("Remote execution (rsh/ssh) port")); +cl::opt RemotePort("remote-port", + cl::desc("Remote execution (rsh/ssh) port")); - cl::opt - RemoteUser("remote-user", - cl::desc("Remote execution (rsh/ssh) user id")); +cl::opt RemoteUser("remote-user", + cl::desc("Remote execution (rsh/ssh) user id")); - cl::opt - RemoteExtra("remote-extra-options", - cl::desc("Remote execution (rsh/ssh) extra options")); -} +cl::opt + RemoteExtra("remote-extra-options", + cl::desc("Remote execution (rsh/ssh) extra options")); +} // namespace /// RunProgramWithTimeout - This function provides an alternate interface /// to the sys::Program::ExecuteAndWait interface. /// @see sys::Program::ExecuteAndWait -static int RunProgramWithTimeout(StringRef ProgramPath, - const char **Args, - StringRef StdInFile, - StringRef StdOutFile, - StringRef StdErrFile, - unsigned NumSeconds = 0, +static int RunProgramWithTimeout(StringRef ProgramPath, const char **Args, + StringRef StdInFile, StringRef StdOutFile, + StringRef StdErrFile, unsigned NumSeconds = 0, unsigned MemoryLimit = 0, std::string *ErrMsg = nullptr) { - const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile }; + const StringRef *Redirects[3] = {&StdInFile, &StdOutFile, &StdErrFile}; #if 0 // For debug purposes { @@ -74,8 +68,8 @@ static int RunProgramWithTimeout(StringRef ProgramPath, } #endif - return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects, - NumSeconds, MemoryLimit, ErrMsg); + return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects, NumSeconds, + MemoryLimit, ErrMsg); } /// RunProgramRemotelyWithTimeout - This function runs the given program @@ -85,13 +79,12 @@ static int RunProgramWithTimeout(StringRef ProgramPath, /// code otherwise. /// @see sys::Program::ExecuteAndWait static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath, - const char **Args, - StringRef StdInFile, + const char **Args, StringRef StdInFile, StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0, unsigned MemoryLimit = 0) { - const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile }; + const StringRef *Redirects[3] = {&StdInFile, &StdOutFile, &StdErrFile}; #if 0 // For debug purposes { @@ -130,7 +123,7 @@ static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath, return ReturnCode; } -static std::string ProcessFailure(StringRef ProgPath, const char** Args, +static std::string ProcessFailure(StringRef ProgPath, const char **Args, unsigned Timeout = 0, unsigned MemoryLimit = 0) { std::ostringstream OS; @@ -169,44 +162,41 @@ static std::string ProcessFailure(StringRef ProgPath, const char** Args, // LLI Implementation of AbstractIntepreter interface // namespace { - class LLI : public AbstractInterpreter { - std::string LLIPath; // The path to the LLI executable - std::vector ToolArgs; // Args to pass to LLI - public: - LLI(const std::string &Path, const std::vector *Args) +class LLI : public AbstractInterpreter { + std::string LLIPath; // The path to the LLI executable + std::vector ToolArgs; // Args to pass to LLI +public: + LLI(const std::string &Path, const std::vector *Args) : LLIPath(Path) { - ToolArgs.clear (); - if (Args) { ToolArgs = *Args; } + ToolArgs.clear(); + if (Args) { + ToolArgs = *Args; } + } - int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs, - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0) override; - }; -} + int ExecuteProgram( + const std::string &Bitcode, const std::vector &Args, + const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector &GCCArgs, + const std::vector &SharedLibs = std::vector(), + unsigned Timeout = 0, unsigned MemoryLimit = 0) override; +}; +} // namespace int LLI::ExecuteProgram(const std::string &Bitcode, const std::vector &Args, const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, + const std::string &OutputFile, std::string *Error, const std::vector &GCCArgs, const std::vector &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { - std::vector LLIArgs; + unsigned Timeout, unsigned MemoryLimit) { + std::vector LLIArgs; LLIArgs.push_back(LLIPath.c_str()); LLIArgs.push_back("-force-interpreter=true"); for (std::vector::const_iterator i = SharedLibs.begin(), - e = SharedLibs.end(); i != e; ++i) { + e = SharedLibs.end(); + i != e; ++i) { LLIArgs.push_back("-load"); LLIArgs.push_back((*i).c_str()); } @@ -217,26 +207,25 @@ int LLI::ExecuteProgram(const std::string &Bitcode, LLIArgs.push_back(Bitcode.c_str()); // Add optional parameters to the running program from Argv - for (unsigned i=0, e = Args.size(); i != e; ++i) + for (unsigned i = 0, e = Args.size(); i != e; ++i) LLIArgs.push_back(Args[i].c_str()); LLIArgs.push_back(nullptr); - outs() << ""; outs().flush(); + outs() << ""; + outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i=0, e = LLIArgs.size()-1; i != e; ++i) - errs() << " " << LLIArgs[i]; - errs() << "\n"; - ); - return RunProgramWithTimeout(LLIPath, &LLIArgs[0], - InputFile, OutputFile, OutputFile, - Timeout, MemoryLimit, Error); + for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs() + << " " << LLIArgs[i]; + errs() << "\n";); + return RunProgramWithTimeout(LLIPath, &LLIArgs[0], InputFile, OutputFile, + OutputFile, Timeout, MemoryLimit, Error); } -void AbstractInterpreter::anchor() { } +void AbstractInterpreter::anchor() {} #if defined(LLVM_ON_UNIX) const char EXESuffix[] = ""; -#elif defined (LLVM_ON_WIN32) +#elif defined(LLVM_ON_WIN32) const char EXESuffix[] = "exe"; #endif @@ -266,11 +255,11 @@ static std::string PrependMainExecutablePath(const std::string &ExeName, } // LLI create method - Try to find the LLI executable -AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, - std::string &Message, - const std::vector *ToolArgs) { +AbstractInterpreter * +AbstractInterpreter::createLLI(const char *Argv0, std::string &Message, + const std::vector *ToolArgs) { std::string LLIPath = - PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createLLI); + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createLLI); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new LLI(LLIPath, ToolArgs); @@ -287,42 +276,36 @@ AbstractInterpreter *AbstractInterpreter::createLLI(const char *Argv0, // example, to compile a bitcode fragment without linking or executing, then // using a custom wrapper script to check for compiler errors. namespace { - class CustomCompiler : public AbstractInterpreter { - std::string CompilerCommand; - std::vector CompilerArgs; - public: - CustomCompiler( - const std::string &CompilerCmd, std::vector CompArgs) : - CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {} - - void compileProgram(const std::string &Bitcode, - std::string *Error, - unsigned Timeout = 0, - unsigned MemoryLimit = 0) override; - - int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs = - std::vector(), - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0) override { - *Error = "Execution not supported with -compile-custom"; - return -1; - } - }; -} +class CustomCompiler : public AbstractInterpreter { + std::string CompilerCommand; + std::vector CompilerArgs; + +public: + CustomCompiler(const std::string &CompilerCmd, + std::vector CompArgs) + : CompilerCommand(CompilerCmd), CompilerArgs(CompArgs) {} + + void compileProgram(const std::string &Bitcode, std::string *Error, + unsigned Timeout = 0, unsigned MemoryLimit = 0) override; + + int ExecuteProgram( + const std::string &Bitcode, const std::vector &Args, + const std::string &InputFile, const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = std::vector(), + const std::vector &SharedLibs = std::vector(), + unsigned Timeout = 0, unsigned MemoryLimit = 0) override { + *Error = "Execution not supported with -compile-custom"; + return -1; + } +}; +} // namespace void CustomCompiler::compileProgram(const std::string &Bitcode, - std::string *Error, - unsigned Timeout, + std::string *Error, unsigned Timeout, unsigned MemoryLimit) { - std::vector ProgramArgs; + std::vector ProgramArgs; ProgramArgs.push_back(CompilerCommand.c_str()); for (std::size_t i = 0; i < CompilerArgs.size(); ++i) @@ -334,11 +317,10 @@ void CustomCompiler::compileProgram(const std::string &Bitcode, for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i) ProgramArgs.push_back(CompilerArgs[i].c_str()); - if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0], - "", "", "", - Timeout, MemoryLimit, Error)) - *Error = ProcessFailure(CompilerCommand, &ProgramArgs[0], - Timeout, MemoryLimit); + if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0], "", "", "", + Timeout, MemoryLimit, Error)) + *Error = + ProcessFailure(CompilerCommand, &ProgramArgs[0], Timeout, MemoryLimit); } //===---------------------------------------------------------------------===// @@ -348,38 +330,34 @@ void CustomCompiler::compileProgram(const std::string &Bitcode, // for example, to invoke a cross compiler for code generation followed by // a simulator that executes the generated binary. namespace { - class CustomExecutor : public AbstractInterpreter { - std::string ExecutionCommand; - std::vector ExecutorArgs; - public: - CustomExecutor( - const std::string &ExecutionCmd, std::vector ExecArgs) : - ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} - - int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs, - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0) override; - }; -} +class CustomExecutor : public AbstractInterpreter { + std::string ExecutionCommand; + std::vector ExecutorArgs; + +public: + CustomExecutor(const std::string &ExecutionCmd, + std::vector ExecArgs) + : ExecutionCommand(ExecutionCmd), ExecutorArgs(ExecArgs) {} + + int ExecuteProgram( + const std::string &Bitcode, const std::vector &Args, + const std::string &InputFile, const std::string &OutputFile, + std::string *Error, const std::vector &GCCArgs, + const std::vector &SharedLibs = std::vector(), + unsigned Timeout = 0, unsigned MemoryLimit = 0) override; +}; +} // namespace int CustomExecutor::ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs, - const std::vector &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { - - std::vector ProgramArgs; + const std::vector &Args, + const std::string &InputFile, + const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs, + const std::vector &SharedLibs, + unsigned Timeout, unsigned MemoryLimit) { + + std::vector ProgramArgs; ProgramArgs.push_back(ExecutionCommand.c_str()); for (std::size_t i = 0; i < ExecutorArgs.size(); ++i) @@ -391,10 +369,9 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, for (unsigned i = 0, e = Args.size(); i != e; ++i) ProgramArgs.push_back(Args[i].c_str()); - return RunProgramWithTimeout( - ExecutionCommand, - &ProgramArgs[0], InputFile, OutputFile, - OutputFile, Timeout, MemoryLimit, Error); + return RunProgramWithTimeout(ExecutionCommand, &ProgramArgs[0], InputFile, + OutputFile, OutputFile, Timeout, MemoryLimit, + Error); } // Tokenize the CommandLine to the command and the args to allow @@ -418,9 +395,9 @@ static void lexCommand(std::string &Message, const std::string &CommandLine, while (std::string::npos != pos || std::string::npos != lastPos) { std::string token = CommandLine.substr(lastPos, pos - lastPos); if (Command == "") - Command = token; + Command = token; else - Args.push_back(token); + Args.push_back(token); // Skip delimiters. Note the "not_of" lastPos = CommandLine.find_first_not_of(delimiters, pos); // Find next "non-delimiter" @@ -429,9 +406,8 @@ static void lexCommand(std::string &Message, const std::string &CommandLine, auto Path = sys::findProgramByName(Command); if (!Path) { - Message = - std::string("Cannot find '") + Command + - "' in PATH: " + Path.getError().message() + "\n"; + Message = std::string("Cannot find '") + Command + + "' in PATH: " + Path.getError().message() + "\n"; return; } CmdPath = *Path; @@ -442,8 +418,7 @@ static void lexCommand(std::string &Message, const std::string &CommandLine, // Custom execution environment create method, takes the execution command // as arguments AbstractInterpreter *AbstractInterpreter::createCustomCompiler( - std::string &Message, - const std::string &CompileCommandLine) { + std::string &Message, const std::string &CompileCommandLine) { std::string CmdPath; std::vector Args; @@ -456,10 +431,9 @@ AbstractInterpreter *AbstractInterpreter::createCustomCompiler( // Custom execution environment create method, takes the execution command // as arguments -AbstractInterpreter *AbstractInterpreter::createCustomExecutor( - std::string &Message, - const std::string &ExecCommandLine) { - +AbstractInterpreter * +AbstractInterpreter::createCustomExecutor(std::string &Message, + const std::string &ExecCommandLine) { std::string CmdPath; std::vector Args; @@ -495,25 +469,22 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, LLCArgs.push_back("-o"); LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file - LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode + LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode if (UseIntegratedAssembler) LLCArgs.push_back("-filetype=obj"); - LLCArgs.push_back (nullptr); + LLCArgs.push_back(nullptr); outs() << (UseIntegratedAssembler ? "" : ""); outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = LLCArgs.size()-1; i != e; ++i) - errs() << " " << LLCArgs[i]; - errs() << "\n"; - ); - if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], - "", "", "", - Timeout, MemoryLimit)) - Error = ProcessFailure(LLCPath, &LLCArgs[0], - Timeout, MemoryLimit); + for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs() + << " " << LLCArgs[i]; + errs() << "\n";); + if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], "", "", "", Timeout, + MemoryLimit)) + Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; } @@ -527,37 +498,33 @@ void LLC::compileProgram(const std::string &Bitcode, std::string *Error, int LLC::ExecuteProgram(const std::string &Bitcode, const std::vector &Args, const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, + const std::string &OutputFile, std::string *Error, const std::vector &ArgsForGCC, const std::vector &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { + unsigned Timeout, unsigned MemoryLimit) { std::string OutputAsmFile; - GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, - MemoryLimit); + GCC::FileType FileKind = + OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); std::vector GCCArgs(ArgsForGCC); GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); // Assuming LLC worked, compile the result with GCC and run it. - return gcc->ExecuteProgram(OutputAsmFile, Args, FileKind, - InputFile, OutputFile, Error, GCCArgs, - Timeout, MemoryLimit); + return gcc->ExecuteProgram(OutputAsmFile, Args, FileKind, InputFile, + OutputFile, Error, GCCArgs, Timeout, MemoryLimit); } /// createLLC - Try to find the LLC executable /// -LLC *AbstractInterpreter::createLLC(const char *Argv0, - std::string &Message, +LLC *AbstractInterpreter::createLLC(const char *Argv0, std::string &Message, const std::string &GCCBinary, const std::vector *Args, const std::vector *GCCArgs, bool UseIntegratedAssembler) { std::string LLCPath = - PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t) & createLLC); + PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t)&createLLC); if (LLCPath.empty()) { Message = "Cannot find `llc' in executable directory!\n"; return nullptr; @@ -576,41 +543,37 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0, // JIT Implementation of AbstractIntepreter interface // namespace { - class JIT : public AbstractInterpreter { - std::string LLIPath; // The path to the LLI executable - std::vector ToolArgs; // Args to pass to LLI - public: - JIT(const std::string &Path, const std::vector *Args) +class JIT : public AbstractInterpreter { + std::string LLIPath; // The path to the LLI executable + std::vector ToolArgs; // Args to pass to LLI +public: + JIT(const std::string &Path, const std::vector *Args) : LLIPath(Path) { - ToolArgs.clear (); - if (Args) { ToolArgs = *Args; } + ToolArgs.clear(); + if (Args) { + ToolArgs = *Args; } + } - int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs = - std::vector(), - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0) override; - }; -} + int ExecuteProgram( + const std::string &Bitcode, const std::vector &Args, + const std::string &InputFile, const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = std::vector(), + const std::vector &SharedLibs = std::vector(), + unsigned Timeout = 0, unsigned MemoryLimit = 0) override; +}; +} // namespace int JIT::ExecuteProgram(const std::string &Bitcode, const std::vector &Args, const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, + const std::string &OutputFile, std::string *Error, const std::vector &GCCArgs, const std::vector &SharedLibs, - unsigned Timeout, - unsigned MemoryLimit) { + unsigned Timeout, unsigned MemoryLimit) { // Construct a vector of parameters, incorporating those from the command-line - std::vector JITArgs; + std::vector JITArgs; JITArgs.push_back(LLIPath.c_str()); JITArgs.push_back("-force-interpreter=false"); @@ -624,28 +587,28 @@ int JIT::ExecuteProgram(const std::string &Bitcode, } JITArgs.push_back(Bitcode.c_str()); // Add optional parameters to the running program from Argv - for (unsigned i=0, e = Args.size(); i != e; ++i) + for (unsigned i = 0, e = Args.size(); i != e; ++i) JITArgs.push_back(Args[i].c_str()); JITArgs.push_back(nullptr); - outs() << ""; outs().flush(); + outs() << ""; + outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i=0, e = JITArgs.size()-1; i != e; ++i) - errs() << " " << JITArgs[i]; - errs() << "\n"; - ); + for (unsigned i = 0, e = JITArgs.size() - 1; i != e; ++i) errs() + << " " << JITArgs[i]; + errs() << "\n";); DEBUG(errs() << "\nSending output to " << OutputFile << "\n"); - return RunProgramWithTimeout(LLIPath, &JITArgs[0], - InputFile, OutputFile, OutputFile, - Timeout, MemoryLimit, Error); + return RunProgramWithTimeout(LLIPath, &JITArgs[0], InputFile, OutputFile, + OutputFile, Timeout, MemoryLimit, Error); } /// createJIT - Try to find the LLI executable /// -AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, - std::string &Message, const std::vector *Args) { +AbstractInterpreter * +AbstractInterpreter::createJIT(const char *Argv0, std::string &Message, + const std::vector *Args) { std::string LLIPath = - PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t) & createJIT); + PrependMainExecutablePath("lli", Argv0, (void *)(intptr_t)&createJIT); if (!LLIPath.empty()) { Message = "Found lli: " + LLIPath + "\n"; return new JIT(LLIPath, Args); @@ -659,9 +622,10 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, // GCC abstraction // -static bool IsARMArchitecture(std::vector Args) { - for (std::vector::const_iterator - I = Args.begin(), E = Args.end(); I != E; ++I) { +static bool IsARMArchitecture(std::vector Args) { + for (std::vector::const_iterator I = Args.begin(), + E = Args.end(); + I != E; ++I) { if (StringRef(*I).equals_lower("-arch")) { ++I; if (I != E && StringRef(*I).startswith_lower("arm")) @@ -673,23 +637,21 @@ static bool IsARMArchitecture(std::vector Args) { } int GCC::ExecuteProgram(const std::string &ProgramFile, - const std::vector &Args, - FileType fileType, + const std::vector &Args, FileType fileType, const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, + const std::string &OutputFile, std::string *Error, const std::vector &ArgsForGCC, - unsigned Timeout, - unsigned MemoryLimit) { - std::vector GCCArgs; + unsigned Timeout, unsigned MemoryLimit) { + std::vector GCCArgs; GCCArgs.push_back(GCCPath.c_str()); if (TargetTriple.getArch() == Triple::x86) GCCArgs.push_back("-m32"); - for (std::vector::const_iterator - I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) + for (std::vector::const_iterator I = gccArgs.begin(), + E = gccArgs.end(); + I != E; ++I) GCCArgs.push_back(I->c_str()); // Specify -x explicitly in case the extension is wonky @@ -709,7 +671,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, } } - GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. + GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. GCCArgs.push_back("-x"); GCCArgs.push_back("none"); @@ -731,27 +693,27 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) GCCArgs.push_back(ArgsForGCC[i].c_str()); - GCCArgs.push_back("-lm"); // Hard-code the math library... - GCCArgs.push_back("-O2"); // Optimize the program a bit... -#if defined (HAVE_LINK_R) - GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files + GCCArgs.push_back("-lm"); // Hard-code the math library... + GCCArgs.push_back("-O2"); // Optimize the program a bit... +#if defined(HAVE_LINK_R) + GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files #endif if (TargetTriple.getArch() == Triple::sparc) GCCArgs.push_back("-mcpu=v9"); - GCCArgs.push_back(nullptr); // NULL terminator + GCCArgs.push_back(nullptr); // NULL terminator - outs() << ""; outs().flush(); + outs() << ""; + outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) - errs() << " " << GCCArgs[i]; - errs() << "\n"; - ); + for (unsigned i = 0, e = GCCArgs.size() - 1; i != e; ++i) errs() + << " " << GCCArgs[i]; + errs() << "\n";); if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) { *Error = ProcessFailure(GCCPath, &GCCArgs[0]); return -1; } - std::vector ProgramArgs; + std::vector ProgramArgs; // Declared here so that the destructor only runs after // ProgramArgs is used. @@ -776,7 +738,7 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, // Full path to the binary. We need to cd to the exec directory because // there is a dylib there that the exec expects to find in the CWD - char* env_pwd = getenv("PWD"); + char *env_pwd = getenv("PWD"); Exec = "cd "; Exec += env_pwd; Exec += "; ./"; @@ -787,15 +749,15 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, // Add optional parameters to the running program from Argv for (unsigned i = 0, e = Args.size(); i != e; ++i) ProgramArgs.push_back(Args[i].c_str()); - ProgramArgs.push_back(nullptr); // NULL terminator + ProgramArgs.push_back(nullptr); // NULL terminator // Now that we have a binary, run it! - outs() << ""; outs().flush(); + outs() << ""; + outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = ProgramArgs.size()-1; i != e; ++i) - errs() << " " << ProgramArgs[i]; - errs() << "\n"; - ); + for (unsigned i = 0, e = ProgramArgs.size() - 1; i != e; ++i) errs() + << " " << ProgramArgs[i]; + errs() << "\n";); FileRemover OutputBinaryRemover(OutputBinary.str(), !SaveTemps); @@ -814,10 +776,11 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, } return ExitCode; } else { - outs() << ""; outs().flush(); - return RunProgramRemotelyWithTimeout(RemoteClientPath, - &ProgramArgs[0], InputFile, OutputFile, - OutputFile, Timeout, MemoryLimit); + outs() << ""; + outs().flush(); + return RunProgramRemotelyWithTimeout(RemoteClientPath, &ProgramArgs[0], + InputFile, OutputFile, OutputFile, + Timeout, MemoryLimit); } } @@ -834,15 +797,16 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, } OutputFile = UniqueFilename.str(); - std::vector GCCArgs; + std::vector GCCArgs; GCCArgs.push_back(GCCPath.c_str()); if (TargetTriple.getArch() == Triple::x86) GCCArgs.push_back("-m32"); - for (std::vector::const_iterator - I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) + for (std::vector::const_iterator I = gccArgs.begin(), + E = gccArgs.end(); + I != E; ++I) GCCArgs.push_back(I->c_str()); // Compile the C/asm file into a shared object @@ -851,25 +815,25 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); } GCCArgs.push_back("-fno-strict-aliasing"); - GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. + GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. GCCArgs.push_back("-x"); GCCArgs.push_back("none"); if (TargetTriple.getArch() == Triple::sparc) - GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc + GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc else if (TargetTriple.isOSDarwin()) { // link all source files into a single module in data segment, rather than // generating blocks. dynamic_lookup requires that you set // MACOSX_DEPLOYMENT_TARGET=10.3 in your env. FIXME: it would be better for // bugpoint to just pass that in the environment of GCC. GCCArgs.push_back("-single_module"); - GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC + GCCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC GCCArgs.push_back("-undefined"); GCCArgs.push_back("dynamic_lookup"); } else - GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others + GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others if (TargetTriple.getArch() == Triple::x86_64) - GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC + GCCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC if (TargetTriple.getArch() == Triple::sparc) GCCArgs.push_back("-mcpu=v9"); @@ -878,24 +842,20 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. GCCArgs.push_back("-O2"); // Optimize the program a bit. - - // Add any arguments intended for GCC. We locate them here because this is // most likely -L and -l options that need to come before other libraries but // after the source. Other options won't be sensitive to placement on the // command line, so this should be safe. for (unsigned i = 0, e = ArgsForGCC.size(); i != e; ++i) GCCArgs.push_back(ArgsForGCC[i].c_str()); - GCCArgs.push_back(nullptr); // NULL terminator + GCCArgs.push_back(nullptr); // NULL terminator - - - outs() << ""; outs().flush(); + outs() << ""; + outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) - errs() << " " << GCCArgs[i]; - errs() << "\n"; - ); + for (unsigned i = 0, e = GCCArgs.size() - 1; i != e; ++i) errs() + << " " << GCCArgs[i]; + errs() << "\n";); if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) { Error = ProcessFailure(GCCPath, &GCCArgs[0]); return 1; @@ -905,13 +865,12 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, /// create - Try to find the `gcc' executable /// -GCC *GCC::create(std::string &Message, - const std::string &GCCBinary, +GCC *GCC::create(std::string &Message, const std::string &GCCBinary, const std::vector *Args) { auto GCCPath = sys::findProgramByName(GCCBinary); if (!GCCPath) { - Message = "Cannot find `" + GCCBinary + "' in PATH: " + - GCCPath.getError().message() + "\n"; + Message = "Cannot find `" + GCCBinary + + "' in PATH: " + GCCPath.getError().message() + "\n"; return nullptr; } @@ -919,8 +878,8 @@ GCC *GCC::create(std::string &Message, if (!RemoteClient.empty()) { auto Path = sys::findProgramByName(RemoteClient); if (!Path) { - Message = "Cannot find `" + RemoteClient + "' in PATH: " + - Path.getError().message() + "\n"; + Message = "Cannot find `" + RemoteClient + + "' in PATH: " + Path.getError().message() + "\n"; return nullptr; } RemoteClientPath = *Path; diff --git a/tools/bugpoint/ToolRunner.h b/tools/bugpoint/ToolRunner.h index 5d67a942..98a4e69c 100644 --- a/tools/bugpoint/ToolRunner.h +++ b/tools/bugpoint/ToolRunner.h @@ -36,19 +36,20 @@ class LLC; // GCC abstraction // class GCC { - std::string GCCPath; // The path to the gcc executable. - std::string RemoteClientPath; // The path to the rsh / ssh executable. + std::string GCCPath; // The path to the gcc executable. + std::string RemoteClientPath; // The path to the rsh / ssh executable. std::vector gccArgs; // GCC-specific arguments. GCC(StringRef gccPath, StringRef RemotePath, const std::vector *GCCArgs) - : GCCPath(gccPath), RemoteClientPath(RemotePath) { - if (GCCArgs) gccArgs = *GCCArgs; + : GCCPath(gccPath), RemoteClientPath(RemotePath) { + if (GCCArgs) + gccArgs = *GCCArgs; } + public: enum FileType { AsmFile, ObjectFile, CFile }; - static GCC *create(std::string &Message, - const std::string &GCCBinary, + static GCC *create(std::string &Message, const std::string &GCCBinary, const std::vector *Args); /// ExecuteProgram - Execute the program specified by "ProgramFile" (which is @@ -58,16 +59,12 @@ public: /// option specifies optional native shared objects that can be loaded into /// the program for execution. /// - int ExecuteProgram(const std::string &ProgramFile, - const std::vector &Args, - FileType fileType, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error = nullptr, - const std::vector &GCCArgs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0); + int ExecuteProgram( + const std::string &ProgramFile, const std::vector &Args, + FileType fileType, const std::string &InputFile, + const std::string &OutputFile, std::string *Error = nullptr, + const std::vector &GCCArgs = std::vector(), + unsigned Timeout = 0, unsigned MemoryLimit = 0); /// MakeSharedObject - This compiles the specified file (which is either a .c /// file or a .s file) into a shared object. @@ -78,7 +75,6 @@ public: std::string &Error); }; - //===---------------------------------------------------------------------===// /// AbstractInterpreter Class - Subclasses of this class are used to execute /// LLVM bitcode in a variety of ways. This abstract interface hides this @@ -86,30 +82,30 @@ public: /// class AbstractInterpreter { virtual void anchor(); + public: static LLC *createLLC(const char *Argv0, std::string &Message, - const std::string &GCCBinary, + const std::string &GCCBinary, const std::vector *Args = nullptr, const std::vector *GCCArgs = nullptr, bool UseIntegratedAssembler = false); - static AbstractInterpreter* + static AbstractInterpreter * createLLI(const char *Argv0, std::string &Message, const std::vector *Args = nullptr); - static AbstractInterpreter* + static AbstractInterpreter * createJIT(const char *Argv0, std::string &Message, const std::vector *Args = nullptr); - static AbstractInterpreter* + static AbstractInterpreter * createCustomCompiler(std::string &Message, const std::string &CompileCommandLine); - static AbstractInterpreter* + static AbstractInterpreter * createCustomExecutor(std::string &Message, const std::string &ExecCommandLine); - virtual ~AbstractInterpreter() {} /// compileProgram - Compile the specified program from bitcode to executable @@ -135,17 +131,13 @@ public: /// returns false if a problem was encountered that prevented execution of /// the program. /// - virtual int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs = - std::vector(), - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0) = 0; + virtual int ExecuteProgram( + const std::string &Bitcode, const std::vector &Args, + const std::string &InputFile, const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = std::vector(), + const std::vector &SharedLibs = std::vector(), + unsigned Timeout = 0, unsigned MemoryLimit = 0) = 0; }; //===---------------------------------------------------------------------===// @@ -156,14 +148,15 @@ class LLC : public AbstractInterpreter { std::vector ToolArgs; // Extra args to pass to LLC. GCC *gcc; bool UseIntegratedAssembler; + public: LLC(const std::string &llcPath, GCC *Gcc, - const std::vector *Args, - bool useIntegratedAssembler) - : LLCPath(llcPath), gcc(Gcc), - UseIntegratedAssembler(useIntegratedAssembler) { + const std::vector *Args, bool useIntegratedAssembler) + : LLCPath(llcPath), gcc(Gcc), + UseIntegratedAssembler(useIntegratedAssembler) { ToolArgs.clear(); - if (Args) ToolArgs = *Args; + if (Args) + ToolArgs = *Args; } ~LLC() override { delete gcc; } @@ -173,28 +166,23 @@ public: void compileProgram(const std::string &Bitcode, std::string *Error, unsigned Timeout = 0, unsigned MemoryLimit = 0) override; - int ExecuteProgram(const std::string &Bitcode, - const std::vector &Args, - const std::string &InputFile, - const std::string &OutputFile, - std::string *Error, - const std::vector &GCCArgs = - std::vector(), - const std::vector &SharedLibs = - std::vector(), - unsigned Timeout = 0, - unsigned MemoryLimit = 0) override; + int ExecuteProgram( + const std::string &Bitcode, const std::vector &Args, + const std::string &InputFile, const std::string &OutputFile, + std::string *Error, + const std::vector &GCCArgs = std::vector(), + const std::vector &SharedLibs = std::vector(), + unsigned Timeout = 0, unsigned MemoryLimit = 0) override; /// OutputCode - Compile the specified program from bitcode to code /// understood by the GCC driver (either C or asm). If the code generator /// fails, it sets Error, otherwise, this function returns the type of code /// emitted. - GCC::FileType OutputCode(const std::string &Bitcode, - std::string &OutFile, std::string &Error, - unsigned Timeout = 0, + GCC::FileType OutputCode(const std::string &Bitcode, std::string &OutFile, + std::string &Error, unsigned Timeout = 0, unsigned MemoryLimit = 0) override; }; -} // End llvm namespace +} // namespace llvm #endif diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp index d74107a9..eb87364e 100644 --- a/tools/bugpoint/bugpoint.cpp +++ b/tools/bugpoint/bugpoint.cpp @@ -29,81 +29,79 @@ #include "llvm/Support/Valgrind.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" -//Enable this macro to debug bugpoint itself. -//#define DEBUG_BUGPOINT 1 +// Enable this macro to debug bugpoint itself. +// #define DEBUG_BUGPOINT 1 using namespace llvm; static cl::opt -FindBugs("find-bugs", cl::desc("Run many different optimization sequences " - "on program to find bugs"), cl::init(false)); + FindBugs("find-bugs", + cl::desc("Run many different optimization sequences " + "on program to find bugs"), + cl::init(false)); static cl::list -InputFilenames(cl::Positional, cl::OneOrMore, - cl::desc("")); + InputFilenames(cl::Positional, cl::OneOrMore, + cl::desc("")); -static cl::opt -TimeoutValue("timeout", cl::init(300), cl::value_desc("seconds"), - cl::desc("Number of seconds program is allowed to run before it " - "is killed (default is 300s), 0 disables timeout")); +static cl::opt TimeoutValue( + "timeout", cl::init(300), cl::value_desc("seconds"), + cl::desc("Number of seconds program is allowed to run before it " + "is killed (default is 300s), 0 disables timeout")); static cl::opt -MemoryLimit("mlimit", cl::init(-1), cl::value_desc("MBytes"), - cl::desc("Maximum amount of memory to use. 0 disables check." - " Defaults to 400MB (800MB under valgrind).")); + MemoryLimit("mlimit", cl::init(-1), cl::value_desc("MBytes"), + cl::desc("Maximum amount of memory to use. 0 disables check." + " Defaults to 400MB (800MB under valgrind).")); static cl::opt -UseValgrind("enable-valgrind", - cl::desc("Run optimizations through valgrind")); + UseValgrind("enable-valgrind", + cl::desc("Run optimizations through valgrind")); // The AnalysesList is automatically populated with registered Passes by the // PassNameParser. // -static cl::list -PassList(cl::desc("Passes available:"), cl::ZeroOrMore); +static cl::list + PassList(cl::desc("Passes available:"), cl::ZeroOrMore); static cl::opt -StandardLinkOpts("std-link-opts", - cl::desc("Include the standard link time optimizations")); + StandardLinkOpts("std-link-opts", + cl::desc("Include the standard link time optimizations")); static cl::opt -OptLevelO1("O1", - cl::desc("Optimization level 1. Identical to 'opt -O1'")); + OptLevelO1("O1", cl::desc("Optimization level 1. Identical to 'opt -O1'")); static cl::opt -OptLevelO2("O2", - cl::desc("Optimization level 2. Identical to 'opt -O2'")); + OptLevelO2("O2", cl::desc("Optimization level 2. Identical to 'opt -O2'")); static cl::opt -OptLevelO3("O3", - cl::desc("Optimization level 3. Identical to 'opt -O3'")); + OptLevelO3("O3", cl::desc("Optimization level 3. Identical to 'opt -O3'")); static cl::opt -OverrideTriple("mtriple", cl::desc("Override target triple for module")); + OverrideTriple("mtriple", cl::desc("Override target triple for module")); /// BugpointIsInterrupted - Set to true when the user presses ctrl-c. bool llvm::BugpointIsInterrupted = false; #ifndef DEBUG_BUGPOINT -static void BugpointInterruptFunction() { - BugpointIsInterrupted = true; -} +static void BugpointInterruptFunction() { BugpointIsInterrupted = true; } #endif // Hack to capture a pass list. namespace { - class AddToDriver : public legacy::FunctionPassManager { - BugDriver &D; - public: - AddToDriver(BugDriver &_D) : FunctionPassManager(nullptr), D(_D) {} - - void add(Pass *P) override { - const void *ID = P->getPassID(); - const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID); - D.addPass(PI->getPassArgument()); - } - }; -} +class AddToDriver : public legacy::FunctionPassManager { + BugDriver &D; + +public: + AddToDriver(BugDriver &_D) : FunctionPassManager(nullptr), D(_D) {} + + void add(Pass *P) override { + const void *ID = P->getPassID(); + const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID); + D.addPass(PI->getPassArgument()); + } +}; +} // namespace #ifdef LINK_POLLY_INTO_TOOLS namespace polly { @@ -115,7 +113,7 @@ int main(int argc, char **argv) { #ifndef DEBUG_BUGPOINT llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. #endif // Initialize passes @@ -144,7 +142,7 @@ int main(int argc, char **argv) { sys::SetInterruptFunction(BugpointInterruptFunction); #endif - LLVMContext& Context = getGlobalContext(); + LLVMContext &Context = getGlobalContext(); // If we have an override, set it and then track the triple we want Modules // to use. if (!OverrideTriple.empty()) { @@ -161,9 +159,10 @@ int main(int argc, char **argv) { MemoryLimit = 400; } - BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit, - UseValgrind, Context); - if (D.addSources(InputFilenames)) return 1; + BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit, UseValgrind, + Context); + if (D.addSources(InputFilenames)) + return 1; AddToDriver PM(D); @@ -188,10 +187,10 @@ int main(int argc, char **argv) { Builder.populateModulePassManager(PM); } - for (std::vector::iterator I = PassList.begin(), - E = PassList.end(); + for (std::vector::iterator I = PassList.begin(), + E = PassList.end(); I != E; ++I) { - const PassInfo* PI = *I; + const PassInfo *PI = *I; D.addPass(PI->getPassArgument()); } ``````````
llvm-beanz commented 3 months ago

Abandoning since it looks like there is more work to really make this useful. We can revive it if it is worth doing in the future.