LoginSignup
6
3

More than 5 years have passed since last update.

[メモ] LLVM

Last updated at Posted at 2016-11-28
  • 自分のメモも兼ねて、LLVMのAPI(C++)についてまとめていきます。
  • LLVM 3.5 での話です(古い
  • 順次更新中

コンパイル

  • Ubuntu, Debian の場合はapt-getで以下を実行 (コンパイルするだけならoptとかいらないかな)
$ apt-get install clang-3.5 clang-3.5-doc libclang-common-3.5-dev libclang-3.5-dev libclang1-3.5 libclang1-3.5-dbg libllvm3.5v5 libllvm3.5-dbg lldb-3.5 llvm-3.5 llvm-3.5-dev llvm-3.5-doc llvm-3.5-examples llvm-3.5-runtime clang-modernize-3.5 clang-format-3.5 python-clang-3.5 lldb-3.5-dev opt libedit-dev
  • source.cpp をコンパイル (llvm-config のオプションは適当)
$ clang++-3.5 source.cpp -o source -std=c++11 `llvm-config-3.5 --system-libs --cppflags --ldflags --libs all`

関数生成

  • こんな感じの、特に何もしない関数を作っていきます
int func(char *s) {
  return 0;
}

プロトタイプ

  • 戻り値がint, 引数が char *funcという名前の関数のプロトタイプを作る
#include "llvm/Analysis/Passes.h"
#include "llvm/IR/Verifier.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/PassManager.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

llvm::LLVMContext &context(llvm::getGlobalContext());
llvm::IRBuilder<> builder(context);
llvm::Module *mod;


int main() {
  // Moduleを作る
  mod = new llvm::Module("sample", context);

  // 関数の名前
  std::string func_name = "func";
  // 戻り値の型
  llvm::Type *func_ret_type = builder.getInt32Ty();
  // 引数の型
  std::vector<llvm::Type *> func_args_type;
  func_args_type.push_back(builder.getInt8Ty()->getPointerTo());

  llvm::FunctionType *llvm_func_type =
    llvm::FunctionType::get(func_ret_type, func_args_type, /*可変長引数=*/false);
  llvm::Function *llvm_func = llvm::Function::Create(llvm_func_type, llvm::Function::ExternalLinkage, func_name, mod);

  llvm_func->dump(); // 作った関数を表示 (LLVM-IR)
}
  • ちょっと補足
  • builder.getXXX で型を得られますが
builder.getInt8Ty()
builder.getInt16Ty()
builder.getIntNTy()
  • とか、ある程度規則的に名前が付いているのでわかりやすいと思います
  • あと、getPointerTo はその名の通り、その型のポインタを得られるようです
  • 8ビットの整数に限り、(多分よく使うから)getInt8PtrTy()ってのも用意されてます
// int *
builder.getInt32Ty()->getPointerTo()
// char **
builder.getInt8Ty()->getPointerTo()->getPointerTo()
builder.getInt8PtrTy()->getPointerTo()

本体

  • 次に、関数の本体を作る
  • 特に何もしないで、0を返してみます
  • create_func_bodyという関数を作ってその中で処理させましょうか
// 省略
void create_func_body(llvm::Function *llvm_func) {
  llvm::BasicBlock *entry = llvm::BasicBlock::Create(
      context, 
      "entry", // BasicBlockの名前 
      llvm_func);
  builder.SetInsertPoint(entry); // entryの開始
  builder.CreateRet( // return
      llvm::ConstantInt::get(builder.getInt32Ty(), 0, true) // i32 0
      );
}
  • 一つのBasicBlockに、一つの return があります。voidを返す?関数ならCreateRetVoidを使います
6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3