这期内容当中小编将会给大家带来有关LLVM IR中怎么实现简单循环,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
LLVM实现IR共有三种方式,这是最笨拙的方式,但也最与IR语义接近,是IR入门的最基础语法。本文实现了IR的For循环指令,具体实现的逻辑可参见代码的注释部分。运行指令可参见上一篇博文的结尾处。国内LLVM资料相对较少,分享出来代码,可以丰富网上LLVM IR相关的代码,有利于促进LLVM IR语法的理解,进而相关从业人员和相关行业的进步。代码虽粗陋,但功能进本完备可运行,还望各位海涵。
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/TargetSelect.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Function.h" #include "llvm/IR/BasicBlock.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/IR/TypeBuilder.h" #include <iostream> #include <algorithm> #include <cassert> #include <cctype> #include <cstdint> #include <cstdio> #include <cstdlib> #include <map> #include <memory> #include <string> #include <vector> using namespace llvm; using namespace std; //===----------------------------------------------------------------------===// // simple `for loop` //===----------------------------------------------------------------------===// // // int result ; // void foo(){ // for(int i=0;i<100000;i++){ // int condition = i%4; // if(condition == 0) { // result +=10; // }else if(condition == 1) { // result -= 2; // }else if(condition == 1) { // result *= 6; // }else if(condition == 1) { // result /= 3; // }else { // result ++; // } // // } //===----------------------------------------------------------------------===// int main() { // initialize global context static LLVMContext MyGlobalContext; LLVMContext &context = MyGlobalContext; //1. create module Module *module = new Module("test", context); { //set datalayout and Triples module ->setDataLayout("e-m:e-i64:64-f80:128-n8:16:32:64-S128"); module ->setTargetTriple("x86_64-unknown-linux-gnu"); } //create LLVM constant ConstantInt* const_int32_0 = ConstantInt::get(module->getContext(), APInt(32, StringRef("0")StringRef("0"), 10)); ConstantInt* const_int32_1 = ConstantInt::get(module->getContext(), APInt(32, StringRef("0")StringRef("1"), 10)); ConstantInt* const_int32_2 = ConstantInt::get(module->getContext(), APInt(32, StringRef("0")StringRef("2"), 10)); ConstantInt* const_int32_3 = ConstantInt::get(module->getContext(), APInt(32, StringRef("0")StringRef("3"), 10)); ConstantInt* const_int32_4 = ConstantInt::get(module->getContext(), APInt(32, StringRef("0")StringRef("4"), 10)); ConstantInt* const_int32_6 = ConstantInt::get(module->getContext(), APInt(32, StringRef("0")StringRef("6"), 10)); ConstantInt* const_int32_10 = ConstantInt::get(module->getContext(), APInt(32, StringRef("10"), 10)); ConstantInt* const_int32_n = ConstantInt::get(module->getContext(), APInt(32, StringRef("10000000"), 10)); //2. create function FunctionType *foo_type = TypeBuilder<int(int), false>::get(context); Function *func = Function::Create(foo_type, GlobalValue::LinkageTypes::ExternalLinkage, "compareExec", module); func->setCallingConv(CallingConv::C); //3. basic block BasicBlock* label_entry = BasicBlock::Create(module->getContext(), "entry",func); BasicBlock* label_for_cond = BasicBlock::Create(module->getContext(), "for.cond",func); BasicBlock* label_for_body = BasicBlock::Create(module->getContext(), "for.body",func); BasicBlock* label_if_then = BasicBlock::Create(module->getContext(), "if.then",func); BasicBlock* label_if_else = BasicBlock::Create(module->getContext(), "if.else",func); BasicBlock* label_if_then3 = BasicBlock::Create(module->getContext(), "if.then3",func); BasicBlock* label_if_else4 = BasicBlock::Create(module->getContext(), "if.else4",func); BasicBlock* label_if_then6 = BasicBlock::Create(module->getContext(), "if.then6",func); BasicBlock* label_if_else7 = BasicBlock::Create(module->getContext(), "if.else7",func); BasicBlock* label_if_then9 = BasicBlock::Create(module->getContext(), "if.then9",func); BasicBlock* label_if_else10 = BasicBlock::Create(module->getContext(), "if.else10",func); BasicBlock* label_if_end = BasicBlock::Create(module->getContext(), "if.end",func); BasicBlock* label_if_end11 = BasicBlock::Create(module->getContext(), "if.end11",func); BasicBlock* label_if_end12 = BasicBlock::Create(module->getContext(), "if.end12",func); BasicBlock* label_if_end13 = BasicBlock::Create(module->getContext(), "if.end13",func); BasicBlock* label_for_inc = BasicBlock::Create(module->getContext(), "for.inc",func); BasicBlock* label_for_end = BasicBlock::Create(module->getContext(), "for.end",func); //block entry(label entry) AllocaInst* ptr_result = new AllocaInst(IntegerType::get(module->getContext(), 32),module->getDataLayout().getAllocaAddrSpace(), "result", label_entry); ptr_result->setAlignment(4); AllocaInst* ptr_i = new AllocaInst(IntegerType::get(module->getContext(), 32),module->getDataLayout().getAllocaAddrSpace(), "i", label_entry); ptr_i->setAlignment(4); AllocaInst* ptr_condition = new AllocaInst(IntegerType::get(module->getContext(), 32),module->getDataLayout().getAllocaAddrSpace(), "condition", label_entry); ptr_condition->setAlignment(4); StoreInst* inst_0 = new StoreInst(const_int32_0, ptr_i, false, label_entry); inst_0->setAlignment(4); BranchInst::Create(label_for_cond, label_entry); //block for.cond (label_for_cond). LoadInst* int32_var = new LoadInst(ptr_i, "0", false, label_for_cond); int32_var->setAlignment(4); ICmpInst* int1_cmp = new ICmpInst(*label_for_cond, ICmpInst::ICMP_SLT, int32_var, const_int32_n, "cmp"); BranchInst::Create(label_for_body, label_for_end, int1_cmp, label_for_cond); //block for.body(label_for_body). LoadInst* int32_var1 = new LoadInst(ptr_i, "1", false, label_for_body); int32_var1->setAlignment(4); BinaryOperator* rem = BinaryOperator::Create(Instruction::SRem, int32_var1 , const_int32_4, "srem", label_for_body); StoreInst* void_rem = new StoreInst(rem, ptr_condition, false, label_for_body); void_rem->setAlignment(4); LoadInst* int32_var2 = new LoadInst(ptr_condition, "2", false, label_for_body); int32_var2->setAlignment(4); ICmpInst* int1_cmp0 = new ICmpInst(*label_for_body, ICmpInst::ICMP_EQ, int32_var2, const_int32_0, "cmpeq"); BranchInst::Create(label_if_then, label_if_else, int1_cmp0, label_for_body); //block if.then(label_if_then). LoadInst* int32_var3 = new LoadInst(ptr_result, "3", false, label_if_then); int32_var3->setAlignment(4); BinaryOperator* int32_add = BinaryOperator::CreateNSW(Instruction::Add, int32_var3 , const_int32_10, "add", label_if_then); StoreInst* void_add = new StoreInst(int32_add, ptr_result, false, label_if_then); void_add->setAlignment(4); BranchInst::Create(label_if_end13, label_if_then); //block if.else(label_if_else). LoadInst* int32_var4 = new LoadInst(ptr_condition, "4", false, label_if_else); int32_var4->setAlignment(4); ICmpInst* int1_cmp2 = new ICmpInst(*label_if_else, ICmpInst::ICMP_EQ, int32_var4, const_int32_1, "cmpeq2"); BranchInst::Create(label_if_then3, label_if_else4, int1_cmp2, label_if_else); //block if.then3(label_if_then3). LoadInst* int32_var5 = new LoadInst(ptr_result, "5", false, label_if_then3); int32_var5->setAlignment(4); BinaryOperator* int32_sub = BinaryOperator::CreateNSW(Instruction::Sub, int32_var5 , const_int32_2, "sub", label_if_then3); StoreInst* void_sub = new StoreInst(int32_sub, ptr_result, false, label_if_then3); void_sub->setAlignment(4); BranchInst::Create(label_if_end12, label_if_then3); //block if.else4(label_if_else). LoadInst* int32_var6 = new LoadInst(ptr_condition, "6", false, label_if_else4); int32_var6->setAlignment(4); ICmpInst* int1_cmp5 = new ICmpInst(*label_if_else4, ICmpInst::ICMP_EQ, int32_var6, const_int32_2, "cmpeq5"); BranchInst::Create(label_if_then6, label_if_else7, int1_cmp5, label_if_else4); //block if.then6(label_if_then6) LoadInst* int32_var7 = new LoadInst(ptr_result, "7", false, label_if_then6); int32_var7->setAlignment(4); BinaryOperator* int32_mul = BinaryOperator::CreateNSW(Instruction::Mul, int32_var7 , const_int32_6, "Mul", label_if_then6); StoreInst* void_mul = new StoreInst(int32_mul, ptr_result, false, label_if_then6); void_mul->setAlignment(4); BranchInst::Create(label_if_end11, label_if_then6); //block if.else7(label_if_else7) LoadInst* int32_var8 = new LoadInst(ptr_condition, "8", false, label_if_else7); int32_var8->setAlignment(4); ICmpInst* int1_cmp8 = new ICmpInst(*label_if_else7, ICmpInst::ICMP_EQ, int32_var8, const_int32_3, "cmpeq8"); BranchInst::Create(label_if_then9, label_if_else10, int1_cmp8, label_if_else7); //block if.then9(label_if_then9). LoadInst* int32_var9 = new LoadInst(ptr_result, "9", false, label_if_then9); int32_var9->setAlignment(4); BinaryOperator* int32_div = BinaryOperator::Create(Instruction::SDiv, int32_var9 , const_int32_3, "div", label_if_then9); StoreInst* void_div = new StoreInst(int32_div, ptr_result, false, label_if_then9); void_div->setAlignment(4); BranchInst::Create(label_if_end, label_if_then9); //block if.else10(label_if_else10). LoadInst* int32_var10 = new LoadInst(ptr_condition, "10", false, label_if_else10); int32_var10->setAlignment(4); BinaryOperator* int32_inc = BinaryOperator::CreateNSW(Instruction::Add, int32_var10 , const_int32_1, "inc", label_if_else10); StoreInst* void_inc = new StoreInst(int32_inc, ptr_result, false, label_if_else10); void_inc->setAlignment(4); BranchInst::Create(label_if_end, label_if_else10); //block if.end(label_if_end) BranchInst::Create(label_if_end11, label_if_end); //block if.end11(label_if_end11) BranchInst::Create(label_if_end12, label_if_end11); //block if.end12(label_if_end12) BranchInst::Create(label_if_end13, label_if_end12); //block if.end13(label_if_end13) BranchInst::Create(label_for_inc, label_if_end13); //block for.inc(label_for_inc) LoadInst* int32_var11 = new LoadInst(ptr_i, "11", false, label_for_inc); int32_var11->setAlignment(4); BinaryOperator* int32_inc14 = BinaryOperator::CreateNSW(Instruction::Add, int32_var11 , const_int32_1, "inc14", label_for_inc); StoreInst* void_12 = new StoreInst(int32_inc14, ptr_i, false, label_for_inc); void_12->setAlignment(4); BranchInst::Create(label_for_cond, label_for_inc); //block for.end(label_for_end) ReturnInst::Create(module->getContext(), const_int32_0, label_for_end); //verify module bool Result = llvm::verifyModule(*module); if(Result) { std::cout << "IR verify success" << std::endl; } module->dump(); //Initialize native library InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); //printf("Hello, world\n"); ExecutionEngine *ee = EngineBuilder(std::unique_ptr<Module>(module)).setEngineKind(EngineKind::JIT).setOptLevel(CodeGenOpt::None).create(); void * funcAddr = ee->getPointerToFunction(func); //Run the function typedef int (*FuncType)(); FuncType firFunc = (FuncType)funcAddr; firFunc(); // endst = clock(); std::cout << "calling consume time (s): " << "ssss" << std::endl; return 0; }
上述就是小编为大家分享的LLVM IR中怎么实现简单循环了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。