master
tinysnail 3 years ago
parent f5f2a9a299
commit 8dda4afde1

@ -42,53 +42,53 @@
├── src ├── src
│   ├── ... │   ├── ...
│   ├── SysYFIR │   ├── SysYFIR
│   └── SysYFBuilder │   └── SysYFIRBuilder
| ├── CMakeLists.txt | ├── CMakeLists.txt
| └── SysYFBuilder.cpp <- | └── IRBuilder.cpp <-
└── SysYF_Student └── Student
├── CMakeLists.txt ├── CMakeLists.txt
├── SysYF_Task1 ├── task1
| ├── student_ll <- PW6.ll | ├── ll <- PW6.ll
| | ├── assign_hand.ll | | ├── assign_hand.ll
|   │   ├── fun_hand.ll |   │   ├── fun_hand.ll
|   │   ├── if_hand.ll |   │   ├── if_hand.ll
|   │   └── while_hand.ll |   │   └── while_hand.ll
| ├── student_sy | ├── sy
| | ├── assign.sy | | ├── assign_test.sy
|   │   ├── fun.sy |   │   ├── fun_test.sy
|   │   ├── if.sy |   │   ├── if_test.sy
|   │   └── while.sy |   │   └── while_test.sy
| └── ta_demo | └── demo
|      └── go_upstairs.c |      └── go_upstairs.c
├── SysYF_Task2 ├── task2
| ├── student_cpp <- PW6.cpp | ├── cpp <- PW6.cpp
| | ├── CMakeLists.txt | | ├── CMakeLists.txt
| | ├── assign_gen.cpp | | ├── assign_gen.cpp
|   │   ├── fun_gen.cpp |   │   ├── fun_gen.cpp
|   │   ├── if_gen.cpp |   │   ├── if_gen.cpp
|   │   └── while_gen.cpp |   │   └── while_gen.cpp
| ├── student_sy | ├── sy
| | ├── assign.sy | | ├── assign_test.sy
|   │   ├── fun.sy |   │   ├── fun_test.sy
|   │   ├── if.sy |   │   ├── if_test.sy
|   │   └── while.sy |   │   └── while_test.sy
| └── ta_demo | └── demo
|      |── CMakeLists.txt |      |── CMakeLists.txt
|      |── go_upstairs.sy |      |── go_upstairs.sy
|      └── go_upstairs_gen.cpp <- go_upstairs.llcpp |      └── go_upstairs_gen.cpp <- go_upstairs.llcpp
└── SysYF_Task3 └── task3
└── Test_H └── test
├── test_H.py <- PW6 ├── test.py <- PW6
└── Easy_H <- └── test <-
``` ```
### 1.2 提交要求和评分标准 ### 1.2 提交要求和评分标准
* 提交要求 * 提交要求
本实验的提交要求分为两部分: 实验部分的文件和报告。 本实验的提交要求分为两部分: 实验部分的文件和报告。
* 实验部分: * 实验部分:
* 需要完成 `./SysYF_Student/SysYF_Task1/student_ll`目录下的4个文件 * 需要完成 `./Student/task1/ll`目录下的4个文件
* 需要完成 `./SysYF_Student/SysYF_Task2/student_cpp`目录下的4个文件 * 需要完成 `./Student/task2/cpp`目录下的4个文件
* 需要完成 `./src/SysYFBuilder/SysYFBuilder.cpp` * 需要完成 `./src/SysYFIRBuilder/IRBuilder.cpp`
* 需要在 `./report/report.md` 中撰写实验报告 * 需要在 `./report/report.md` 中撰写实验报告
* 实验报告内容包括: * 实验报告内容包括:
* 实验要求、问题回答、实验设计、实验难点及解决方案、实验总结、实验反馈、组间交流(具体参考[report.md](./report.md)) * 实验要求、问题回答、实验设计、实验难点及解决方案、实验总结、实验反馈、组间交流(具体参考[report.md](./report.md))

@ -3,13 +3,13 @@
--- ---
### 任务描述 ### 任务描述
本关任务熟悉LLVM IR并根据给出的4个sy程序手写ll文件以实现相同功能。 **本关任务**熟悉LLVM IR并根据给出的4个sy程序手写相应的LLVM IR的ll文件以实现相同功能。
### 相关知识 ### 相关知识
#### LLVM IR介绍 #### LLVM IR介绍
根据[维基百科](https://zh.wikipedia.org/zh-cn/LLVM)的介绍LLVM是一个自由软件项目它是一种编译器基础设施以C++写成,包含一系列模块化的编译器组件和工具链,用来开发编译器前端和后端。IR的全称是Intermediate Representation即中间表示。LLVM IR是一种类似于汇编的底层语言。 [LLVM](https://llvm.org/)是一个开源的编译器基础设施用C++语言编写,包含一系列模块化的编译器组件和工具链,用来支持编译器前端和后端的开发。IR的全称是Intermediate Representation即中间表示。LLVM IR是一种类型化的三地址中间表示,是类似于汇编的底层语言。
LLVM IR的具体指令可以参考[Reference Manual](http://llvm.org/docs/LangRef.html)。但是你会发现其内容庞杂。虽然助教认为,高效地查阅官方文档及手册是非常必要的一项技能,但是由于其手册过于复杂,因此助教筛选了后续实验中将要用到的子集,总结为了**精简的IR Reference手册**`doc/SysYFIR.md`。 LLVM IR的具体指令可以参考[Reference Manual](http://llvm.org/docs/LangRef.html)。但是你会发现其内容庞杂为便于你尽快了解本实训项目需要涉及的LLVM IR指令子集请查看本实训提供的**精简的IR Reference手册**`doc/SysYFIR.md`。
作为一开始的参考,你可以先阅读其中`IR Features`和`IR Format`两节,后续有需要再反复参考。 作为一开始的参考,你可以先阅读其中`IR Features`和`IR Format`两节,后续有需要再反复参考。
#### 样例学习 #### 样例学习
<details> <details>
@ -47,22 +47,28 @@ int main(){
``` ```
</details> </details>
阅读`SysYF_Student/SysYF_Task1/ta_demo/go_upstairs.c`。
在`SysYF_Student/SysYF_Task1/ta_demo`文件夹内输入`clang -S -emit-llvm go_upstairs.c`指令,你可以得到对应的`go_upstairs.ll`。 - 阅读`Student/task1/demo/go_upstairs.c`。
- 进入`Student/task1/demo`文件夹,输入命令
```clang -S -emit-llvm go_upstairs.c```
你可以得到对应的`go_upstairs.ll`。
你需要结合`go_upstairs.c`阅读`go_upstairs.ll`理解其中每条LLVM IR指令与C代码的对应情况。 你需要结合`go_upstairs.c`阅读`go_upstairs.ll`理解其中每条LLVM IR指令与C代码的对应情况。
通过`lli go_upstairs.ll; echo $?`指令,你可以测试`go_upstairs.ll`执行结果的正确性。 - 通过执行命令
```lli go_upstairs.ll; echo $?```
你可以测试`go_upstairs.ll`执行结果的正确性。
### 本关具体任务 ### 本关具体任务
1. 助教在`SysYF_Student/SysYF_Task1/student_sy/`内提供了四个简单的sy程序:`assign_test.sy``func_test.sy``if_test.sy``while_test.sy`。 1. 在`Student/task1/student_sy/`内提供了四个简单的SysYF 程序:`assign_test.sy``func_test.sy``if_test.sy``while_test.sy`。
你需要在`SysYF_Student/SysYF_Task1/student_ll/`内手工完成自己的`assign_test.ll``func_test.ll``if_test.ll``while_test.ll`文件以实现与上述C程序相同的逻辑功能。 你需要在`Student/task1/ll/`目录下手工编写`assign_hand.ll``func_hand.ll``if_hand.ll``while_hand.ll`文件,以实现与上述 SysYF 程序相同的逻辑功能。
你需要在`ll`文件内添加必要的注释,`ll`文件的注释是以`;`开头的。 你需要在`ll`文件内添加必要的注释,`ll`文件的注释是以`;`开头的。
必要的情况下,你可以参考`clang -S -emit-llvm`的输出,但是你提交的结果必须避免同此输出一字不差。 必要的情况下,你可以参考`clang -S -emit-llvm`的输出,但是你提交的结果必须避免同此输出一字不差。
2. 在`report.md`内回答[思考题](#思考题) 2. 在`report.md`内回答[思考题](#思考题)
### 运行说明 ### 运行说明
- `lli`会运行`*.ll`文件 - 利用LLVM的命令`lli`,可以执行`*.ll`文件
- `$?`的内容是上一条命令所返回的结果,而`echo $?`可以将其输出到终端中 - `$?`的内容是上一条命令所返回的结果,而`echo $?`可以将其输出到终端中
- 使用`clang`时,注意`sy`文件是我们定义的语言文件,`clang`是无法直接识别的 - 使用`clang`时,注意扩展名为`sy`的文件是SysYF语言的程序文件,`clang`是无法直接识别的
### 思考题 ### 思考题
请在`report/report.md`中详细回答下述思考题。 请在`report/report.md`中详细回答下述思考题。

@ -3,12 +3,12 @@
--- ---
### 任务描述 ### 任务描述
本关任务熟悉SysYF IR接口并根据给出的4个C程序手写C++代码调用SysYF IR接口生成与sy文件功能相同的ll文件。 **本关任务**熟悉SysYF IR的应用编程接口并根据给出的4个SysYF程序手写调用SysYF IR应用编程接口的C++代码,生成与sy文件功能相同的ll文件。
### 相关知识 ### 相关知识
#### SysYF IR - LLVM IR的C++接口 #### SysYF IR 应用编程接口
由于LLVM IR官方的C++接口的文档同样过于冗长助教提供了SysYF IR这一C++接口库。你需要阅读**SysYF IR核心类的介绍**`doc/SysYFIR.md`。 由于LLVM IR官方的C++应用编程接口的文档内容繁多本实训项目提供SysYF IR应用编程接口库该库用C++编写可以用于生成LLVM IR的子集。你需要阅读**SysYF IR核心类的介绍**`doc/SysYFIR.md`。
本关会要求大家通过SysYF IR根据AST构建生成LLVM IR。所以你需要仔细阅读文档了解其接口的设计。 本关要求你根据AST使用SysYF IR应用编程接口来构建生成LLVM IR。你需要先仔细阅读文档`doc/SysYFIR.md`以了解其接口的设计。
#### 样例学习 #### 样例学习
<details> <details>
@ -98,15 +98,15 @@
``` ```
</details> </details>
为了让大家更直观地感受并学会SysYF IR接口的使用助教提供了`SysYF_Student/SysYF_Task2/ta_demo/go_upstairs_gen.cpp`。 为了更直观地感受并学会使用 SysYF IR应用编程接口本实训项目提供了示例代码位于`Student/task2/demo/go_upstairs_gen.cpp`。
该C++程序会生成与go_upstairs.c逻辑相同的LLVM IR文件。助教提供了详尽的注释,一定要好好利用 该C++程序会生成与go_upstairs.c逻辑相同的LLVM IR文件在该C++程序中提供了详尽的注释,请阅读理解,以便更好地开展你的实验
### 本关具体任务 ### 本关具体任务
1. 你需要在`SysYF_Student/SysYF_Task2/student_cpp/`文件夹中调用SysYF IR接口,编写自己的`assign_gen.cpp``func_gen.cpp``if_gen.cpp``while_gen.cpp`程序,以生成与phase1的四个sy程序相同逻辑功能的ll文件。 1. 你需要在`Student/task2/cpp/`文件夹中调用SysYF IR应用编程接口,编写自己的`assign_gen.cpp``func_gen.cpp``if_gen.cpp``while_gen.cpp`程序,以生成与第1关的四个sy 程序相同逻辑功能的ll文件。
2. 在`report.md`内回答[思考题](#思考题) 2. 在`report.md`内回答[思考题](#思考题)
### 编译、运行和验证 ### 编译、运行和验证
`SysYF_Student/SysYF_Task2/build/` 下执行: `Student/task2/build/` 下执行:
``` shell ``` shell
# 如果存在 CMakeCache.txt 要先删除 # 如果存在 CMakeCache.txt 要先删除
# rm CMakeCache.txt # rm CMakeCache.txt
@ -114,15 +114,15 @@ cmake ..
make make
``` ```
你可以得到对应`assign_gen.cpp``func_gen.cpp``if_gen.cpp``while_gen.cpp``go_upstairs_gen.cpp`的可执行文件`assign_generator``func_generator``if_generator``while_generator``go_upstairs_generator`。 你可以得到对应`assign_gen.cpp``func_gen.cpp``if_gen.cpp``while_gen.cpp``go_upstairs_gen.cpp`的可执行文件`assign_generator``func_generator``if_generator``while_generator``go_upstairs_generator`。
之后直接执行可执行文件即可得到对应ll文件 之后直接执行可执行文件即可得到对应ll文件
``` shell ``` shell
# 在build文件夹内 # 在build文件夹内
./go_upstairs_generator ./go_upstairs_generator
``` ```
### 思考题 ### 思考题
请在`report/report.md`中详细回答下述思考题 请在`report/report.md`中详细回答下述思考题
1. 请给出`SysYFIR.md`中提到的两种getelementptr用法的区别, 并解释原因: 2-1. 请给出`SysYFIR.md`中提到的两种getelementptr用法的区别, 并解释原因:
- `%2 = getelementptr [10 x i32], [10 x i32]* %1, i32 0, i32 %0` - `%2 = getelementptr [10 x i32], [10 x i32]* %1, i32 0, i32 %0`
- `%2 = getelementptr i32, i32* %1, i32 %0` - `%2 = getelementptr i32, i32* %1, i32 %0`

@ -3,13 +3,13 @@
--- ---
### 任务描述 ### 任务描述
本关任务:编写`SysYFBuilder.cpp`文件,以实现 IR 的自动生成 **本关任务**:编写`IRBuilder.cpp`文件实现低级中间代码生成器为SysYF语言程序生成兼容的LLVM IR代码。
### 相关知识 ### 相关知识
#### 实验框架 #### 实验框架
次实验使用了由 C++ 编写的 SysYF IR 来生成 LLVM IR。为了便于大家进行实验该框架自动完成了语法树到 C++ 上的抽象语法树的转换。 实训项目提供用C++语言编写的SysYF IR 应用编程库,用于构建 LLVM IR的子集。为了简化你的实验本实训的实验框架代码已完成了SysYF源程序到 C++ 上的抽象语法树的转换。
在`SysYFBuilder.hpp`中,我们还定义了一个用于存储作用域的类`Scope`。它的作用是辅助我们在遍历语法树时,管理不同作用域中的变量。它提供了以下接口: 在`IRBuilder.h`中,还定义了一个用于存储作用域的类`Scope`。它的作用是在遍历语法树时,辅助管理不同作用域中的变量。它提供了以下接口:
```cpp ```cpp
// 进入一个新的作用域 // 进入一个新的作用域
void enter(); void enter();
@ -23,11 +23,12 @@ Value* find(std::string name, bool isfunc);
// 判断当前是否在全局作用域内 // 判断当前是否在全局作用域内
bool in_global(); bool in_global();
``` ```
需要根据语义合理调用`enter`与`exit`,并且在变量声明和使用时正确调用`push`与`find`。在类`SysYFBuilder`中,有一个`Scope`类型的成员变量`scope`,它在初始化时已经将特殊函数加入了作用域中。因此,你在进行名字查找时不需要顾虑是否需要对特殊函数进行特殊操作。 你需要根据语义合理调用`enter`与`exit`,并且在变量声明和使用时正确调用`push`与`find`。在类`SysYFIRBuilder`中,有一个`Scope`类型的成员变量`scope`,它在初始化时已经将特殊函数加入了作用域中。因此,你在进行名字查找时不需要顾虑是否需要对特殊函数进行特殊操作。
### 本关具体任务 ### 本关具体任务
1. 你需要在`src/SysYFBuilder`文件夹中调用SysYF IR接口填写`SysYFBuilder.cpp`文件,以实现 IR 的自动生成。 1. 你需要在`src/SysYFIRBuilder`文件夹中调用SysYF IR应用编程接口填写`IRBuilder.cpp`文件,以实现 LLVM IR 的自动生成。
2. 在`report.md`内回答[思考题](#思考题) 2. 在`report.md`内回答[思考题](#思考题)
3. 在`contribution.md`内由组长填写各组员的贡献比
### 编译、运行与验证 ### 编译、运行与验证
@ -40,7 +41,7 @@ cmake ..
make make
``` ```
编译后会产生 `SysYFCompiler` 程序它能将sy文件输出为LLVM IR。 编译后会产生 `SysYFCompiler` 程序,它能将SysYF源程序sy文件输出为LLVM IR。
当需要对 sy 文件测试时,可以这样使用: 当需要对 sy 文件测试时,可以这样使用:
```sh ```sh
@ -50,19 +51,19 @@ SysYFCompiler test.sy -emit-ir -o test.ll
#### 自动测试 #### 自动测试
助教提供了自动评测脚本, 在`SysYF_Student/SysYF_Task3/Test_H/`目录下执行`python3 test_H.py`, 即可得到评测信息 本实训项目提供了自动评测脚本, 在`Student/task3/`目录下执行`python3 test.py`, 即可得到评测信息
### 思考题 ### 思考题
请在`report/report.md`中详细回答下述思考题。 请在`report/report.md`中详细回答下述思考题。
1. 在`scope`内单独处理`func`的好处有哪些。 3-1. 在`scope`内单独处理`func`的好处有哪些。
2.
### 选做 ### 选做
对于学有余力的小组, 我们提供了选做环节, 若小组能完成选做部分, 将会有额外加分(仅针对本次实验的团队代码得分, 并且分数不能超过该部分得分上限) 本实训项目提供了选做内容, 若你能完成选做部分, 将会有额外加分(仅针对本次实验的团队代码得分, 并且分数不能超过该部分得分上限)
选做部分验收方式为线下验收,你需要在线下检查时提供对应代码通过助教给出的选做部分测试样例,并且讲解你的代码 选做部分验收方式为线下验收,你需要在线下检查时提供对应代码通过助教给出的选做部分测试样例,并且讲解你的代码
选做部分说明如下: 选做部分说明如下:
- 多维数组 - 多维数组
@ -70,20 +71,20 @@ SysYFCompiler test.sy -emit-ir -o test.ll
#### 多维数组 #### 多维数组
目前给出的SysYF IR接口并不支持多维数组的实现因此你需要修改接口以实现多维数组的声明、初始化和使用你可以修改的内容为文件夹`include/SysYFIR``include/SysYFBuilder``src/SysYFIR``src/SysYFBuilder`内的所有内容 目前给出的SysYF IR应用编程接口并不支持多维数组的实现,因此你需要修改接口,以实现多维数组的声明、初始化和使用,你可以修改的内容为文件夹`include/SysYFIR``include/SysYFIRBuilder``src/SysYFIR``src/SysYFIRBuilder`内的所有内容
多维数组在目前的接口基础上,一般有两种做法: 多维数组在目前的接口基础上,一般有两种做法:
- 直接实现,参考 clang 生成的 LLVM IR修改当前接口使其支持多维的数组类型 - 直接实现,可以参考 clang 生成的 LLVM IR修改当前接口使其支持多维的数组类型
- 展平,把高维数组当成一维数组存储,修改当前接口使其能保存一些必要信息 - 展平,把高维数组当成一维数组存储,修改当前接口使其能保存一些必要信息
在初始化多维数组时,与一维数组不同的是存在对齐问题,我们设定多维数组的初始化为完全对齐(在每个大括号处均对齐),以下两种初始化是等价的: 在初始化多维数组时,与一维数组不同的是,存在对齐问题,这里假设多维数组的初始化为完全对齐(在每个大括号处均对齐),以下两种初始化是等价的:
`int a[5][2] = {1,{2,3},{4},{5,6,7}}` `int a[5][2] = {1,{2,3},{4},{5,6,7}}`
`int a[5][2] = {{1,0},{2,3},{4,0},{5,6},{7,0}}` `int a[5][2] = {{1,0},{2,3},{4,0},{5,6},{7,0}}`
### 备注 ### 备注
测试样例并不止公开的20个样例, 助教准备了许多隐藏测例来考验大家:), 隐藏测例并不会放在平台上 测试样例除了位于版本库中的公开测例外,还包含不开放的隐藏测例。
平台上第三部分的评测只判断公开样例是否完全通过, 第三部分的分数由助教线下检查后根据公开样例和隐藏样例的通过情况确定, 因此请自行设计合法样例测试你们的代码,确保你们的代码考虑了足够多情况以通过尽可能多的隐藏样例 平台上第三关的评测只判断公开测例是否完全通过, 第三关的分数由助教线下检查后,根据公开测例和隐藏测例的通过情况确定, 因此请自行设计合法测例测试你们的代码,确保你们的代码考虑了足够多情况以通过尽可能多的隐藏测例。
平台编译评测耗时会较长请耐心等待可能会在十分钟以上因此请大家都尽量提前完成不要卡Deadline 请将你编写的测例代码上传到`Student/task3/test_stu/`。

Loading…
Cancel
Save