这期内容当中小编将会给大家带来有关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中怎么实现简单循环了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注天达云行业资讯频道。