当前位置:网站首页>Llvm - generate local variables
Llvm - generate local variables
2022-04-23 15:04:00 【Mrpre】
Follow the above article :https://wonderful.blog.csdn.net/article/details/106902005
The above article implements the following functions , however Are all pairs of input parameters a The operation of
double myfor(double a)
{
for(i = 0; i < a; i++) {
a = a + 1
}
return a
}
In this case , What we want to achieve is the addition and subtraction of local variables , then return, as follows
double myvar(double a)
{
double b = 0;
for(i = 0; i < a; i++) {
b = a + 1
}
return b
}
After running the source code of this example , It generates llvm ir as follows :
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、 Create a function
2、 Use CreateEntryBlockAlloca(TheFunction, "la");
Create a "la" The variable of
3、 Use
Value *StartVal = ConstantFP::get(TheContext, APFloat(0.0)); Builder.CreateStore(innerargs[0], Alloca);
Initialize local variable to 0
Source code :
#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://yzsam.com/2022/04/202204231409588064.html
边栏推荐
- How to design a good API interface?
- 分布式事务Seata介绍
- Redis主从同步
- Provided by Chengdu control panel design_ It's detailed_ Introduction to the definition, compilation and quotation of single chip microcomputer program header file
- How to use OCR in 5 minutes
- Vscode Chinese plug-in doesn't work. Problem solving
- 每日一题-LeetCode396-旋转函数-递推
- Advanced version of array simulation queue - ring queue (real queuing)
- 如何打开Win10启动文件夹?
- I/O复用的高级应用:同时处理 TCP 和 UDP 服务
猜你喜欢
我的 Raspberry Pi Zero 2W 折腾笔记,记录一些遇到的问题和解决办法
1-初识Go语言
Detailed comparison between asemi three-phase rectifier bridge and single-phase rectifier bridge
For 22 years, you didn't know the file contained vulnerabilities?
8.4 realization of recurrent neural network from zero
你还不知道责任链模式的使用场景吗?
What is the role of the full connection layer?
Swift protocol Association object resource name management multithreading GCD delay once
博睿数据携手F5共同构建金融科技从代码到用户的全数据链DNA
Thread synchronization, life cycle
随机推荐
Chapter 7 of JVM series -- bytecode execution engine
capacitance
JUC学习记录(2022.4.22)
Share 20 tips for ES6 that should not be missed
Comment eolink facilite le télétravail
Ffmpeg installation error: NASM / yasm not found or too old Use --disable-x86asm for a clipped build
When splicing HQL, the new field does not appear in the construction method
thinkphp5+数据大屏展示效果
Sqlserver transaction and lock problem
go基础 反射
Epolloneshot event of epoll -- instance program
LeetCode 练习——396. 旋转函数
JUC learning record (2022.4.22)
Leetcode151 - invert words in string - String - simulation
Redis master-slave synchronization
2-GO variable operation
We reference My97DatePicker to realize the use of time plug-in
Flink DataStream 类型系统 TypeInformation
JS -- realize click Copy function
编程哲学——自动加载、依赖注入与控制反转