Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
549 views
in Technique[技术] by (71.8m points)

static analysis - How to write a custom intermodular pass in LLVM?

I've written a standard Analysis pass in LLVM, by extending the FunctionPass class. Everything seems to make sense.

Now what I'd like to do is write a couple of intermodular passes, that is, passes that allows me to analyze more than one module at a time. The purpose of one such pass is to construct a call graph of the entire application. The purpose of the other such pass is that I have an idea for an optimization involving function calls and their parameters.

I know about interprocedural passes in LLVM, via extending the ModulePass class, but that only allows analysis within a single module.

I know about link time optimization (LTO) in LLVM, but (a) I'm not quite clear if this is what I want and (b) I've found no examples or documentation on how to actually write an LTO pass.

How can I write an intermodular pass, i.e., a pass that has access to all the modules in an application, in LLVM?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I found one way to achieve my goal: write a simple program that uses llvm::parseBitcodeFile() to read in a bitcode file and create a Module object that can be traversed and analyzed. It's not ideal, because it's not a Pass that can be run within the LLVM framework. However, it is a way to achieve my goal of analyzing multiple modules at once.

For future readers, here's what I did.

Create a simple tool to read in a bitcode file and produce a Module

//ReadBitcode.cpp
#include <iostream>
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Bitcode/ReaderWriter.h"

using namespace llvm;

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cerr << "Usage: " << argv[0] << " bitcode_filename" << std::endl;
        return 1;
    }
    StringRef filename = argv[1];
    LLVMContext context;

    ErrorOr<std::unique_ptr<MemoryBuffer>> fileOrErr = MemoryBuffer::getFileOrSTDIN(filename);
    if (std::error_code ec = fileOrErr.getError())
    {
        std::cerr << "Error opening input file: " + ec.message() << std::endl;
        return 2;
    }

    ErrorOr<llvm::Module *> moduleOrErr = parseBitcodeFile(fileOrErr.get()->getMemBufferRef(), context);
    if (std::error_code ec = fileOrErr.getError())
    {
        std::cerr << "Error reading Module: " + ec.message() << std::endl;
        return 3;
    }

    Module *m = moduleOrErr.get();
    std::cout << "Successfully read Module:" << std::endl;
    std::cout << " Name: " << m->getName().str() << std::endl;
    std::cout << " Target triple: " << m->getTargetTriple() << std::endl;

    for (auto iter1 = m->getFunctionList().begin(); iter1 != m->getFunctionList().end(); iter1++)
    {
        Function &f = *iter1;
        std::cout << "  Function: " << f.getName().str() << std::endl;
        for (auto iter2 = f.getBasicBlockList().begin(); iter2 != f.getBasicBlockList().end();
             iter2++)
        {
            BasicBlock &bb = *iter2;
            std::cout << "    BasicBlock: " << bb.getName().str() << std::endl;
            for (auto iter3 = bb.begin(); iter3 != bb.end(); iter3++)
            {
                Instruction &i = *iter3;
                std::cout << "      Instruction: " << i.getOpcodeName() << std::endl;
            }
        }
    }
    return 0;
}

Compile the tool

$ clang++ ReadBitcode.cpp -o reader `llvm-config --cxxflags --libs --ldflags --system-libs`

Create a bitcode file to analyze

$ cat foo.c 
int my_fun(int arg1){
    int x = arg1;
    return x+1;
}

int main(){
    int a = 11;
    int b = 22;
    int c = 33;
    int d = 44;
    if (a > 10){
        b = c;
    } else {
        b = my_fun(d);
    }
    return b;
}

$ clang -emit-llvm -o foo.bc -c foo.c

Run the reader tool on the bitcode

$ ./reader foo.bc
Successfully read Module:
 Name: foo.bc
 Target triple: x86_64-pc-linux-gnu
  Function: my_fun
    BasicBlock: 
      Instruction: alloca
      Instruction: alloca
      Instruction: store
      Instruction: load
      Instruction: store
      Instruction: load
      Instruction: add
      Instruction: ret
  Function: main
    BasicBlock: 
      Instruction: alloca
      Instruction: alloca
      Instruction: alloca
      Instruction: alloca
      Instruction: alloca
      Instruction: store
      Instruction: store
      Instruction: store
      Instruction: store
      Instruction: store
      Instruction: load
      Instruction: icmp
      Instruction: br
    BasicBlock: 
      Instruction: load
      Instruction: store
      Instruction: br
    BasicBlock: 
      Instruction: load
      Instruction: call
      Instruction: store
      Instruction: br
    BasicBlock: 
      Instruction: load
      Instruction: ret

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...