欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

LLVM - 生成局部变量

程序员文章站 2022-04-18 18:47:02
...

接上面一篇: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;
}
相关标签: llvm