llvm 创建函数

Posted Ajanuw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了llvm 创建函数相关的知识,希望对你有一定的参考价值。

IR:

define i32 @add1(i32 %p1) {
entry:
  %retVal = add i32 1, %p1
  ret i32 %retVal
}
#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() {
  // context 拥有许多核心的 LLVM 数据结构,例如类型和常量值表
  auto Context = std::make_unique<LLVMContext>();

  // module 包含函数和全局变量的LLVM构造,它是 LLVM IR 用来包含代码的顶级结构。它将拥有我们生成的所有 IR 的内存
  auto M = std::make_unique<Module>("test", *Context);

  // 创建一个构建器,可以轻松生成 LLVM 指令
  IRBuilder<> builder(*Context);

  // 声明一个函数 int add1(int) 添加到module中
  auto funcType = FunctionType::get(Type::getInt32Ty(*Context), { Type::getInt32Ty(*Context) }, false);
  Function* Add1F = Function::Create(funcType, Function::ExternalLinkage, "add1", M.get());

  // 创建一个block添加到Add1F
  BasicBlock* BB = BasicBlock::Create(*Context, "entry", Add1F);
  
  // 构建器接下来的指令将插入到BB
  builder.SetInsertPoint(BB);

  // 获取指向常量“1”的指针
  Value* One = builder.getInt32(1);

  // 获取指向 add1 函数的整数参数的指针
  assert(Add1F->arg_size() == 1);        // 确保有一个 arg
  Argument* p1 = Add1F->getArg(0);   // 获取参数
  p1->setName("p1"); // 设置arg name, int add1(int p1);

  // 创建 add 指令,将其插入到 BB
  // 创建返回指令并将其添加到基本块
  builder.CreateRet(builder.CreateAdd(One, p1, "retVal")); // ret 1 + p1
  
  // 打印出所有生成的代码
  M->print(errs(), nullptr);

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

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

  // Create an LLJIT instance.
  auto _jit = ExitOnErr(LLJITBuilder().create());
  auto M = createTSM();
  
  ExitOnErr(_jit->addIRModule(std::move(M)));

  // 查找 JIT 函数,将其转换为函数指针,然后调用它.
  auto Add1Sym = ExitOnErr(_jit->lookup("add1"));
  int (*Add1)(int) = (int (*)(int))Add1Sym.getAddress();
  int Result = Add1(42);
  outs() << "add1(42) = " << Result << "\\n";

  return 0;
}

以上是关于llvm 创建函数的主要内容,如果未能解决你的问题,请参考以下文章

如何创建 LLVM 结构值?

如何使用 Clang 在 C 程序中嵌入 LLVM 程序集或内在函数?

如何禁用 LLVM 中的优化

使用 LLVM 创建本地字符串

编译器似乎没有找到类 llvm::Instruction 的成员函数

使用 LLVM C API 生成对内部函数的调用