Shichien/Compiler2026-DNA

[CSCC2026] 2026年全国大学生计算机系统能力大赛 - 编译系统设计赛初赛

★ 0Forks 0RustGitHub ↗Compare

Project website ↗

compilersysy2022

README

compiler

一个面向 2026 编译系统设计赛 RISC-V 赛道的 Rust 编译器。项目按前端、语义、后端分层组织,整体架构风格参考教学编译器常见的分阶段实现方式,便于解释、维护和继续优化;当前仓库中的具体实现均按本项目需求从零编写。

项目概览

当前编译流程如下:

  1. 读取命令行参数与输入文件
  2. 进行词法分析
  3. 进行递归下降语法分析并构建 AST
  4. 完成符号解析、类型检查、常量表达式求值与对象布局
  5. 生成 64 位 RISC-V 汇编
  6. 将结果写入输出文件

核心模块如下:

  • src/main.rs 在独立工作线程中启动编译流程,并为深层语法树和深层作用域样例提供更大的编译期栈空间
  • src/driver.rs 负责命令行解析、文件读写和整条编译管线调度
  • src/syntax/lexer.rs 负责词法分析
  • src/syntax/parser.rs 负责递归下降语法分析
  • src/ast.rs 定义统一 AST 结构
  • src/sema.rs 负责语义分析、类型检查、常量求值、对象布局和运行时接口签名管理
  • src/backend/riscv.rs 负责 RISC-V 汇编生成与调用约定落地

当前支持能力

  • int、float、void
  • 全局变量、局部变量、函数声明、函数定义
  • 全局与局部 const 标量
  • 一维和多维整型、浮点数组
  • 标量与数组初始化列表
  • 数组下标访问与数组参数退化传递
  • 整型与浮点表达式、比较、条件判断和函数调用
  • 基础隐式类型转换,包含 float -> int
  • if / else
  • while
  • break / continue
  • return
  • 逻辑短路
  • getint、getarray、putint、putarray
  • getfloat、getfarray、putfloat、putfarray
  • starttime、stoptime 按运行时宏语义降为 _sysy_starttime、_sysy_stoptime
  • 生成 64 位 RISC-V 汇编

命令入口

源码仓库内置的单元测试可以直接运行:

cargo test

如果本机已经另行准备好被 .gitignore 排除的 tests/ 测试资料,可以运行完整的本地验证:

just

它会依次执行 Rust 单元测试、tests/examples/ 本地回归和 tests/ 中的全部公开样例编译。测试资料只用于本地验证,不随源码仓库提交。其余入口可以通过 just --list 查看,目前只保留四项:

  • just run input.sy:编译一个 SysY 程序,汇编自动写入 .verify/run/
  • just test [suite]:执行完整验证,或只选择一组公开样例
  • just test-riscv [suite] [mode]:在 WSL 中组装、链接并实际运行样例
  • just benchmark:比较全部公开性能源码在两种优化模式下的总编译耗时

本机具备测试资料时,日常完整验证使用 just 即可。

命令行参数现在由 clap 解析,比赛要求的调用形式保持不变:

compiler -S -o testcase.s testcase.sy
compiler -S -o testcase.s testcase.sy -O1

如果想查看完整参数说明,可以运行:

cargo run -- --help

当前验证情况

在本机准备好 tests/ 测试资料后,当前版本可以批量编译 functional、hidden_functional、performance 和 final_performance 四组往届公开样例到 RISC-V 汇编。performance 和 final_performance 使用 -O1,其余两组使用默认模式。

已完成的本地验证包括:

  • Rust 单元测试
  • 本机 tests/examples/ 样例的两种优化模式编译
  • 四组公开样例批量编译
  • RISC-V 汇编、静态链接和 QEMU 运行结果核对

项目同时包含针对支配关系、循环回边、内存写入屏障、寄存器分配和机器指令形状等边界的单元测试。当前仍需注意两点:

  • 真实比赛硬件环境上的最终性能还需要继续打磨
  • 真实目标板上的全量运行结果仍以比赛平台测评为准

使用方式

编译单个程序:

just run input.sy

生成的汇编位于 .verify/run/input.s。需要开启优化时,把第二个参数设为 o1:

just run input.sy o1

本项目包名已经设置为 compiler,与比赛要求一致,见 Cargo.toml。

诊断输出

编译错误目前按阶段区分为 CLI、词法、语法、语义和后端几类。带源码位置信息的错误会通过 ariadne 输出彩色定位、附加说明和修复提示,便于快速判断问题发生在哪个编译阶段。

提交前验证

提交前运行完整验证:

just

只验证一组公开样例时,可以把目录名作为参数:

just test functional
just test final_performance

各验证脚本分别做什么、会生成哪些文件,见 scripts/README.md。

验证输出默认写入 .verify/。

如果想做本地 hyperfine 基准测试,可以使用:

just benchmark

相关脚本和说明位于 scripts/README.md。

如果本机安装了 WSL,且其中具备 llvm-mc、riscv64-linux-gnu-gcc、qemu-riscv64 和 timeout,还可以进一步实际运行公开样例并核对输出:

just test-riscv functional o0

验证产物输出到 .verify/riscv-e2e/。

参考资料与代码来源说明

本项目参考过以下资料,但这些参考主要用于确认语言语义、运行时接口和目标平台约定,没有直接复制其中的编译器实现代码:

  • 大赛技术方案
  • SysY2022 语言定义
  • SysY 运行时库 sylib.h 与 sylib.c
  • RISC-V ISA 手册
  • RISC-V psABI 与 -mcmodel=medany 相关约定

代码层面的说明如下:

  • 没有直接引用 GCC、LLVM、Clang、MLIR 等现成编译器框架源码
  • 没有直接引用比赛官方样例编译器或其他开源 SysY 编译器实现
  • 架构分层风格参考过 mitex 一类教学编译器常见写法,但当前仓库里的词法、语法、语义、后端实现均为本项目自行编写
  • 公开样例和 SysY 运行时库仅作为本地测试资料放在被忽略的 tests/ 中,不随源码仓库提交;公开来源及使用边界见 测试资料来源

项目使用以下通用第三方依赖,均通过 Cargo 正常链接,没有复制其源码,也不参与 IR、优化器、寄存器分配或目标指令选择:

  • logos 0.14:用于通用词法记号识别,许可证为 MIT 或 Apache-2.0
  • clap 4.6:用于命令行参数解析,许可证为 MIT 或 Apache-2.0
  • ariadne 0.5:用于编译错误的终端诊断展示,许可证为 MIT

浮点字面量解析通过系统 C 运行时的 strtof 获得与目标环境一致的转换语义,不使用任何第三方编译器框架。

如果需要在设计文档里写借鉴说明,可以直接采用下面这段表述:

本项目参考了比赛技术方案、SysY2022 语言定义、SysY 运行时库接口说明以及 RISC-V 相关规范,用于确定语言语义、运行时调用约定和目标平台代码生成要求。项目整体采用前端、语义、后端分层组织方式,架构风格参考教学编译器常见的阶段化实现思路。除上述规范性参考外,编译器具体实现均由本队独立完成,未直接复用 GCC、LLVM、比赛官方样例编译器或其他开源编译器框架源码。

AI 辅助说明

开发过程中使用了 OpenAI Codex 作为辅助工具,辅助范围包括:

  • 工程骨架生成
  • 语法和语义模块实现
  • RISC-V 后端实现迭代
  • 测试脚本与项目说明整理

所有生成内容都经过人工审阅、修改和继续迭代。提交版本中的代码结构、接口设计、边界处理和最终行为均由项目成员确认。

如果需要在设计文档中单独披露,可直接采用下面这段表述:

本项目在开发过程中使用了 OpenAI Codex 作为辅助工具,辅助范围包括工程骨架、部分前端与后端代码、测试脚本和文档整理。所有由工具生成的内容均经过项目成员逐项审阅、修改、联调和验证,最终提交版本由项目成员负责并确保能够独立解释其设计与实现细节。

比赛提交方式

按当前赛方说明,RISC-V 初赛建议这样提交:

  1. 在比赛平台提供的 GitLab 中创建项目
  2. 使用 HTTPS 地址推送仓库,不要使用 SSH 地址
  3. 默认提交 master 分支
  4. 如果要测评其他分支,在提交面板填写 仓库 HTTPS 地址,后面空格再写分支名
  5. 确保项目可由平台直接通过 cargo 构建
  6. 确保最终可执行程序名为 compiler

平台评测时会按下面的命令调用编译器:

compiler -S -o testcase.s testcase.sy
compiler -S -o testcase.s testcase.sy -O1

本仓库已经满足这几个关键条件:

  • Cargo.toml 中包名为 compiler
  • src/driver.rs 已通过 clap 兼容 -S、-o、-O0、-O1
  • 输出文件由命令行 -o 指定

一个推荐的提交前流程如下:

  1. 运行 cargo test
  2. 本机具备测试资料时运行 just
  3. 视情况运行 just test-riscv functional o0
  4. 确认仓库根目录没有无关的大体积调试产物需要提交
  5. 推送到比赛 GitLab 的 master 分支
  6. 在比赛平台提交 HTTPS 仓库地址

本地样例

本地示例输入位于被忽略的 tests/examples/ 目录,不随源码仓库提交,包括:

  • 标量控制流样例
  • 全局变量与函数调用样例
  • 局部数组样例
  • 全局数组样例
  • 数组参数样例
  • 二维数组样例

更完整的本地回归建议见 本地回归测试清单.md。

Contributors

Shichienazazo1

Issues