#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 << "
"; // 2
return 0;
}
注:
- LLVM的block不像汇编的label,必须要跳转才能进入这个block块
- 如果注释掉
b.CreateBr(BB2);
程序则会报错,"add"函数必须要有一个i32的返回值