# SysY 编译器目录结构设计 ## 1. 编译流程图 ```text [ 前端 Frontend ] C 源代码 ↓ Lexer / Parser(ANTLR) ↓ AST 构建 + 语义分析(Sema) ↓ AST(带类型 / 符号 / 常量) [ 中端 Middle-end ] AST ↓ IR 构建(平台无关 IR,LLVM 风格) ↓ IR 优化(ConstFold / DCE / mem2reg 等,可选) ↓ 优化后的 IR [ 后端 Backend(ARMv8-A / AArch64)] IR ↓ IR → MIR(AArch64 指令 + 虚拟寄存器) ← 指令选择 ↓ MIR → MIR(AArch64 指令 + 物理寄存器) ← 寄存器分配(含 spill/reload) ↓ 栈帧构建 / Prologue / Epilogue 插入 ← FrameLowering ↓ MIR(最终机器指令) ↓ 汇编打印 ↓ ARMv8-A 汇编(.s) ``` ## 2. 目录结构 ```text . ├── CMakeLists.txt ├── README.md ├── .gitignore ├── src/ │ ├── CMakeLists.txt │ ├── main.cpp │ ├── antlr4/ │ │ └── SysY.g4 │ ├── frontend/ │ │ ├── AntlrDriver.cpp │ │ └── AstBuilder.cpp │ ├── ast/ │ │ ├── AstNodes.cpp │ │ └── AstPrinter.cpp │ ├── sem/ │ │ ├── Sema.cpp │ │ ├── SymbolTable.cpp │ │ └── ConstEval.cpp │ ├── irgen/ │ │ └── IRGen.cpp │ ├── ir/ │ │ ├── Context.cpp │ │ ├── Module.cpp │ │ ├── Function.cpp │ │ ├── BasicBlock.cpp │ │ ├── Type.cpp │ │ ├── Value.cpp │ │ ├── Instruction.cpp │ │ ├── IRBuilder.cpp │ │ ├── IRPrinter.cpp │ │ ├── analysis/ │ │ │ ├── DominatorTree.cpp │ │ │ └── LoopInfo.cpp │ │ └── passes/ │ │ ├── PassManager.cpp │ │ ├── Mem2Reg.cpp │ │ ├── ConstFold.cpp │ │ ├── DCE.cpp │ │ └── CFGSimplify.cpp │ ├── mir/ │ │ ├── MIRContext.cpp │ │ ├── MIRFunction.cpp │ │ ├── MIRBasicBlock.cpp │ │ ├── MIRInstr.cpp │ │ ├── Register.cpp │ │ ├── Lowering.cpp │ │ ├── RegAlloc.cpp │ │ ├── FrameLowering.cpp │ │ ├── AsmPrinter.cpp │ │ └── passes/ │ │ ├── PassManager.cpp │ │ └── Peephole.cpp │ └── utils/ │ ├── Log.cpp │ └── CLI.cpp ├── include/ │ ├── frontend/ │ ├── ast/ │ ├── sem/ │ ├── irgen/ │ ├── ir/ │ ├── mir/ │ └── utils/ ├── sylib/ │ ├── sylib.c │ └── sylib.h └── test/ ├── test_case/ ├── test_result/ └── run_tests.sh ``` ## 3. 文件功能说明 ### 3.1 顶层文件 - `CMakeLists.txt` - 工程构建入口:配置编译器、添加子目录、链接生成最终可执行文件。 - 负责集成 ANTLR runtime(通过系统依赖或第三方源码),并将“ANTLR 生成代码所在的构建目录”加入编译。 - `README.md` - 实验/工程说明:依赖环境、构建方式、测试脚本用法、ANTLR 生成命令(写在文档中,不提供脚本)。 - `.gitignore` - 忽略构建产物(如 `build/`)、ANTLR 自动生成文件、`test/test_result/` 等输出目录。 ### 3.2 `src/`:实现代码 #### 3.2.1 入口与构建 - `src/CMakeLists.txt` - `src/` 子目录构建脚本:编译各子模块源文件,生成静态库/目标并链接到最终可执行文件。 - `src/main.cpp` - 编译器入口:解析命令行参数、驱动完整流水线(Frontend → Middle-end → Backend)。 - 负责把不同阶段产物输出为文件(如输出 `.ll` / `.s` 的开关可在此集中实现)。 #### 3.2.2 `src/antlr4/`:SysY 文法(只提交 `.g4`) - `src/antlr4/SysY.g4` - SysY 语法定义(lexer + parser rules),为 ANTLR 生成 C++ lexer/parser 提供输入。 - ANTLR 自动生成文件位置约定:该工程采用工程化方式:ANTLR 生成文件**不进入仓库**,统一放到构建目录,例如: - `build/generated/antlr4/` - 典型生成物包括(随生成选项略有差异): - `SysYLexer.cpp/.h` - `SysYParser.cpp/.h` - `SysYBaseVisitor.cpp/.h`、`SysYVisitor.cpp/.h` - `*.tokens`、`*.interp` #### 3.2.3 `src/frontend/`:ANTLR 调用与 AST 构建 - `src/frontend/AntlrDriver.cpp` - 读取源代码并调用 ANTLR 生成的 lexer/parser,得到 parse tree。 - 由于语法正确性由测试保证,该模块只需提供“可用的解析入口”,不需要实现复杂的语法错误报告体系。 - `src/frontend/AstBuilder.cpp` - 将 parse tree 转换为 AST(`src/ast/*`),并在 AST 节点上保留必要的定位信息(可选,用于调试/日志)。 #### 3.2.4 `src/ast/`:抽象语法树(AST) - `src/ast/AstNodes.cpp` - AST 节点定义与实现:表达式、语句、声明、函数、类型等。 - AST 节点应当能够承载后续阶段附加信息(类型、符号绑定、常量值等)。 - `src/ast/AstPrinter.cpp` - AST 调试打印:用于验证 AST 构建是否符合预期,便于定位前端/语义阶段问题。 #### 3.2.5 `src/sem/`:语义分析(Sema) - `src/sem/Sema.cpp` - 语义分析主流程:符号解析、类型检查、控制流规则检查、必要的隐式转换插入/记录等。 - 输出为“带类型 / 符号 / 常量信息”的 AST(可通过在 AST 节点上附加属性实现)。 - `src/sem/SymbolTable.cpp` - 符号表与作用域管理:支持嵌套作用域、变量/函数/参数/常量的注册与查找。 - `src/sem/ConstEval.cpp` - 常量求值:用于数组维度、全局初始化、`const` 表达式等需要编译期计算的场景。 #### 3.2.6 `src/irgen/`:AST → IR(平台无关,LLVM 风格) - `src/irgen/IRGen.cpp` - 将“带语义信息的 AST”翻译为平台无关 IR(`src/ir/*`)。 - 负责控制流结构化翻译(基本块、分支、循环)、表达式求值翻译、函数与全局对象生成等。 #### 3.2.7 `src/ir/`:LLVM 风格 IR 核心 - `src/ir/Context.cpp` - IR 上下文:管理类型/常量创建与复用、字符串/符号等公共资源。 - `src/ir/Module.cpp` - Module 容器:保存全局变量、函数列表、目标信息(如需要)、符号表等。 - `src/ir/Function.cpp` - Function 容器:参数、基本块列表、属性/元信息等。 - `src/ir/BasicBlock.cpp` - 基本块表示:指令序列、前驱/后继关系(显式或可计算)。 - `src/ir/Type.cpp` - IR 类型系统:`i32/f32/void`、指针、数组、函数类型等(按 SysY 支持范围裁剪)。 - `src/ir/Value.cpp` - SSA 值体系:常量、参数、指令结果等统一抽象。 - `src/ir/Instruction.cpp` - 指令体系:二元运算、比较、load/store、call、br/condbr、ret、phi、alloca 等(按需求逐步补齐)。 - `src/ir/IRBuilder.cpp` - IR 构建工具:集中管理插入点与指令创建,降低 IRGen 复杂度。 - `src/ir/IRPrinter.cpp` - IR 文本输出:打印为 `.ll` 风格文本,支撑调试与测试对比。 - `src/ir/analysis/DominatorTree.cpp` - 支配树分析:为 `mem2reg`、部分 CFG 优化与循环分析提供基础能力。 - `src/ir/analysis/LoopInfo.cpp` - 循环分析:识别循环结构,为后续优化(可选)提供信息。 - `src/ir/passes/PassManager.cpp` - IR pass 管理:按优化级别组织 pipeline,并统一运行与统计。 - `src/ir/passes/Mem2Reg.cpp` - SSA 构造关键 pass:将局部变量的 `alloca/load/store` 提升为 SSA(插入 PHI)。 - `src/ir/passes/ConstFold.cpp` - IR 常量折叠:简化可判定的常量表达与常量控制流分支(按实现范围裁剪)。 - `src/ir/passes/DCE.cpp` - 死代码删除:删除无用指令与无用块(与 CFG 简化配合)。 - `src/ir/passes/CFGSimplify.cpp` - CFG 简化:删除不可达块、合并空块、简化分支等。 #### 3.2.8 `src/mir/`:Machine IR - `src/mir/MIRContext.cpp` - MIR 上下文:保存目标约束、指令集信息等。 - `src/mir/MIRFunction.cpp` - 机器函数:包含机器基本块、栈帧信息、虚拟/物理寄存器管理等。 - `src/mir/MIRBasicBlock.cpp` - 机器基本块:机器指令列表与 CFG 信息。 - `src/mir/MIRInstr.cpp` - 机器指令:opcode + operands(寄存器/立即数/栈槽/符号/标签等)。 - `src/mir/Register.cpp` - 寄存器表示:区分虚拟寄存器与物理寄存器,提供编号/属性等。 - 寄存器类(RegClass):GPR/FPR 等分类与可分配集合描述(供 RA 使用)。 - `src/mir/Lowering.cpp` - IR → MIR:从平台无关 IR 生成 AArch64 指令的 MIR(在此完成指令选择),初始使用虚拟寄存器。 - `src/mir/RegAlloc.cpp` - 寄存器分配主入口:将虚拟寄存器分配到物理寄存器,并驱动 spill/reload 等后续处理。 - `src/mir/FrameLowering.cpp` - 栈帧布局与序言尾声:根据寄存器分配阶段记录的栈槽需求计算栈大小与对齐,插入 prologue/epilogue,保存/恢复 callee-saved 等。 - `src/mir/AsmPrinter.cpp` - 汇编打印:将最终机器指令 MIR 打印为 ARMv8-A 汇编 `.s`。 - `src/mir/passes/PassManager.cpp` - MIR pass 管理:组织后端 pass 的运行顺序(PreRA/PostRA/PEI 等阶段)。 - `src/mir/passes/Peephole.cpp` - 窥孔优化:删除冗余 move、合并常见指令模式,提升最终汇编质量。 #### 3.2.9 `src/utils/`:日志与命令行 - `src/utils/Log.cpp` - 日志输出:统一调试信息、阶段信息与错误信息输出。 - `src/utils/CLI.cpp` - 命令行参数解析:输入/输出路径、输出类型(IR/MIR/ASM)、优化级别等。 ### 3.3 `include/`:头文件目录 `include/` 目录与 `src/` 分层保持一致,用于放置对外可复用的头文件(具体头文件列表按实现新增)。 ### 3.4 `sylib/`:SysY 运行库 - `sylib/sylib.c` - SysY 运行库实现(按实验/评测规范提供 I/O 等函数)。 - `sylib/sylib.h` - 运行库头文件声明(供编译器生成 `call` 时引用,或用于链接阶段)。 ### 3.5 `test/`:测试 - `test/test_case/` - 测试输入目录:存放 `*.sy` 测试用例(可选搭配 `*.in` 作为 stdin 输入)。 - `test/test_result/` - 测试输出目录:由测试脚本生成 `.ll/.s`、运行输出、diff 结果与日志等。 - 建议通过 `.gitignore` 忽略,不纳入版本管理。 - `test/run_tests.sh` - Bash 测试脚本:批量编译 `test_case/`,将产物写入 `test_result/`,并汇总通过/失败信息。