可以转载,请注明出处!
练习一、写一个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
}
本文详细介绍如何使用 LLVM 的 API 来实现 C 语言中的 if 和 while 语句,包括函数声明、参数传递、基本块创建、条件判断和循环控制等关键步骤,并提供完整的代码示例。
709

被折叠的 条评论
为什么被折叠?



