master
tinysnail 4 years ago
parent c6bccfeb47
commit 0eae00a037

@ -32,7 +32,7 @@
- [Constant](#constant) - [Constant](#constant)
- [Function](#function) - [Function](#function)
- [GlobalVariable](#globalvariable) - [GlobalVariable](#globalvariable)
- [IRBuilder](#irbuilder) - [IRStmtBuilder](#irstmtbuilder)
- [Instruction](#instruction-1) - [Instruction](#instruction-1)
- [Module](#module) - [Module](#module)
- [Type](#type) - [Type](#type)
@ -43,10 +43,10 @@
## IR ## IR
### IR Features ### IR Features
- 采用 3 地址的方式 - 采用类型化三地址代码的方式
- 区别于 X86 汇编的目标和源寄存器共用的模式: ADD EAX, EBX - 区别于 X86 汇编的目标和源寄存器共用的模式: ADD EAX, EBX
- %2 = add i32 %0, %1 - %2 = add i32 %0, %1
- SSA 形式 + 无限寄存器 - 静态单赋值 (SSA) 形式 + 无限寄存器
- 每个变量都只被赋值一次 - 每个变量都只被赋值一次
- 容易确定操作间的依赖关系,便于优化分析 - 容易确定操作间的依赖关系,便于优化分析
- 强类型系统 - 强类型系统
@ -61,8 +61,8 @@
- `functiontype`函数类型,包括函数返回值类型与参数类型(下述文档未提及) - `functiontype`函数类型,包括函数返回值类型与参数类型(下述文档未提及)
### IR Format ### IR Format
以下面的`easy.c`与`easy.ll`为例进行说明。 下面以`easy.c`与`easy.ll`为例进行说明。
通过命令`clang -S -emit-llvm easy.c`可以得到对应的`easy.ll`如下(助教增加了额外的注释)。`.ll`文件中注释以`;`开头。 通过命令`clang -S -emit-llvm easy.c`可以得到对应的`easy.ll`如下(其中增加了额外的注释)。`.ll`文件中注释以`;`开头。
- `easy.c`: - `easy.c`:
``` c ``` c
@ -125,7 +125,7 @@
!0 = !{i32 1, !"wchar_size", i32 4} !0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 10.0.1 "} !1 = !{!"clang version 10.0.1 "}
``` ```
其中每个program由1个或多个module组成module之间由LLVM Linker合并 每个program由1个或多个module组成每个module对应1个程序文件module之间由LLVM Linker进行链接形成1个可执行文件或者库
每个module组成如下 每个module组成如下
- Target Information - Target Information
``` c ``` c
@ -136,9 +136,9 @@
- Others:尾部其他信息 - Others:尾部其他信息
每个函数的组成如下: 每个函数的组成如下:
- 头部:函数返回值类型,函数名,函数参数 - 头部:函数返回值类型、函数名、函数参数
- 一个或多个基本块: - 一个或多个基本块:
- 每个基本块又有Label和Instruction组成。 - 每个基本块Label和Instruction组成。
``` c ``` c
8: ; preds = %7, %0 8: ; preds = %7, %0
%9 = load i32, i32* %2, align 4 %9 = load i32, i32* %2, align 4
@ -150,7 +150,7 @@
`%9 = load i32, i32* %2, align 4`中的`%9`是目的操作数,`load`是指令助记符,`i32`是`int32`的类型,`i32*`是指向`int32`的地址类型,`%2`是源操作数,`align 4`表示对齐。 `%9 = load i32, i32* %2, align 4`中的`%9`是目的操作数,`load`是指令助记符,`i32`是`int32`的类型,`i32*`是指向`int32`的地址类型,`%2`是源操作数,`align 4`表示对齐。
### Instruction ### Instruction
#### Terminator Instructions #### Terminator Instructions
**注**ret与br都是Terminator Instructions也就是终止指令在llvm基本块的定义里基本块是单进单出的因此只能有一条终止指令ret或br。当一个基本块有两条终止指令clang 在做解析会认为第一个终结指令是此基本块的结束,并会开启一个新的匿名的基本块(并占用了下一个编号)。 **注**ret与br都是Terminator Instructions也就是终止指令在llvm基本块的定义里基本块是单进单出的因此只能有一条终止指令ret或br。当一个基本块有两条终止指令clang 在做解析会认为第一个终结指令是此基本块的结束,并会开启一个新的匿名的基本块(并占用了下一个编号)。
##### Ret ##### Ret
- 格式 - 格式
- `ret <type> <value>` - `ret <type> <value>`
@ -201,7 +201,7 @@
- 例子: - 例子:
- `%ptr = alloca i32` - `%ptr = alloca i32`
- `%ptr = alloca [10 x i32]` - `%ptr = alloca [10 x i32]`
- 概念: `alloca`指令在当前执行函数的栈帧上分配内存,当该函数返回其调用者时将自动释放该内存。 始终在地址空间中为数据布局中指示的分配资源分配对象 - 概念: `alloca`指令在当前执行函数的栈帧上分配内存,当该函数返回其调用者时将自动释放该内存。 始终在地址空间中为数据布局中指示的分配资源分配对象
##### Load ##### Load
- 格式:`<result> = load <type>, <type>* <pointer>` - 格式:`<result> = load <type>, <type>* <pointer>`
@ -259,7 +259,7 @@
### 核心类概念图 ### 核心类概念图
to make ![](figs/核心类概念图.png)
### BasicBlock ### BasicBlock
- 继承:从[value](#value)继承 - 继承:从[value](#value)继承
@ -275,31 +275,31 @@ to make
- API: - API:
```c++ ```c++
static BasicBlock *create(Module *m, const std::string &name , Function *parent )
// 创建并返回BB块参数分别是BB块所属的Modulename是其名字默认为空BB块所属的Function // 创建并返回BB块参数分别是BB块所属的Modulename是其名字默认为空BB块所属的Function
Function *get_parent(); static BasicBlock *create(Module *m, const std::string &name , Function *parent )
// 返回BB块所属的函数 // 返回BB块所属的函数
Module *get_module(); Function *get_parent();
// 返回BB块所属的Module // 返回BB块所属的Module
Module *get_module();
// 返回BB块的终止指令(ret|br)若BB块最后一条指令不是终止指令返回null
Instruction *get_terminator(); Instruction *get_terminator();
// 返回BB块的终止指令(ret|br)若BB块最后一条指令不是终止指令返回null
void add_instruction(Instruction *instr);
// 将instr指令添加到此BB块指令链表结尾调用IRBuilder里来创建函数会自动调用此方法 // 将instr指令添加到此BB块指令链表结尾调用IRBuilder里来创建函数会自动调用此方法
void add_instr_begin(Instruction *instr); void add_instruction(Instruction *instr);
// 将instr指令添加到此BB块指令链表开头 // 将instr指令添加到此BB块指令链表开头
void add_instr_begin(Instruction *instr);
// 将instr指令从BB块指令链表中移除同时调用api维护好instr的操作数的use链表
void delete_instr(Instruction *instr); void delete_instr(Instruction *instr);
// 将instr指令从BB块指令链表中移除同时调用api维护好instr的操作数的use链表。 // BB块中指令数为空返回true
bool empty(); bool empty();
// BB块中为空返回true
int get_num_of_instr();
// 返回BB块中指令的数目 // 返回BB块中指令的数目
std::list<Instruction *> &get_instructions(); int get_num_of_instr();
//返回BB块的指令链表 //返回BB块的指令链表
void erase_from_parent(); std::list<Instruction *> &get_instructions();
// 将此BB块从所属函数的bb链表中移除 // 将此BB块从所属函数的bb链表中移除
void erase_from_parent();
/****************api about cfg****************/ /****************api about cfg****************/
std::list<BasicBlock *> &get_pre_basic_blocks() // 返回前驱集合 std::list<BasicBlock *> &get_pre_basic_blocks() // 返回前驱集合
std::list<BasicBlock *> &get_succ_basic_blocks() // 返回后继块集合 std::list<BasicBlock *> &get_succ_basic_blocks() // 返回后继块集合
void add_pre_basic_block(BasicBlock *bb) // 添加前驱块 void add_pre_basic_block(BasicBlock *bb) // 添加前驱块
void add_succ_basic_block(BasicBlock *bb) // 添加后继块 void add_succ_basic_block(BasicBlock *bb) // 添加后继块
@ -314,14 +314,14 @@ to make
- 继承:从[User](#user)继承 - 继承:从[User](#user)继承
- 含义:常数,各种类型常量的基类 - 含义:常数,各种类型常量的基类
- 子类: - 子类:
- ConstantInt - ConstantInt
- 含义int类型的常数 - 含义int类型的常数
- 成员 - 成员
- val_常数值 - val_常数值
- API - API
```cpp ```cpp
int get_value() // 返回该常数类型中存的常数值 int get_value() // 返回该常数类型中存的常数值
@ -330,25 +330,25 @@ to make
static ConstantInt *get(bool val, Module *m) // 以val值来创建bool常数类 static ConstantInt *get(bool val, Module *m) // 以val值来创建bool常数类
``` ```
- ConstantFP: - ConstantFP
- 含义float类型的常数 - 含义float类型的常数
- 成员 - 成员
- val_常数值 - val_常数值
- API - API
```cpp ```cpp
static ConstantFP *get(float val, Module *m) // 以val值创建并返回浮点数常量类 static ConstantFP *get(float val, Module *m) // 以val值创建并返回浮点数常量类
float get_value() // 返回该常数类型中存的常数值 float get_value() // 返回该常数类型中存的常数值
``` ```
- ConstantZero - ConstantZero
- 含义用于全局变量初始化的常量0值。 - 含义用于全局变量初始化的常量0值。
- API - API
```cpp ```cpp
static ConstantZero *get(Type *ty, Module *m);// 创建并返回ConstantZero常量类 static ConstantZero *get(Type *ty, Module *m);// 创建并返回ConstantZero常量类
@ -357,7 +357,7 @@ to make
- ConstantArray - ConstantArray
- 含义:数组类型的常数 - 含义:数组类型的常数
- 成员 - 成员
- const_array_数组常量值 - const_array_数组常量值
- APIcminus语法不需要数组常量的支持本次实验不需要用到在此不过多解释。感兴趣可以自行查看源代码。 - APIcminus语法不需要数组常量的支持本次实验不需要用到在此不过多解释。感兴趣可以自行查看源代码。
@ -366,16 +366,16 @@ to make
- 含义:函数,该类描述 LLVM 的一个简单过程,维护基本块表,格式化参数表 - 含义:函数,该类描述 LLVM 的一个简单过程,维护基本块表,格式化参数表
- 成员 - 成员
- basic_blocks_基本块列表 - basic_blocks_基本块列表
- arguments_形参列表 - arguments_形参列表
- parent_函数属于的module - parent_函数属于的module
- API - API
```cpp ```cpp
static Function *create(FunctionType *ty, const std::string &name, Module *parent); static Function *create(FunctionType *ty, const std::string &name, Module *parent);
// 创建并返回Function参数依次是待创建函数类型ty函数名字name(不可为空)函数所属的Module // 创建并返回Function参数依次是待创建函数类型ty、函数名字name(不可为空)、函数所属的Module
FunctionType *get_function_type() const; FunctionType *get_function_type() const;
// 返回此函数类的函数类型 // 返回此函数类的函数类型
Type *get_return_type() const; Type *get_return_type() const;
@ -404,11 +404,11 @@ to make
- 相关类 - 相关类
- Argument - Argument
- 含义:参数 - 含义:参数
- 成员 - 成员
- arg_no_参数序号 - arg_no_参数序号
- parent_参数属于哪个函数 - parent_参数属于哪个函数
@ -425,40 +425,40 @@ to make
- is_const是否为常量 - is_const是否为常量
- init_val_初始值 - init_val_初始值
- API由于cminusf语义要求所有的全局变量都默认初始化为0故`GlobalVariable`中成员和API再构造CminusFBuilder用不到 - API由于cminusf语义要求所有的全局变量都默认初始化为0故`GlobalVariable`中成员和API再构造CminusFBuilder用不到
### IRBuilder ### IRStmtBuilder
- 含义生成IR的辅助类该类提供了独立的接口创建各种 IR 指令,并将它们插入基本块中, 该辅助类不做任何类型检查。 - 含义生成IR的辅助类该类提供了独立的接口创建各种 IR 指令,并将它们插入基本块中, 该辅助类不做任何类型检查。
- API - API
```cpp ```cpp
BasicBlock *get_insert_block()// 返回正在插入指令的BB BasicBlock *get_insert_block()// 返回正在插入指令的BB
void set_insert_point(BasicBlock *bb)// 设置当前需要插入指令的bb void set_insert_point(BasicBlock *bb)// 设置当前需要插入指令的bb
Instruction *create_[instr_type]()// 创建instr_type(具体名字参考IRBuilder.h代码)的指令并对应插入到正在插入的BB块这种类型的指令看函数名字和参数名字和IR文档是一一对应的。 XXXInst *create_[instr_type]()// 创建instr_type(具体名字参考IRStmtBuilder.h代码)的指令并对应插入到正在插入的BB块这种类型的指令看函数名字和参数名字和IR文档是一一对应的。
``` ```
### Instruction ### Instruction
- 继承:从[User](#user)继承 - 继承:从[User](#user)继承
- 含义:指令,该类是所有 LLVM 指令的基类,主要维护指令的操作码(指令类别),指令所属的基本块,指令的操作数个数信息 - 含义:指令,该类是所有 LLVM 指令的基类,主要维护指令的操作码(指令类别),指令所属的基本块,指令的操作数个数信息
- 成员 - 成员
- parent_指令所属的BasicBlock - parent_指令所属的BasicBlock
- op_id_指令的类型id - op_id_指令的类型id
- num_ops_指令的操作数个数 - num_ops_指令的操作数个数
- 子类 - 子类
- BinaryInst双目运算指令包括add、sub、mul、div - BinaryInst双目运算指令包括add、sub、mul、div
- 其他子类和前述文档中提到的指令一一对应,不在此赘述。 - 其他子类和前述文档中提到的指令一一对应,不在此赘述。
- API所有指令的创建都要通过IRBuilder进行不需要关注Instruction类的实现细节**注**不通过IRBuilder来创建指令而直接调用指令子类的创建方法未经助教完善的测试 - API所有指令的创建都要通过 IRStmtBuilder 进行不需要关注Instruction类的实现细节**注**:不通过 IRStmtBuilder 来创建指令,而直接调用指令子类的创建方法未经助教完善的测试)
### Module ### Module
- 含义:一个编译单元,在此源语言的意义下是一个文件 - 含义:一个编译单元,在此源语言的意义下是一个文件
- 成员 - 成员
- function_list_函数链表记录了这个编译单元的所有函数 - function_list_函数链表记录了这个编译单元的所有函数
- global_list_全局变量链表 - global_list_全局变量链表
- instr_id2string_通过指令类型id得到其打印的string - instr_id2string_通过指令类型id得到其打印的string
- module_name_, source_file_name未使用 - module_name_, source_file_name未使用
- 从module中能取到的基本类型 - 从module中能取到的基本类型
- API - API
```cpp ```cpp
Type *get_void_type(); Type *get_void_type();
@ -479,19 +479,19 @@ to make
### Type ### Type
- 含义IR的类型该类是所有类型的超类 - 含义IR的类型该类是所有类型的超类
- 成员 - 成员
- tid_枚举类型表示type的类型包含VoidType、LabelType、FloatType、Int1、Int32、ArrayType、PointerType - tid_枚举类型表示type的类型包含VoidType、LabelType、FloatType、Int1、Int32、ArrayType、PointerType
- 子类 - 子类
- IntegerType - IntegerType
- 含义int 类型 - 含义int 类型
- 成员 - 成员
- num_bits长度i1或者i32 - num_bits长度i1或者i32
- API - API
```cpp ```cpp
unsigned get_num_bits();// 返回int的位数 unsigned get_num_bits();// 返回int的位数
@ -502,11 +502,11 @@ to make
- FunctionType - FunctionType
- 含义:函数类型 - 含义:函数类型
- 成员 - 成员
- result_返回值类型 - result_返回值类型
- args_参数类型列表 - args_参数类型列表
- API - API
```cpp ```cpp
static FunctionType *get(Type *result, std::vector<Type*> params); static FunctionType *get(Type *result, std::vector<Type*> params);
@ -525,11 +525,11 @@ to make
- ArrayType - ArrayType
- 含义:数组类型 - 含义:数组类型
- 成员 - 成员
- contained_数组成员的类型 - contained_数组成员的类型
- num_elements_数组维数 - num_elements_数组维数
- API - API
```cpp ```cpp
static ArrayType *get(Type *contained, unsigned num_elements) static ArrayType *get(Type *contained, unsigned num_elements)
@ -542,11 +542,11 @@ to make
- PointerType - PointerType
- 含义:指针类型 - 含义:指针类型
- 成员 - 成员
- contained_指针指向的类型 - contained_指针指向的类型
- API - API
```cpp ```cpp
Type *get_element_type() const { return contained_; } Type *get_element_type() const { return contained_; }
@ -557,7 +557,7 @@ to make
// 对于pointertype而言返回指针指向的类型其他则返回nullptr // 对于pointertype而言返回指针指向的类型其他则返回nullptr
``` ```
- API: - API
```cpp ```cpp
bool is_void_type()// 判断是否是void类型其他类型有类似API请查看Type.h bool is_void_type()// 判断是否是void类型其他类型有类似API请查看Type.h
@ -572,11 +572,11 @@ to make
- 含义:使用者,提供一个操作数表,表中每个操作数都直接指向一个 Value, 提供了 use-def 信息,它本身是 Value 的子类, Value 类会维护一个该数据使用者的列表提供def-use信息。简单来说操作数表表示我用了谁该数据使用者列表表示谁用了我。这两个表在后续的**优化实验**会比较重要请务必理解。 - 含义:使用者,提供一个操作数表,表中每个操作数都直接指向一个 Value, 提供了 use-def 信息,它本身是 Value 的子类, Value 类会维护一个该数据使用者的列表提供def-use信息。简单来说操作数表表示我用了谁该数据使用者列表表示谁用了我。这两个表在后续的**优化实验**会比较重要请务必理解。
- 成员 - 成员
- operands_参数列表表示这个使用者所用到的参数 - operands_参数列表表示这个使用者所用到的参数
- num_ops_表示该使用者使用的参数的个数 - num_ops_表示该使用者使用的参数的个数
- API - API
```cpp ```cpp
Value *get_operand(unsigned i) const; Value *get_operand(unsigned i) const;
@ -593,18 +593,15 @@ to make
// 移除操作数链表中索引为index1-index2的操作数例如想删除第0个操作数remove_operands(0,0) // 移除操作数链表中索引为index1-index2的操作数例如想删除第0个操作数remove_operands(0,0)
``` ```
### Value ### Value
- 含义:最基础的类,代表一个操作数,代表一个可能用于指令操作数的带类型数据 - 含义:最基础的类,代表一个操作数,代表一个可能用于指令操作数的带类型数据
- 成员 - 成员
- use_list_记录了所有使用该操作数的指令的列表 - use_list_记录了所有使用该操作数的指令的列表
- name_名字 - name_名字
- type_类型一个type类表示操作数的类型 - type_类型一个type类表示操作数的类型
- API - API
```cpp ```cpp
Type *get_type() const //返回这个操作数的类型 Type *get_type() const //返回这个操作数的类型
@ -617,8 +614,6 @@ to make
// 将val从this的use_list_中移除 // 将val从this的use_list_中移除
``` ```
### 总结 ### 总结
助教在接口文档里筛选了可能会需要用到的接口,如果对API有问题的请移步issue讨论本次`SysYF IR`接口由助教自行设计实现并做了大量测试如有对助教的实现方法有异议或者建议的也请移步issue讨论**请不要直接修改助教的代码,若因修改助教代码造成后续实验仓库合并的冲突请自行解决**。 在本文档里提供了为SysYF语言程序生成LLVM IR可能需要用到的SysYF IR应用编程接口如果对这些API有问题的请移步issue讨论本次`SysYF IR`应用编程接口由助教自行设计实现并做了大量测试如有对助教的实现方法有异议或者建议的也请移步issue讨论**请不要直接修改助教的代码,若因修改助教代码造成后续实验仓库合并的冲突请自行解决**。

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Loading…
Cancel
Save