Question

I am learning how to write passes in llvm. I am trying to implement

virtual void emitFunctionAnnot(const Function *, formatted_raw_ostream &){}

as given at http://llvm.org/doxygen/AssemblyAnnotationWriter_8h_source.html to print #[uses]=1 before start of a function.

The code below works if I manually call emitFunctionAnnot(&F, ferrs()); inside runOnFunction() method, which(emitFunctionAnnot) I have overridden. However shouldn't it work without calling it manullay because that's the whole point of overriding it. I believe I am doing something wrong while overriding. I have spent countless hours trying to debug it. I would appreciate any help.

This is what I have so far.

#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/IR/Instruction.h"
#include "llvm/DebugInfo.h"
#include "llvm/Assembly/AssemblyAnnotationWriter.h"


#include <ostream>
#include <fstream>
#include <iostream>
#include <stdlib.h>

using namespace llvm;

namespace {


class CommentWriter : public AssemblyAnnotationWriter {
public:
 virtual void emitFunctionAnnot(const Function *F,
                         formatted_raw_ostream &OS) {
    OS << "; [#uses=" << F->getNumUses() << ']';  // Output # uses
    OS << '\n';
  }

};

class FunctionInfo : public FunctionPass, public AssemblyAnnotationWriter{

public:
  static char ID;
  FunctionInfo() : FunctionPass(ID) {}

 void emitFunctionAnnot(const Function *F, formatted_raw_ostream &OS) {
    errs() << "CALLED";
    OS << "; [#uses=" << F->getNumUses() << ']';  // Output # uses
    OS << '\n';
  }


  virtual bool runOnFunction(Function &F) {

//  emitFunctionAnnot(&F, ferrs());
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I){
      Instruction &II = *I;
      errs() << *I;

    }
    return false;
  }


  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};


char FunctionInfo::ID = 0;

//    clang -c -Xclang -load -Xclang ./FunctionInfo.so loop.c
static void registerMyPass(const PassManagerBuilder &,
                           PassManagerBase &PM) {
    PM.add(new FunctionInfo());
}
RegisterStandardPasses
    RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible,
                   registerMyPass);

    RegisterPass<FunctionInfo> X("function-info", "Function Information");

    }
Was it helpful?

Solution

Annotations exist only as comments in an LLVM IR printout. They are not actually a part of the IR, and consequently they are not something you "add" in a pass.

The way to use an AssemblyAnnotationWriter is to pass it as the 2nd argument to a print function (e.g. Module::print). You can do that inside a pass, but it's not something that is done automatically for you. Specifically, making the pass inherit from AssemblyAnnotationWriter is nonsensical - the first approach you've shown in your question, inheriting from it in a separate class, is the correct approach.

In short, if you want a printout of the module in your pass, call print on it. If you want to add comments to the printout, call the same print but pass an instance of your CommentWriter as the 2nd argument.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top