Первый поиск по глубине - PullRequest
1 голос
/ 19 июня 2019

Я пишу свой первый проход llvm и хотел бы сделать DFS из базового блока возврата функции.

Чтобы получить базовый блок возврата функции (если он есть), яиспользовал проход UnifyFunctionExitNodes, который обеспечивает метод getReturnBlock().Затем я нашел то, что мне нужно в llvm/ADT/DepthFirstIterator.h, чтобы сделать DFS для обратного CFG из блока его возврата.Я думаю, что это скорее проблема C ++, чем проблема llvm, но я полностью застрял.

NB. Я совсем новичок в C ++ и llvm, но довольно хорошо знаком с C.

Существует минимальный нерабочий пример:

#include "llvm/Pass.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DepthFirstIterator.h"

using namespace llvm;

namespace {
struct Exploration : public llvm::FunctionPass {

    static char ID;

    Exploration() : FunctionPass(ID) {}

    void getAnalysisUsage(llvm::AnalysisUsage &au) const {
        au.setPreservesAll();
        au.addRequiredTransitive<UnifyFunctionExitNodes>();
    }

    virtual bool runOnFunction(llvm::Function &F) override {
        UnifyFunctionExitNodes *UFEN = &getAnalysis<UnifyFunctionExitNodes>();
        BasicBlock *returnBB = UFEN->getReturnBlock();

        if (returnBB != nullptr) {
            errs() << "Return Block : ";
            errs().write_escaped(returnBB->getName()) << '\n';

        } else {
            errs() << "There is no return block\n";
        }

        // first try
        for (BasicBlock *BB : inverse_depth_first(*returnBB)) {
            // visit *BB
        }
        // second try        
        for (auto BB = idf_begin(*returnBB); BB != idf_end(*returnBB); BB++) {
            // visit BB
        }

        return false; // didn't alter the IR
    }

};
}

char Exploration::ID = 0;
// Register the pass with llvm, so that we can call it
static RegisterPass<Exploration> X("Exploration", "Exploration Pass",
                                   false /* Only looks at CFG */,
                                   false /* Analysis Pass */);

первый цикл дает мне

llvm-pass/Exploration/Exploration.cpp:34:60: error: no matching function for call to ‘inverse_depth_first(llvm::BasicBlock&)’
         for (BasicBlock *BB : inverse_depth_first(*returnBB)) {
                                                            ^
In file included from llvm-pass/Exploration/Exploration.cpp:6:0:
/usr/local/include/llvm/ADT/DepthFirstIterator.h:276:33: note: candidate: template<class T> llvm::iterator_range<llvm::idf_iterator<T> > llvm::inverse_depth_first(const T&)
 iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) {
                                 ^~~~~~~~~~~~~~~~~~~

, а второй дает

llvm-pass/Exploration/Exploration.cpp:37:43: error: no matching function for call to ‘idf_begin(llvm::BasicBlock&)’
         for (auto BB = idf_begin(*returnBB); BB != idf_end(*returnBB); BB++) {
                                           ^
In file included from llvm-pass/Exploration/Exploration.cpp:6:0:
/usr/local/include/llvm/ADT/DepthFirstIterator.h:265:17: note: candidate: template<class T> llvm::idf_iterator<T> llvm::idf_begin(const T&)
 idf_iterator<T> idf_begin(const T& G) {
                 ^~~~~~~~~
/usr/local/include/llvm/ADT/DepthFirstIterator.h:265:17: note:   substitution of deduced template arguments resulted in errors seen above
llvm-pass/Exploration/Exploration.cpp:37:69: error: no matching function for call to ‘idf_end(llvm::BasicBlock&)’
         for (auto BB = idf_begin(*returnBB); BB != idf_end(*returnBB); BB++) {
                                                                     ^

Я не знаю, как передать returnBB в обоих случаях, так что inverse_depth_first / idf_begin /idf_end не выдает ошибок при печати. ​​

...