Files
nudt-compiler-cpp/doc/Lab2-中间表示生成.md
2026-03-12 16:20:09 +08:00

2.8 KiB
Raw Blame History

Lab2中间表示生成

1. 本实验定位

Lab2 的目标是在该示例基础上扩展语义覆盖范围,逐步把更多 SysY 语法正确翻译为 IR。

2. Lab2 要求

需要同学完成:

  1. 熟悉 IR 相关数据结构与构建接口。
  2. 理解当前语法树 -> IR 的最小实现流程。
  3. 在现有框架上扩展 IR 生成能力使其覆盖课程要求的Sysy语法。

3. 当前代码框架

  1. IR 定义与打印

    • include/ir/IR.h
    • src/ir/IRBuilder.cpp
    • src/ir/IRPrinter.cpp
  2. 语法树 -> IR 生成器

    • include/irgen/IRGen.h
    • src/irgen/IRGenDriver.cpp
    • src/irgen/IRGenFunc.cpp
    • src/irgen/IRGenDecl.cpp
    • src/irgen/IRGenStmt.cpp
    • src/irgen/IRGenExp.cpp
  3. 入口流程

    • src/main.cpp

4. Lab2 需要补充的内容

  1. 必须修改的文件

    • src/irgen/IRGenDecl.cpp
    • src/irgen/IRGenStmt.cpp
    • src/irgen/IRGenExp.cpp
    • include/ir/IR.h(当现有 IR 指令/类型不够用时)
    • src/ir/IRBuilder.cpp(当需要新增构建接口时)
    • src/ir/IRPrinter.cpp(新增 IR 指令后补齐打印)
    • include/irgen/IRGen.h(当需要扩展状态或辅助接口时)
  2. 视实现需要可能修改

    • src/main.cpp(当需要调整输出阶段行为)

5. 当前最小示例实现说明

当前语法树 -> IR 仅覆盖最小子集:

  1. 常量整数、变量引用、二元加法表达式。
  2. 局部变量声明(当前采用 LLVM 前端常见的 alloca/load/store 内存模型)。
  3. return 语句。
  4. 单函数 main 的最小流程。

说明:当前阶段变量统一采用内存模型:先 alloca 分配栈槽,再通过 store/load 读写。即使变量由常量初始化(如 int a = 1;),也会先 store 到栈槽,而不是直接把变量替换成 SSA 值。后续实验中,同学可按需求再重构。

此外,当前 IR 还维护了最基本的 use-def 关系:每个 Value 会记录哪些 Instruction 使用了它。
这对后续做数据流分析、死代码删除、常量传播等优化会很有帮助;但目前相关实现,接口仍不完整,后续实验中还需要同学继续补充和完善。

6. 构建与运行

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

7. Lab2 验证方式

项目编译后按提供测试输入回归:

./build/bin/compiler --emit-ir test/test_case/simple_add.sy

如需打印语法树:

./build/bin/compiler --emit-parse-tree test/test_case/simple_add.sy

推荐使用统一脚本验证 “IR -> LLVM 后端 -> 可执行程序” 整体链路。--run 模式下会自动读取同名 .in,并将程序输出与退出码和同名 .out 比对,用于验证 IR 的正确性:

./scripts/verify_ir.sh test/test_case/simple_add.sy test/test_result/ir --run