IR API(四)——操作IR的全局变量、全局常量及数组

可以转载,请注明出处!

需要注意的是: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

你可能感兴趣的:(LLVM)