diff options
Diffstat (limited to 'contrib/llvm/tools/bugpoint')
-rw-r--r-- | contrib/llvm/tools/bugpoint/BugDriver.cpp | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/BugDriver.h | 19 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/CrashDebugger.cpp | 265 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ExecutionDriver.cpp | 41 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ExtractFunction.cpp | 71 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ListReducer.h | 12 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/Miscompilation.cpp | 277 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ToolRunner.cpp | 217 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/ToolRunner.h | 50 | ||||
-rw-r--r-- | contrib/llvm/tools/bugpoint/bugpoint.cpp | 10 |
10 files changed, 568 insertions, 400 deletions
diff --git a/contrib/llvm/tools/bugpoint/BugDriver.cpp b/contrib/llvm/tools/bugpoint/BugDriver.cpp index 43f4c29..030749f 100644 --- a/contrib/llvm/tools/bugpoint/BugDriver.cpp +++ b/contrib/llvm/tools/bugpoint/BugDriver.cpp @@ -72,7 +72,7 @@ BugDriver::BugDriver(const char *toolname, bool find_bugs, LLVMContext& ctxt) : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile), Program(nullptr), Interpreter(nullptr), SafeInterpreter(nullptr), - gcc(nullptr), run_find_bugs(find_bugs), Timeout(timeout), + cc(nullptr), run_find_bugs(find_bugs), Timeout(timeout), MemoryLimit(memlimit), UseValgrind(use_valgrind) {} BugDriver::~BugDriver() { @@ -80,7 +80,7 @@ BugDriver::~BugDriver() { if (Interpreter != SafeInterpreter) delete Interpreter; delete SafeInterpreter; - delete gcc; + delete cc; } std::unique_ptr<Module> llvm::parseInputFile(StringRef Filename, @@ -132,7 +132,7 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) { if (!M.get()) return true; outs() << "Linking in input file: '" << Filenames[i] << "'\n"; - if (Linker::LinkModules(Program, M.get())) + if (Linker::linkModules(*Program, std::move(M))) return true; } diff --git a/contrib/llvm/tools/bugpoint/BugDriver.h b/contrib/llvm/tools/bugpoint/BugDriver.h index 5797812..20efff3 100644 --- a/contrib/llvm/tools/bugpoint/BugDriver.h +++ b/contrib/llvm/tools/bugpoint/BugDriver.h @@ -36,7 +36,7 @@ class LLVMContext; class DebugCrashes; -class GCC; +class CC; extern bool DisableSimplifyCFG; @@ -52,7 +52,7 @@ class BugDriver { std::vector<std::string> PassesToRun; AbstractInterpreter *Interpreter; // How to run the program AbstractInterpreter *SafeInterpreter; // To generate reference output, etc. - GCC *gcc; + CC *cc; bool run_find_bugs; unsigned Timeout; unsigned MemoryLimit; @@ -321,16 +321,21 @@ void PrintFunctionList(const std::vector<Function*> &Funcs); /// void PrintGlobalVariableList(const std::vector<GlobalVariable*> &GVs); +// DeleteGlobalInitializer - "Remove" the global variable by deleting its +// initializer, making it external. +// +void DeleteGlobalInitializer(GlobalVariable *GV); + // DeleteFunctionBody - "Remove" the function by deleting all of it's basic // blocks, making it external. // 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<Function*> &F, - ValueToValueMapTy &VMap); +/// 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. +std::unique_ptr<Module> +SplitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F, + ValueToValueMapTy &VMap); } // End llvm namespace diff --git a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp index e2aaf6b..6cdc43ab 100644 --- a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp +++ b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp @@ -15,6 +15,7 @@ #include "ListReducer.h" #include "ToolRunner.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringSet.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -49,6 +50,10 @@ namespace { DontReducePassList("disable-pass-list-reduction", cl::desc("Skip pass list reduction steps"), cl::init(false)); + + cl::opt<bool> NoNamedMDRM("disable-namedmd-remove", + cl::desc("Do not remove global named metadata"), + cl::init(false)); } namespace llvm { @@ -138,7 +143,7 @@ ReduceCrashingGlobalVariables::TestGlobalVariables( std::vector<GlobalVariable*> &GVs) { // Clone the program to try hacking it apart... ValueToValueMapTy VMap; - Module *M = CloneModule(BD.getProgram(), VMap); + Module *M = CloneModule(BD.getProgram(), VMap).release(); // Convert list to set for fast lookup... std::set<GlobalVariable*> GVSet; @@ -155,11 +160,10 @@ ReduceCrashingGlobalVariables::TestGlobalVariables( // Loop over and delete any global variables which we aren't supposed to be // playing with... - for (Module::global_iterator I = M->global_begin(), E = M->global_end(); - I != E; ++I) - if (I->hasInitializer() && !GVSet.count(I)) { - I->setInitializer(nullptr); - I->setLinkage(GlobalValue::ExternalLinkage); + for (GlobalVariable &I : M->globals()) + if (I.hasInitializer() && !GVSet.count(&I)) { + DeleteGlobalInitializer(&I); + I.setLinkage(GlobalValue::ExternalLinkage); } // Try running the hacked up program... @@ -235,7 +239,7 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { // Clone the program to try hacking it apart... ValueToValueMapTy VMap; - Module *M = CloneModule(BD.getProgram(), VMap); + Module *M = CloneModule(BD.getProgram(), VMap).release(); // Convert list to set for fast lookup... std::set<Function*> Functions; @@ -253,9 +257,9 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { if (!ReplaceFuncsWithNull) { // Loop over and delete any functions which we aren't supposed to be playing // with... - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) - if (!I->isDeclaration() && !Functions.count(I)) - DeleteFunctionBody(I); + for (Function &I : *M) + if (!I.isDeclaration() && !Functions.count(&I)) + DeleteFunctionBody(&I); } else { std::vector<GlobalValue*> ToRemove; // First, remove aliases to functions we're about to purge. @@ -280,12 +284,12 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { ToRemove.push_back(&Alias); } - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { - if (!I->isDeclaration() && !Functions.count(I)) { - PointerType *Ty = cast<PointerType>(I->getType()); + for (Function &I : *M) { + if (!I.isDeclaration() && !Functions.count(&I)) { + PointerType *Ty = cast<PointerType>(I.getType()); Constant *Replacement = ConstantPointerNull::get(Ty); - I->replaceAllUsesWith(Replacement); - ToRemove.push_back(I); + I.replaceAllUsesWith(Replacement); + ToRemove.push_back(&I); } } @@ -342,7 +346,7 @@ namespace { bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { // Clone the program to try hacking it apart... ValueToValueMapTy VMap; - Module *M = CloneModule(BD.getProgram(), VMap); + Module *M = CloneModule(BD.getProgram(), VMap).release(); // Convert list to set for fast lookup... SmallPtrSet<BasicBlock*, 8> Blocks; @@ -361,20 +365,22 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { // Loop over and delete any hack up any blocks that are not listed... for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB) - if (!Blocks.count(BB) && BB->getTerminator()->getNumSuccessors()) { + if (!Blocks.count(&*BB) && BB->getTerminator()->getNumSuccessors()) { // Loop over all of the successors of this block, deleting any PHI nodes // that might include it. - for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) - (*SI)->removePredecessor(BB); + for (succ_iterator SI = succ_begin(&*BB), E = succ_end(&*BB); SI != E; + ++SI) + (*SI)->removePredecessor(&*BB); TerminatorInst *BBTerm = BB->getTerminator(); - - if (!BB->getTerminator()->getType()->isVoidTy()) + if (BBTerm->isEHPad()) + continue; + if (!BBTerm->getType()->isVoidTy() && !BBTerm->getType()->isTokenTy()) BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType())); // Replace the old terminator instruction. BB->getInstList().pop_back(); - new UnreachableInst(BB->getContext(), BB); + new UnreachableInst(BB->getContext(), &*BB); } // The CFG Simplifier pass may delete one of the basic blocks we are @@ -450,7 +456,7 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> &Insts) { // Clone the program to try hacking it apart... ValueToValueMapTy VMap; - Module *M = CloneModule(BD.getProgram(), VMap); + Module *M = CloneModule(BD.getProgram(), VMap).release(); // Convert list to set for fast lookup... SmallPtrSet<Instruction*, 64> Instructions; @@ -468,10 +474,10 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { - Instruction *Inst = I++; + Instruction *Inst = &*I++; if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst) && - !isa<LandingPadInst>(Inst)) { - if (!Inst->getType()->isVoidTy()) + !Inst->isEHPad()) { + if (!Inst->getType()->isVoidTy() && !Inst->getType()->isTokenTy()) Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); Inst->eraseFromParent(); } @@ -497,6 +503,149 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> return false; } +namespace { +// Reduce the list of Named Metadata nodes. We keep this as a list of +// names to avoid having to convert back and forth every time. +class ReduceCrashingNamedMD : public ListReducer<std::string> { + BugDriver &BD; + bool (*TestFn)(const BugDriver &, Module *); + +public: + ReduceCrashingNamedMD(BugDriver &bd, + bool (*testFn)(const BugDriver &, Module *)) + : BD(bd), TestFn(testFn) {} + + TestResult doTest(std::vector<std::string> &Prefix, + std::vector<std::string> &Kept, + std::string &Error) override { + if (!Kept.empty() && TestNamedMDs(Kept)) + return KeepSuffix; + if (!Prefix.empty() && TestNamedMDs(Prefix)) + return KeepPrefix; + return NoFailure; + } + + bool TestNamedMDs(std::vector<std::string> &NamedMDs); +}; +} + +bool ReduceCrashingNamedMD::TestNamedMDs(std::vector<std::string> &NamedMDs) { + + ValueToValueMapTy VMap; + Module *M = CloneModule(BD.getProgram(), VMap).release(); + + outs() << "Checking for crash with only these named metadata nodes:"; + unsigned NumPrint = std::min<size_t>(NamedMDs.size(), 10); + for (unsigned i = 0, e = NumPrint; i != e; ++i) + outs() << " " << NamedMDs[i]; + if (NumPrint < NamedMDs.size()) + outs() << "... <" << NamedMDs.size() << " total>"; + outs() << ": "; + + // Make a StringMap for faster lookup + StringSet<> Names; + for (const std::string &Name : NamedMDs) + Names.insert(Name); + + // First collect all the metadata to delete in a vector, then + // delete them all at once to avoid invalidating the iterator + std::vector<NamedMDNode *> ToDelete; + ToDelete.reserve(M->named_metadata_size() - Names.size()); + for (auto &NamedMD : M->named_metadata()) + if (!Names.count(NamedMD.getName())) + ToDelete.push_back(&NamedMD); + + for (auto *NamedMD : ToDelete) + NamedMD->eraseFromParent(); + + // Verify that this is still valid. + legacy::PassManager Passes; + Passes.add(createVerifierPass()); + Passes.run(*M); + + // Try running on the hacked up program... + if (TestFn(BD, M)) { + BD.setNewProgram(M); // It crashed, keep the trimmed version... + return true; + } + delete M; // It didn't crash, try something else. + return false; +} + +namespace { +// Reduce the list of operands to named metadata nodes +class ReduceCrashingNamedMDOps : public ListReducer<const MDNode *> { + BugDriver &BD; + bool (*TestFn)(const BugDriver &, Module *); + +public: + ReduceCrashingNamedMDOps(BugDriver &bd, + bool (*testFn)(const BugDriver &, Module *)) + : BD(bd), TestFn(testFn) {} + + TestResult doTest(std::vector<const MDNode *> &Prefix, + std::vector<const MDNode *> &Kept, + std::string &Error) override { + if (!Kept.empty() && TestNamedMDOps(Kept)) + return KeepSuffix; + if (!Prefix.empty() && TestNamedMDOps(Prefix)) + return KeepPrefix; + return NoFailure; + } + + bool TestNamedMDOps(std::vector<const MDNode *> &NamedMDOps); +}; +} + +bool ReduceCrashingNamedMDOps::TestNamedMDOps( + std::vector<const MDNode *> &NamedMDOps) { + // Convert list to set for fast lookup... + SmallPtrSet<const MDNode *, 64> OldMDNodeOps; + for (unsigned i = 0, e = NamedMDOps.size(); i != e; ++i) { + OldMDNodeOps.insert(NamedMDOps[i]); + } + + outs() << "Checking for crash with only " << OldMDNodeOps.size(); + if (OldMDNodeOps.size() == 1) + outs() << " named metadata operand: "; + else + outs() << " named metadata operands: "; + + ValueToValueMapTy VMap; + Module *M = CloneModule(BD.getProgram(), VMap).release(); + + // This is a little wasteful. In the future it might be good if we could have + // these dropped during cloning. + for (auto &NamedMD : BD.getProgram()->named_metadata()) { + // Drop the old one and create a new one + M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName())); + NamedMDNode *NewNamedMDNode = + M->getOrInsertNamedMetadata(NamedMD.getName()); + for (MDNode *op : NamedMD.operands()) + if (OldMDNodeOps.count(op)) + NewNamedMDNode->addOperand(cast<MDNode>(MapMetadata(op, VMap))); + } + + // Verify that this is still valid. + legacy::PassManager Passes; + Passes.add(createVerifierPass()); + Passes.run(*M); + + // Try running on the hacked up program... + if (TestFn(BD, M)) { + // Make sure to use instruction pointers that point into the now-current + // module, and that they don't include any deleted blocks. + NamedMDOps.clear(); + for (const MDNode *Node : OldMDNodeOps) + NamedMDOps.push_back(cast<MDNode>(VMap.MD()[Node].get())); + + BD.setNewProgram(M); // It crashed, keep the trimmed version... + return true; + } + delete M; // It didn't crash, try something else. + return false; +} + /// DebugACrash - Given a predicate that determines whether a component crashes /// on a program, try to destructively reduce the program while still keeping /// the predicate true. @@ -509,13 +658,13 @@ static bool DebugACrash(BugDriver &BD, BD.getProgram()->global_begin() != BD.getProgram()->global_end()) { // Now try to reduce the number of global variable initializers in the // module to something small. - Module *M = CloneModule(BD.getProgram()); + Module *M = CloneModule(BD.getProgram()).release(); bool DeletedInit = false; for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer()) { - I->setInitializer(nullptr); + DeleteGlobalInitializer(&*I); I->setLinkage(GlobalValue::ExternalLinkage); DeletedInit = true; } @@ -538,7 +687,7 @@ static bool DebugACrash(BugDriver &BD, for (Module::global_iterator I = BD.getProgram()->global_begin(), E = BD.getProgram()->global_end(); I != E; ++I) if (I->hasInitializer()) - GVs.push_back(I); + GVs.push_back(&*I); if (GVs.size() > 1 && !BugpointIsInterrupted) { outs() << "\n*** Attempting to reduce the number of global " @@ -558,10 +707,9 @@ static bool DebugACrash(BugDriver &BD, // Now try to reduce the number of functions in the module to something small. std::vector<Function*> Functions; - for (Module::iterator I = BD.getProgram()->begin(), - E = BD.getProgram()->end(); I != E; ++I) - if (!I->isDeclaration()) - Functions.push_back(I); + for (Function &F : *BD.getProgram()) + if (!F.isDeclaration()) + Functions.push_back(&F); if (Functions.size() > 1 && !BugpointIsInterrupted) { outs() << "\n*** Attempting to reduce the number of functions " @@ -581,10 +729,9 @@ static bool DebugACrash(BugDriver &BD, // if (!DisableSimplifyCFG && !BugpointIsInterrupted) { std::vector<const BasicBlock*> 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) - Blocks.push_back(FI); + for (Function &F : *BD.getProgram()) + for (BasicBlock &BB : F) + Blocks.push_back(&BB); unsigned OldSize = Blocks.size(); ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error); if (Blocks.size() < OldSize) @@ -595,14 +742,11 @@ static bool DebugACrash(BugDriver &BD, // cases with large basic blocks where the problem is at one end. if (!BugpointIsInterrupted) { std::vector<const Instruction*> Insts; - for (Module::const_iterator MI = BD.getProgram()->begin(), - 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) - if (!isa<TerminatorInst>(I)) - Insts.push_back(I); + for (const Function &F : *BD.getProgram()) + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + if (!isa<TerminatorInst>(&I)) + Insts.push_back(&I); ReduceCrashingInstructions(BD, TestFn).reduceList(Insts, Error); } @@ -642,12 +786,12 @@ static bool DebugACrash(BugDriver &BD, } else { if (BugpointIsInterrupted) goto ExitLoops; - if (isa<LandingPadInst>(I)) + if (I->isEHPad() || I->getType()->isTokenTy()) continue; outs() << "Checking instruction: " << *I; std::unique_ptr<Module> M = - BD.deleteInstructionFromProgram(I, Simplification); + BD.deleteInstructionFromProgram(&*I, Simplification); // Find out if the pass still crashes on this pass... if (TestFn(BD, M.get())) { @@ -666,12 +810,37 @@ static bool DebugACrash(BugDriver &BD, } } while (Simplification); + + if (!NoNamedMDRM) { + BD.EmitProgressBitcode(BD.getProgram(), "reduced-instructions"); + + if (!BugpointIsInterrupted) { + // Try to reduce the amount of global metadata (particularly debug info), + // by dropping global named metadata that anchors them + outs() << "\n*** Attempting to remove named metadata: "; + std::vector<std::string> NamedMDNames; + for (auto &NamedMD : BD.getProgram()->named_metadata()) + NamedMDNames.push_back(NamedMD.getName().str()); + ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames, Error); + } + + if (!BugpointIsInterrupted) { + // Now that we quickly dropped all the named metadata that doesn't + // contribute to the crash, bisect the operands of the remaining ones + std::vector<const MDNode *> NamedMDOps; + for (auto &NamedMD : BD.getProgram()->named_metadata()) + for (auto op : NamedMD.operands()) + NamedMDOps.push_back(op); + ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps, Error); + } + } + ExitLoops: // Try to clean up the testcase by running funcresolve and globaldce... if (!BugpointIsInterrupted) { outs() << "\n*** Attempting to perform final cleanups: "; - Module *M = CloneModule(BD.getProgram()); + Module *M = CloneModule(BD.getProgram()).release(); M = BD.performFinalCleanups(M, true).release(); // Find out if the pass still crashes on the cleaned up program... diff --git a/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp index 25813b3..41b8ccc 100644 --- a/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp +++ b/contrib/llvm/tools/bugpoint/ExecutionDriver.cpp @@ -17,6 +17,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" +#include "llvm/Support/Program.h" #include "llvm/Support/SystemUtils.h" #include "llvm/Support/raw_ostream.h" #include <fstream> @@ -124,11 +125,10 @@ namespace { cl::ZeroOrMore, cl::PositionalEatsArgs); cl::opt<std::string> - GCCBinary("gcc", cl::init("gcc"), - cl::desc("The gcc binary to use. (default 'gcc')")); + CCBinary("gcc", cl::init(""), cl::desc("The gcc binary to use.")); cl::list<std::string> - GCCToolArgv("gcc-tool-args", cl::Positional, + CCToolArgv("gcc-tool-args", cl::Positional, cl::desc("<gcc-tool arguments>..."), cl::ZeroOrMore, cl::PositionalEatsArgs); } @@ -148,6 +148,13 @@ bool BugDriver::initializeExecutionEnvironment() { SafeInterpreter = nullptr; std::string Message; + if (CCBinary.empty()) { + if (sys::findProgramByName("clang")) + CCBinary = "clang"; + else + CCBinary = "gcc"; + } + switch (InterpreterSel) { case AutoPick: if (!Interpreter) { @@ -158,8 +165,8 @@ bool BugDriver::initializeExecutionEnvironment() { if (!Interpreter) { InterpreterSel = RunLLC; Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, - GCCBinary, &ToolArgv, - &GCCToolArgv); + CCBinary, &ToolArgv, + &CCToolArgv); } if (!Interpreter) { InterpreterSel = RunLLI; @@ -179,8 +186,8 @@ bool BugDriver::initializeExecutionEnvironment() { case RunLLCIA: case LLC_Safe: Interpreter = AbstractInterpreter::createLLC(getToolName(), Message, - GCCBinary, &ToolArgv, - &GCCToolArgv, + CCBinary, &ToolArgv, + &CCToolArgv, InterpreterSel == RunLLCIA); break; case RunJIT: @@ -213,9 +220,9 @@ bool BugDriver::initializeExecutionEnvironment() { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, + CCBinary, &SafeToolArgs, - &GCCToolArgv); + &CCToolArgv); } if (!SafeInterpreter && @@ -224,9 +231,9 @@ bool BugDriver::initializeExecutionEnvironment() { SafeInterpreterSel = RunLLC; SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, + CCBinary, &SafeToolArgs, - &GCCToolArgv); + &CCToolArgv); } if (!SafeInterpreter) { SafeInterpreterSel = AutoPick; @@ -237,8 +244,8 @@ bool BugDriver::initializeExecutionEnvironment() { case RunLLCIA: SafeToolArgs.push_back("--relocation-model=pic"); SafeInterpreter = AbstractInterpreter::createLLC(Path.c_str(), Message, - GCCBinary, &SafeToolArgs, - &GCCToolArgv, + CCBinary, &SafeToolArgs, + &CCToolArgv, SafeInterpreterSel == RunLLCIA); break; case Custom: @@ -252,8 +259,8 @@ bool BugDriver::initializeExecutionEnvironment() { } if (!SafeInterpreter) { outs() << Message << "\nExiting.\n"; exit(1); } - gcc = GCC::create(Message, GCCBinary, &GCCToolArgv); - if (!gcc) { outs() << Message << "\nExiting.\n"; exit(1); } + cc = CC::create(Message, CCBinary, &CCToolArgv); + if (!cc) { outs() << Message << "\nExiting.\n"; exit(1); } // If there was an error creating the selected interpreter, quit with error. return Interpreter == nullptr; @@ -388,13 +395,13 @@ std::string BugDriver::compileSharedObject(const std::string &BitcodeFile, std::string OutputFile; // Using the known-good backend. - GCC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile, + CC::FileType FT = SafeInterpreter->OutputCode(BitcodeFile, OutputFile, Error); if (!Error.empty()) return ""; std::string SharedObjectFile; - bool Failure = gcc->MakeSharedObject(OutputFile, FT, SharedObjectFile, + bool Failure = cc->MakeSharedObject(OutputFile, FT, SharedObjectFile, AdditionalLinkerArgs, Error); if (!Error.empty()) return ""; diff --git a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp index 238cbbc..fe0ab69 100644 --- a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp +++ b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp @@ -86,7 +86,7 @@ std::unique_ptr<Module> BugDriver::deleteInstructionFromProgram(const Instruction *I, unsigned Simplification) { // FIXME, use vmap? - Module *Clone = CloneModule(Program); + Module *Clone = CloneModule(Program).release(); const BasicBlock *PBB = I->getParent(); const Function *PF = PBB->getParent(); @@ -100,7 +100,7 @@ BugDriver::deleteInstructionFromProgram(const Instruction *I, 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()) @@ -179,11 +179,43 @@ std::unique_ptr<Module> BugDriver::extractLoop(Module *M) { return NewM; } +static void eliminateAliases(GlobalValue *GV) { + // First, check whether a GlobalAlias references this definition. + // GlobalAlias MAY NOT reference declarations. + for (;;) { + // 1. Find aliases + SmallVector<GlobalAlias*,1> aliases; + Module *M = GV->getParent(); + for (Module::alias_iterator I=M->alias_begin(), E=M->alias_end(); I!=E; ++I) + if (I->getAliasee()->stripPointerCasts() == GV) + aliases.push_back(&*I); + if (aliases.empty()) + break; + // 2. Resolve aliases + for (unsigned i=0, e=aliases.size(); i<e; ++i) { + aliases[i]->replaceAllUsesWith(aliases[i]->getAliasee()); + aliases[i]->eraseFromParent(); + } + // 3. Repeat until no more aliases found; there might + // be an alias to an alias... + } +} + +// +// DeleteGlobalInitializer - "Remove" the global variable by deleting its initializer, +// making it external. +// +void llvm::DeleteGlobalInitializer(GlobalVariable *GV) { + eliminateAliases(GV); + GV->setInitializer(nullptr); +} // DeleteFunctionBody - "Remove" the function by deleting all of its basic // blocks, making it external. // void llvm::DeleteFunctionBody(Function *F) { + eliminateAliases(F); + // delete the body of the function... F->deleteBody(); assert(F->isDeclaration() && "This didn't make the function external!"); @@ -271,13 +303,8 @@ static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2, } } - -/// 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<Function*> &F, +std::unique_ptr<Module> +llvm::SplitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F, ValueToValueMapTy &VMap) { // Make sure functions & globals are all external so that linkage // between the two modules will work. @@ -291,7 +318,7 @@ llvm::SplitFunctionsOutOfModule(Module *M, } ValueToValueMapTy NewVMap; - Module *New = CloneModule(M, NewVMap); + std::unique_ptr<Module> New = CloneModule(M, NewVMap); // Remove the Test functions from the Safe module std::set<Function *> TestFunctions; @@ -306,16 +333,14 @@ llvm::SplitFunctionsOutOfModule(Module *M, // 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); - + for (Function &I : *New) + 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(); - I != E; ++I) { - GlobalVariable *GV = cast<GlobalVariable>(NewVMap[I]); - if (Function *TestFn = globalInitUsesExternalBA(I)) { + for (GlobalVariable &I : M->globals()) { + GlobalVariable *GV = cast<GlobalVariable>(NewVMap[&I]); + if (Function *TestFn = globalInitUsesExternalBA(&I)) { if (Function *SafeFn = globalInitUsesExternalBA(GV)) { errs() << "*** Error: when reducing functions, encountered " "the global '"; @@ -325,18 +350,18 @@ llvm::SplitFunctionsOutOfModule(Module *M, << "' and from test function '" << TestFn->getName() << "'.\n"; exit(1); } - I->setInitializer(nullptr); // Delete the initializer to make it external + DeleteGlobalInitializer(&I); // 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); + DeleteGlobalInitializer(GV); } } // Make sure that there is a global ctor/dtor array in both halves of the // module if they both have static ctor/dtor functions. - SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap); - SplitStaticCtorDtor("llvm.global_dtors", M, New, NewVMap); - + SplitStaticCtorDtor("llvm.global_ctors", M, New.get(), NewVMap); + SplitStaticCtorDtor("llvm.global_dtors", M, New.get(), NewVMap); + return New; } diff --git a/contrib/llvm/tools/bugpoint/ListReducer.h b/contrib/llvm/tools/bugpoint/ListReducer.h index a0bb570..f08bc97 100644 --- a/contrib/llvm/tools/bugpoint/ListReducer.h +++ b/contrib/llvm/tools/bugpoint/ListReducer.h @@ -75,6 +75,11 @@ struct ListReducer { // Maximal number of allowed splitting iterations, // before the elements are randomly shuffled. const unsigned MaxIterationsWithoutProgress = 3; + + // Maximal number of allowed single-element trim iterations. We add a + // threshhold here as single-element reductions may otherwise take a + // very long time to complete. + const unsigned MaxTrimIterationsWithoutBackJump = 3; bool ShufflingEnabled = true; Backjump: @@ -157,6 +162,7 @@ Backjump: if (TheList.size() > 2) { bool Changed = true; std::vector<ElTy> EmptyList; + unsigned TrimIterations = 0; while (Changed) { // Trimming loop. Changed = false; @@ -186,9 +192,9 @@ Backjump: if (!Error.empty()) return true; } - // This can take a long time if left uncontrolled. For now, don't - // iterate. - break; + if (TrimIterations >= MaxTrimIterationsWithoutBackJump) + break; + TrimIterations++; } } diff --git a/contrib/llvm/tools/bugpoint/Miscompilation.cpp b/contrib/llvm/tools/bugpoint/Miscompilation.cpp index fad1636..16919f5 100644 --- a/contrib/llvm/tools/bugpoint/Miscompilation.cpp +++ b/contrib/llvm/tools/bugpoint/Miscompilation.cpp @@ -176,12 +176,15 @@ ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix, namespace { class ReduceMiscompilingFunctions : public ListReducer<Function*> { BugDriver &BD; - bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); + bool (*TestFn)(BugDriver &, std::unique_ptr<Module>, + std::unique_ptr<Module>, std::string &); + public: ReduceMiscompilingFunctions(BugDriver &bd, - bool (*F)(BugDriver &, Module *, Module *, + bool (*F)(BugDriver &, std::unique_ptr<Module>, + std::unique_ptr<Module>, std::string &)) - : BD(bd), TestFn(F) {} + : BD(bd), TestFn(F) {} TestResult doTest(std::vector<Function*> &Prefix, std::vector<Function*> &Suffix, @@ -207,32 +210,24 @@ namespace { }; } -/// TestMergedProgram - Given two modules, link them together and run the -/// program, checking to see if the program matches the diff. If there is -/// an error, return NULL. If not, return the merged module. The Broken argument -/// will be set to true if the output is different. If the DeleteInputs -/// argument is set to true then this function deletes both input -/// modules before it returns. +/// Given two modules, link them together and run the program, checking to see +/// if the program matches the diff. If there is an error, return NULL. If not, +/// return the merged module. The Broken argument will be set to true if the +/// output is different. If the DeleteInputs argument is set to true then this +/// function deletes both input modules before it returns. /// -static Module *TestMergedProgram(const BugDriver &BD, Module *M1, Module *M2, - bool DeleteInputs, std::string &Error, - bool &Broken) { - // Link the two portions of the program back to together. - if (!DeleteInputs) { - M1 = CloneModule(M1); - M2 = CloneModule(M2); - } - if (Linker::LinkModules(M1, M2)) +static std::unique_ptr<Module> testMergedProgram(const BugDriver &BD, + std::unique_ptr<Module> M1, + std::unique_ptr<Module> M2, + std::string &Error, + bool &Broken) { + if (Linker::linkModules(*M1, std::move(M2))) exit(1); - delete M2; // We are done with this module. // Execute the program. - Broken = BD.diffProgram(M1, "", "", false, &Error); - if (!Error.empty()) { - // Delete the linked module - delete M1; + Broken = BD.diffProgram(M1.get(), "", "", false, &Error); + if (!Error.empty()) return nullptr; - } return M1; } @@ -259,7 +254,7 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &Funcs, // we can conclude that a function triggers the bug when in fact one // needs a larger set of original functions to do so. ValueToValueMapTy VMap; - Module *Clone = CloneModule(BD.getProgram(), VMap); + Module *Clone = CloneModule(BD.getProgram(), VMap).release(); Module *Orig = BD.swapProgramIn(Clone); std::vector<Function*> FuncsOnClone; @@ -270,12 +265,12 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*> &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); + std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap); + std::unique_ptr<Module> ToOptimize = + SplitFunctionsOutOfModule(ToNotOptimize.get(), FuncsOnClone, VMap); - // Run the predicate, note that the predicate will delete both input modules. - bool Broken = TestFn(BD, ToOptimize, ToNotOptimize, Error); + bool Broken = + TestFn(BD, std::move(ToOptimize), std::move(ToNotOptimize), Error); delete BD.swapProgramIn(Orig); @@ -294,29 +289,29 @@ static void DisambiguateGlobalSymbols(Module *M) { I->setName("anon_fn"); } -/// ExtractLoops - Given a reduced list of functions that still exposed the bug, -/// check to see if we can extract the loops in the region without obscuring the -/// bug. If so, it reduces the amount of code identified. +/// Given a reduced list of functions that still exposed the bug, check to see +/// if we can extract the loops in the region without obscuring the bug. If so, +/// it reduces the amount of code identified. /// static bool ExtractLoops(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *, - std::string &), - std::vector<Function*> &MiscompiledFunctions, + bool (*TestFn)(BugDriver &, std::unique_ptr<Module>, + std::unique_ptr<Module>, std::string &), + std::vector<Function *> &MiscompiledFunctions, std::string &Error) { bool MadeChange = false; while (1) { if (BugpointIsInterrupted) return MadeChange; ValueToValueMapTy VMap; - Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, - MiscompiledFunctions, - VMap); - Module *ToOptimizeLoopExtracted = BD.extractLoop(ToOptimize).release(); + std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap); + Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize.get(), + MiscompiledFunctions, VMap) + .release(); + std::unique_ptr<Module> ToOptimizeLoopExtracted = + BD.extractLoop(ToOptimize); if (!ToOptimizeLoopExtracted) { // If the loop extractor crashed or if there were no extractible loops, // then this chapter of our odyssey is over with. - delete ToNotOptimize; delete ToOptimize; return MadeChange; } @@ -330,13 +325,14 @@ static bool ExtractLoops(BugDriver &BD, // extraction. AbstractInterpreter *AI = BD.switchToSafeInterpreter(); bool Failure; - Module *New = TestMergedProgram(BD, ToOptimizeLoopExtracted, - ToNotOptimize, false, Error, Failure); + std::unique_ptr<Module> New = + testMergedProgram(BD, std::move(ToOptimizeLoopExtracted), + std::move(ToNotOptimize), Error, Failure); if (!New) return false; // Delete the original and set the new program. - Module *Old = BD.swapProgramIn(New); + Module *Old = BD.swapProgramIn(New.release()); for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]); delete Old; @@ -350,16 +346,15 @@ static bool ExtractLoops(BugDriver &BD, errs() << " Continuing on with un-loop-extracted version.\n"; BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc", - ToNotOptimize); + ToNotOptimize.get()); BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc", ToOptimize); BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc", - ToOptimizeLoopExtracted); + ToOptimizeLoopExtracted.get()); errs() << "Please submit the " << OutputPrefix << "-loop-extract-fail-*.bc files.\n"; delete ToOptimize; - delete ToNotOptimize; return MadeChange; } delete ToOptimize; @@ -367,18 +362,20 @@ 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); + std::unique_ptr<Module> TOLEBackup = + CloneModule(ToOptimizeLoopExtracted.get(), VMap); + std::unique_ptr<Module> TNOBackup = CloneModule(ToNotOptimize.get(), VMap); for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) MiscompiledFunctions[i] = cast<Function>(VMap[MiscompiledFunctions[i]]); - Failure = TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize, Error); + Failure = TestFn(BD, std::move(ToOptimizeLoopExtracted), + std::move(ToNotOptimize), Error); if (!Error.empty()) return false; - ToOptimizeLoopExtracted = TOLEBackup; - ToNotOptimize = TNOBackup; + ToOptimizeLoopExtracted = std::move(TOLEBackup); + ToNotOptimize = std::move(TNOBackup); if (!Failure) { outs() << "*** Loop extraction masked the problem. Undoing.\n"; @@ -390,7 +387,8 @@ static bool ExtractLoops(BugDriver &BD, MisCompFunctions.emplace_back(F->getName(), F->getFunctionType()); } - if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted)) + if (Linker::linkModules(*ToNotOptimize, + std::move(ToOptimizeLoopExtracted))) exit(1); MiscompiledFunctions.clear(); @@ -401,8 +399,7 @@ static bool ExtractLoops(BugDriver &BD, MiscompiledFunctions.push_back(NewF); } - delete ToOptimizeLoopExtracted; - BD.setNewProgram(ToNotOptimize); + BD.setNewProgram(ToNotOptimize.release()); return MadeChange; } @@ -418,11 +415,9 @@ static bool ExtractLoops(BugDriver &BD, // extraction both didn't break the program, and didn't mask the problem. // Replace the current program with the loop extracted version, and try to // extract another loop. - if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted)) + if (Linker::linkModules(*ToNotOptimize, std::move(ToOptimizeLoopExtracted))) exit(1); - delete ToOptimizeLoopExtracted; - // All of the Function*'s in the MiscompiledFunctions list are in the old // module. Update this list to include all of the functions in the // optimized and loop extracted module. @@ -434,7 +429,7 @@ static bool ExtractLoops(BugDriver &BD, MiscompiledFunctions.push_back(NewF); } - BD.setNewProgram(ToNotOptimize); + BD.setNewProgram(ToNotOptimize.release()); MadeChange = true; } } @@ -442,14 +437,15 @@ static bool ExtractLoops(BugDriver &BD, namespace { class ReduceMiscompiledBlocks : public ListReducer<BasicBlock*> { BugDriver &BD; - bool (*TestFn)(BugDriver &, Module *, Module *, std::string &); + bool (*TestFn)(BugDriver &, std::unique_ptr<Module>, + std::unique_ptr<Module>, std::string &); std::vector<Function*> FunctionsBeingTested; public: ReduceMiscompiledBlocks(BugDriver &bd, - bool (*F)(BugDriver &, Module *, Module *, - std::string &), - const std::vector<Function*> &Fns) - : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {} + bool (*F)(BugDriver &, std::unique_ptr<Module>, + std::unique_ptr<Module>, std::string &), + const std::vector<Function *> &Fns) + : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {} TestResult doTest(std::vector<BasicBlock*> &Prefix, std::vector<BasicBlock*> &Suffix, @@ -495,7 +491,7 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs, // Split the module into the two halves of the program we want. ValueToValueMapTy VMap; - Module *Clone = CloneModule(BD.getProgram(), VMap); + Module *Clone = CloneModule(BD.getProgram(), VMap).release(); Module *Orig = BD.swapProgramIn(Clone); std::vector<Function*> FuncsOnClone; std::vector<BasicBlock*> BBsOnClone; @@ -509,45 +505,37 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs, } VMap.clear(); - Module *ToNotOptimize = CloneModule(BD.getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, - FuncsOnClone, - VMap); + std::unique_ptr<Module> ToNotOptimize = CloneModule(BD.getProgram(), VMap); + std::unique_ptr<Module> ToOptimize = + SplitFunctionsOutOfModule(ToNotOptimize.get(), 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. if (std::unique_ptr<Module> New = - BD.extractMappedBlocksFromModule(BBsOnClone, ToOptimize)) { - delete ToOptimize; - // Run the predicate, - // note that the predicate will delete both input modules. - bool Ret = TestFn(BD, New.get(), ToNotOptimize, Error); + BD.extractMappedBlocksFromModule(BBsOnClone, ToOptimize.get())) { + bool Ret = TestFn(BD, std::move(New), std::move(ToNotOptimize), Error); delete BD.swapProgramIn(Orig); return Ret; } delete BD.swapProgramIn(Orig); - delete ToOptimize; - delete ToNotOptimize; 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. +/// 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. /// static bool ExtractBlocks(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *, + bool (*TestFn)(BugDriver &, std::unique_ptr<Module>, + std::unique_ptr<Module>, std::string &), - std::vector<Function*> &MiscompiledFunctions, + std::vector<Function *> &MiscompiledFunctions, std::string &Error) { if (BugpointIsInterrupted) return false; std::vector<BasicBlock*> 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) - Blocks.push_back(I); + for (BasicBlock &BB : *MiscompiledFunctions[i]) + Blocks.push_back(&BB); // Use the list reducer to identify blocks that can be extracted without // obscuring the bug. The Blocks list will end up containing blocks that must @@ -571,10 +559,10 @@ static bool ExtractBlocks(BugDriver &BD, } ValueToValueMapTy VMap; - Module *ProgClone = CloneModule(BD.getProgram(), VMap); - Module *ToExtract = SplitFunctionsOutOfModule(ProgClone, - MiscompiledFunctions, - VMap); + Module *ProgClone = CloneModule(BD.getProgram(), VMap).release(); + Module *ToExtract = + SplitFunctionsOutOfModule(ProgClone, MiscompiledFunctions, VMap) + .release(); std::unique_ptr<Module> Extracted = BD.extractMappedBlocksFromModule(Blocks, ToExtract); if (!Extracted) { @@ -595,7 +583,7 @@ static bool ExtractBlocks(BugDriver &BD, if (!I->isDeclaration()) MisCompFunctions.emplace_back(I->getName(), I->getFunctionType()); - if (Linker::LinkModules(ProgClone, Extracted.get())) + if (Linker::linkModules(*ProgClone, std::move(Extracted))) exit(1); // Set the new program and delete the old one. @@ -613,14 +601,13 @@ 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. +/// This is a generic driver to narrow down miscompilations, either in an +/// optimization or a code generator. /// -static std::vector<Function*> +static std::vector<Function *> DebugAMiscompilation(BugDriver &BD, - bool (*TestFn)(BugDriver &, Module *, Module *, - std::string &), + bool (*TestFn)(BugDriver &, std::unique_ptr<Module>, + std::unique_ptr<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 @@ -628,9 +615,9 @@ DebugAMiscompilation(BugDriver &BD, // the program. std::vector<Function*> MiscompiledFunctions; Module *Prog = BD.getProgram(); - for (Module::iterator I = Prog->begin(), E = Prog->end(); I != E; ++I) - if (!I->isDeclaration()) - MiscompiledFunctions.push_back(I); + for (Function &F : *Prog) + if (!F.isDeclaration()) + MiscompiledFunctions.push_back(&F); // Do the reduction... if (!BugpointIsInterrupted) @@ -699,28 +686,28 @@ DebugAMiscompilation(BugDriver &BD, return MiscompiledFunctions; } -/// TestOptimizer - This is the predicate function used to check to see if the -/// "Test" portion of the program is misoptimized. If so, return true. In any -/// case, both module arguments are deleted. +/// This is the predicate function used to check to see if the "Test" portion of +/// the program is misoptimized. If so, return true. In any case, both module +/// arguments are deleted. /// -static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe, - std::string &Error) { +static bool TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test, + std::unique_ptr<Module> Safe, std::string &Error) { // Run the optimization passes on ToOptimize, producing a transformed version // of the functions being tested. outs() << " Optimizing functions being tested: "; - std::unique_ptr<Module> Optimized = BD.runPassesOn(Test, BD.getPassesToRun(), - /*AutoDebugCrashes*/ true); + std::unique_ptr<Module> Optimized = + BD.runPassesOn(Test.get(), BD.getPassesToRun(), + /*AutoDebugCrashes*/ true); outs() << "done.\n"; - delete Test; outs() << " Checking to see if the merged program executes correctly: "; bool Broken; - Module *New = - TestMergedProgram(BD, Optimized.get(), Safe, true, Error, Broken); + std::unique_ptr<Module> New = testMergedProgram( + BD, std::move(Optimized), std::move(Safe), Error, Broken); if (New) { outs() << (Broken ? " nope.\n" : " yup.\n"); // Delete the original and set the new program. - delete BD.swapProgramIn(New); + delete BD.swapProgramIn(New.release()); } return Broken; } @@ -753,10 +740,10 @@ void BugDriver::debugMiscompilation(std::string *Error) { // Output a bunch of bitcode files for the user... outs() << "Outputting reduced bitcode files which expose the problem:\n"; ValueToValueMapTy VMap; - Module *ToNotOptimize = CloneModule(getProgram(), VMap); - Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, - MiscompiledFunctions, - VMap); + Module *ToNotOptimize = CloneModule(getProgram(), VMap).release(); + Module *ToOptimize = + SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, VMap) + .release(); outs() << " Non-optimized portion: "; EmitProgressBitcode(ToNotOptimize, "tonotoptimize", true); @@ -769,13 +756,13 @@ void BugDriver::debugMiscompilation(std::string *Error) { return; } -/// CleanupAndPrepareModules - Get the specified modules ready for code -/// generator testing. +/// Get the specified modules ready for code generator testing. /// -static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, +static void CleanupAndPrepareModules(BugDriver &BD, + std::unique_ptr<Module> &Test, Module *Safe) { // Clean up the modules, removing extra cruft that we don't need anymore... - Test = BD.performFinalCleanups(Test).release(); + Test = BD.performFinalCleanups(Test.get()); // If we are executing the JIT, we have several nasty issues to take care of. if (!BD.isExecutingJIT()) return; @@ -788,21 +775,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.get()); // 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); + oldMain->getName(), Test.get()); // Set up and remember the argument list for the main function. std::vector<Value*> 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); + args.push_back(&*I); } // Call the old main function and return its result @@ -905,9 +892,8 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Save the argument list. std::vector<Value*> Args; - for (Function::arg_iterator i = FuncWrapper->arg_begin(), - e = FuncWrapper->arg_end(); i != e; ++i) - Args.push_back(i); + for (Argument &A : FuncWrapper->args()) + Args.push_back(&A); // Pass on the arguments to the real function, return its result if (F->getReturnType()->isVoidTy()) { @@ -932,15 +918,14 @@ 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. +/// 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. /// -static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, +static bool TestCodeGenerator(BugDriver &BD, std::unique_ptr<Module> Test, + std::unique_ptr<Module> Safe, std::string &Error) { - CleanupAndPrepareModules(BD, Test, Safe); + CleanupAndPrepareModules(BD, Test, Safe.get()); SmallString<128> TestModuleBC; int TestModuleFD; @@ -951,12 +936,11 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, << EC.message() << "\n"; exit(1); } - if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test)) { + if (BD.writeProgramToFile(TestModuleBC.str(), TestModuleFD, Test.get())) { errs() << "Error writing bitcode to `" << TestModuleBC.str() << "'\nExiting."; exit(1); } - delete Test; FileRemover TestModuleBCRemover(TestModuleBC.str(), !SaveTemps); @@ -971,7 +955,7 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, exit(1); } - if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe)) { + if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe.get())) { errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting."; exit(1); @@ -982,7 +966,6 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe, std::string SharedObject = BD.compileSharedObject(SafeModuleBC.str(), Error); if (!Error.empty()) return false; - delete Safe; FileRemover SharedObjectRemover(SharedObject, !SaveTemps); @@ -1030,11 +1013,12 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { // Split the module into the two halves of the program we want. ValueToValueMapTy VMap; - Module *ToNotCodeGen = CloneModule(getProgram(), VMap); - Module *ToCodeGen = SplitFunctionsOutOfModule(ToNotCodeGen, Funcs, VMap); + std::unique_ptr<Module> ToNotCodeGen = CloneModule(getProgram(), VMap); + std::unique_ptr<Module> ToCodeGen = + SplitFunctionsOutOfModule(ToNotCodeGen.get(), Funcs, VMap); // Condition the modules - CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen); + CleanupAndPrepareModules(*this, ToCodeGen, ToNotCodeGen.get()); SmallString<128> TestModuleBC; int TestModuleFD; @@ -1046,12 +1030,11 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { exit(1); } - if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen)) { + if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen.get())) { errs() << "Error writing bitcode to `" << TestModuleBC << "'\nExiting."; exit(1); } - delete ToCodeGen; // Make the shared library SmallString<128> SafeModuleBC; @@ -1064,7 +1047,8 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { exit(1); } - if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, ToNotCodeGen)) { + if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, + ToNotCodeGen.get())) { errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting."; exit(1); @@ -1072,7 +1056,6 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { std::string SharedObject = compileSharedObject(SafeModuleBC.str(), *Error); if (!Error->empty()) return true; - delete ToNotCodeGen; outs() << "You can reproduce the problem with the command line: \n"; if (isExecutingJIT()) { @@ -1080,7 +1063,7 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { } else { outs() << " llc " << TestModuleBC << " -o " << TestModuleBC << ".s\n"; - outs() << " gcc " << SharedObject << " " << TestModuleBC.str() + outs() << " cc " << SharedObject << " " << TestModuleBC.str() << ".s -o " << TestModuleBC << ".exe"; #if defined (HAVE_LINK_R) outs() << " -Wl,-R."; @@ -1093,7 +1076,7 @@ bool BugDriver::debugCodeGenerator(std::string *Error) { outs() << '\n'; outs() << "The shared object was created with:\n llc -march=c " << SafeModuleBC.str() << " -o temporary.c\n" - << " gcc -xc temporary.c -O2 -o " << SharedObject; + << " cc -xc temporary.c -O2 -o " << SharedObject; if (TargetTriple.getArch() == Triple::sparc) outs() << " -G"; // Compile a shared library, `-G' for Sparc else diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.cpp b/contrib/llvm/tools/bugpoint/ToolRunner.cpp index 51091e2..2ccd649 100644 --- a/contrib/llvm/tools/bugpoint/ToolRunner.cpp +++ b/contrib/llvm/tools/bugpoint/ToolRunner.cpp @@ -64,16 +64,6 @@ static int RunProgramWithTimeout(StringRef ProgramPath, unsigned MemoryLimit = 0, std::string *ErrMsg = nullptr) { const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile }; - -#if 0 // For debug purposes - { - errs() << "RUN:"; - for (unsigned i = 0; Args[i]; ++i) - errs() << " " << Args[i]; - errs() << "\n"; - } -#endif - return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects, NumSeconds, MemoryLimit, ErrMsg); } @@ -93,15 +83,6 @@ static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath, unsigned MemoryLimit = 0) { const StringRef *Redirects[3] = { &StdInFile, &StdOutFile, &StdErrFile }; -#if 0 // For debug purposes - { - errs() << "RUN:"; - for (unsigned i = 0; Args[i]; ++i) - errs() << " " << Args[i]; - errs() << "\n"; - } -#endif - // Run the program remotely with the remote client int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, nullptr, Redirects, NumSeconds, MemoryLimit); @@ -152,7 +133,7 @@ static std::string ProcessFailure(StringRef ProgPath, const char** Args, ErrorFilename.str(), Timeout, MemoryLimit); // FIXME: check return code ? - // Print out the error messages generated by GCC if possible... + // Print out the error messages generated by CC if possible... std::ifstream ErrorFile(ErrorFilename.c_str()); if (ErrorFile) { std::copy(std::istreambuf_iterator<char>(ErrorFile), @@ -184,7 +165,7 @@ namespace { const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &GCCArgs, + const std::vector<std::string> &CCArgs, const std::vector<std::string> &SharedLibs = std::vector<std::string>(), unsigned Timeout = 0, @@ -197,7 +178,7 @@ int LLI::ExecuteProgram(const std::string &Bitcode, const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &GCCArgs, + const std::vector<std::string> &CCArgs, const std::vector<std::string> &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { @@ -305,7 +286,7 @@ namespace { const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &GCCArgs = + const std::vector<std::string> &CCArgs = std::vector<std::string>(), const std::vector<std::string> &SharedLibs = std::vector<std::string>(), @@ -361,7 +342,7 @@ namespace { const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &GCCArgs, + const std::vector<std::string> &CCArgs, const std::vector<std::string> &SharedLibs = std::vector<std::string>(), unsigned Timeout = 0, @@ -374,7 +355,7 @@ int CustomExecutor::ExecuteProgram(const std::string &Bitcode, const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &GCCArgs, + const std::vector<std::string> &CCArgs, const std::vector<std::string> &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { @@ -473,7 +454,7 @@ AbstractInterpreter *AbstractInterpreter::createCustomExecutor( //===----------------------------------------------------------------------===// // LLC Implementation of AbstractIntepreter interface // -GCC::FileType LLC::OutputCode(const std::string &Bitcode, +CC::FileType LLC::OutputCode(const std::string &Bitcode, std::string &OutputAsmFile, std::string &Error, unsigned Timeout, unsigned MemoryLimit) { const char *Suffix = (UseIntegratedAssembler ? ".llc.o" : ".llc.s"); @@ -514,7 +495,7 @@ GCC::FileType LLC::OutputCode(const std::string &Bitcode, Timeout, MemoryLimit)) Error = ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit); - return UseIntegratedAssembler ? GCC::ObjectFile : GCC::AsmFile; + return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile; } void LLC::compileProgram(const std::string &Bitcode, std::string *Error, @@ -529,22 +510,22 @@ int LLC::ExecuteProgram(const std::string &Bitcode, const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &ArgsForGCC, + const std::vector<std::string> &ArgsForCC, const std::vector<std::string> &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { std::string OutputAsmFile; - GCC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, + CC::FileType FileKind = OutputCode(Bitcode, OutputAsmFile, *Error, Timeout, MemoryLimit); FileRemover OutFileRemover(OutputAsmFile, !SaveTemps); - std::vector<std::string> GCCArgs(ArgsForGCC); - GCCArgs.insert(GCCArgs.end(), SharedLibs.begin(), SharedLibs.end()); + std::vector<std::string> CCArgs(ArgsForCC); + CCArgs.insert(CCArgs.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, + // Assuming LLC worked, compile the result with CC and run it. + return cc->ExecuteProgram(OutputAsmFile, Args, FileKind, + InputFile, OutputFile, Error, CCArgs, Timeout, MemoryLimit); } @@ -552,9 +533,9 @@ int LLC::ExecuteProgram(const std::string &Bitcode, /// LLC *AbstractInterpreter::createLLC(const char *Argv0, std::string &Message, - const std::string &GCCBinary, + const std::string &CCBinary, const std::vector<std::string> *Args, - const std::vector<std::string> *GCCArgs, + const std::vector<std::string> *CCArgs, bool UseIntegratedAssembler) { std::string LLCPath = PrependMainExecutablePath("llc", Argv0, (void *)(intptr_t) & createLLC); @@ -563,13 +544,13 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0, return nullptr; } - GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs); - if (!gcc) { + CC *cc = CC::create(Message, CCBinary, CCArgs); + if (!cc) { errs() << Message << "\n"; exit(1); } Message = "Found llc: " + LLCPath + "\n"; - return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler); + return new LLC(LLCPath, cc, Args, UseIntegratedAssembler); } //===---------------------------------------------------------------------===// @@ -591,7 +572,7 @@ namespace { const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &GCCArgs = + const std::vector<std::string> &CCArgs = std::vector<std::string>(), const std::vector<std::string> &SharedLibs = std::vector<std::string>(), @@ -605,7 +586,7 @@ int JIT::ExecuteProgram(const std::string &Bitcode, const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &GCCArgs, + const std::vector<std::string> &CCArgs, const std::vector<std::string> &SharedLibs, unsigned Timeout, unsigned MemoryLimit) { @@ -656,7 +637,7 @@ AbstractInterpreter *AbstractInterpreter::createJIT(const char *Argv0, } //===---------------------------------------------------------------------===// -// GCC abstraction +// CC abstraction // static bool IsARMArchitecture(std::vector<const char*> Args) { @@ -672,82 +653,82 @@ static bool IsARMArchitecture(std::vector<const char*> Args) { return false; } -int GCC::ExecuteProgram(const std::string &ProgramFile, +int CC::ExecuteProgram(const std::string &ProgramFile, const std::vector<std::string> &Args, FileType fileType, const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &ArgsForGCC, + const std::vector<std::string> &ArgsForCC, unsigned Timeout, unsigned MemoryLimit) { - std::vector<const char*> GCCArgs; + std::vector<const char*> CCArgs; - GCCArgs.push_back(GCCPath.c_str()); + CCArgs.push_back(CCPath.c_str()); if (TargetTriple.getArch() == Triple::x86) - GCCArgs.push_back("-m32"); + CCArgs.push_back("-m32"); for (std::vector<std::string>::const_iterator - I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) - GCCArgs.push_back(I->c_str()); + I = ccArgs.begin(), E = ccArgs.end(); I != E; ++I) + CCArgs.push_back(I->c_str()); // Specify -x explicitly in case the extension is wonky if (fileType != ObjectFile) { - GCCArgs.push_back("-x"); + CCArgs.push_back("-x"); if (fileType == CFile) { - GCCArgs.push_back("c"); - GCCArgs.push_back("-fno-strict-aliasing"); + CCArgs.push_back("c"); + CCArgs.push_back("-fno-strict-aliasing"); } else { - GCCArgs.push_back("assembler"); + CCArgs.push_back("assembler"); // For ARM architectures we don't want this flag. bugpoint isn't // explicitly told what architecture it is working on, so we get - // it from gcc flags - if (TargetTriple.isOSDarwin() && !IsARMArchitecture(GCCArgs)) - GCCArgs.push_back("-force_cpusubtype_ALL"); + // it from cc flags + if (TargetTriple.isOSDarwin() && !IsARMArchitecture(CCArgs)) + CCArgs.push_back("-force_cpusubtype_ALL"); } } - GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. + CCArgs.push_back(ProgramFile.c_str()); // Specify the input filename. - GCCArgs.push_back("-x"); - GCCArgs.push_back("none"); - GCCArgs.push_back("-o"); + CCArgs.push_back("-x"); + CCArgs.push_back("none"); + CCArgs.push_back("-o"); SmallString<128> OutputBinary; std::error_code EC = - sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.gcc.exe", OutputBinary); + sys::fs::createUniqueFile(ProgramFile + "-%%%%%%%.cc.exe", OutputBinary); if (EC) { errs() << "Error making unique filename: " << EC.message() << "\n"; exit(1); } - GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... + CCArgs.push_back(OutputBinary.c_str()); // Output to the right file... - // Add any arguments intended for GCC. We locate them here because this is + // Add any arguments intended for CC. 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()); + for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i) + CCArgs.push_back(ArgsForCC[i].c_str()); - GCCArgs.push_back("-lm"); // Hard-code the math library... - GCCArgs.push_back("-O2"); // Optimize the program a bit... + CCArgs.push_back("-lm"); // Hard-code the math library... + CCArgs.push_back("-O2"); // Optimize the program a bit... #if defined (HAVE_LINK_R) - GCCArgs.push_back("-Wl,-R."); // Search this dir for .so files + CCArgs.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 + CCArgs.push_back("-mcpu=v9"); + CCArgs.push_back(nullptr); // NULL terminator - outs() << "<gcc>"; outs().flush(); + outs() << "<CC>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) - errs() << " " << GCCArgs[i]; + for (unsigned i = 0, e = CCArgs.size()-1; i != e; ++i) + errs() << " " << CCArgs[i]; errs() << "\n"; ); - if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) { - *Error = ProcessFailure(GCCPath, &GCCArgs[0]); + if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", "")) { + *Error = ProcessFailure(CCPath, &CCArgs[0]); return -1; } @@ -821,9 +802,9 @@ int GCC::ExecuteProgram(const std::string &ProgramFile, } } -int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, +int CC::MakeSharedObject(const std::string &InputFile, FileType fileType, std::string &OutputFile, - const std::vector<std::string> &ArgsForGCC, + const std::vector<std::string> &ArgsForCC, std::string &Error) { SmallString<128> UniqueFilename; std::error_code EC = sys::fs::createUniqueFile( @@ -834,84 +815,84 @@ int GCC::MakeSharedObject(const std::string &InputFile, FileType fileType, } OutputFile = UniqueFilename.str(); - std::vector<const char*> GCCArgs; + std::vector<const char*> CCArgs; - GCCArgs.push_back(GCCPath.c_str()); + CCArgs.push_back(CCPath.c_str()); if (TargetTriple.getArch() == Triple::x86) - GCCArgs.push_back("-m32"); + CCArgs.push_back("-m32"); for (std::vector<std::string>::const_iterator - I = gccArgs.begin(), E = gccArgs.end(); I != E; ++I) - GCCArgs.push_back(I->c_str()); + I = ccArgs.begin(), E = ccArgs.end(); I != E; ++I) + CCArgs.push_back(I->c_str()); // Compile the C/asm file into a shared object if (fileType != ObjectFile) { - GCCArgs.push_back("-x"); - GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); + CCArgs.push_back("-x"); + CCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); } - GCCArgs.push_back("-fno-strict-aliasing"); - GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. - GCCArgs.push_back("-x"); - GCCArgs.push_back("none"); + CCArgs.push_back("-fno-strict-aliasing"); + CCArgs.push_back(InputFile.c_str()); // Specify the input filename. + CCArgs.push_back("-x"); + CCArgs.push_back("none"); if (TargetTriple.getArch() == Triple::sparc) - GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc + CCArgs.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("-undefined"); - GCCArgs.push_back("dynamic_lookup"); + // bugpoint to just pass that in the environment of CC. + CCArgs.push_back("-single_module"); + CCArgs.push_back("-dynamiclib"); // `-dynamiclib' for MacOS X/PowerPC + CCArgs.push_back("-undefined"); + CCArgs.push_back("dynamic_lookup"); } else - GCCArgs.push_back("-shared"); // `-shared' for Linux/X86, maybe others + CCArgs.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 + CCArgs.push_back("-fPIC"); // Requires shared objs to contain PIC if (TargetTriple.getArch() == Triple::sparc) - GCCArgs.push_back("-mcpu=v9"); + CCArgs.push_back("-mcpu=v9"); - GCCArgs.push_back("-o"); - GCCArgs.push_back(OutputFile.c_str()); // Output to the right filename. - GCCArgs.push_back("-O2"); // Optimize the program a bit. + CCArgs.push_back("-o"); + CCArgs.push_back(OutputFile.c_str()); // Output to the right filename. + CCArgs.push_back("-O2"); // Optimize the program a bit. - // Add any arguments intended for GCC. We locate them here because this is + // Add any arguments intended for CC. 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 + for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i) + CCArgs.push_back(ArgsForCC[i].c_str()); + CCArgs.push_back(nullptr); // NULL terminator - outs() << "<gcc>"; outs().flush(); + outs() << "<CC>"; outs().flush(); DEBUG(errs() << "\nAbout to run:\t"; - for (unsigned i = 0, e = GCCArgs.size()-1; i != e; ++i) - errs() << " " << GCCArgs[i]; + for (unsigned i = 0, e = CCArgs.size()-1; i != e; ++i) + errs() << " " << CCArgs[i]; errs() << "\n"; ); - if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "", "", "")) { - Error = ProcessFailure(GCCPath, &GCCArgs[0]); + if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", "")) { + Error = ProcessFailure(CCPath, &CCArgs[0]); return 1; } return 0; } -/// create - Try to find the `gcc' executable +/// create - Try to find the CC executable /// -GCC *GCC::create(std::string &Message, - const std::string &GCCBinary, +CC *CC::create(std::string &Message, + const std::string &CCBinary, const std::vector<std::string> *Args) { - auto GCCPath = sys::findProgramByName(GCCBinary); - if (!GCCPath) { - Message = "Cannot find `" + GCCBinary + "' in PATH: " + - GCCPath.getError().message() + "\n"; + auto CCPath = sys::findProgramByName(CCBinary); + if (!CCPath) { + Message = "Cannot find `" + CCBinary + "' in PATH: " + + CCPath.getError().message() + "\n"; return nullptr; } @@ -926,6 +907,6 @@ GCC *GCC::create(std::string &Message, RemoteClientPath = *Path; } - Message = "Found gcc: " + *GCCPath + "\n"; - return new GCC(*GCCPath, RemoteClientPath, Args); + Message = "Found CC: " + *CCPath + "\n"; + return new CC(*CCPath, RemoteClientPath, Args); } diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.h b/contrib/llvm/tools/bugpoint/ToolRunner.h index 5d67a94..3accd70 100644 --- a/contrib/llvm/tools/bugpoint/ToolRunner.h +++ b/contrib/llvm/tools/bugpoint/ToolRunner.h @@ -33,22 +33,22 @@ extern Triple TargetTriple; class LLC; //===---------------------------------------------------------------------===// -// GCC abstraction +// CC abstraction // -class GCC { - std::string GCCPath; // The path to the gcc executable. +class CC { + std::string CCPath; // The path to the cc executable. std::string RemoteClientPath; // The path to the rsh / ssh executable. - std::vector<std::string> gccArgs; // GCC-specific arguments. - GCC(StringRef gccPath, StringRef RemotePath, - const std::vector<std::string> *GCCArgs) - : GCCPath(gccPath), RemoteClientPath(RemotePath) { - if (GCCArgs) gccArgs = *GCCArgs; + std::vector<std::string> ccArgs; // CC-specific arguments. + CC(StringRef ccPath, StringRef RemotePath, + const std::vector<std::string> *CCArgs) + : CCPath(ccPath), RemoteClientPath(RemotePath) { + if (CCArgs) ccArgs = *CCArgs; } public: enum FileType { AsmFile, ObjectFile, CFile }; - static GCC *create(std::string &Message, - const std::string &GCCBinary, + static CC *create(std::string &Message, + const std::string &CCBinary, const std::vector<std::string> *Args); /// ExecuteProgram - Execute the program specified by "ProgramFile" (which is @@ -64,7 +64,7 @@ public: const std::string &InputFile, const std::string &OutputFile, std::string *Error = nullptr, - const std::vector<std::string> &GCCArgs = + const std::vector<std::string> &CCArgs = std::vector<std::string>(), unsigned Timeout = 0, unsigned MemoryLimit = 0); @@ -74,7 +74,7 @@ public: /// int MakeSharedObject(const std::string &InputFile, FileType fileType, std::string &OutputFile, - const std::vector<std::string> &ArgsForGCC, + const std::vector<std::string> &ArgsForCC, std::string &Error); }; @@ -88,9 +88,9 @@ class AbstractInterpreter { virtual void anchor(); public: static LLC *createLLC(const char *Argv0, std::string &Message, - const std::string &GCCBinary, + const std::string &CCBinary, const std::vector<std::string> *Args = nullptr, - const std::vector<std::string> *GCCArgs = nullptr, + const std::vector<std::string> *CCArgs = nullptr, bool UseIntegratedAssembler = false); static AbstractInterpreter* @@ -119,15 +119,15 @@ public: unsigned Timeout = 0, unsigned MemoryLimit = 0) {} /// OutputCode - Compile the specified program from bitcode to code - /// understood by the GCC driver (either C or asm). If the code generator + /// understood by the CC driver (either C or asm). If the code generator /// fails, it sets Error, otherwise, this function returns the type of code /// emitted. - virtual GCC::FileType OutputCode(const std::string &Bitcode, + virtual CC::FileType OutputCode(const std::string &Bitcode, std::string &OutFile, std::string &Error, unsigned Timeout = 0, unsigned MemoryLimit = 0) { Error = "OutputCode not supported by this AbstractInterpreter!"; - return GCC::AsmFile; + return CC::AsmFile; } /// ExecuteProgram - Run the specified bitcode file, emitting output to the @@ -140,7 +140,7 @@ public: const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &GCCArgs = + const std::vector<std::string> &CCArgs = std::vector<std::string>(), const std::vector<std::string> &SharedLibs = std::vector<std::string>(), @@ -154,18 +154,18 @@ public: class LLC : public AbstractInterpreter { std::string LLCPath; // The path to the LLC executable. std::vector<std::string> ToolArgs; // Extra args to pass to LLC. - GCC *gcc; + CC *cc; bool UseIntegratedAssembler; public: - LLC(const std::string &llcPath, GCC *Gcc, + LLC(const std::string &llcPath, CC *cc, const std::vector<std::string> *Args, bool useIntegratedAssembler) - : LLCPath(llcPath), gcc(Gcc), + : LLCPath(llcPath), cc(cc), UseIntegratedAssembler(useIntegratedAssembler) { ToolArgs.clear(); if (Args) ToolArgs = *Args; } - ~LLC() override { delete gcc; } + ~LLC() override { delete cc; } /// compileProgram - Compile the specified program from bitcode to executable /// code. This does not produce any output, it is only used when debugging @@ -178,7 +178,7 @@ public: const std::string &InputFile, const std::string &OutputFile, std::string *Error, - const std::vector<std::string> &GCCArgs = + const std::vector<std::string> &CCArgs = std::vector<std::string>(), const std::vector<std::string> &SharedLibs = std::vector<std::string>(), @@ -186,10 +186,10 @@ public: 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 + /// understood by the CC 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, + CC::FileType OutputCode(const std::string &Bitcode, std::string &OutFile, std::string &Error, unsigned Timeout = 0, unsigned MemoryLimit = 0) override; diff --git a/contrib/llvm/tools/bugpoint/bugpoint.cpp b/contrib/llvm/tools/bugpoint/bugpoint.cpp index af6d9fc..48f30e6 100644 --- a/contrib/llvm/tools/bugpoint/bugpoint.cpp +++ b/contrib/llvm/tools/bugpoint/bugpoint.cpp @@ -126,7 +126,6 @@ int main(int argc, char **argv) { initializeVectorization(Registry); initializeIPO(Registry); initializeAnalysis(Registry); - initializeIPA(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); initializeInstrumentation(Registry); @@ -181,19 +180,12 @@ int main(int argc, char **argv) { Builder.Inliner = createFunctionInliningPass(225); else Builder.Inliner = createFunctionInliningPass(275); - - // Note that although clang/llvm-gcc use two separate passmanagers - // here, it shouldn't normally make a difference. Builder.populateFunctionPassManager(PM); Builder.populateModulePassManager(PM); } - for (std::vector<const PassInfo*>::iterator I = PassList.begin(), - E = PassList.end(); - I != E; ++I) { - const PassInfo* PI = *I; + for (const PassInfo *PI : PassList) D.addPass(PI->getPassArgument()); - } // Bugpoint has the ability of generating a plethora of core files, so to // avoid filling up the disk, we prevent it |