温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

LLVM IR中怎么实现简单循环

发布时间:2021-06-24 17:18:15 来源:亿速云 阅读:361 作者:Leah 栏目:大数据

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

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI