LLVM IRファイルを読み込む

はじめに

ファイルに出力されたLLVM IRをC++で読み込んで遊んでみます。

環境

$ clang++ --version
clang version 8.0.1-svn360950-1~exp1~20190517004233.70 (branches/release_80)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ llvm-config --cxxflags --ldflags --system-libs --libs core
-I/usr/lib/llvm-8/include -std=c++11  -fno-exceptions -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
-L/usr/lib/llvm-8/lib 
-lLLVM-8

LLVM IRファイルの読み込み

アプリケーションの引数にLLVM IRファイルパスを指定する想定です。

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>

int main(int argc, char** argv) {
    if (argc < 2) {
        llvm::errs() << "Expected an argument - IR file name\n";
        exit(1);
    }

    llvm::LLVMContext Context;
    llvm::SMDiagnostic Err;
    auto module = llvm::parseIRFile(argv[1], Err, Context);

    if (!module) {
        Err.print(argv[0], llvm::errs());
        return 1;
    }

    return 0;
}

llvm::parseIRFileに、ファイルパスを与えるだけで、llvm::Module (のunique_ptr) を得ることができます。

下のコマンドでLLVM IRファイルが読み込めます。

clang++ main.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -o ir_reader
./ir_reader main.ll

少し内部を覗く

main.llにはmain関数があり、いくつか命令があります。 そのオペコードを表示してみます。

次のようなコードで実現できました。

    auto func = module->getFunction("main");
    std::cout << "function name: " << func->getName().data() << std::endl;
    for (auto &bb: *func) {
        auto i = 0;
        for (auto &instr: bb) {
            std::cout << "%" << i << ": " << instr.getOpcodeName() << std::endl;
            i++;
        }
    }
$ ./ir_reader main.ll 
function name: main
%0: alloca
%1: bitcast
%2: call
%3: getelementptr
%4: load
%5: call
%6: ret

お手軽ですね!