# SysY 编译器课程实验（C++）

本仓库为“并行编译课程实验”提供一个 SysY 编译器的最小可运行示例，实验按 Lab1–Lab6 逐步完成：
从前端（词法/语法分析与语法树处理）到中端（IR 生成与优化），再到后端（ARM64/AArch64 汇编生成、寄存器分配与后端优化），最后进行循环/并行相关优化。

## 1. 实验介绍

| 实验 | 名称 | 任务/目标 |
| --- | --- | --- |
| Lab1 | 语法树构建 | 基于 SysY 源程序完成语法分析与语法树构建，并按约定输出语法树 |
| Lab2 | 中间表示生成 | 将语法树翻译为 LLVM 风格的中间表示（IR），并输出 IR |
| Lab3 | 指令选择与汇编生成 | 将 IR 翻译为目标平台汇编代码（本项目以 ARM64/AArch64 为主） |
| Lab4 | 寄存器分配与后端优化 | 为后端生成的虚拟寄存器分配物理寄存器，并完成 spill/reload、冗余指令消除与局部后端优化 |
| Lab5 | 基本标量优化 | 实现常见的标量优化（如常量传播、死代码删除、简化 CFG 等） |
| Lab6 | 并行与循环优化 | 面向循环的优化（循环变换/并行化等），进一步提升程序性能 |

## 2. 实验环境配置

### 2.1 系统建议

建议使用 Ubuntu  22.04 或 WSL（Ubuntu  22.04 环境）。

### 2.2 安装基础依赖

本项目使用 CMake + C++17 构建；前端基于 ANTLR，运行 ANTLR 的 `antlr-*.jar` 需要 Java。

```bash
sudo apt update
sudo apt install -y build-essential cmake git openjdk-11-jre
```

### 2.3 安装 LLVM 工具链

`scripts/verify_ir.sh` 在 `--run` 模式下会调用 LLVM 工具链（`llc` 与 `clang`）将生成的 IR 编译并运行。

```bash
sudo apt update
sudo apt install -y llvm clang
```

### 2.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
```

## 3. 编译与运行

### 3.1 生成 Lexer/Parser

本仓库已内置 ANTLR jar：`third_party/antlr-4.13.2-complete.jar`。
当前 CMake 只会收集构建目录中的 Lexer/Parser 生成文件，不会自动调用 ANTLR；因此首次构建前，需要先生成 Lexer/Parser 及相关生成文件。

生成文件不提交到仓库，统一输出到 `build/generated/antlr4/`。

```bash
mkdir -p build/generated/antlr4

java -jar third_party/antlr-4.13.2-complete.jar \
  -Dlanguage=Cpp \
  -visitor -no-listener \
  -Xexact-output-dir \
  -o build/generated/antlr4 \
  src/antlr4/SysY.g4
```

### 3.2 CMake 构建

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j "$(nproc)"
```

构建成功后，可执行文件位于：`./build/bin/compiler`。

### 3.3 运行自检

运行帮助信息能正常输出，说明基本环境与可执行文件均正常：

```bash
./build/bin/compiler --help
```

跑完整编译流程自检：从 SysY 源码生成 AArch64 汇编，完成汇编、链接，并在 QEMU 下运行结果程序：

```bash
./scripts/verify_asm.sh test/test_case/simple_add.sy test/test_result/asm --run
```

如果最终看到 `退出码: 3`，说明当前最小子集示例 `return a + b` 的完整链路已经跑通。
