llvm block

#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;
using namespace llvm::orc;

ExitOnError ExitOnErr;

ThreadSafeModule createTSM() {
  auto ctx = std::make_unique<LLVMContext>();
  auto M = std::make_unique<Module>("test", *ctx);
  IRBuilder<> b(*ctx);

  auto FT = FunctionType::get(Type::getInt32Ty(*ctx), { }, false);
  Function* AddF = Function::Create(FT, Function::ExternalLinkage, "add", M.get());
  
  // block 1
  auto BB1 = BasicBlock::Create(*ctx, "BB1", AddF);
  // 之后由builder生成的IR都将插入到BB1块中
  b.SetInsertPoint(BB1);
  
  // 创建一个变量
  auto r = b.CreateAlloca(Type::getInt32Ty(*ctx), 0, "r");

  // r = 2
  b.CreateStore(b.getInt32(2), r);
  
  // block 2
  auto BB2 = BasicBlock::Create(*ctx, "BB2", AddF);

  // 无条件从当前的b1跳到b2
  b.CreateBr(BB2);

  b.SetInsertPoint(BB2);
  b.CreateRet(b.CreateLoad(r));

  // 打印出所有生成的代码
  M->print(errs(), nullptr);

  // 返回线程模块
  return ThreadSafeModule(std::move(M), std::move(ctx));
}

int main() {
  InitializeNativeTarget();
  InitializeNativeTargetAsmPrinter();

  auto _jit = ExitOnErr(LLJITBuilder().create());
  auto M = createTSM();

  ExitOnErr(_jit->addIRModule(std::move(M)));

  auto AddSym = ExitOnErr(_jit->lookup("add"));
  int (*Add)() = (int (*)())AddSym.getAddress();
  int Result = Add();
  outs() << "add() = " << Result << "\n"; // 2

  return 0;
}

注:

  • LLVM的block不像汇编的label,必须要跳转才能进入这个block块
  • 如果注释掉b.CreateBr(BB2);程序则会报错,"add"函数必须要有一个i32的返回值
posted @ 2021-06-07 15:34  Ajanuw  阅读(152)  评论(0编辑  收藏  举报