Ejemplo n.º 1
0
/// 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;
}