当前位置:网站首页>LLVM - 生成局部变量
LLVM - 生成局部变量
2022-04-23 14:11:00 【Mrpre】
接上面一篇:https://wonderful.blog.csdn.net/article/details/106902005
上面一篇实现了如下函数,但是 都是对入参a的操作
double myfor(double a)
{
for(i = 0; i < a; i++) {
a = a + 1
}
return a
}
本例中,我们希望实现是局部变量的加减,然后return,如下
double myvar(double a)
{
double b = 0;
for(i = 0; i < a; i++) {
b = a + 1
}
return b
}
运行本例源码后,它生成的llvm ir如下:
define fastcc double @myvar(double %a) {
myentry:
%cmptmp = fcmp ult double %a, 1.000000e+01
br i1 %cmptmp, label %then, label %else
then: ; preds = %myentry
br label %end
else: ; preds = %myentry
br label %end
end: ; preds = %else, %then
%la.0 = phi double [ 7.000000e+00, %then ], [ 9.000000e+00, %else ]
ret double %la.0
}
1、创建函数
2、使用 CreateEntryBlockAlloca(TheFunction, "la");
创建名为"la"的变量
3、使用
Value *StartVal = ConstantFP::get(TheContext, APFloat(0.0)); Builder.CreateStore(innerargs[0], Alloca);
初始化局部变量为0
源码:
#include "./llvm-8.0.1.src/examples/Kaleidoscope/include/KaleidoscopeJIT.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Utils.h"
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <iostream>
using namespace std;
using namespace llvm;
using namespace llvm::orc;
//LLVM items
static LLVMContext TheContext;
static IRBuilder<> Builder(TheContext);
static std::unique_ptr<Module> TheModule;
//JIT
static std::unique_ptr<KaleidoscopeJIT> TheJIT;
static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
const std::string &VarName) {
IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
TheFunction->getEntryBlock().begin());
return TmpB.CreateAlloca(Type::getDoubleTy(TheContext), 0,
VarName.c_str());
}
/* *double myvar(double a) *{ * double b = 0; * for(i = 0; i < a; i++) { * b = a + 1 * } * return b *} * */
int main()
{
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
//init module
TheModule = llvm::make_unique<Module>("myjit", TheContext);
//used to be runned by jit later
TheJIT = llvm::make_unique<KaleidoscopeJIT>();
TheModule->setDataLayout(TheJIT->getTargetMachine().createDataLayout());
static std::unique_ptr<legacy::FunctionPassManager> TheFPM;
TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
TheFPM->add(createPromoteMemoryToRegisterPass());
//define the args
vector<std::string> ArgNames;
//mycfor has 1 args
ArgNames.push_back(string("a"));
//make the 1 args attach to LLVM Type::double
std::vector<Type *> Doubles(ArgNames.size(), Type::getDoubleTy(TheContext));
//generate llvm function type
FunctionType *FT = FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false);
//Create function whose FunctionType is FT
Function *TheFunction = Function::Create(FT, Function::ExternalLinkage, "myvar", TheModule.get());
//give the name of Function args and save the args as innerargs
unsigned Idx = 0;
std::vector<Value *>innerargs;
for (auto &Arg : TheFunction->args()) {
Arg.setName(ArgNames[Idx++]);
innerargs.push_back(&Arg);
}
//this function's basic block
BasicBlock *BB = BasicBlock::Create(TheContext, "myentry", TheFunction);
BasicBlock *ThenBB = BasicBlock::Create(TheContext, "then");
BasicBlock *ElseBB = BasicBlock::Create(TheContext, "else");
BasicBlock *EndBB = BasicBlock::Create(TheContext, "end");
Builder.SetInsertPoint(BB);
//create local var la and inited to 0
AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, "la");
Value *StartVal = ConstantFP::get(TheContext, APFloat(0.0));
Builder.CreateStore(innerargs[0], Alloca);
//if a < 0 ThenBB else ElseBB
Value *CondV = Builder.CreateFCmpULT(innerargs[0], ConstantFP::get(TheContext, APFloat(10.0)), "cmptmp");
Builder.CreateCondBr(CondV, ThenBB, ElseBB);
TheFunction->getBasicBlockList().push_back(ThenBB);
Builder.SetInsertPoint(ThenBB);
Value *NextVar = ConstantFP::get(TheContext, APFloat(7.0));
Builder.CreateStore(NextVar, Alloca);
Builder.CreateBr(EndBB);
TheFunction->getBasicBlockList().push_back(ElseBB);
Builder.SetInsertPoint(ElseBB);
NextVar = ConstantFP::get(TheContext, APFloat(9.0));
Builder.CreateStore(NextVar, Alloca);
Builder.CreateBr(EndBB);
TheFunction->getBasicBlockList().push_back(EndBB);
Builder.SetInsertPoint(EndBB);
Builder.CreateRet( Builder.CreateLoad(Alloca, "la") );
TheFunction->setCallingConv(llvm::CallingConv::Fast);
verifyFunction(*TheFunction);
//will opt the code into phi even we haven't use it.
TheFPM->run(*TheFunction);
TheFunction->print(errs());
//using jit to run this code
auto H = TheJIT->addModule(std::move(TheModule));
auto ExprSymbol = TheJIT->findSymbol("myvar");
double (*myvar)(double) = (double (*)(double))(intptr_t)cantFail(ExprSymbol.getAddress());
cout <<myvar(9)<<endl;
}
版权声明
本文为[Mrpre]所创,转载请带上原文链接,感谢
https://wonderful.blog.csdn.net/article/details/106902346
边栏推荐
猜你喜欢
使用开源调研工具Prophet是一种什么体验?
使用Executors类快速创建线程池
redis数据库讲解二(redis高可用、持久化、性能管理)
After entering the new company, the operation and maintenance engineer can understand the deployment of the system from the following items
政务云迁移实践 北明数科使用HyperMotion云迁移产品为某政府单位实施上云迁移项目,15天内完成近百套主机迁移
squid代理
KVM learning resources
金融行业云迁移实践 平安金融云整合HyperMotion云迁移解决方案,为金融行业客户提供迁移服务
x509证书cer格式转pem格式
Use the executors class to quickly create a thread pool
随机推荐
TLS/SSL 协议详解 (30) SSL中的RSA、DHE、ECDHE、ECDH流程与区别
容灾有疑问?点这里
krpano全景之vtour文件夹和tour
Use cases of the arrays class
政务云迁移实践 北明数科使用HyperMotion云迁移产品为某政府单位实施上云迁移项目,15天内完成近百套主机迁移
Date的after时间判断
Arrays类的使用案例
tcp_diag 内核相关实现 1 调用层次
操作系统常见面试题目:
微信小程序轮播图swiper
ssh限制登录的四种手段
JumpServer
线程间控制之CountDownLatch和CyclicBarrier使用介绍
错误:无法远程查找到密钥 “428F7ECC7117F726“
什么是云迁移?云迁移的四种模式分别是?
redis数据库讲解(四)主从复制、哨兵、Cluster群集
预览CSV文件
返回数组排序后下标
在电视屏幕上进行debug调试
HyperBDR云容灾V3.3.0版本发布|容灾功能升级,资源组管理功能优化