Files
nudt-compiler-cpp/doc/目录结构设计.md

11 KiB
Raw Blame History

SysY 编译器目录结构设计

1. 编译流程图

[ 前端 Frontend ]
  C 源代码
    ↓
  Lexer / ParserANTLR
    ↓
  AST 构建 + 语义分析Sema
    ↓
  AST带类型 / 符号 / 常量)

[ 中端 Middle-end ]
  AST
    ↓
  IR 构建(平台无关 IRLLVM 风格)
    ↓
  IR 优化ConstFold / DCE / mem2reg 等,可选)
    ↓
  优化后的 IR

[ 后端 BackendARMv8-A / AArch64]
  IR
    ↓
  IR → MIRAArch64 指令 + 虚拟寄存器)      ← 指令选择
    ↓
  MIR → MIRAArch64 指令 + 物理寄存器)      ← 寄存器分配(含 spill/reload
    ↓
  栈帧构建 / Prologue / Epilogue 插入         ← FrameLowering
    ↓
  MIR最终机器指令
    ↓
  汇编打印
    ↓
  ARMv8-A 汇编(.s

2. 目录结构

.
├── 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/.hSysYVisitor.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 转换为 ASTsrc/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”翻译为平台无关 IRsrc/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
    • 寄存器表示:区分虚拟寄存器与物理寄存器,提供编号/属性等。
    • 寄存器类RegClassGPR/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/,并汇总通过/失败信息。