可以转载,请注明出处!
需要注意的是:sum
是一个全局变量;globa_array
是一个全局数组常量,也就是它的值一旦初始化就不会在改变;array
是一个局部数组变量。
对应的C代码:
int sum = 0;
int globa_array[4] = {1,2,3,4};
int main(){
int array[4] = {5,6,7,8};
for(int i = 0; i < 4; i++)
sum = sum + array[i] + globa_array[i];
return sum;
}
完整代码:
#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
int main(){
static llvm::LLVMContext llvmContext;
llvm::LLVMContext& context = llvmContext;
llvm::Module* module = new llvm::Module( "array_test", context);
llvm::IRBuilder<> builder(context);
//定义常量
llvm::Constant* con_0 = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0);
llvm::Constant* con_1 = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 1);
llvm::Constant* con_2 = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 2);
llvm::Constant* con_3 = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 3);
llvm::Constant* con_4 = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 4);
llvm::Constant* con_5 = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 5);
llvm::Constant* con_6 = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 6);
llvm::Constant* con_7 = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 7);
llvm::Constant* con_8 = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 8);
//定义一个int类型的全局变量
llvm::GlobalVariable* sum_global = new llvm::GlobalVariable(/*Module=*/*module,
/*Type=*/llvm::Type::getInt32Ty(context),
/*isConstant=*/false,
/*Linkage=*/llvm::GlobalValue::PrivateLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"sum");
sum_global->setInitializer(con_0);//对全局变量初始化,按照ir的语法是必须要初始化的
//定义一个int类型的全局数组常量
llvm::ArrayType* array_type = llvm::ArrayType::get(llvm::Type::getInt32Ty(context), 4);
llvm::GlobalVariable* array_global = new llvm::GlobalVariable(/*Module=*/*module,
/*Type=*/array_type,
/*isConstant=*/true,
/*Linkage=*/llvm::GlobalValue::PrivateLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/"array_global");
array_global->setAlignment(16);
std::vector<llvm::Constant*> const_array_elems;
const_array_elems.push_back(con_1);
const_array_elems.push_back(con_2);
const_array_elems.push_back(con_3);
const_array_elems.push_back(con_4);
llvm::Constant* const_array = llvm::ConstantArray::get(array_type, const_array_elems);//数组常量
array_global->setInitializer(const_array);//将数组常量初始化给全局常量
//定义函数
llvm::FunctionType* main_type = llvm::TypeBuilder<int(), false>::get(context);
llvm::Function* main_func = llvm::cast<llvm::Function>(module->getOrInsertFunction("main", main_type));
//entry基本块
llvm::BasicBlock* entry_main = llvm::BasicBlock::Create(context, "entry", main_func);
builder.SetInsertPoint(entry_main);
//int array[4] = {5,6,7,8};
llvm::Type* arrayType = llvm::ArrayType::get(llvm::Type::getInt32Ty(context), 4);
llvm::Value* array = builder.CreateAlloca(arrayType);
builder.CreateStore(con_5, builder.CreateConstGEP2_32(arrayType, array, 0, 0));
builder.CreateStore(con_6, builder.CreateConstGEP2_32(arrayType, array, 0, 1));
builder.CreateStore(con_7, builder.CreateConstGEP2_32(arrayType, array, 0, 2));
builder.CreateStore(con_8, builder.CreateConstGEP2_32(arrayType, array, 0, 3));
llvm::Value* i_allo = builder.CreateAlloca(llvm::Type::getInt32Ty(context));
builder.CreateStore(con_0, i_allo);
llvm::BasicBlock* for_cont = llvm::BasicBlock::Create(context, "for.cond", main_func);
llvm::BasicBlock* for_body = llvm::BasicBlock::Create(context, "for.body", main_func);
llvm::BasicBlock* for_end = llvm::BasicBlock::Create(context, "for.end", main_func);
builder.CreateBr(for_cont);
//for_cont基本块
builder.SetInsertPoint(for_cont);
llvm::Value* i_load = builder.CreateLoad(i_allo);
llvm::Value* icmp = builder.CreateICmpSLT(i_load, con_4);
builder.CreateCondBr(icmp, for_body, for_end);
//for_body基本块
builder.SetInsertPoint(for_body);
llvm::Value *Idxs[] = {con_0, i_load};
llvm::Value* array_i = builder.CreateGEP(array, Idxs);//使用gep指令获取元素地址的指令的方式有好几个,最好都掌握
llvm::Value* array_i_load = builder.CreateLoad(array_i);
llvm::Value* array_global_i_gep = builder.CreateGEP(array_global, Idxs);
llvm::Value* array_global_i_load = builder.CreateLoad(array_global_i_gep);
llvm::Value* sum = builder.CreateLoad(sum_global);
llvm::Value* add_sum = builder.CreateAdd(builder.CreateAdd(array_i_load, sum), array_global_i_load);
builder.CreateStore(add_sum, sum_global);
llvm::Value* i_add = builder.CreateAdd(i_load, con_1);
builder.CreateStore(i_add, i_allo);
builder.CreateBr(for_cont);
//for_end基本块,注意这里的返回值不能直接使用for_body中的sum,而是要用load指令再取一次
builder.SetInsertPoint(for_end);
llvm::Value* ret_sum = builder.CreateLoad(llvm::Type::getInt32Ty(context), sum_global);
builder.CreateRet(ret_sum);
module->dump();
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetAsmParser();
llvm::ExecutionEngine *ee = llvm::EngineBuilder(std::unique_ptr<llvm::Module>(module)).setEngineKind(llvm::EngineKind::JIT).create();
void *mainAddr = ee->getPointerToFunction(main_func);
typedef int(*FuncType)();
FuncType mianFunc = (FuncType)mainAddr;
ee->finalizeObject();
std::cout<<"Result: "<<mianFunc()<<std::endl;
delete module;
return 0;
}
用API生成的IR代码:
; ModuleID = 'array_test'
source_filename = "array_test"
@sum = private global i32 0
@array_global = private constant [4 x i32] [i32 1, i32 2, i32 3, i32 4], align 16
define i32 @main() {
entry:
%0 = alloca [4 x i32]
%1 = getelementptr [4 x i32], [4 x i32]* %0, i32 0, i32 0
store i32 5, i32* %1
%2 = getelementptr [4 x i32], [4 x i32]* %0, i32 0, i32 1
store i32 6, i32* %2
%3 = getelementptr [4 x i32], [4 x i32]* %0, i32 0, i32 2
store i32 7, i32* %3
%4 = getelementptr [4 x i32], [4 x i32]* %0, i32 0, i32 3
store i32 8, i32* %4
%5 = alloca i32
store i32 0, i32* %5
br label %for.cond
for.cond: ; preds = %for.body, %entry
%6 = load i32, i32* %5
%7 = icmp slt i32 %6, 4
br i1 %7, label %for.body, label %for.end
for.body: ; preds = %for.cond
%8 = getelementptr [4 x i32], [4 x i32]* %0, i32 0, i32 %6
%9 = load i32, i32* %8
%10 = getelementptr [4 x i32], [4 x i32]* @array_global, i32 0, i32 %6
%11 = load i32, i32* %10
%12 = load i32, i32* @sum
%13 = add i32 %9, %12
%14 = add i32 %13, %11
store i32 %14, i32* @sum
%15 = add i32 %6, 1
store i32 %15, i32* %5
br label %for.cond
for.end: ; preds = %for.cond
%16 = load i32, i32* @sum
ret i32 %16
}
//下面是执行结果
Result: 36