IR API(一)——使用LLVM提供的C接口和IRBuilder来生成LLVM IR(if 和 while 语句)

本文详细介绍如何使用 LLVM 的 API 来实现 C 语言中的 if 和 while 语句,包括函数声明、参数传递、基本块创建、条件判断和循环控制等关键步骤,并提供完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可以转载,请注明出处!

练习一、写一个if语句

对应C的伪代码:

int main(){
	a = 10;
	b = 20;
	return max(a, b);
}

int max(int a, int b){
	if(a > b)
		return a;
	else
		return b;
}

API代码:

#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 main(){
	static LLVMContext MyGlobalContext;
    LLVMContext &context = MyGlobalContext;
	
	//创建一个module
	Module *module = new Module("test", context);
	
	//声明一个函数-----------------------------------
	SmallVector<Type *, 2> functionArgs;
    //各种类型都是通过get方法来构造对应的实例
    functionArgs.push_back(Type::getInt32Ty(context)); //32为整型参数Tina及到vector数组中
    functionArgs.push_back(Type::getInt32Ty(context));
	Type *returnType = Type::getInt32Ty(context);//返回值类型
	FunctionType *max_type = FunctionType::get(returnType, functionArgs, /*isVarArg*/ false);
	
	//构建函数签名,包括返回类型和参数,这种方式有些特殊有些特殊,到/usr/local/include/llvm/IR目录下看TypeBuilder.h源码就知道了
	//下面这种构建函数类型的方式和上面的选一个就可以了,很显然下面这种可以用C++的类型,方便很多,语法也很简单,长得也好看
	//FunctionType *max_type = TypeBuilder<int(int, int), false>::get(context);

	//声明 int max(int,a int b); 函数
	//cast将指针或者引用从基类转向为派生类,可以从http://llvm.org/docs/ProgrammersManual.html#the-c-standard-template-library这个链接学习
	Function *max_fun = cast<Function>(module->getOrInsertFunction("max", max_type));//将函数插入module
	//-----------------------------------------------
	
	//函数体-----------------------------------------------
	//存储参数(获取参数的引用)
	Function::arg_iterator argsIT = max_fun->arg_begin();//Function中的一个方法,获取参数的迭代器
	Value *arg_a = argsIT++;//获取第一个参数
	arg_a->setName("a");//设置第一个参数名为a
	Value *arg_b = argsIT++;
	arg_b->setName("b");
	
	//创建max函数的entry代码块
	BasicBlock *entry_max = BasicBlock::Create(context, "entry", max_fun);
	IRBuilder<> builder_max(entry_max);//创建builder实例,每个basicblock对应一个irbulider

	//比较arg_a和arg_b的大小
	Value *cmp_value = builder_max.CreateICmpSGT(arg_a, arg_b);
	
	//创建一个if.then代码块
	BasicBlock *if_then = BasicBlock::Create(context, "if_then", max_fun);
	IRBuilder<> builder_then(if_then);
	
	//创建一个if.else代码块
	BasicBlock *if_else = BasicBlock::Create(context, "if_else", max_fun);
	IRBuilder<> builder_else(if_else);
	
	//根据cmp的值跳转,也就是if条件
	builder_max.CreateCondBr(cmp_value, if_then, if_else);
	
	//创建返回值
	builder_then.CreateRet(arg_a);
	builder_else.CreateRet(arg_b);
	//-----------------------------------------------------
	
	//声明 int main() 函数----------------------------------
	FunctionType *main_type = TypeBuilder<int(), false>::get(context);
	Function *main_fun = cast<Function>(module->getOrInsertFunction("main", main_type));
	
	//创建main函数的entry代码块
	BasicBlock *entry_mian = BasicBlock::Create(context, "entry", main_fun);
	IRBuilder<> builder_main(entry_mian);
	
	//创建一个i32常量
	Value *a_value = ConstantInt::get(Type::getInt32Ty(context), -10);
	Value *b_value = ConstantInt::get(Type::getInt32Ty(context),20);
	
	//构造实参列表
	std::vector<Value*> putsargs;
	putsargs.push_back(a_value);
	putsargs.push_back(b_value);
	ArrayRef<Value*>  argsRef(putsargs);
	
	// 调用函数max
	Value *ret = builder_main.CreateCall(max_fun, argsRef);
	
	//创建返回值
	builder_main.CreateRet(ret);
	//----------------------------------------------------
	
    module->dump();
	
	//使用JIT引擎---------------------------------------
	//https://blog.csdn.net/xfxyy_sxfancy/article/details/50485090
	InitializeNativeTarget();
    InitializeNativeTargetAsmPrinter();
    InitializeNativeTargetAsmParser();
	
	//创建ExecutionEngine
	ExecutionEngine *ee = EngineBuilder(std::unique_ptr<Module>(module)).setEngineKind(EngineKind::JIT).create();
	
	//生成机器指令
    void *mainAddr = ee->getPointerToFunction(main_fun);
	
	//运行机器指令
    typedef int (*FuncType)();
    FuncType mianFunc = (FuncType)mainAddr;//使用类型转换将mainAddr转换成一个函数mianFunc,然后调用
    ee->finalizeObject();
    std::cout << mianFunc() << std::endl;
    //---------------------------------------------------
	
	delete module ;
    return 0;
}

使用下面命令可以生成IR,其余的demo都一样,后面不再写:

clang++ -O3 main.cpp -o main `llvm-config --cflags --ldflags` `llvm-config --libs` `llvm-config --system-libs`

用API生成的IR代码:

; ModuleID = 'test'
source_filename = "test"

define i32 @max(i32 %a, i32 %b) {
entry:
  %0 = icmp sgt i32 %a, %b
  br i1 %0, label %if_then, label %if_else

if_then:                                          ; preds = %entry
  ret i32 %a

if_else:                                          ; preds = %entry
  ret i32 %b
}

define i32 @main() {
entry:
  %0 = call i32 @max(i32 -10, i32 20)
  ret i32 %0
}

练习二、写一个while语句

对应C的伪代码:

int main(){
	int n = 10;
	return sum(n);
}

int sum(int n){
	int i = 0;
	int sum = 0;
	while(i <= n){
		sum = sum + i;
		i++;
	}
	return sum;
}

API代码:

#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 main(){
	static LLVMContext MyGlobalContext;
    LLVMContext &context = MyGlobalContext;
	
	//创建一个module
	Module *module = new Module("test", context);
	IRBuilder<> builder(context);
	
	//-------------------------------------------------------------------------------------
	//声明 int sum(int,n); 函数
	FunctionType *sum_type = TypeBuilder<int(int), false>::get(context);//构建函数签名,包括返回类型和参数
	Function *sum_fun = cast<Function>(module->getOrInsertFunction("sum", sum_type));//将函数插入module
	
	//存储参数(获取参数的引用)
	Function::arg_iterator argsIT = sum_fun->arg_begin();//Function中的一个方法,获取参数的迭代器
	Value *arg_n = argsIT++;//获取第一个参数
	arg_n->setName("n");//设置第一个参数名为a
	
	//创建两个常量值
	Value *con_0 = ConstantInt::get(IntegerType::getInt32Ty(context), 0);
	Value *con_1 = ConstantInt::get(IntegerType::getInt32Ty(context), 1);
	
	//创建max函数的entry代码块
	BasicBlock *entry_sum = BasicBlock::Create(context, "entry", sum_fun);
	builder.SetInsertPoint(entry_sum);
	
	//创建循环使用到的三个代码块
	BasicBlock *while_count = BasicBlock::Create(context, "while_count", sum_fun);
	BasicBlock *while_body = BasicBlock::Create(context, "while_body", sum_fun);
	BasicBlock *while_end = BasicBlock::Create(context, "while_end", sum_fun);
	
	//给变量i和sum申请内存,并放入初值0
	Value* i_alloca = builder.CreateAlloca(Type::getInt32Ty(context));
	Value* sum_alloca = builder.CreateAlloca(Type::getInt32Ty(context));
	builder.CreateStore(con_0, i_alloca);
	builder.CreateStore(con_0, sum_alloca);
	builder.CreateBr(while_count);
	
	//while_count基本块
	builder.SetInsertPoint(while_count);
	Value* i_load = builder.CreateLoad(Type::getInt32Ty(context), i_alloca);
	Value *cmp_value = builder.CreateICmpSLE(i_load, arg_n);
	//根据cmp的值跳转,也就是if条件
	builder.CreateCondBr(cmp_value, while_body, while_end);
	
	//while_body基本块
	builder.SetInsertPoint(while_body);
	//sum = sum + i;
	Value* sum_load = builder.CreateLoad(Type::getInt32Ty(context), sum_alloca);
	Value* temp_sum = builder.CreateAdd(sum_load, i_load);
	builder.CreateStore(temp_sum, sum_alloca);
	//i++;
	Value* temp_i = builder.CreateAdd(i_load, con_1);
	builder.CreateStore(temp_i, i_alloca);
	builder.CreateBr(while_count);
	
	//while_end基本块
	builder.SetInsertPoint(while_end);
	//创建返回值
	Value* ret_sum = builder.CreateLoad(Type::getInt32Ty(context), sum_alloca);
	builder.CreateRet(ret_sum);
	//-------------------------------------------------------------------------------------
	
	//-------------------------------------------------------------------------------------
	//声明 int main() 函数
	FunctionType *main_type = TypeBuilder<int(), false>::get(context);
	Function *main_fun = cast<Function>(module->getOrInsertFunction("main", main_type));
	
	//创建main函数的entry代码块
	BasicBlock *entry_mian = BasicBlock::Create(context, "entry", main_fun);
	
	//创建一个i32常量
	Value *n_value = ConstantInt::get(Type::getInt32Ty(context), 10);
	
	//构造实参列表
	std::vector<Value*> putsargs;
	putsargs.push_back(n_value);
	ArrayRef<Value*>  argsRef(putsargs);
	
	builder.SetInsertPoint(entry_mian);
	
	// 调用函数max
	Value *ret_value = builder.CreateCall(sum_fun, argsRef);
	
	//创建返回值
	builder.CreateRet(ret_value);
	
	module->dump();
	
	InitializeNativeTarget();
    InitializeNativeTargetAsmPrinter();
    InitializeNativeTargetAsmParser();
	
	//创建ExecutionEngine
	ExecutionEngine *ee = EngineBuilder(std::unique_ptr<Module>(module)).setEngineKind(EngineKind::JIT).create();
	
	//生成机器指令
    void *mainAddr = ee->getPointerToFunction(main_fun);
	
	//运行机器指令
    typedef int (*FuncType)();
    FuncType mianFunc = (FuncType)mainAddr;//使用类型转换将mainAddr转换成一个函数mianFunc,然后调用
    ee->finalizeObject();
    std::cout << mianFunc() << std::endl;
    
    delete module;
    return 0;
}

用API生成的IR代码:

; ModuleID = 'test'
source_filename = "test"

define i32 @sum(i32 %n) {
entry:
  %0 = alloca i32
  %1 = alloca i32
  store i32 0, i32* %0
  store i32 0, i32* %1
  br label %while_count

while_count:                                      ; preds = %while_body, %entry
  %2 = load i32, i32* %0
  %3 = icmp sle i32 %2, %n
  br i1 %3, label %while_body, label %while_end

while_body:                                       ; preds = %while_count
  %4 = load i32, i32* %1
  %5 = add i32 %4, %2
  store i32 %5, i32* %1
  %6 = add i32 %2, 1
  store i32 %6, i32* %0
  br label %while_count

while_end:                                        ; preds = %while_count
  %7 = load i32, i32* %1
  ret i32 %7
}

define i32 @main() {
entry:
  %0 = call i32 @sum(i32 10)
  ret i32 %0
}
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yelvens

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值