• LLVM IR 构建 分析 转换 优化 IRBuilder Pass AI编译器后端代码生成


    LLVM IR 构建 分析 转换 优化

    LLVM汇编语言是一种 静态单赋值(SSA) 的中间表示,提供了类型安全检查,低层次的操作符,灵活和清晰表达‘几乎所有’高级语言的能力。同时,它也是LLVM编译算法中各个阶段的一种通用代码表达形式。

    LLVM IR 创建 Construct Builder

    根据 其他IR(比如TVM IR 、python ast、gimple ir) 使用 llvm提供的API创建 LLVMir来表征代码

    模块 Module

    LLVM中的模块(Module),代表了一块代码。它是一个比较完整独立的代码块,是一个最小的编译单元。

    需要注意的是,它跟我们平常说的“程序模块”不一样。程序模块是一个更大的集合,包含了很多个编译单元;而LLVM中的模块(Module),我们可以把它初步理解为一个编译单元。

    在LLVM IR的基本概念(构件)中,模块是一个组合,它包含了其它更小的基本构件。比如,它可以包含的基本构件有全局变量globalval、函数Function、数据结构Struct等。

    // HelloModule.cpp
    
    #include "llvm/IR/Module.h"
    #include "llvm/IR/LLVMContext.h"
    
    using namespace llvm;
    
    int main(int argc, char* argv[])
    {
        LLVMContext context; // 代码上下文管理器
        Module* module = new Module("HelloModule", context);
    
        module->print(outs(), nullptr);
    
        return 0;
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    函数 Function

    模块也好,函数也好,都是LLVM IR代码。LLVM提供了一个叫IRBuilder的工具来帮助我们创建IR代码。

    当然,如果要创建一个函数,我们还需要用到其它工具,比如llvm::Function、llvm::FunctionType等。

    我们知道,函数也是有类型的,而llvm::FunctionType就是用来创建(FunctionType::get)函数的类型的(返回值类型,输入参数类型)。

    创建函数之前,需要先创建( Type::getVoidTy Type::getxxx)类型(void、int、float、void*、int*、float*…),然后才能用llvm::Function::Create创建函数。

    IR创建完成后可以使用 llvm::verifyFunction 来检验一个LLVM模块是否是“良好结构的”。

    
    // HelloFunction.cpp
    
    #include "llvm/IR/Function.h"   // Function 
    #include "llvm/IR/IRBuilder.h"  // IRBuilder 代码构建器
    #include "llvm/IR/LLVMContext.h"// LLVMContext 代码上下文 (记录一些全局信息, 各种作用域scope等)
    #include "llvm/IR/Module.h"     // Module 模块
    #include "llvm/IR/Verifier.h"   // Verifier IR验证
    
    using namespace llvm;
    
    int main(int argc, char* argv[])
    {
        LLVMContext context;         // 上下文 管理器
        IRBuilder<> builder(context);// IR构建器
    
        // Create a module
        Module* module = new Module("HelloModule", context); // source_filename = "HelloModule"  模块id  ModuleID
    
        // Add a function
        Type* voidType = Type::getVoidTy(context); // 创建 void 类型 类型变量
        FunctionType* functionType = FunctionType::get(voidType, false); // 创建函数类型  (void)()
        //                                      函数类型       函数作用范围(链接类型)         函数名          所属代码模块
        Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "HelloFunction", module);
    
        // Print the IR
        verifyFunction(*function); // verifyFunction 验证函数IR正确性
        // llvm::verifyFunction 作用是检查 创建的函数是否正确,确保它是符合编程语言规范的,否则会报错
        module->print(outs(), nullptr);
    
        return 0;
    }
    
    // 全局标识符(例如函数、全局变量)会以``‘@’`` 开始,而本地标识符(例如寄存器名、类型名)会以 ‘%’ 开始。
    /*
    ; ModuleID = 'HelloModule'
    source_filename = "HelloModule"
    
    declare void @HelloFunction() // @ 全局标识符 HelloFunction
    
    */
    //LLVM中的保留字和其他语言中保留字非常相似。
    //有对不同的操作码的关键字 ( ‘add’, ‘mul’, ‘bitcast’, ‘ret’ 等 )、基本类型名 ( ‘void’, ‘i32’ 等)、还有其他。
    //这些保留字不会和变量名冲突,由于他们没有一个是以特殊字符开头的( '%' 或 '@' )。
    //%result = mul i32 %X, 8  // 局部变量 mul 8 得到结果变量 result
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    类型系统

    • 空类型 void

    • 整数类型 Integer Type iN

    i1 a single-bit integer.
    i32 a 32-bit integer.
    i1942652 a really big integer of over 1 million bits.

    • 浮点数类型 Floating Point Types

    half 16-bit floating point value
    float 32-bit floating point value
    double 64-bit floating point value
    fp128 128-bit floating point value (112-bit mantissa)

    • 指针类型 Pointer Type *

    [4 x i32]* A pointer to array of four i32 values.
    i32 (i32*) * A pointer to a function that takes an i32*, returning an i32.
    i32 addrspace(5)* A pointer to an i32 value that resides in address space #5.

    • 向量类型 Vector Type < <# elements> x >

    <4 x i32> Vector of 4 32-bit integer values.
    <8 x float> Vector of 8 32-bit floating-point values.
    <2 x i64> Vector of 2 64-bit integer values.
    <4 x i64*> Vector of 4 pointers to 64-bit integer values.

    • 数组类型 [<# elements> x ]

    [40 x i32] Array of 40 32-bit integer values.
    [41 x i32] Array of 41 32-bit integer values.
    [4 x i8] Array of 4 8-bit integer values.

    • 多维数组类型

    [3 x [4 x i32]] 3x4 array of 32-bit integer values.
    [12 x [10 x float]] 12x10 array of single precision floating point values.
    [2 x [3 x [4 x i16]]] 2x3x4 array of 16-bit integer values.

    • 函数类型 Function Type ()

    i32 (i32) 函数 输入一个 i32类型参数 返回 i32类型 int(int)
    float (i16, i32 ) * 函数指针类型 指向一个函数 输入 i16类型和 指向i32类型指针类型参数 返回 float 类型
    i32 (i8
    , …) 一个变参数 vararg 类型函数function 输入至少一个 i8类型指针 (char in C), 返回一个 integer. 可以为 printf 函数类型
    {i32, i32} (i32) 函数 输入一个 i32类型参数, 返回一个结构体structure 类型 包含两个 i32类型的结构体

    • 结构体类型

    { } ; 一般结构体类型 struct type
    <{ }> ; 打包结构体类型 packed struct type

    { i32, i32, i32 } 包含3个 i32类型值 的结构体类型
    { float, i32 (i32) * } 包含两个值的结构体类型,一个是 float 类型,第二个是指针类型 指向一个函数 输入一个 i32, 返回一个 i32.
    <{ i8, i32 }> 打包结构体类型 大小为 5 bytes .

    常量 Constant

    布尔常量 Boolean constants false / true
    整数常量 Integer constants 1/2/4/10 builder.getInt32
    浮点数常量 Floating point constants 1.25/1.23421e+2
    空指针常量 Null pointer constants null
    结构体常量 Structure constants {i32 4, float 17.0}
    数组常量 Array constants [ i32 42, i32 11, i32 74 ] c"Hello World\0A\00"
    向量常量 Vector constants < i32 42, i32 11, i32 74, i32 100 >

    • 类型常量 相关操作
    Type *voidType = Type::getVoidTy(module->getContext());        // void 类型
    Type *int32Type = Type::getInt32Ty(module->getContext());      // int  类型
    Type *int8PtrType = Type::getInt8PtrTy(module->getContext());  // int8* 类型  char* 类型
    Type *int8PtrPtrType = int8PtrType->getPointerTo();            // int8** ;类型 char**  
     
    Constant *int32Zero = ConstantInt::get(int32Type, 0, true);    // 常量 0
    ConstantInt* value66 = builder.getInt32(66); // 获取常量 66
    ConstantInt* zero = builder.getInt32(0); // 获取一个整数常量 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    代码块 Block

    函数(Function)是由基本的逻辑代码块(Basic Block)组成的。

    为了简单起见,我们就把“逻辑代码块”简称为“代码块”吧。

    一个代码块只有一个起点(entry)和终点。代码块的主要部分当然是代码,即一系列的IR指令(代码)。

    最后一条IR指令就是结束指令。代码块的起点可以是一个标签,它指示了下一行代码的位置。

    LLVM提供了一个名为BasicBlock的工具来创建代码块 BasicBlock::Create 。当然,在构建代码块的过程中,我们还需要用到通用的构建工具IRBuilder。

    
    // HelloBlock.cpp
    
    #include "llvm/IR/BasicBlock.h"
    #include "llvm/IR/Function.h"
    #include "llvm/IR/IRBuilder.h"
    #include "llvm/IR/LLVMContext.h"
    #include "llvm/IR/Module.h"
    #include "llvm/IR/Verifier.h"
    
    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 function
        Type* voidType = Type::getVoidTy(context);// 获取 void类型
        FunctionType* functionType = FunctionType::get(voidType, false); // 获取 void() 函数类型
        Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "HelloFunction", module);// 创建函数
    
        // Create a block
        BasicBlock* block = BasicBlock::Create(context, "entry", function); // 创建 函数入口代码块
        builder.SetInsertPoint(block); // 设置当前 处理的代码块 (之后的 IR构建在这个block中)切换到其他blcok 需要使用这个 SetInsertPoint 设置 新的 block
    
        // Print the IR
        verifyFunction(*function);
        module->print(outs(), nullptr);
    
        return 0;
    }
    /*
    ; ModuleID = 'HelloModule'
    source_filename = "HelloModule"
    
    define void @HelloFunction() {
    entry: ; 函数入口代码块
    }
    */
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    全局变量 Global Variable

    全局变量(Global Variable)是在一个模块(Module)之内全局可见的变量,也就是说模块内所有的函数都能用它。

    LLVM提供了 Module::getOrInsertGlobal() 函数来创建全局变量,以及 Module::getNamedGlobal() 来找到一个全局变量。

    创建全局变量之后,我们可以配置它的属性,如链接类型、内存对齐模型等。

    全局变量在链接的时候,到底是指向同一个全局变量,还是多个不同的全局变量,是由链接类型决定的。

    这里说的“多个不同的全局变量”,意思是其名称相同,但是有“多个分身”,“分身”之间互不影响。

    链接类型用途
    ExternalLinkage模块外部可见的函数
    AvailableExternallyLinkage只在查询而非代码生成的时候外部可见
    LinkOnceAnyLinkage函数在链接(或内连inline)的时候仅保存一份实现
    LinkOnceODRLinkage同上,但有些链接属性可以用类似的属性替换
    WeakAnyLinkage函数在链接的时候仅保存一份实现(弱链接)
    WeakODRLinkage同上,但有些链接属性可以用类似的属性替换
    AppendingLinkage这是特殊的链接类型,只适用于全局数组
    InternalLinkage链接时若发现有重命的静态函数,则进行重命名
    PrivateLinkage只做内部链接,但不会添加到符号表中
    ExternalWeakLinkage外部弱链接
    CommonLinkage由编译器(链接器)自动选择链接类型
    // HelloGlobalVariable.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"
    
    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", Type::getInt32Ty(context)); // 模块中创建一个名为helloGlobalVariable int32类型的全局变量 
        GlobalVariable* globalVariable = module->getNamedGlobal("helloGlobalVariable"); // 获取该全局变量
        globalVariable->setLinkage(GlobalValue::CommonLinkage); // 设置全局变量的 链接类型
        globalVariable->setAlignment(MaybeAlign(4));// 设置 全局变量的 内存对齐属性
    
        // Add a function
        Type* voidType = Type::getVoidTy(context);
        FunctionType* functionType = FunctionType::get(voidType, false);
        Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "HelloFunction", module);
    
        // Create a block
        BasicBlock* block = BasicBlock::Create(context, "entry", function);
        builder.SetInsertPoint(block); // 设置当前 处理的代码块
    
        // Print the IR
        verifyFunction(*function);
        module->print(outs(), nullptr);
    
        return 0;
    }
    
    /*
    ; ModuleID = 'HelloModule'
    source_filename = "HelloModule"
    
    @helloGlobalVariable = common global i32, align 4  ; 全局变量
    
    define void @HelloFunction() {
    entry:
    }
    
    
    */
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    Function Return 函数返回值 builder.CreatRet

    // HelloReturn.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"
    
    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
        FunctionType* functionType = FunctionType::get(builder.getInt32Ty(), false);
        Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "HelloFunction", module);
    
        // Create a block
        BasicBlock* block = BasicBlock::Create(context, "entry", function);
        builder.SetInsertPoint(block);   // 设置当前 处理的代码块
    
        // Add a return
        ConstantInt* zero = builder.getInt32(0); // 获取一个整数常量 0
        builder.CreateRet(zero); //创建返回语句 return 0;
    
        // Print the IR
        verifyFunction(*function);
        module->print(outs(), nullptr);
    
        return 0;
    }
    /*
    ; ModuleID = 'HelloModule'
    source_filename = "HelloModule"
    
    @helloGlobalVariable = common global i32, align 4
    
    define i32 @HelloFunction() {
    entry:
      ret i32 0  ; 返回语句  return 0
    }
    
    */
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    函数参数 Function Arguments function->getArg(0)->setName

    // HelloFunctionArguments.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 
    
    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
        std::vector<Type*> parameters(2, builder.getInt32Ty()); //  类型向量 
        FunctionType* functionType = FunctionType::get(builder.getInt32Ty(), parameters, false);// 创建函数类型  i32(i32,i32)
        Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "HelloFunction", module);
    
        // Set arguments for the function
        function->getArg(0)->setName("a"); // 为函数 创建参数 名为 a
        function->getArg(1)->setName("b"); // 为函数 创建参数 名为 b
    
        // Create a block
        BasicBlock* block = BasicBlock::Create(context, "entry", function);
        builder.SetInsertPoint(block);     // 设置当前 处理的代码块
    
        // Add a return
        ConstantInt* zero = builder.getInt32(0);
        builder.CreateRet(zero);
    
        // Print the IR
        verifyFunction(*function);
        module->print(outs(), nullptr);
    
        return 0;
    }
    
    /*
    
    ; ModuleID = 'HelloModule'
    source_filename = "HelloModule"
    
    @helloGlobalVariable = common global i32, align 4
    
    define i32 @HelloFunction(i32 %a, i32 %b) { ; 输入两个i32类型参数(名为 a,b)的 函数
    entry:
      ret i32 0
    }
    
    */
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    赋值语句 Statement

    数学运算赋值语句 Arithmetic Statement builder.CreateMul

    一个基本的逻辑代码块(Basic Block)是由一系列的指令(Instruction)组成的。

    一条指令主要是为了完成某个任务(操作),比如一个算术运算。

    一条指令可以是一个简单的语句,比如一个算术运算语句。

    在LLVM中,一个简单的算术运算需要用到操作符和操作数。例如,一个乘法运算用到了一个乘法操作符和两个乘数。

    所以,要创建一个乘法运算语句,我们首先要得到两个操作数,比如它可以来自于函数的参数、数字常量等等。

    我们知道,乘法操作是一个二元操作,IRBuilder里面提供了很多API,可以用来方便地创建二元操作语句。

    // 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 
    
    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
        std::vector<Type*> parameters(2, builder.getInt32Ty());
        FunctionType* functionType = FunctionType::get(builder.getInt32Ty(), parameters, false);  // int HelloFunction(int a, int b);
        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); // 创建一个常量 3
    
        // 都是 三段码的形式 没有嵌套的表达式  一个运算后就会产生一个目标变量赋值语句 
        Value* result = builder.CreateMul(arg1, three, "multiplyResult"); // 构建语句 multiplyResult = a* 3
    
        // Add a return
        builder.CreateRet(result); // IR构建器插入 返回语句  return multiplyResult;
    
        // Print the IR
        verifyFunction(*function);
        module->print(outs(), nullptr);
    
        return 0;
    }
    
    /*
    ; ModuleID = 'HelloModule'
    source_filename = "HelloModule"
    
    @helloGlobalVariable = common global i32, align 4
    
    define i32 @HelloFunction(i32 %a, i32 %b) {
    entry:
      %multiplyResult = mul i32 %a, 3   ; multiplyResult = a* 3;
      ret i32 %multiplyResult           ; return multiplyResult;
    }
    
    
    */
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 加法 value = builder.CreateNSWAdd(left, right); add nsw i32 %2, %3
    • 减法 value = builder.CreateNSWSub(left, right); sub nsw i32 %5, %6
    • 乘法 value = builder.CreateNSWMul(left, right); mul nsw i32 %4, 3 result = builder.CreateMul(arg1, three, “multiplyResult”); mul i32 %a, 3
    • 除法 value = builder.CreateSDiv(left, right); sdiv i32 10, %2

    比较语句 Cmp

    CreateICmpSGT 整数 比较语句 有符号 singed great then > compare.result = arg > value33

    Value* condition = builder.CreateICmpSGT(arg, value33, “compare.result”)

    函数调用 builder.CreateCall

    builder.CreateCall(函数类型 FunctionType, 函数 Function, 函数实参)

    builder.CreateCall(calculatorWriteFunctionType, calculatorWriteFunction, {value}) // call void @calc_write(i32 %7)

    临时变量 栈变量 操作 CreateAlloca CreateStore CreateLoad

    CreateAlloca 指令在栈上申明一个局部变量。
    注意用alloca 指令申明的变量,其实得到是变量的地址。
    如果要访问它,我们需要用 CreateStore 和 CreateLoad 指令。

    分配变量 Value* bPtr = builder.CreateAlloca(builder.getInt32Ty() 类型, nullptr 初始值 , “b.address” 指针变量名)
    %b.address = alloca i32, align 4
    存储值 变量更新 builder.CreateStore(value66, bPtr); // bPtr = value66;
    store i32 %i.incremented, i32
    %i.address, align 4
    变量载入读取 Value* returnValue = builder.CreateLoad(bPtr, “return.value”); // return.value = bPtr;
    %3 = load i32, i32
    %i.address, align 4

    分支跳转 语句 CreateBr

    无条件跳转语句 builder.CreateBr(returnBlock 目标代码块);
    br label %for.condition

    条件跳转语句 builder.CreateCondBr(condition 条件变量, thenBlock 真 执行分支代码块, elseBlock 假执行分支代码块);

    br i1 %for.condition.compare.result, label %for.body, label %for.end

    分支汇合变量 phi

    PHINode* phi = builder.CreatePHI(builder.getInt32Ty(), 2); // 创建 phi 变量 类型 int32 两个候选 分支变量
    phi->addIncoming(value66, thenBlock); // 为phi 变量添加候选 分支变量组合 如果执行了 thenBlock 那么 phi = value66;
    phi->addIncoming(value77, elseBlock); // 为phi 变量添加候选 分支变量组合 如果执行了 elseBlock 那么 phi = value77;

    创建 指向 变量的指针变量

    GlobalVariable* str = new GlobalVariable(…);

    GlobalVariable* str = new GlobalVariable(*module,
    strText->getType(),
    /isConstant=/true,
    GlobalValue::PrivateLinkage,
    strText,
    Twine(variable).concat(“.str”));
    // 创建全局字符串变量
    @a.str = private constant [2 x i8] c"a\00"

    Value* ptr = builder.CreateInBoundsGEP(str, {int32Zero, int32Zero}, “ptr”);

    i8* getelementptr inbounds ([4 x i8], [4 x i8]* @abc.str, i32 0, i32 0)

    控制流 control flow if-else

    一个if-else语句包含了一个条件判断以及两个逻辑分支。

    最终会运行哪个分支的代码,取决于条件判断的结果为真还是假。而“条件”则一般是一个比较表达式 Compare。

    以下述c代码为例子,创建 对应的LLVM IR

    // Test.c
    
    int Test(int a)
    {
        int b; //可变变量b,当然它也是一个局部变量,我们可以在 函数 栈 上创建一个可变变量。
        // builder.CreateAlloca(Type类型, Value值, 名字) 返回的是 改变量的 指针
        // 然后使用 load 获取改变量的值    store value, var 改变该变量  存数据 到该变量上
        if (a > 33)
        {
            b = 66;
        }
        else
        {
            b = 77;
        }
    
        return b;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    对应 LLVM ir 构建方式

    
    // HelloIfElse.cpp
    
    #include "llvm/IR/Function.h"
    #include "llvm/IR/IRBuilder.h"
    #include "llvm/IR/LLVMContext.h"
    #include "llvm/IR/Module.h"
    #include "llvm/IR/Verifier.h"
    
    #include 
    
    using namespace llvm;
    
    int main(int argc, char* argv[])
    {
        LLVMContext context;
        IRBuilder<> builder(context);
    
        // Create a module
        Module* module = new Module("Test.c", context); // 模块文件名为 Test.c
    
        // Add a function
        std::vector<Type*> parameters(1, builder.getInt32Ty());
        FunctionType* functionType = FunctionType::get(builder.getInt32Ty(), parameters, false); // 函数类型 包含一个i32输入参数 返回值类型为 i32
        Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "Test", module); // 创建一个 函数 int test(int a)
    
        // Add an argument to the function 
        Value* arg = function->getArg(0);
        arg->setName("a"); //   设置函数参数名
    
        // Add some basic blocks to the function 创建函数内用到的代码块   scope代码块
        BasicBlock* entryBlock = BasicBlock::Create(context, "entry", function);   // 函数入口代码块 entry  也是主函数 score 代码块
        BasicBlock* thenBlock = BasicBlock::Create(context, "if.then", function);  // if then 分支代码块
        BasicBlock* elseBlock = BasicBlock::Create(context, "if.else", function);  // if else 分支代码块
        BasicBlock* returnBlock = BasicBlock::Create(context, "if.end", function); // if-else 后的代码块
        // Fill the "entry" block (1):
    
        // builder.SetInsertPoint 插入 入口代码块 主函数代码块
        //   int b;
        builder.SetInsertPoint(entryBlock); // 当前处理的的代码块
        // 函数栈 上分配 一个变量 返回变量指针  i32 类型变量 值为 nullptr  名为 b.address
        Value* bPtr = builder.CreateAlloca(builder.getInt32Ty(), nullptr, "b.address");
    
        // Fill the "entry" block (2):
        //   if (a > 33)
        ConstantInt* value33 = builder.getInt32(33); // 创建常量 33
        Value* condition = builder.CreateICmpSGT(arg, value33, "compare.result"); //创建 比较语句 compare.result = a > 33
        builder.CreateCondBr(condition, thenBlock, elseBlock); // 创建 控制流 条件跳转  if compare.result thenBlock; else elseBlock;
    
        // Fill the "if.then" block:
        //   b = 66;
        builder.SetInsertPoint(thenBlock); // 设置当前 处理的代码块 thenBlock 条件正确会执行的 代码块
        ConstantInt* value66 = builder.getInt32(66); // 获取常量 66
        builder.CreateStore(value66, bPtr);          // 栈变量 存储 b.address = 66;
        builder.CreateBr(returnBlock);               // 创建 直接跳转 无条件跳转语句  跳转到 if-else 后面的 returnBlock 代码块
    
        // Fill the "if.else" block:
        //   b = 77;
        builder.SetInsertPoint(elseBlock); // 设置当前 处理的代码块 elseBlock 条件错误会执行的 代码块
        ConstantInt* value77 = builder.getInt32(77); // 获取常量 77
        builder.CreateStore(value77, bPtr);          // 栈变量 存储 b.address = 77;
        builder.CreateBr(returnBlock);
    
        // Fill the "if.end" block:
        //   return b;
        builder.SetInsertPoint(returnBlock); // 设置当前 处理的代码块 returnBlock  if-else 后的代码块
        Value* returnValue = builder.CreateLoad(bPtr, "return.value"); // 创建栈变量 载入 语句  return.value = b.address;
        builder.CreateRet(returnValue);      // 当前 代码块 插入 返回语句  return return.value;
    
        // Print the IR
        verifyFunction(*function);
        module->print(outs(), nullptr);
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    ; ModuleID = 'Test.c'
    source_filename = "Test.c"
    
    define i32 @Test(i32 %a) {
    entry:
      %b.address = alloca i32, align 4                ; 分配栈变量 b.address = alloca
      %compare.result = icmp sgt i32 %a, 33           ; 比较语句  compare.result = a > 33
      br i1 %compare.result, label %if.then, label %if.else ; 条件跳转语句 if compare.result if.then; else if.else;
    
    if.then:                                          ; preds = %entry  父 代码块为 entry
      store i32 66, i32* %b.address, align 4          ; 栈变量存储语句 *b.address = 66
      br label %if.end                                ; 无条件跳转 到 if-else 之后的代码块 if.end
    
    if.else:                                          ; preds = %entry
      store i32 77, i32* %b.address, align 4          ; 栈变量存储语句 *b.address = 77
      br label %if.end
    
    if.end:                                           ; preds = %if.else, %if.then 父 代码块为 if.else if.then  入边所在的代码块
      %return.value = load i32, i32* %b.address, align 4 ; 栈变量读取语句 return.value  = *b.address;
      ret i32 %return.value                              ;  返回语句 return return.value
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    控制流 if-else phi CreatePHI 分支汇合 模式

    一个if-else语句包含了一个条件判断以及两个逻辑分支。最终会运行哪个分支的代码,取决于条件判断的结果为真还是假。而“条件”则一般是一个比较表达式。

    在很多情况下,控制流只是为了给某一个变量赋值,而phi 指令,则可以根据控制流来选择合适的值。它的用法如下(示例):

    %value = phi i32 [66, %branch1], [77, %branch2], [88, %branch3] ; 返回类型 i32 , ... 控制流变量
    
    • 1

    可以看到phi指令可以接收多个输入参数,参数的个数也不是固定的。

    第一个参数表示的是phi指令的返回值类型,如在以上示例中为i32。

    接下来的每一个参数都是一个数组,代表了每一个分支及其对应的返回值。

    例如,如果前一步执行的是branch1分支,则返回值为66;当执行的是branch2,则返回值为77;以此类推…

    
    // 创建PHI
    PHINode * llvm::IRBuilderBase::CreatePHI(Type * Ty, unsigned NumReservedValues, const Twine & Name = ""); // 返回类型, 候选值数量, phi变量名
    // 以及向phi指令中添加条件返回值:
    void llvm::PHINode::addIncoming(Value * V, BasicBlock * BB); // 值, 条件分子代码块
    
    • 1
    • 2
    • 3
    • 4
    • 5

    C函数跟上面 用到的是一样的,只不过 这次在IR代码中用到了phi指令而已。

    
    // HelloIfElsePhi.cpp
    
    #include "llvm/IR/Function.h"
    #include "llvm/IR/IRBuilder.h"
    #include "llvm/IR/LLVMContext.h"
    #include "llvm/IR/Module.h"
    #include "llvm/IR/Verifier.h"
    
    #include 
    
    using namespace llvm;
    
    int main(int argc, char* argv[])
    {
        LLVMContext context;
        IRBuilder<> builder(context);
    
        // Create a module
        Module* module = new Module("Test.c", context);
    
        // Add a function
        std::vector<Type*> parameters(1, builder.getInt32Ty());
        FunctionType* functionType = FunctionType::get(builder.getInt32Ty(), parameters, false); // 函数类型 int Test (int a)
        Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "Test", module);
    
        // Add an argument to the function
        Value* arg = function->getArg(0);
        arg->setName("a"); // 函数参数 a
    
        // Add some basic blocks to the function
        BasicBlock* entryBlock = BasicBlock::Create(context, "entry", function); // 入口代码块
        BasicBlock* thenBlock = BasicBlock::Create(context, "if.then", function);// 条件成立代码块
        BasicBlock* elseBlock = BasicBlock::Create(context, "if.else", function);// 条件不成立代码块
        BasicBlock* returnBlock = BasicBlock::Create(context, "if.end", function);// 条件语句后的代码块
    
        // Fill the "entry" block (1):
        //   int b;
        builder.SetInsertPoint(entryBlock); // 设置当前的代码快为 入口代码块
        Value* b = builder.CreateAlloca(builder.getInt32Ty(), nullptr, "b.address"); // 分配栈变量 b.address   int* = malloc()
    
        // Fill the "entry" block (2):
        //   if (a > 33)
        ConstantInt* value33 = builder.getInt32(33);
        Value* condition = builder.CreateICmpSGT(arg, value33, "compare.result");  // 条件语句 CreateICmpSGT compare.result = a > 33
        builder.CreateCondBr(condition, thenBlock, elseBlock);                     // 创建 条件跳转语句 CreateCondBr
    
        // Fill the "if.then" block:
        //   b = 66;
        builder.SetInsertPoint(thenBlock); // 设置当前的代码快为  条件true分支代码块
        ConstantInt* value66 = builder.getInt32(66); // 创建 value66 = 66;
        builder.CreateBr(returnBlock);               // 跳转到后面的代码块
    
        // Fill the "if.else" block:
        //   b = 77;
        builder.SetInsertPoint(elseBlock); // 设置当前的代码快为  条件false分支代码块
        ConstantInt* value77 = builder.getInt32(77); // 创建 value77 = 77;
        builder.CreateBr(returnBlock);
    
        // Fill the "if.end" block with phi instruction:
        //   return b;
        builder.SetInsertPoint(returnBlock);// 设置当前的代码快为 最后的代码快
        PHINode* phi = builder.CreatePHI(builder.getInt32Ty(), 2);  // 创建 phi 变量 类型 int32 两个候选 分支变量
        phi->addIncoming(value66, thenBlock);  // 为phi 变量添加候选 分支变量组合  如果执行了 thenBlock 那么 phi = value66;
        phi->addIncoming(value77, elseBlock);  // 为phi 变量添加候选 分支变量组合  如果执行了 elseBlock 那么 phi = value77;
        builder.CreateStore(phi, b);           // 创建 栈变量 存储语句    *b.address = phi;
        Value* returnValue = builder.CreateLoad(b, "return.value"); // 创建 栈变量 读取语句 return.value = *b.address
        builder.CreateRet(returnValue);        // 创建 返回值 语句 return return.value;
    
        // Print the IR
        verifyFunction(*function);
        module->print(outs(), nullptr);
    
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    ; ModuleID = 'Test.c'
    source_filename = "Test.c"
    
    define i32 @Test(i32 %a) {
    entry:
      %b.address = alloca i32, align 4
      %compare.result = icmp sgt i32 %a, 33
      br i1 %compare.result, label %if.then, label %if.else
    
    if.then:                                          ; preds = %entry
      br label %if.end
    
    if.else:                                          ; preds = %entry
      br label %if.end
    
    if.end:                                           ; preds = %if.else, %if.then
      %0 = phi i32 [ 66, %if.then ], [ 77, %if.else ] ; 分支变量汇合节点 %0 = 66 if if.then; else 77 if.else
      store i32 %0, i32* %b.address, align 4          ; 栈变量保存结果 *b.address = %0
      %return.value = load i32, i32* %b.address, align 4 ; 创建返回值变量    return.value  = *b.address
      ret i32 %return.value
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    循环语句 for

    一个for语句包含了条件判断以及循环执行的任务。具体循环多少次,取决于条件判断的结果。而“条件”则包含了循环的起点、终止条件、步进长度。

    这里的for循环语句IR,其实跟前面章节的if-else语句有些相似的地方。它们都需要用到 比较指令、跳转指令、栈上的变量等。

    // Test.c
    
    int Test(int a)
    {
        int b = 0; // 栈上的变量
    
        for (int i = 0; i < a; i++) // 比较指令、跳转指令
        {
            b = b + i; ; for body
        }
    
        return b;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    // HelloLoop.cpp
    
    #include "llvm/IR/Function.h"
    #include "llvm/IR/IRBuilder.h"
    #include "llvm/IR/LLVMContext.h"
    #include "llvm/IR/Module.h"
    #include "llvm/IR/Verifier.h"
    
    #include 
    
    using namespace llvm;
    
    int main(int argc, char* argv[])
    {
        LLVMContext context;
        IRBuilder<> builder(context);
    
        // Create a module
        Module* module = new Module("Test.c", context);
    
        // Add a function with argument
        //   int Test(int a)
        std::vector<Type*> parameters(1, builder.getInt32Ty()); // 参数类型数组
        FunctionType* functionType = FunctionType::get(builder.getInt32Ty(), parameters, false); // int(int)
        Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "Test", module);
        Value* a = function->getArg(0);
        a->setName("a");
    
        // Add some basic blocks to the function
        BasicBlock* entryBlock = BasicBlock::Create(context, "entry", function); // 函数 入口代码块
        BasicBlock* forConditionBlock = BasicBlock::Create(context, "for.condition", function); // for 条件代码块
        BasicBlock* forBodyBlock = BasicBlock::Create(context, "for.body", function);           // for 循环体代码块
        BasicBlock* forIncrementBlock = BasicBlock::Create(context, "for.increment", function); // for 计数代码块
        BasicBlock* forEndBlock = BasicBlock::Create(context, "for.end", function);             // 结束 代码块
         
        // entry -> for.condition
        // for.condition -> for.body -> for.increment -> for.condition 
        //               -> for.end
    
        // Fill the "entry" block (1):
        //   int b = 0;
        builder.SetInsertPoint(entryBlock); // 处理的当前 代码块 entry
        Value* bPtr = builder.CreateAlloca(builder.getInt32Ty(), nullptr, "b.address"); // 创建栈变量
        builder.CreateStore(builder.getInt32(0), bPtr); // 初始化为1  *b.address=0;
    
        // Fill the "entry" block (2):
        //   for (int i = 0; ...)
        Value* iPtr = builder.CreateAlloca(builder.getInt32Ty(), nullptr, "i.address"); // 创建 for 迭代 变量  也是临时变量 栈变量
        builder.CreateStore(builder.getInt32(0), iPtr); // i=0;
    
        builder.CreateBr(forConditionBlock);// 无条件跳转到 条件判断 代码块
    
        // 控制流 1
        // entry -> for.condition
    
        // Fill the "for.condition" block:
        //   for (... i < a; ...)
        builder.SetInsertPoint(forConditionBlock);// 处理的当前 代码块 for.condition
        Value* i0 = builder.CreateLoad(iPtr);     // 载入栈变量  循环迭代变量
        Value* forConditionCompare = builder.CreateICmpSLT(i0, a, "for.condition.compare.result"); // 创建比较语句 i
        builder.CreateCondBr(forConditionCompare, forBodyBlock, forEndBlock); // 创建条件跳转语句 
       
        // 控制流 2
        // for.condition ->cond==true  for.body 
        //               ->cond==false for.end
    
        // Fill the "for.body" block:
        //   b = b + i;
        builder.SetInsertPoint(forBodyBlock);// 处理的当前 代码块 for.body 
        Value* b0 = builder.CreateLoad(bPtr);// 读取栈变量 b =*bptr
        Value* i1 = builder.CreateLoad(iPtr);// 读取栈变量 i =*iptr
        Value* addResult = builder.CreateAdd(b0, i1, "add.result"); // 创建add运算并赋值  add.result = b +i
        builder.CreateStore(addResult, bPtr);// 存储栈变量  *bptr = add.result
        builder.CreateBr(forIncrementBlock); // 创建无条件跳转  
    
        // 控制流 3
        // for.body -> for.increment
    
    
        // Fill the "for.increment" block:
        //   for (... i++)
        builder.SetInsertPoint(forIncrementBlock);// 处理的当前 代码块 for.increment
        Value* i2 = builder.CreateLoad(iPtr);     // 读取栈变量 i =*iptr
        Value* incrementedI = builder.CreateAdd(i2, builder.getInt32(1), "i.incremented"); // 创建迭代变量自增语句  i.incremented = i++
        builder.CreateStore(incrementedI, iPtr);  // 更新 迭代变量  *iPtr = i.incremented
        builder.CreateBr(forConditionBlock); // 创建无条件跳转 
     
        // 控制流 4
        // for.increment -> for.condition 
       
    
        // Fill the "for.end" block:
        //   return b;
        builder.SetInsertPoint(forEndBlock); // 处理的当前 代码块 for.end
        Value* returnValue = builder.CreateLoad(bPtr, "return.value"); //  读取栈变量 return.value =*bptr
        builder.CreateRet(returnValue);      // 创建返回语句  return return.value;
    
        // Print the IR
        verifyFunction(*function);
        module->print(outs(), nullptr);
    
        return 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105

    IR 分析转换优化 IR PASS

    Pass是LLVM中很重要的部分。Pass大体上可以理解为一个“处理”,它处理的对象是IR代码。
    LLVM对代码的分析、转换和优化等处理工作都是由Pass来做的。
    LLVM以流水线的方式把各个Pass组合起来,让它们成为一个有序的流程。
    LLVM Pass可以处理的对象有模块(Module)、函数(Function)、循环(Loop),甚至函数调用栈(Function Call Graph)等等。

    简单分析 遍历函数打印函数名

    // MyPass.cpp
    
    #include "llvm/IR/PassManager.h"      // 遍管理器
    #include "llvm/Passes/PassBuilder.h"  // 遍构建器
    #include "llvm/Passes/PassPlugin.h"   // 遍插件
    #include "llvm/Support/raw_ostream.h"
    
    // Only needed for printing
    #include  
    
    using namespace llvm;
    
    namespace
    {
        class MyPass : public PassInfoMixin<MyPass>
        {
        public:
    
            // The first argument of the run() function defines on what level
            // of granularity your pass will run (e.g. Module, Function).
            // The second argument is the corresponding AnalysisManager
            // (e.g ModuleAnalysisManager, FunctionAnalysisManager)
            PreservedAnalyses run(Function& function, FunctionAnalysisManager& analysisManager)
            {
                std::cout << "MyPass in function: " << function.getName().str() << std::endl; // 打印当前遍历到函数名
    
                // Here goes what you want to do with a pass
    
                // Assuming we did not change anything of the IR code
                return PreservedAnalyses::all();
            }
        };
    }
    
    // This part is the new way of registering your pass
    extern "C" PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK llvmGetPassPluginInfo()
    {
        return
        {
            LLVM_PLUGIN_API_VERSION,
            "MyPass",
            "v0.1",
            [](PassBuilder &passBuilder) {
                passBuilder.registerPipelineParsingCallback(
                    [](StringRef name, FunctionPassManager &passManager, ArrayRef<PassBuilder::PipelineElement>) {
                        if(name == "my-pass")
                        {
                            passManager.addPass(MyPass());
                            return true;
                        }
    
                        return false;
                    }
                );
            }
        };
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
  • 相关阅读:
    一种基于Tent混沌映射初始化种群的改进灰狼算法
    网络安全(补充)
    3D图表有效提升数据大屏档次
    目标检测YOLO实战应用案例100讲-船舶目标检测及编队识别(续)
    xv6---Lab2: system calls
    【单片机毕业设计】【mcuclub-jk-003】基于单片机的非接触红外测温的设计
    Linux部署多个jar包脚本
    14. 线性代数 - 线性方程组
    有什么软件能实现erp、crm、oa、财务系统一体化?
    hadoop中遇到的问题
  • 原文地址:https://blog.csdn.net/xiaoxiaowenqiang/article/details/126217332