Search code examples
llvmllvm-clang

LLVM LoopInfo in FunctionPass doesn't compile


i'm starting to learn llvm api and i wrote my first pass. My goal is to print how functions call each others.

Lately i wanted to add some loop information to the display to look if a function can be call several time or not. But when i try to use LoopInfo i got this compilation error :

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.

Here is my code :

#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);

I can't find any reference to an "no member named 'ID' in 'llvm::LoopInfo'" error anywhere, does anyone have an idea about what's is wrong here ?


Solution

  • Why your code could not be build

    AU.addRequired<typename passclass>() need a type of LLMV::Pass, however what you pass in is LoopInfo, which is just an LLVM internal class for loop information maintenance. It does not has a field ID.

    LoopInfoWrapperPass should be used instead

    If you want to get the loop information. Try to change it to AU.addRequired<LoopInfoWrapperPass> as shown in the LLVM Write a new Pass document. LoopInfoWrapperPass is used to generate LoopInfo.

    LoopInfo should be get from the pass

    There is also a problem in your code about how to get the LoopInfo, you are trying to use new to create a LoopInfo, what you get will be an empty LoopInfo.

    The "should work" code for your question

    Following is a modified version of your code, which could printout expected informations.

    #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);
    

    For the following code feed to 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;
    }
    

    The output will be:

    foo : 
         BB : 
         BB : loop{}
         BB : loop{}
         BB : loop{}
         BB : 
    main : 
         BB : llvm.memset.p0i8.i64  foo printf