LLVM中的FunctionPass中的LoopInfo无法编译

8

我开始学习LLVM API,并写了我的第一个Pass。我的目标是打印函数之间的调用关系。

最近,我想在显示上添加一些循环信息,以查看一个函数是否可以被多次调用。但是当我尝试使用LoopInfo时,我遇到了这个编译错误:

llvm[0]: Compiling cfg.cpp for Debug+Asserts build (PIC)
In file included from cfg.cpp:19:
In file included from /home/llvm-lab/llvm/include/llvm/Pass.h:378:
  /home/llvm-lab/llvm/include/llvm/PassAnalysisSupport.h:56:37: error:
        no member named 'ID' in 'llvm::LoopInfo'
      return addRequiredID(PassClass::ID);
                                  ^
cfg.cpp:33:10: note: in instantiation of function template
      specialization 'llvm::AnalysisUsage::addRequired<llvm::LoopInfo>'
      requested here
      AU.addRequired<LoopInfo>();
         ^
1 error generated.

这是我的代码:

#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "iostream"
#include "llvm/Pass.h"
#include "llvm/IR/InstIterator.h"
#include <llvm/IR/Instructions.h>
#include <llvm/Analysis/LoopInfo.h>

using namespace llvm;


namespace {
  struct CFG : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    CFG() : FunctionPass(ID) {}

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.addRequired<LoopInfo>();
    }

    bool runOnFunction(Function &F) override {
      errs().write_escaped(F.getName());

      errs() << " : ";

      for( Function::iterator b = F.begin() , be = F.end(); b != be; ++b){
        errs() << "\n\t BB : ";
        LoopInfo *loop = new LoopInfo();
        bool isLoop = loop->getLoopFor(b);
        if(isLoop){
          errs() << "loop{";
        }
        for(BasicBlock::iterator i = b->begin() , ie = b->end(); i!=ie; ++i){
          if( isa<CallInst>(&(*i)) || isa<InvokeInst>(&(*i))){
            errs() << cast<CallInst>(&(*i))->getCalledFunction()->getName() << "\t";
          }
        }
        if(isLoop){
          errs() << "}";
        }
     }

     errs() << '\n';
     return false;
   }



  };
}

char CFG::ID = 0;
static RegisterPass<CFG> X("CFG", "Gen CFG",true ,true);

我在任何地方都找不到关于“llvm::LoopInfo中没有名为'ID'的成员”的参考错误,有人知道出了什么问题吗?

1个回答

17

为什么你的代码无法构建

AU.addRequired<typename passclass>()需要一个LLMV::Pass类型,但你传入的是LoopInfo,它只是用于循环信息维护的LLVM内部类。它没有ID字段。

应该使用LoopInfoWrapperPass

如果你想获取循环信息,请尝试将其更改为AU.addRequired<LoopInfoWrapperPass>,如LLVM编写新Pass文档中所示。 LoopInfoWrapperPass用于生成LoopInfo

LoopInfo应从pass中获取

你的代码还存在一个问题,即如何获取LoopInfo,你试图使用new创建一个LoopInfo,但你得到的将是一个空的LoopInfo

针对你问题的“应该工作”的代码

以下是修改后的代码,可以输出预期的信息。

#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "iostream"
#include "llvm/Pass.h"
#include "llvm/IR/InstIterator.h"
#include <llvm/IR/Instructions.h>
#include <llvm/Analysis/LoopInfo.h>


using namespace llvm;


namespace {
  struct CFG : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    CFG() : FunctionPass(ID) {}

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.setPreservesCFG();
      AU.addRequired<LoopInfoWrapperPass>();
    }
    bool runOnFunction(Function &F) override {
      LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
      errs().write_escaped(F.getName());
      errs() << " : ";
      for( Function::iterator b = F.begin() , be = F.end(); b != be; ++b){
        errs() << "\n\t BB : ";
        bool isLoop = LI.getLoopFor(b);
        if(isLoop){ 
          errs() << "loop{";
        }
        for(BasicBlock::iterator i = b->begin() , ie = b->end(); i!=ie; ++i){
          if( isa<CallInst>(&(*i)) || isa<InvokeInst>(&(*i))){
            errs() << cast<CallInst>(&(*i))->getCalledFunction()->getName() << "\t";
          }
        }
        if(isLoop){ 
          errs() << "}";
        }
     }
     errs() << '\n';
     return false;
   }
  };
}

char CFG::ID = 0;
static RegisterPass<CFG> X("CFG", "Gen CFG",true ,true);

以下代码可供LLVM的opt使用:

#include <stdio.h>

#define ARRAY_SIZE 100

int foo(int* a , int n) {
  int i;
  int sum = 0;
  for (; i < n; i++) {
    sum += a[i];
  }
  return sum;
}


int main() {
  int a[ARRAY_SIZE] = {1};

  int sum = foo(a, ARRAY_SIZE);

  printf("sum:0x%x\n", sum);
  return 0;
}

输出将会是:
foo : 
     BB : 
     BB : loop{}
     BB : loop{}
     BB : loop{}
     BB : 
main : 
     BB : llvm.memset.p0i8.i64  foo printf  

非常好,谢谢!现在我感觉有点傻,但真的非常感谢你,我卡在这个问题上太久了 :) - islandia
谢谢,省了我很多时间!有趣的是,当我将一个旧版本的LLVM移植到3.6.2时,我遇到了同样的问题,似乎旧版本没有包装器也可以正常工作。 - Leeor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接