Lab3 实验建立在 Lab2 的基础上,带领大家进一步理解源代码到 IR 的生成过程。同前置实验一样,需要你使用 LightIR
框架自动产生 cminus-f
语言的LLVM IR。经过 Lab2 的练手,相信你已经初步掌握了 LightIR 的使用,并且对于 LLVM IR 也有了一定的理解。
在本次实验中,你的核心任务是使用访问者模式来实现 IR 的自动生成。完成这一阶段后,调用 clang 从 IR 进一步生成可执行文件,这样一个初级的 cminus-f 编译器就完成了。
- 阅读cminus-f 的语义规则,我们将按照语义实现程度进行评分
- 阅读LightIR 核心类介绍
- 阅读实验框架,理解如何使用框架以及注意事项
- 修改
src/cminusfc/cminusf_builder.cpp
来实现 IR 自动产生的算法,使得它能正确编译任何合法的 cminus-f 程序。 - 在
report.md
中解释你的设计,遇到的困难和解决方案
友情提示:
- 助教们在
cminusf_builder.cpp
中提供了基础实现,比如CminusfBuilder::visit(ASTFunDeclaration &node)
等函数。这些函数为示例代码,请你在开始实验前先仔细阅读学习文件中的这些代码片段,理解其含义和作用。 - 助教们在
cminusf_builder.cpp
提供的部分函数是不完整的,无法通过所有测试用例。需要你补充代码的地方已经用TODO
标出。我们提供的cminusf_builder.cpp
只可以满足测试用例lv0_1
中的return.cminus
。虽然eval.py
会显示其他一些测试用例也是success
,但它对应的.ll
文件是不正确的,不要因其显示success
忽略了对应的代码补充,那会影响你后面较复杂样例的正确性。 - 简要阅读
cminusf_builder.hpp
和其他头文件中定义的函数和变量,理解项目框架也会为你的实验提供很大的帮助。 - 请独立完成实验,不要抄袭他人代码。
- 为方便同学们更好完成实验,补充提示文档,参见Lab3 More Tips。
本次实验使用了由C++编写的 LightIR 来生成 LLVM IR。为了便于大家进行实验,该框架自动完成了语法树到 C++ 上的抽象语法树的转换。
我们可以使用访问者模式来设计抽象语法树
中的算法。大家可以参考lab2的样例和打印抽象语法树的算法,
以及运行 test_ast
来理解访问者模式下算法的执行流程。
在 include/cminusf_builder.hpp
中,我们还定义了一个用于存储作用域的类Scope
。它的作用是辅助我们在遍历语法树时,管理不同作用域中的变量。它提供了以下接口:
// 进入一个新的作用域
void enter();
// 退出一个作用域
void exit();
// 往当前作用域插入新的名字->值映射
bool push(std::string name, Value *val);
// 根据名字,寻找到值
Value* find(std::string name);
// 判断当前是否在全局作用域内
bool in_global();
你需要根据语义合理调用enter
与exit
,并且在变量声明和使用时正确调用push
与find
。在类CminusfBuilder
中,有一个Scope
类型的成员变量scope
,它在初始化时已经将input
、output
等函数加入了作用域中。因此,你们在进行名字查找时不需要顾虑是否需要对特殊函数进行特殊操作。
mkdir build && cd build
cmake ..
make clean
make -j
# 安装库 libcminus_io.a 至系统目录
# docker 实验环境下
make install
# 其他非 docker 实验环境且非 root 用户需要 sudo make install
编译后会产生 cminusfc
程序,它能将cminus文件输出为LLVM IR,也可以利用 clang 将 IR 编译成二进制可执行文件。程序逻辑写在src/cminusfc/cminusfc.cpp
中。
当需要对 .cminus
文件测试时,可以这样使用:
# 假设 cminusfc 的路径在你的$PATH中
# 1. 利用构建好的 Module 生成 test.ll
# 注意,如果调用了外部函数,如 input, output 等,则无法使用lli运行
cminusfc test.cminus -emit-llvm
# 假设libcminus_io.a的路径在$LD_LIBRARY_PATH中,clang的路径在$PATH中
# 1. 利用构建好的 Module 生成 test.ll
# 2. 调用 clang 来编译 IR 并链接上静态链接库 libcminus_io.a,生成二进制文件 test
cminusfc test.cminus
自动测试脚本和所有测试样例都是公开的,它在 tests/3-ir-gen
目录下,使用方法如下:
# 在 tests/3-ir-gen 目录下运行:
./eval.py
测试结果会输出到同文件夹的 eval_result
下。
分析输出日志是进行程序调试的好方法,为方便大家进行实验,助教们提供了一个轻量级的日志分析工具 logging
,可分等级打印调试信息,更详细的说明请阅读使用文档。
- 请比较通过你编写的编译器产生的 IR 和通过 clang 产生的IR来找出可能的问题或发现新的思路
- 可以使用 logging 工具来打印调试信息
- 可以使用 GDB 等软件进行动态分析,可以单步调试来检查错误的原因
.
├── CMakeLists.txt
├── Documentations
│ ├── ...
│ ├── common
│ | ├── LightIR.md <- LightIR 相关文档
│ | ├── logging.md <- logging 工具相关文档
│ | └── cminusf.md <- cminus-f 的语法和语义文档
│ └── 3-ir-gen
│ └── README.md <- lab3 实验文档说明(你在这里)
├── include <- 实验所需的头文件
│ ├── ...
│ ├── lightir/*
│ ├── cminusf_builder.hpp
| └── ast.hpp
├── Reports
│ ├── ...
│ └── 3-ir-gen
│ └── report.md <- lab3 所需提交的实验报告,请详细说明你们的设计(需要上交)
├── src
│ ├── ...
│ └── cminusfc
│ ├── cminusfc.cpp <- cminusfc 的主程序文件
│ └── cminusf_builder.cpp <- lab3 需要修改的文件,你们要在该文件中用访问者模式实现自动 IR 生成的算法(需要上交)
└── tests
├── ...
└── 3-ir-gen
├── testcases <- 助教提供的测试样例
├── answers <- 助教提供的测试样例
└── eval.py <- 助教提供的测试脚本
-
提交要求 本实验的提交要求分为两部分: 实验部分的文件和报告,git提交的规范性。
-
实验部分:
-
需要完善
src/cminusfc/cminusf_builder.cpp
-
需要在
Reports/3-ir-gen/
目录下撰写实验报告report.md
- 实验报告内容主要包括实验要求、实现难点、实验反馈等(具体参考repord.md)
-
本次实验收取
src/cminusfc/cminusf_builder.cpp
文件和Reports/3-ir-gen
目录
-
-
git提交规范:
- 请勿破坏目录结构,特别是
CMakeLists.txt
文件 - 如果需要在报告文档 repord.md 中插入图片,请放在目录
Reports/3-ir-gen/figs/
下) - 请勿上传构建过程中生成的临时文件
- (不强制)git commit message 请提供简洁有效信息,可以参考学习 Augular git commit 格式规范
- 请勿破坏目录结构,特别是
-
-
提交方式:
-
代码提交:本次实验需要在希冀课程平台上发布的作业Lab3-代码提交提交自己仓库的 gitlab 链接(注:由于平台限制,请提交http协议格式的仓库链接。例:学号为 PB011001 的同学,Lab3 的实验仓库地址为
http://202.38.79.174/PB011001/2022fall-compiler_cminus.git
),我们会收集最后一次提交的评测分数,作为最终代码得分。 -
报告提交:
将 Reports/3-ir-gen/report.md
导出成 pdf 文件单独提交到Lab3-报告提交。 -
提交异常:如果遇到在平台上提交异常的问题,请通过邮件联系助教,助教将收取截止日期之前,学生在 gitlab 仓库最近一次 commit 内容进行评测。
-
-
评分标准:
- 实验分数组成如下:
- cminusf 程序测试 (75分)
report.md
(25分)
- 禁止执行恶意代码,违者本次实验0分处理
- 实验分数组成如下:
-
迟交规定
Soft Deadline
: 2022/11/13 23:59:59 (北京标准时间,UTC+8)Hard Deadline
: 2022/11/20 23:59:59 (北京标准时间,UTC+8)- 迟交需要邮件通知TA:
- 邮箱:
[email protected]
抄送[email protected]
- 邮件主题: lab3迟交-学号-姓名
- 内容: 包括迟交原因、最后版本commitID、迟交时间等
- 邮箱:
- 迟交分数
- x为迟交天数(对于
Soft Deadline
而言),grade为满分final_grade = grade, x = 0 final_grade = grade * (0.9)^x, 0 < x <= 7 final_grade = 0, x > 7
- x为迟交天数(对于
-
关于抄袭和雷同 经过助教和老师判定属于实验抄袭或雷同情况,所有参与方一律零分,不接受任何解释和反驳。
如有任何问题,可以通过邮件联系助教,也欢迎在论坛提意见进行批判指正。