LLVM与C++代码的相互调用(全注释)

1 篇文章 0 订阅

一、在C++中调用LLVM编写的IR函数

#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/JIT.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/CodeGen/MachineCodeInfo.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/DerivedTypes.h"
#include <iostream>
/*
      务必使用llvm-3.3
*/
using namespace llvm;
using namespace std;
int main()
{
    int x = 9;
    // 获取LLVM上下文
    LLVMContext &context = llvm::getGlobalContext();
    //获取LLVM Module,Module类似于一个完整的.cc文件
    Module *module = new Module("test", context);
    //获取一个函数,如果这个函数已经声明,获取相应的函数指针,如果没有,声明
    Function *f = cast<Function>(module->getOrInsertFunction("foo", Type::getInt32Ty(context),
                                                             Type::getInt32Ty(context), NULL));
    //创建一个代码块,这个代码块是之前声明的函数foo的。代码块就是C++中的 {}
    BasicBlock *BB = BasicBlock::Create(context, "entryBar", f);
    //创建LLVM Builder,Builder的作用就是辅助完成IR代码,这个builder用于在代码块BB中完成IR
    IRBuilder<> builder(BB);
    //下面是foo中的主要逻辑:int ret=x;return ret;
    Value *ret = builder.getInt32(x);
    builder.CreateRet(ret);
    //这行代码的作用是引入初始化native,JIT会将IR编译成当前主机可以运行的二进制代码,而native中包含了当前主机的操作系统信息
    InitializeNativeTarget();
    //创建执行JIT引擎,并将IR代码放入,也就是放入module(因为IR代码都在其中)
    ExecutionEngine *ee = EngineBuilder(module).setEngineKind(EngineKind::JIT).create();
    //从执行引擎中获取相应的函数指针,JIT即时编译器后我们之前写的IR函数可以通过函数指针获取
    void *barAddr = ee->getPointerToFunction(f);
    //将函数指针进行强转
    typedef int32_t (*FuncType)(int32_t);
    FuncType barFunc = (FuncType)barAddr;
    //正式调用经由JIT编译后的IR函数
    int64_t n = 9;
    cout << barFunc(n) << endl;
    return 0;
}

二、在LLVM编写的IR函数中调用C++代码

#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/JIT.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/CodeGen/MachineCodeInfo.h"
#include "llvm/Analysis/Verifier.h"
#include <iostream>

using namespace llvm;

/*
    务必使用llvm-3.3
*/
int foo(int x)
{
    return 2 * x;
}

int value = 10;

int main()
{
    LLVMContext &context = llvm::getGlobalContext();
    Module *module = new Module("test", context);

    //在IR代码中声明一个全局变量
    GlobalVariable *v = cast<GlobalVariable>(module->getOrInsertGlobal("value", Type::getInt32Ty(context)));
    //在IR中声明一个函数,注意我们并不会在IR中定义foo,我们会将这个IR中声明的函数映射到C++代码中的函数
    Function *f = cast<Function>(module->getOrInsertFunction("foo", Type::getInt32Ty(context),
                                                             Type::getInt32Ty(context), NULL));

    //在IR中声明一个函数bar,我们会用IR定义这个函数
    Function *bar = cast<Function>(module->getOrInsertFunction("bar", Type::getInt32Ty(context), NULL));

    //创建函数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();
    ExecutionEngine *ee = EngineBuilder(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;

    std::cout << barFunc() << std::endl;
    return 0;
}

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是一个简单的C++代码示例,使用LLVM框架中的API生成系统调用IR: ```c++ #include <llvm/IR/LLVMContext.h> #include <llvm/IR/Module.h> #include <llvm/IR/IRBuilder.h> using namespace llvm; int main() { LLVMContext context; Module module("syscall_module", context); IRBuilder<> builder(context); // Define the function signature Type *syscall_args[] = {builder.getInt64Ty(), builder.getInt64PtrTy()}; FunctionType *syscall_type = FunctionType::get(builder.getInt64Ty(), syscall_args, false); // Declare the function in the module Function *syscall_func = Function::Create(syscall_type, Function::ExternalLinkage, "syscall", &module); // Create a basic block to contain the instructions BasicBlock *entry = BasicBlock::Create(context, "entry", syscall_func); // Add instructions to the basic block Value *syscall_num = builder.getInt64(1); Value *syscall_args_ptr = builder.getInt64PtrTy()->getPointerTo(builder.getInt64(0)); Value *syscall_result = builder.CreateCall(syscall_func, {syscall_num, syscall_args_ptr}); // Add return instruction to the basic block builder.CreateRet(syscall_result); // Print the IR code to stdout module.print(outs(), nullptr); return 0; } ``` 该代码创建了一个名为`syscall_module`的LLVM模块,并在其中声明了一个名为`syscall`的外部函数。接下来,它创建了一个名为`entry`的基本块,并在其中添加了一个调用`syscall`函数的指令,该指令传递了系统调用号和参数指针。最后,它添加了一个`ret`指令,将系统调用结果作为函数返回值。 输出的IR代码类似于以下内容: ``` ; ModuleID = 'syscall_module' source_filename = "syscall_module" define i64 @syscall(i64, i64*) { entry: %0 = call i64 @syscall(i64 1, i64* null) ret i64 %0 } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值