LLVM系列第八章:算术运算语句Arithmetic Statement

  • Post author:
  • Post category:其他



系列文章目录


LLVM系列第一章:编译LLVM源码



LLVM系列第二章:模块Module



LLVM系列第三章:函数Function



LLVM系列第四章:逻辑代码块Block



LLVM系列第五章:全局变量Global Variable



LLVM系列第六章:函数返回值Return



LLVM系列第七章:函数参数Function Arguments



LLVM系列第八章:算术运算语句Arithmetic Statement



LLVM系列第九章:控制流语句if-else



LLVM系列第十章:控制流语句if-else-phi



LLVM系列第十一章:写一个Hello World



LLVM系列第十二章:写一个简单的词法分析器Lexer



LLVM系列第十三章:写一个简单的语法分析器Parser



LLVM系列第十四章:写一个简单的语义分析器Semantic Analyzer



LLVM系列第十五章:写一个简单的中间代码生成器IR Generator



LLVM系列第十六章:写一个简单的编译器



LLVM系列第十七章:for循环



LLVM系列第十八章:写一个简单的IR处理流程Pass



LLVM系列第十九章:写一个简单的Module Pass



LLVM系列第二十章:写一个简单的Function Pass



LLVM系列第二十一章:写一个简单的Loop Pass



LLVM系列第二十二章:写一个简单的编译时函数调用统计器(Pass)



LLVM系列第二十三章:写一个简单的运行时函数调用统计器(Pass)



LLVM系列第二十四章:用Xcode编译调试LLVM源码



LLVM系列第二十五章:简单统计一下LLVM源码行数



LLVM系列第二十六章:理解LLVMContext



LLVM系列第二十七章:理解IRBuilder



LLVM系列第二十八章:写一个JIT Hello World



LLVM系列第二十九章:写一个简单的常量加法“消除”工具(Pass)


flex&bison系列





前言

在此记录下用LLVM创建一个算术运算语句(Arithmetic Statement)的过程,以备查阅。

开发环境的配置请参考第一章 《

LLVM系列第一章:编译LLVM源码

》。

我们知道一个基本逻辑代码块(BasicBlock)是由一系列的指令(Instruction)组成的。一条指令主要是为了完成某个任务(操作),比如一个算术运算操作。为简单起见,我们在这里可以把一个简单的算术运算语句理解为一条指令。

在LLVM中,一个简单的算术运算操作需要用到操作符和操作数。例如,一个乘法操作用到了一个乘法操作符和两个乘数。所以,要创建一条乘法运算指令,我们首先要得到两个操作数,它们可以来自于函数的参数、数值变量、数值常量等等。乘法操作是一个二元操作,IRBuilder里面提供了很多API,可以用来方便地创建二元操作指令。

本章,我们就在一个函数里创建一条简单的算术运算指令。



一、Hello Arithmetic Statement

为简单起见,假定这个函数带有两个整数型参数,它们的名称分别为a和b。我们把第一个参数乘以3,其结果就是函数的返回值。代码如下(示例):

// HelloArithmeticStatement.cpp

#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"

#include <vector>

using namespace llvm;

int main(int argc, char* argv[])
{
    LLVMContext context;
    IRBuilder<> builder(context);

    // Create a module
    Module* module = new Module("HelloModule", context);

    // Add a global variable
    module->getOrInsertGlobal("helloGlobalVariable", builder.getInt32Ty());
    GlobalVariable* globalVariable = module->getNamedGlobal("helloGlobalVariable");
    globalVariable->setLinkage(GlobalValue::CommonLinkage);
    globalVariable->setAlignment(MaybeAlign(4));

    // Add a function with parameters
    std::vector<Type*> parameters(2, builder.getInt32Ty());
    FunctionType* functionType = FunctionType::get(builder.getInt32Ty(), parameters, false);
    Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "HelloFunction", module);

    // Set arguments for the function
    function->getArg(0)->setName("a");
    function->getArg(1)->setName("b");

    // Create a block
    BasicBlock* block = BasicBlock::Create(context, "entry", function);
    builder.SetInsertPoint(block);

    // Create an arithmetic statement
    Value* arg1 = function->getArg(0);
    ConstantInt* three = builder.getInt32(3);
    Value* result = builder.CreateMul(arg1, three, "multiplyResult");

    // Add a return
    builder.CreateRet(result);

    // Print the IR
    verifyFunction(*function);
    module->print(outs(), nullptr);

    return 0;
}



二、编译

用clang++进行编译(示例):

# Set up C++ standard library and header path
export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)

# Compile
clang++ -w -o HelloArithmeticStatement `llvm-config --cxxflags --ldflags --system-libs --libs core` HelloArithmeticStatement.cpp

以上命令会生成一个名为HelloArithmeticStatement的可执行程序。



三、运行

运行HelloArithmeticStatement(示例):

./HelloArithmeticStatement

输出结果如下(示例):

; ModuleID = 'HelloModule'
source_filename = "HelloModule"

@helloGlobalVariable = common global i32, align 4

define i32 @HelloFunction(i32 %a, i32 %b) {
entry:
  %multiplyResult = mul i32 %a, 3
  ret i32 %multiplyResult
}

以上IR代码中,变量%multiplyResult就是乘法运算的结果,也是函数的返回值。



四、总结

我们用LLVM提供的C++ API,创建了一个算术运算语句(Arithmetic Statement),并打印出了它的IR代码。完整源码示例请参看:


https://github.com/wuzhanglin/llvm-IR-examples



版权声明:本文为Zhanglin_Wu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。