Я пишу свой первый проход 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
не выдает ошибок при печати.