94 lines
3.7 KiB
Markdown
94 lines
3.7 KiB
Markdown
要打通从SysY到RISC-V的完整编译流程,以下是必须实现的核心模块和关键步骤(按编译流程顺序)。在你们当前IR生成阶段,可以优先实现这些基础模块来快速获得可工作的RISC-V汇编输出:
|
||
|
||
### 1. **前端必须模块**
|
||
- **词法/语法分析**(已完成):
|
||
- `SysYLexer`/`SysYParser`:ANTLR生成的解析器
|
||
- **IR生成核心**:(已完成)
|
||
- `SysYIRGenerator`:将AST转换为中间表示(IR)
|
||
- `IRBuilder`:构建指令和基本块的工具类(你们正在实现的部分)
|
||
- **IR打印器**:(基本完成)
|
||
- `SysYIRPrinter`: 打印llvm ir格式的指令,优化遍后查看优化效果,la指令,subarray数组翻译范式需要改进
|
||
|
||
### 2. **中端必要优化(最小集合)**
|
||
- **CFG优化**:(待测试)
|
||
- `SysYIROptPre`:CFG优化顺便解决IR生成的缺陷(void自动添加ret指令,合并嵌套if/while语句生成的多个exit(后续可以实现回填机制))
|
||
|
||
常量传播
|
||
| 优化阶段 | 关键作用 | 是否必须 |
|
||
|-------------------|----------------------------------|----------|
|
||
| `Mem2Reg` | 消除冗余内存访问,转换为SSA形式 | ✅ 核心 |(必须)
|
||
| `DCE` (死代码消除) | 移除无用指令 | ✅ 必要 |(必须)
|
||
| `DFE` (死函数消除) | 移除未使用的函数 | ✅ 必要 |(必须)
|
||
| `Global2Local` | 全局变量降级为局部变量 | ✅ 重要 |
|
||
|
||
还需要做 Reg2Mem
|
||
|
||
|
||
### 3. **后端核心流程(必须实现)**
|
||
```mermaid
|
||
graph LR
|
||
A[IR指令选择] --> B[寄存器分配]
|
||
B --> C[指令调度]
|
||
C --> D[汇编生成]
|
||
```
|
||
|
||
1. **指令选择**(关键步骤):
|
||
- `DAGBuilder`:将IR转换为有向无环图(DAG)
|
||
- `DAGCoverage`:DAG到目标指令的映射
|
||
- `Mid2End`:IR到机器指令的转换接口
|
||
|
||
2. **寄存器分配**:
|
||
- `RegisterAlloc`:基础寄存器分配器(可先实现简单算法如线性扫描)
|
||
|
||
3. **汇编生成**:
|
||
- `RiscvPrinter`:将机器指令输出为RISC-V汇编
|
||
- 实现基础指令集:`add`/`sub`/`lw`/`sw`/`beq`/`jal`等
|
||
|
||
### 4. **最小可工作流程**
|
||
```cpp
|
||
// 精简版编译流程(跳过复杂优化)
|
||
int main() {
|
||
// 1. 前端解析
|
||
auto module = sysy::SysYIRGenerator().genIR(input);
|
||
|
||
// 2. 关键中端优化
|
||
sysy::Mem2Reg(module).run(); // 必须
|
||
sysy::Global2Local(module).run(); // 必须
|
||
sysy::DCE(module).run(); // 推荐
|
||
|
||
// 3. 后端代码生成
|
||
auto backendModule = mid2end::CodeGenerater().run(module);
|
||
riscv::RiscvPrinter().print("output.s", backendModule);
|
||
}
|
||
```
|
||
|
||
### 5. **当前开发优先级建议**
|
||
1. **完成IR生成**:
|
||
- 确保能构建基本块、函数、算术/内存/控制流指令
|
||
- 实现`createCall`/`createLoad`/`createStore`等核心方法
|
||
|
||
2. **实现Mem2Reg**:
|
||
- 插入Phi节点
|
||
- 变量重命名(关键算法)
|
||
|
||
3. **构建基础后端**:
|
||
- 指令选择:实现IR到RISC-V的简单映射(例如:`IRAdd` → `add`)
|
||
- 寄存器分配:使用无限寄存器方案(后期替换为真实分配)
|
||
- 汇编打印:支持基础指令输出
|
||
|
||
> **注意**:循环优化、函数内联、高级寄存器分配等可在基础流程打通后逐步添加。初期可跳过复杂优化。
|
||
|
||
### 6. 调试建议
|
||
- 添加IR打印模块(`SysYPrinter`)验证前端输出
|
||
- 使用简化测试用例:
|
||
```c
|
||
int main() {
|
||
int a = 1;
|
||
int b = a + 2;
|
||
return b;
|
||
}
|
||
```
|
||
- 逐步扩展支持:
|
||
1. 算术运算 → 2. 条件分支 → 3. 函数调用 → 4. 数组访问
|
||
|
||
通过聚焦这些核心模块,你们可以快速打通从SysY到RISC-V的基础编译流程,后续再逐步添加优化传递提升代码质量。 |