8

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 ?

1 Answer 1

17

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  
Sign up to request clarification or add additional context in comments.

2 Comments

Works great, thanks ! Now i feel a little bit stupid, but really thanks you i was stucked on this for far too long :)
Thanks, saved me a lot of time!. Interestingly enough, I got the same problem when porting a pass from an old version of LLVM into 3.6.2, it seems that the old versions were ok without the wrappers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.