/// 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. /// static bool ExtractBlocks(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *, Module *, std::string &), 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 (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 // be retained from the original program. unsigned OldSize = Blocks.size(); // Check to see if all blocks are extractible first. bool Ret = ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions) .TestFuncs(std::vector<BasicBlock*>(), Error); if (!Error.empty()) return false; if (Ret) { Blocks.clear(); } else { ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions).reduceList(Blocks, Error); if (!Error.empty()) return false; if (Blocks.size() == OldSize) return false; } ValueToValueMapTy VMap; Module *ProgClone = CloneModule(BD.getProgram(), VMap); Module *ToExtract = SplitFunctionsOutOfModule(ProgClone, MiscompiledFunctions, VMap); std::unique_ptr<Module> Extracted = BD.extractMappedBlocksFromModule(Blocks, ToExtract); if (!Extracted) { // Weird, extraction should have worked. errs() << "Nondeterministic problem extracting blocks??\n"; delete ProgClone; delete ToExtract; return false; } // Otherwise, block extraction succeeded. Link the two program fragments back // together. delete ToExtract; std::vector<std::pair<std::string, FunctionType*> > MisCompFunctions; for (Module::iterator I = Extracted->begin(), E = Extracted->end(); I != E; ++I) if (!I->isDeclaration()) MisCompFunctions.emplace_back(I->getName(), I->getFunctionType()); if (Linker::linkModules(*ProgClone, *Extracted, diagnosticHandler)) exit(1); // Set the new program and delete the old one. BD.setNewProgram(ProgClone); // Update the list of miscompiled functions. MiscompiledFunctions.clear(); for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) { Function *NewF = ProgClone->getFunction(MisCompFunctions[i].first); assert(NewF && "Function not found??"); MiscompiledFunctions.push_back(NewF); } return true; }