diff --git a/doc/phase1.md b/doc/phase1.md index 6f1f9c6..9c8039f 100644 --- a/doc/phase1.md +++ b/doc/phase1.md @@ -1,33 +1,33 @@ # IR实验阶段一 本实验由黄庄湫、吴毓辰助教设计 -## 前言 +## 0 前言 本次实验的目的是让大家熟悉阶段三所需相关知识: LLVM IR -## 任务描述 +## 1 任务描述 [了解LLVM IR](#llvm-ir介绍) [通过clang生成的.ll,了解LLVM IR与c代码的对应关系](#例子-利用clang生成的ll) [根据c程序手写.ll文件实现相同功能](#你需要做-手动编写ll) -## 实验内容 -### LLVM IR介绍 +## 2 实验内容 +### 2.1 LLVM IR介绍 根据[维基百科](https://zh.wikipedia.org/zh-cn/LLVM)的介绍,LLVM是一个自由软件项目,它是一种编译器基础设施,以C++写成,包含一系列模块化的编译器组件和工具链,用来开发编译器前端和后端。IR的全称是Intermediate Representation,即中间表示。LLVM IR是一种类似于汇编的底层语言。 LLVM IR的具体指令可以参考[Reference Manual](http://llvm.org/docs/LangRef.html)。但是你会发现其内容庞杂。虽然助教认为,高效地查阅官方文档及手册是非常必要的一项技能,但是由于其手册过于复杂,因此助教筛选了后续实验中将要用到的子集,总结为了[精简的IR Reference手册](./SysYIR.md)。 作为一开始的参考,你可以先阅读其中`IR Features`和`IR Format`两节,后续有需要再反复参考。 -### 例子: 利用clang生成的.ll +### 2.2 例子: 利用clang生成的.ll 阅读`SysYF_Student/SysYF_Task1/ta_demo/go_upstairs.c` 在对应文件夹内输入`clang -S -emit-llvm go_upstairs.c`指令,你可以得到对应的`go_upstairs.ll` 你需要结合`go_upstairs.c`阅读`go_upstairs.ll`,理解其中每条LLVM IR指令与c代码的对应情况。 通过`lli go_upstairs.ll; echo $?`指令,你可以测试`go_upstairs.ll`执行结果的正确性。 -### 你需要做: 手动编写.ll +### 2.3 你需要做: 手动编写.ll 助教在`SysYF_Student/SysYF_Task1/student_sy/`内提供了四个简单的sy程序: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程序相同的逻辑功能。你需要添加必要的注释,`.ll`文件的注释是以`;`开头的 必要的情况下,你可以参考`clang -S -emit-llvm`的输出,但是你提交的结果必须避免同此输出一字不差 注:`.sy`文件是我们定义的语言文件,`clang`无法直接识别 -### 运行.ll文件 +### 2.4 运行.ll文件 - `lli`会运行`*.ll`文件 - `$?`的内容是上一条命令所返回的结果,而`echo $?`可以将其输出到终端中 \ No newline at end of file diff --git a/doc/phase2.md b/doc/phase2.md index 6e92574..db646d7 100644 --- a/doc/phase2.md +++ b/doc/phase2.md @@ -1,28 +1,28 @@ # IR实验阶段二 本实验由黄庄湫、吴毓辰助教设计 -## 前言 +## 0 前言 本次实验的目的是让大家熟悉阶段三所需相关知识: SysY IR(由助教编写的LLVM IR的轻量级C++接口)。 -## 任务描述 +## 1 任务描述 [了解SysY IR](#sysy-ir---llvm-ir的c接口) [通过助教提供的C++例子,了解SysY IR的C++接口及实现](#例子-利用sysy-ir--cpp-生成ll) [根据c程序手写C++文件调用SysY IR的API生成相同功能的.ll文件](#你需要做-利用sysy-ir--c编写生成ll的程序) -## 实验内容 -### SysY IR - LLVM IR的C++接口 +## 2 实验内容 +### 2.1 SysY IR - LLVM IR的C++接口 由于LLVM IR官方的C++接口的文档同样过于冗长,助教提供了SysY IR这一C++接口库。你需要阅读[SysY IR核心类的介绍](./SysYIR.md)。 本关会要求大家通过SysY IR根据AST构建生成LLVM IR。所以你需要仔细阅读文档了解其接口的设计。 -### 例子: 利用SysY IR + C++ 生成.ll +### 2.2 例子: 利用SysY IR + C++ 生成.ll 为了让大家更直观地感受并学会LightIR接口的使用,助教提供了`SysYF_Student/SysYF_Task2/ta_demo/go_upstairs_gen.cpp`。 该C++程序会生成与go_upstairs.c逻辑相同的LLVM IR文件。助教提供了详尽的注释,一定要好好利用! -### 你需要做: 利用SysY IR + C++编写生成.ll的程序 +### 2.3 你需要做: 利用SysY IR + C++编写生成.ll的程序 你需要在`SysYF_Student/SysYF_Task2/student_cpp/`文件夹中,调用SysY IR接口,编写自己的assign_gen.cpp,func_gen.cpp,if_gen.cpp,while_gen.cpp程序,以生成与phase1的四个sy程序相同逻辑功能的`.ll`文件。 -### 编译、运行和验证 +### 2.4 编译、运行和验证 在 `SysYF_Student/SysYF_Task2/build/` 下执行: ``` shell # 如果存在 CMakeCache.txt 要先删除 diff --git a/doc/phase3.md b/doc/phase3.md index 5c5a5a4..7f41aaa 100644 --- a/doc/phase3.md +++ b/doc/phase3.md @@ -1,11 +1,11 @@ # IR实验阶段三 本实验由黄庄湫、吴毓辰助教设计 -## 前言 +## 0 前言 本次实验我们要使用访问者模式来实现 IR 自动生成。 对于产生的IR, 我们可以调用 clang 生成可执行文件,这样一个初级的 SysYF 编译器就完成啦! -## 任务描述 +## 1 任务描述 阅读[SysYF 的语义规则](../SysYF语言定义.pdf),注意本次实验必做部分语言可能与前几次实验有不同 阅读[SysY IR 核心类介绍](./SysYIR.md) @@ -14,9 +14,9 @@ 修改 `src/SysYBuilder/SysYBuilder.cpp` 来实现自动 IR 产生的算法,使得它能正确编译任何合法的 SysYF 程序 注: 本次实验不需要实现多维数组 -## 实验框架 +## 2 实验框架 -本次实验使用了由C++编写的 SysY IR 来生成 LLVM IR。为了便于大家进行实验,该框架自动完成了语法树到 C++ 上的抽象语法树的转换。 +本次实验使用了由 C++ 编写的 SysY IR 来生成 LLVM IR。为了便于大家进行实验,该框架自动完成了语法树到 C++ 上的抽象语法树的转换。 在SysYBuilder.hpp中,我们还定义了一个用于存储作用域的类`Scope`。它的作用是辅助我们在遍历语法树时,管理不同作用域中的变量。它提供了以下接口: ```cpp @@ -35,9 +35,9 @@ bool in_global(); ``` 你们需要根据语义合理调用`enter`与`exit`,并且在变量声明和使用时正确调用`push`与`find`。在类`SysYfBuilder`中,有一个`Scope`类型的成员变量`scope`,它在初始化时已经将特殊函数加入了作用域中。因此,你们在进行名字查找时不需要顾虑是否需要对特殊函数进行特殊操作。 -## 运行与调试 +## 3 运行与调试 -### 运行 SysYCompiler +### 3.1 运行 SysYCompiler ```sh mkdir build @@ -54,27 +54,43 @@ make SysYCompiler test.sy -emit-ir -o test.ll ``` -### 自动测试 +### 3.2 自动测试 助教提供了自动评测脚本, 在`SysYF_Student/SysYF_Task3/Test_H/`目录下执行`python3 test_H.py`, 即可得到评测信息 -### Bonus +## 4 选做 -对于学有余力的小组, 我们提供了Bonus环节, 若小组能完成Bonus部分, 将会有额外加分(仅针对本次实验的团队代码得分, 并且分数不能超过该部分得分上限) +对于学有余力的小组, 我们提供了选做环节, 若小组能完成选做部分, 将会有额外加分(仅针对本次实验的团队代码得分, 并且分数不能超过该部分得分上限) -Bonus部分说明如下: +选做部分验收方式为线下验收,你需要在线下检查时提供对应代码通过助教给出的选做部分测试样例,并且讲解你的代码 + +选做部分说明如下: - H班: - 多维数组 - 网安班: + - 多维数组 - 将一维数组指针作为参数 - 逻辑运算(\&\&, \|\|, \!), 重点考察短路计算 - - 多维数组 -Bonus部分得分标准: 每个部分单独给分, 每个部分需要通过全部对应测例并在线下检查时给助教讲清思路才能得分 +### 4.1 多维数组 + +目前给出的SysY IR接口并不支持多维数组的实现,因此你需要修改接口,以实现多维数组的声明、初始化和使用,你可以修改的内容为文件夹`include/SysYIR`,`include/SysYBuilder`,`src/SysYIR`,`src/SysYBuilder`内的所有内容 -若小组完成了Bonus部分, 需在线下检查时向助教提出, 并让助教当场检查. 若在统一线下检查过后自行找助教检查, 该Bonus不算分 +多维数组在目前的接口基础上,一般有两种做法: +- 直接实现,参考 clang 生成的 LLVM IR,修改当前接口使其支持多维的数组类型 +- 展平,把高维数组当成一维数组存储,修改当前接口使其能保存一些必要信息 -### 备注 +在初始化多维数组时,与一维数组不同的是存在对齐问题,我们设定多维数组的初始化为完全对齐(在每个大括号处均对齐),以下两种初始化是等价的: +`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}}` + +### 4.2 数组指针参数 & 逻辑运算 + +目前给出的SysY IR接口支持数组指针参数和逻辑运算的短路计算,因此你不需要修改接口 +注意`pointer`和`array`的区别以及文法中`&&`和`||`的优先级 + +## 5 备注 测试样例并不止公开的20个样例, 助教准备了许多隐藏测例来考验大家:), 隐藏测例并不会放在平台上 -平台上第三部分的分数并不具有参考性, 第三部分的分数由助教线下检查后确定 + +平台上第三部分的评测只判断公开样例是否完全通过, 第三部分的分数由助教线下检查后根据公开样例和隐藏样例的通过情况确定, 因此请自行设计合法样例测试你们的代码,确保你们的代码考虑了足够多情况以通过尽可能多的隐藏样例