#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/IR/TypeBuilder.h"
#include <iostream>
using namespace llvm;
int foo(int x)
{
return 2 * x;
}
int value = 10;
int main()
{
static LLVMContext MyGlobalContext;
LLVMContext &context = MyGlobalContext;
Module *module = new Module("test", context);
// 在IR代码中声明一个全局变量`
GlobalVariable *v = cast<GlobalVariable>(
module->getOrInsertGlobal("value", Type::getInt32Ty(context)));
// 在IR中声明一个函数,注意我们并不会在IR中定义foo,我们会将这个IR中声明的函数映射到C++代码中的函数
FunctionType *foo_type =
TypeBuilder<int(int), false>::get(context);
Function *f = cast<Function>(
module->getOrInsertFunction("foo", foo_type));
// 在IR中声明一个函数bar,我们会用IR定义这个函数
FunctionType *bar_type =
TypeBuilder<int(), false>::get(context);
Function *bar = cast<Function>(
module->getOrInsertFunction("bar", bar_type));
// 创建函数bar的代码块
BasicBlock *entry = BasicBlock::Create(context, "entry", bar);
IRBuilder<> builder(entry);
// 用一个局部变量获取全局变量v的值
Value *v_IR = builder.CreateLoad(v);
// 调用函数foo
Value *ret = builder.CreateCall(f, v_IR);
// 返回值
builder.CreateRet(ret);
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();
ExecutionEngine *ee =
EngineBuilder(std::unique_ptr<Module>(module)).setEngineKind(EngineKind::JIT).create();
// 将外部的C++代码中的全局变量映射到IR代码中,IR代码中只有声明
ee->addGlobalMapping(v, &value);
// 将外部的C++代码中的全局函数映射到IR代码中,IR代码中只有声明
ee->addGlobalMapping(f, (void *)foo);
void *barAddr = ee->getPointerToFunction(bar);
typedef int (*FuncType)();
FuncType barFunc = (FuncType)barAddr;
ee->finalizeObject();
std::cout << barFunc() << std::endl;
return 0;
}
编译:
clang++ -O3 ./main.cpp -o test -I/usr/include/llvm-6.0 -I/usr/include/llvm-c-6.0 `llvm-config-6.0 --cxxflags --ldflags --libs --libfiles --system-libs`