通过IRBuilder新建LLVM IR
这一部分想给出一个完整的例子,来利用IRBuilder建立func_sum,并完成对齐的调用。(网上应该有完整的说明,忘记是哪里来的,留在这里方便记录,找到来源后附链接)来实现类似的功能:
int sum(int n){ int i = 1; int sum = 0; while(i<=n){ sum += i; i++; } return sum; } int main(){ return sum(10); }
相似功能不做更多介绍,代码和注释已经很明确。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include "llvm/IR/LLVMContext.h" 2 #include "llvm/IR/Module.h" 3 #include "llvm/IR/Function.h" 4 #include "llvm/IR/BasicBlock.h" 5 #include "llvm/IR/IRBuilder.h" 6 #include "llvm/ExecutionEngine/MCJIT.h" 7 #include "llvm/Support/TargetSelect.h" 8 #include "llvm/IR/TypeBuilder.h" 9 #include "iostream" 10 11 using namespace llvm; 12 //c 13 14 int main(){ 15 static LLVMContext MyGlobalContext; 16 LLVMContext &context = MyGlobalContext; 17 18 //Create a module 19 Module *module = new Module("test", context); 20 IRBuilder<> builder(context); 21 22 //create a function 23 FunctionType *sum_type = TypeBuilder<int(int), false>::get(context); 24 Function *sum_fun = cast<Function>(module->getOrInsertFunction("sum", sum_type)); 25 26 //create function's args 27 Function::arg_iterator argsIt = sum_fun->arg_begin(); 28 Value *arg_n = argsIt++; 29 arg_n->setName("n"); 30 31 //create two constant value 32 Value *const_0 = ConstantInt::get(IntegerType::getInt32Ty(context), 0); 33 Value *const_1 = ConstantInt::get(IntegerType::getInt32Ty(context), 1); 34 35 //create entry basicblock 36 BasicBlock *entry_sum = BasicBlock::Create(context, "entry", sum_fun); 37 builder.SetInsertPoint(entry_sum); 38 39 //Create 3 while BasicBlock 40 BasicBlock *while_count = BasicBlock::Create(context, 41 "while_count", sum_fun); 42 BasicBlock *while_body = BasicBlock::Create(context, "while_body", sum_fun); 43 BasicBlock *while_end = BasicBlock::Create(context, "while_end", sum_fun); 44 45 46 //Create variable i & sum 47 Value *i_alloc = builder.CreateAlloca(Type::getInt32Ty(context)); 48 Value *sum_alloc = builder.CreateAlloca(Type::getInt32Ty(context)); 49 builder.CreateStore(const_1, i_alloc); 50 builder.CreateStore(const_0, sum_alloc); 51 builder.CreateBr(while_count); 52 53 //while_count 54 builder.SetInsertPoint(while_count); 55 Value *i_load = builder.CreateLoad(Type::getInt32Ty(context), i_alloc); 56 Value *cmp_value = builder.CreateICmpSLE(i_load, arg_n); 57 builder.CreateCondBr(cmp_value, while_body, while_end); 58 59 //while_body 60 builder.SetInsertPoint(while_body); 61 Value *sum_load = builder.CreateLoad(Type::getInt32Ty(context), sum_alloc); 62 Value *temp_sum = builder.CreateAdd(sum_load, i_load); 63 builder.CreateStore(temp_sum, sum_alloc); 64 Value *temp_i = builder.CreateAdd(i_load, const_1); 65 builder.CreateStore(temp_i, i_alloc); 66 builder.CreateBr(while_count); 67 68 builder.SetInsertPoint(while_end); 69 Value *ret_sum = builder.CreateLoad(Type::getInt32Ty(context), sum_alloc); 70 builder.CreateRet(ret_sum); 71 72 //Function Decalare: int main() 73 FunctionType *main_type = TypeBuilder<int(), false>::get(context); 74 Function *main_fun = cast<Function>(module->getOrInsertFunction("main", main_type)); 75 BasicBlock *entry_main = BasicBlock::Create(context, "entry", main_fun); 76 Value *n_value = ConstantInt::get(Type::getInt32Ty(context), 10); 77 78 std::vector<Value*> putsargs; 79 putsargs.push_back(n_value); 80 ArrayRef<Value*> argsRef(putsargs); 81 builder.SetInsertPoint(entry_main); 82 Value *ret_value = builder.CreateCall(sum_fun, argsRef); 83 84 builder.CreateRet(ret_value); 85 86 module->dump(); 87 88 InitializeNativeTarget(); 89 InitializeNativeTargetAsmPrinter(); 90 InitializeNativeTargetAsmParser(); 91 92 //Create ExecutionEngine 93 ExecutionEngine *ee = EngineBuilder(std::unique_ptr<Module>(module)).setEngineKind(EngineKind::JIT).create(); 94 void *mainAddr = ee->getPointerToFunction(main_fun); 95 96 //execute 97 typedef int (*FuncType)(); 98 FuncType mainFunc = (FuncType)mainAddr; 99 ee->finalizeObject(); 100 std::cout << mainFunc() << std::endl; 101 102 delete module; 103 return 0; 104 }
需要调用 clang++ -O3 IRBuilder.cpp -o irmain `llvm-config --cflags --ldflags` `llvm-config --libs` `llvm-config --system-libs` 进行编译