2014-01-19 3 views
1

Я учусь писать пропуски в llvm. Я пытаюсь реализоватьКак реализовать AssemblyAnnotationWriter для печати метаданных

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

, как указано в http://llvm.org/doxygen/AssemblyAnnotationWriter_8h_source.html для печати #[uses]=1 перед началом функции.

Код ниже работает, если я вручную вызываю emitFunctionAnnot(&F, ferrs()); внутри метода runOnFunction(), который (emitFunctionAnnot) Я переопределил. Однако он не должен работать, не называя его manullay, потому что это все, что его переопределяет. Я считаю, что я делаю что-то неправильно, переопределяя. Я потратил бесчисленные часы, пытаясь отладить его. Буду признателен за любую помощь.

Это то, что у меня есть до сих пор.

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

    } 

ответ

0

Аннотации существуют только в качестве комментариев в распечатке IR LLVM. На самом деле они не являются частью IR, и, следовательно, они не являются чем-то, что вы «добавляете» в пас.

Способ использования AssemblyAnnotationWriter состоит в передаче его в качестве второго аргумента функции print (например, Module::print). Вы можете сделать это внутри прохода, но это не то, что делается автоматически для вас. В частности, сделать проход наследованием от AssemblyAnnotationWriter бессмыслен - первый подход, который вы указали в своем вопросе, наследующий его в отдельном классе, является правильным подходом.

Короче говоря, если вы хотите распечатать модуль в своем проходе, позвоните на него print. Если вы хотите добавить комментарии к распечатке, вызовите то же самое print, но передайте экземпляр вашего CommentWriter в качестве второго аргумента.