|
|
|
|
@ -0,0 +1,186 @@
|
|
|
|
|
# SysY 编译器课程实验(Rust)
|
|
|
|
|
|
|
|
|
|
本仓库为“并行编译课程实验”提供一个 SysY 编译器的最小可运行示例,实验按 Lab1 至 Lab6 逐步完成:
|
|
|
|
|
从前端(词法/语法分析与语法树处理)到中端(IR 生成、基本标量优化),再到后端(ARM64/AArch64 汇编生成、寄存器分配与后端优化),最后进行循环/并行相关优化。目前仓库提供了面向 AArch64 的后端实现,未提供 RISC-V 后端代码;但从 SysY 源程序到中端生成的实现与机器无关,Lab1 至 Lab4 的内容对 RISC-V 同样具有参考价值,二者在后端指令集与寄存器方面存在差异,但实现思路是共通的。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 一、实验内容
|
|
|
|
|
|
|
|
|
|
| 实验 | 名称 | 任务/目标 |
|
|
|
|
|
| :--- | :------------------- | :---------------------------------------------------------- |
|
|
|
|
|
| Lab1 | 语法树构建 | 基于 SysY 源程序完成语法分析与语法树构建,并按约定输出语法树 |
|
|
|
|
|
| Lab2 | 中间表示生成 | 将语法树翻译为 LLVM 风格的中间表示(IR),并输出 IR |
|
|
|
|
|
| Lab3 | 指令选择与汇编生成 | 将 IR 翻译为目标平台汇编代码(本项目以 ARM64/AArch64 为主) |
|
|
|
|
|
| Lab4 | 基本标量优化 | 实现常量传播、死代码删除、简化控制流图等标量优化 |
|
|
|
|
|
| Lab5 | 寄存器分配与后端优化 | 为虚拟寄存器分配物理寄存器,完成溢出/重载、冗余指令消除与局部优化 |
|
|
|
|
|
| Lab6 | 并行与循环优化 | 面向循环的优化(循环变换/并行化等),进一步提升程序性能 |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 二、关于 Rust
|
|
|
|
|
|
|
|
|
|
Rust 是一门由 Mozilla 开发的现代系统级编程语言,其特点在于能够在保证与 C/C++ 相媲美的性能(无垃圾收集和运行时)的同时,通过所有权系统和借用检查器,在编译期杜绝内存安全和并发安全方面的常见错误(如空指针、悬垂指针和数据竞争)。此外,Rust 还提供零成本抽象、模式匹配、包管理器 Cargo 以及友好的编译器错误提示。
|
|
|
|
|
|
|
|
|
|
结合编译比赛的实际经验,提供几点参考:
|
|
|
|
|
|
|
|
|
|
- Rust 学习曲线较 C/C++ 稍陡,但本实验所设计的编译器较为基础,未涉及过于复杂的 Rust 高级用法。网上存在许多可用参考资料:
|
|
|
|
|
- [菜鸟教程](https://www.runoob.com/rust/rust-tutorial.html)
|
|
|
|
|
- [Rust 程序设计语言](https://kaisery.github.io/trpl-zh-cn/)
|
|
|
|
|
- [Rust 语言圣经](https://course.rs/basic/intro.html)
|
|
|
|
|
- 此外,[南开大学编译系统原理](https://junimay.github.io/nku-compiler-2024-rs/intro.html#)的实验文档同时提供了 C++ 和 Rust 的实现介绍。
|
|
|
|
|
- Rust 提供成熟的项目管理工具 Cargo,无需手写 Makefile,可一站式解决依赖、编译和运行问题。
|
|
|
|
|
- Rust 编译器检查严格,若实现逻辑正确且通过编译,通常可避免运行时的内存错误,调试时配合 VSCode 的 `CodeLLDB` 插件即可。
|
|
|
|
|
- Rust 并非面向对象语言,不存在类的概念,结构体之间的关系可能不如 C++ 直观,但枚举类型为语法树操作提供了便利。
|
|
|
|
|
- Rust 提供 `lalrpop` 等语法解析工具,便于实现语法分析器和灵活的 AST 操作。
|
|
|
|
|
- Rust 生态系统丰富,许多库可直接使用,相关资源可访问 [Rust 官方学习页面](https://rust-lang.org/zh-CN/learn/)。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 三、实验环境配置
|
|
|
|
|
|
|
|
|
|
### 3.1 系统建议
|
|
|
|
|
|
|
|
|
|
建议使用 **Ubuntu 22.04** 或 **WSL(Ubuntu 22.04 环境)**。虽然 Rust 在 Windows 和 Linux 上均可方便配置,但后续可能使用 ARM 或 RISC-V 工具链,在 Linux 环境下配置更为便捷。
|
|
|
|
|
|
|
|
|
|
### 3.2 Rust 环境配置
|
|
|
|
|
|
|
|
|
|
在 Ubuntu 中安装 Rust 环境:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
安装完成后,验证:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
rustc --version
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
建议搭配 VSCode 使用,并安装插件 `rust-analyzer`。
|
|
|
|
|
|
|
|
|
|
### 3.3 安装 LLVM 工具链
|
|
|
|
|
|
|
|
|
|
LLVM 工具链可用于生成中间表示(IR),若输出的 IR 符合 LLVM-IR 语法,可在 IR 层验证中间代码生成和优化的正确性,便于与后端开发解耦。
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
sudo apt update
|
|
|
|
|
sudo apt install -y llvm clang
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 3.4 安装 ARM64 交叉编译工具链与 QEMU
|
|
|
|
|
|
|
|
|
|
后续实验将生成 ARM64/AArch64 汇编代码,并使用 ARM64 交叉编译工具链完成汇编与链接;通过 QEMU 用户态模拟器运行生成的 ARM 可执行文件。
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# 安装 ARM64 交叉编译工具链
|
|
|
|
|
sudo apt update
|
|
|
|
|
sudo apt install gcc-aarch64-linux-gnu
|
|
|
|
|
|
|
|
|
|
# 安装 QEMU 用户模式模拟器
|
|
|
|
|
sudo apt install qemu-user
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 四、目录结构
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
.
|
|
|
|
|
├── doc
|
|
|
|
|
│ └── Git Commit Message 规范.md
|
|
|
|
|
├── src
|
|
|
|
|
│ ├── backend
|
|
|
|
|
│ │ ├── mir
|
|
|
|
|
│ │ ├── regalloc
|
|
|
|
|
│ │ ├── asm2string.rs
|
|
|
|
|
│ │ ├── mirgen.rs
|
|
|
|
|
│ │ └── mod.rs
|
|
|
|
|
│ ├── frontend
|
|
|
|
|
│ │ ├── ir
|
|
|
|
|
│ │ ├── lalrpop
|
|
|
|
|
│ │ ├── ir2string.rs
|
|
|
|
|
│ │ ├── irgen.rs
|
|
|
|
|
│ │ ├── mod.rs
|
|
|
|
|
│ │ ├── symboltable.rs
|
|
|
|
|
│ │ └── typecheck.rs
|
|
|
|
|
│ ├── passes
|
|
|
|
|
│ ├── utils
|
|
|
|
|
│ │ ├── linked_list.rs
|
|
|
|
|
│ │ ├── mod.rs
|
|
|
|
|
│ │ └── storage.rs
|
|
|
|
|
│ └── main.rs
|
|
|
|
|
├── test
|
|
|
|
|
│ ├── output
|
|
|
|
|
│ │ ├── test
|
|
|
|
|
│ │ ├── test.ll
|
|
|
|
|
│ │ └── test.s
|
|
|
|
|
│ └── test_case
|
|
|
|
|
│ ├── functional
|
|
|
|
|
│ ├── performance
|
|
|
|
|
│ └── test.sy
|
|
|
|
|
├── Cargo.lock
|
|
|
|
|
├── Cargo.toml
|
|
|
|
|
├── README.md
|
|
|
|
|
└── build.rs
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 五、编译与运行
|
|
|
|
|
|
|
|
|
|
### 5.1 编译编译器
|
|
|
|
|
|
|
|
|
|
使用以下命令编译生成可执行文件:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cargo build --release
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
编译生成的可执行文件 `compiler` 位于 `nudt-compiler-rust/target/release/` 中。
|
|
|
|
|
- `--release` 表示以发布模式编译,开启优化,生成的可执行文件运行速度快,但调试信息较少,适合最终测试。
|
|
|
|
|
- 若需调试,可去掉 `--release` 使用默认的 debug 模式,编译速度更快,包含完整调试信息。
|
|
|
|
|
|
|
|
|
|
### 5.2 运行编译器
|
|
|
|
|
|
|
|
|
|
- **基本用法**
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
compiler [选项] source_file
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- **参数列表**
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 描述 | 示例 |
|
|
|
|
|
| :----------- | :--- | :----------------------------------------------------------- | :-------------------- |
|
|
|
|
|
| `-ast <file>` | 可选 | 将抽象语法树(AST)输出到指定文件 | `-ast ast.txt` |
|
|
|
|
|
| `-ir <file>` | 可选 | 将中间表示(IR)输出到指定文件 | `-ir ir.txt` |
|
|
|
|
|
| `-asm <file>` | 可选 | 将汇编代码输出到指定文件(优先级高于 `-S` 和 `-o`) | `-asm output.s` |
|
|
|
|
|
| `-S` | 标志 | 生成汇编代码,输出到 stdout 或通过 `-o` 指定的文件 | `-S` |
|
|
|
|
|
| `-o <file>` | 可选 | 指定汇编代码的输出文件(仅当同时使用 `-S` 时有效) | `-o output.s` |
|
|
|
|
|
| `-O1` | 标志 | 启用一级优化 | `-O1` |
|
|
|
|
|
| `-h` | 标志 | 显示帮助信息 | `-h` |
|
|
|
|
|
|
|
|
|
|
- **示例**
|
|
|
|
|
|
|
|
|
|
1. **生成中间文件**(用于调试)
|
|
|
|
|
```bash
|
|
|
|
|
compiler -ast ast.txt -ir ir.txt -asm output.s test.sy
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
2. **生成优化后的中间文件**
|
|
|
|
|
```bash
|
|
|
|
|
compiler -O1 -ast ast.txt -ir ir.txt -asm output.s test.sy
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
3. **仅生成汇编并输出到文件**(比赛功能用例的编译命令)
|
|
|
|
|
```bash
|
|
|
|
|
compiler -S -o test.s test.sy
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
4. **启用优化**(比赛性能用例的编译命令)
|
|
|
|
|
```bash
|
|
|
|
|
compiler -O1 -S -o test.s test.sy
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明**:`-ast`、`-ir`、`-asm` 参数主要用于开发调试,比赛环境中仅使用上述 3、4 所示的命令格式。
|