Esempio n. 1
0
bool isAllocCall(const llvm::CallInst* CI) {
    if (!CI)
        return false;

    llvm::Function* Callee = CI->getCalledFunction();
    if (Callee == 0 || !Callee->isDeclaration())
        return false;

    return isAllocCall(Callee->getName());
}
bool EscapeAnalysis::runOnFunction(Function& F) {
    return false; // This analysis is currently broken and not maintained

    if (VERBOSITY("opt") >= 1)
        outs() << "Running escape analysis on " << F.getName() << '\n';

    for (inst_iterator inst_it = inst_begin(F), _inst_end = inst_end(F); inst_it != _inst_end; ++inst_it) {
        CallInst* alloc = dyn_cast<CallInst>(&*inst_it);
        if (!alloc || !isAllocCall(alloc))
            continue;

        ChainInfo* chain = new ChainInfo(alloc);
        chains.push_back(chain);

        if (VERBOSITY("opt") >= 2) {
            errs() << "Found chain " << chain << " starting at " << *alloc;
        }

        // Calculating derived pointers, and finding escape points
        {
            // Instructions in the queue to be visited:
            std::deque<Instruction*> queue;
            // Instructions we've fully visited:
            std::unordered_set<Instruction*> checked;

            queue.push_back(alloc);

            while (queue.size()) {
                Instruction* next = queue.back();
                queue.pop_back();

                if (checked.count(next))
                    continue;

                checked.insert(next);

                for (User* user : next->users()) {
                    if (GetElementPtrInst* gep = dyn_cast<GetElementPtrInst>(user)) {
                        queue.push_back(gep);
                        chain->derived.insert(gep);
                        chain_by_pointer[gep] = chain;
                        continue;
                    }

                    if (CastInst* bc = dyn_cast<CastInst>(user)) {
                        queue.push_back(bc);
                        chain->derived.insert(bc);
                        chain_by_pointer[bc] = chain;
                        continue;
                    }

                    if (PHINode* phi = dyn_cast<PHINode>(user)) {
                        queue.push_back(phi);
                        chain->derived.insert(phi);
                        chain_by_pointer[phi] = chain;
                        continue;
                    }

                    if (isa<LoadInst>(user)) {
                        continue;
                    }

                    if (ReturnInst* ret = dyn_cast<ReturnInst>(user)) {
                        if (VERBOSITY() >= 2)
                            errs() << "Not dead; used here: " << *ret << '\n';
                        chain->escape_points.insert(ret);
                        continue;
                    }



                    if (StoreInst* si = dyn_cast<StoreInst>(user)) {
                        if (si->getPointerOperand() == next) {
                        } else {
                            assert(si->getValueOperand() == next);
                            if (VERBOSITY() >= 2)
                                errs() << "Escapes here: " << *si << '\n';
                            chain->escape_points.insert(si);
                        }
                        continue;
                    }

                    if (llvm::isa<CallInst>(user) || llvm::isa<InvokeInst>(user)) {
                        if (VERBOSITY() >= 2)
                            errs() << "Escapes here: " << *user << '\n';
                        chain->escape_points.insert(dyn_cast<Instruction>(user));
                        continue;
                    }



                    user->dump();
                    RELEASE_ASSERT(0, "");
                }
            }
        }

        // Calculating BB-level escape-ness
        {
            std::deque<const BasicBlock*> queue;

            for (const auto I : chain->escape_points) {
                chain->bb_escapes[I->getParent()] = BBPartialEscape;
                queue.insert(queue.end(), succ_begin(I->getParent()), succ_end(I->getParent()));
            }

            while (queue.size()) {
                const BasicBlock* bb = queue.back();
                queue.pop_back();

                if (chain->bb_escapes[bb] == BBFullEscape)
                    continue;

                chain->bb_escapes[bb] = BBFullEscape;
                queue.insert(queue.end(), succ_begin(bb), succ_end(bb));
            }

            for (BasicBlock& bb : F) {
                if (chain->bb_escapes.count(&bb) == 0)
                    chain->bb_escapes[&bb] = BBNoEscape;

                // outs() << bb.getName() << ' ' << chain->bb_escapes[&bb] << '\n';
            }
        }
    }


    return false;
}