2024 中山大学春季学期实验入口,我们将在经过一个学期的测试之后将其合并进入主线代码。
SYsU 是一个教学语言,应用于中山大学(Sun Yat-sen University)编译原理课程的教学。本项目是该课程的实验模板,可以得到一个 SYsU language 的编译器组件。实验的设计目标包括:
在 2022 春季学期的教学中,学生实现的编译器的性能可达 clang -O3
的 48%,相较于初始版本加速比超过 400%,推荐阅读相关论文以了解我们的理念与实验设计,也欢迎其他高校相关课程使用并反馈!我们同样开放了实验文档与基于 docker 的在线评测框架。
需要注意的是,SysY 语言允许编译时能够求值的 const int
作为数组大小,导致部分算例不能通过 gcc
的编译,因此为保持兼容推荐使用 clang
编译。经过测试的实验环境为 ubuntu:noble
。
# 安装依赖
apt-get install -y --no-install-recommends \
libantlr4-runtime-dev default-jre-headless pkg-config uuid-dev flex bison \
clang llvm-dev zlib1g-dev libzstd-dev lld python3 cmake ninja-build git
git clone \
-c feature.manyFiles=true \
--depth=1 \
https://github.com/arcsysu/SYsU-lang
cd SYsU-lang
# 编译安装
# `${CMAKE_C_COMPILER}` 仅用于编译 `.sysu.c`
# 非 SYsU 语言的代码都将直接/间接使用 `${CMAKE_CXX_COMPILER}` 编译(后缀为 `.cc`)
rm -rf $HOME/sysu
cmake -G Ninja \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_INSTALL_PREFIX=$HOME/sysu \
-DCMAKE_PREFIX_PATH="$(llvm-config --cmakedir)" \
-DCPACK_SOURCE_IGNORE_FILES=".git/;tester/third_party/" \
-B $HOME/sysu/build
cmake --build $HOME/sysu/build
cmake --build $HOME/sysu/build -t install
# 检查各实验的得分
CTEST_OUTPUT_ON_FAILURE=1 cmake --build $HOME/sysu/build -t test
# 打包源代码以提交作业
cmake --build $HOME/sysu/build -t package_source
# 检查编译结果
( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
sysu-compiler -S -o a.S tester/functional/000_main.sysu.c &&
clang -O0 -lsysy -lsysu -o a.out a.S &&
./a.out ;
echo $? &&
rm -f a.S a.out )
# 编译器自举(预留接口,当前直接调用 clang)
rm -rf $HOME/sysu-stage2
cmake -G Ninja \
-DCMAKE_C_COMPILER=$HOME/sysu/bin/sysu-compiler \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_INSTALL_PREFIX=$HOME/sysu-stage2 \
-DCPACK_SOURCE_IGNORE_FILES=".git/;tester/third_party/" \
-DSYSU_TESTER=1 \
-B $HOME/sysu-stage2/build
cmake --build $HOME/sysu-stage2/build
cmake --build $HOME/sysu-stage2/build -t install
对于使用其他操作系统的同学,我们准备了一份 docker 开发环境。
docker pull wukan0621/sysu-lang
docker run \
--name sysu-lang \
-v "$PWD/workspace:/workspace" \
-it wukan0621/sysu-lang \
bash
# 随后可以在宿主机当前目录的 workspace/SYsU-lang 目录下开发
SYsU 是 C 语言的子集,同时也是 SysY 语言的超集,在后者的基础上进行了一些调整,以适应课程需要:
.sy
调整为 .sysu.c
。char
、long long
。""
的拼接,不支持斜杠 \
语法。"c"[0]
)。do
- while
循环。clang -E
)处理后传给编译器。#
开头,并且总是占据一整行。#include
。main
函数,可以分模块编译并链接。本项目的运行架构如下图。
flowchart TB
subgraph sysu-compiler
direction TB
subgraph frontend
direction LR
preprocessor--Code-->grammar
grammar--JsonAST-->generator
preprocessor--Code-->lexer
lexer--TokenFlow-->parser
parser--JsonAST-->generator
end
subgraph midend
optimizer
end
subgraph backend
direction LR
translator--Assemble-->linker
end
frontend--LLVM IR-->midend
midend--LLVM IR-->backend
end
compiler
SYsU 编译器的上层驱动,类似于 clang
。当前支持的额外功能包括:
-h
:查看完整使用帮助--unittest
:单元测试--convert-sysy
:转换 SysY 到 SYsU( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
sysu-compiler tester/functional/000_main.sysu.c )
后续功能开发中,详见 -h
;未支持的参数将尝试传递给 clang
执行。
preprocessor
SYsU 的预处理器。当前 sysu-preprocessor
直接调用 clang --driver-mode=cpp
,学有余力的同学也可自行实现。
$ ( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
sysu-preprocessor tester/functional/000_main.sysu.c )
# 1 "tester/functional/000_main.sysu.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 341 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "tester/functional/000_main.sysu.c" 2
int main(){
return 3;
}
grammar
SYsU 的新基于 antlr4 的文法分析器,用于代替被诟病已久的 flex+bison 旧实验,产生类似于 clang -cc1 -dump-tokens 2>&1
、clang -cc1 -ast-dump=json
的输出。作为文法分析实验模块,本仓库中的 sysu-grammar
并不能处理完整的 SYsU,但提供了一个模板,需要学生将其文法分析规则补充完整(详细实验要求)。
$ ( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
sysu-preprocessor tester/functional/000_main.sysu.c |
sysu-grammar -dump-tokens )
int 'int' Loc=<tester/functional/000_main.sysu.c:1:1>
identifier 'main' Loc=<tester/functional/000_main.sysu.c:1:5>
l_paren '(' Loc=<tester/functional/000_main.sysu.c:1:9>
r_paren ')' Loc=<tester/functional/000_main.sysu.c:1:10>
l_brace '{' Loc=<tester/functional/000_main.sysu.c:1:11>
return 'return' Loc=<tester/functional/000_main.sysu.c:2:5>
numeric_constant '3' Loc=<tester/functional/000_main.sysu.c:2:12>
semi ';' Loc=<tester/functional/000_main.sysu.c:2:13>
r_brace '}' Loc=<tester/functional/000_main.sysu.c:3:1>
eof '' Loc=<tester/functional/000_main.sysu.c:3:2>
$ ( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
sysu-preprocessor tester/functional/000_main.sysu.c |
sysu-grammar )
{"inner":[{"inner":[{"inner":[{"inner":[{"kind":"IntegerLiteral","value":"3"}],"kind":"ReturnStmt"}],"kind":"CompoundStmt"}],"kind":"FunctionDecl","name":"main"}],"kind":"TranslationUnitDecl"}
lexer
SYsU 的旧词法分析器,产生类似于 clang -cc1 -dump-tokens 2>&1
的输出。作为词法分析实验模块,本仓库中的 sysu-lexer
并不能处理完整的 SYsU,但提供了一个模板,需要学生将其词法规则补充完整(详细实验要求)。
$ ( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
sysu-preprocessor tester/functional/000_main.sysu.c |
sysu-lexer )
int 'int' Loc=<tester/functional/000_main.sysu.c:1:1>
identifier 'main' Loc=<tester/functional/000_main.sysu.c:1:5>
l_paren '(' Loc=<tester/functional/000_main.sysu.c:1:9>
r_paren ')' Loc=<tester/functional/000_main.sysu.c:1:10>
l_brace '{' Loc=<tester/functional/000_main.sysu.c:1:11>
return 'return' Loc=<tester/functional/000_main.sysu.c:2:5>
numeric_constant '3' Loc=<tester/functional/000_main.sysu.c:2:12>
semi ';' Loc=<tester/functional/000_main.sysu.c:2:13>
r_brace '}' Loc=<tester/functional/000_main.sysu.c:3:1>
eof '' Loc=<tester/functional/000_main.sysu.c:3:2>
parser
SYsU 的旧语法分析器,接受来自 sysu-lexer
的输入,输出一个 json 格式的语法分析树(类似于 clang -cc1 -ast-dump=json
)。作为语法分析实验模块,本仓库中的 sysu-parser
并不能处理完整的 SYsU,但提供了一个模板,需要学生将其语法规则补充完整(详细实验要求)。
$ ( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
sysu-preprocessor tester/functional/000_main.sysu.c |
sysu-lexer |
sysu-parser )
{"inner":[{"inner":[{"inner":[{"inner":[{"kind":"IntegerLiteral","value":"3"}],"kind":"ReturnStmt"}],"kind":"CompoundStmt"}],"kind":"FunctionDecl","name":"main"}],"kind":"TranslationUnitDecl"}
当然,也可以直接从 clang -cc1 -dump-tokens 2>&1
获得输入。
( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
clang -E tester/functional/000_main.sysu.c |
clang -cc1 -dump-tokens 2>&1 |
sysu-parser )
generator
sysu-generator
将 sysu-parser
得到的语法分析树转换为 LLVM IR。作为代码生成实验模块,本仓库中的 sysu-generator
并不能处理完整的 SYsU,但提供了一个模板,需要学生将其补充完整(详细实验要求)。
$ ( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
sysu-preprocessor tester/functional/000_main.sysu.c |
sysu-grammar |
sysu-generator )
; ModuleID = '-'
source_filename = "-"
define i32 @main() {
entry:
ret i32 3
}
optimizer
sysu-optimizer
是 SYsU 的优化器,从 sysu-generator
获得输入,输出优化后的 LLVM IR。作为代码优化实验模块,本仓库中的 sysu-optimizer
并没有实现优化 IR 的功能,需要学生将其补充完整(详细实验要求)。
注意在以下的输出中,; ModuleID = '<stdin>'
前的输出来自 stderr
,包含了一个来自 banach-space/llvm-tutor 的 StaticCallCounter
Pass,可以统计生成代码中包含哪些 call
调用。
$ ( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
sysu-preprocessor tester/functional/000_main.sysu.c |
sysu-grammar |
sysu-generator |
sysu-optimizer )
=================================================
sysu-optimizer: static analysis results
=================================================
NAME #N DIRECT CALLS
-------------------------------------------------
-------------------------------------------------
; ModuleID = '<stdin>'
source_filename = "-"
define i32 @main() {
entry:
ret i32 3
}
同时提供了一个 LLVM 插件 libsysuOptimizer.so
,可以使用 opt
直接加载。这意味着 sysu-optimizer
中的 pass 也可直接用于 LLVM 生态。
( export PATH=$HOME/sysu/bin:$PATH \
CPATH=$HOME/sysu/include:$CPATH \
LIBRARY_PATH=$HOME/sysu/lib:$LIBRARY_PATH \
LD_LIBRARY_PATH=$HOME/sysu/lib:$LD_LIBRARY_PATH &&
clang -E tester/mizuno_ai/mizuno_ai.sysu.c |
clang -cc1 -S -emit-llvm |
opt --enable-new-pm -S -load-pass-plugin=libsysuOptimizer.so -passes="sysu-optimizer-pass" )
translator
将 LLVM IR 翻译成汇编或二进制文件。当前 sysu-translator
直接调用 llc
,学有余力的同学也可自行实现。
linker
链接器。当前 sysu-linker
直接调用 ld.lld
,学有余力的同学也可自行实现。
librarian
为了可移植性以及与 C 标准库的兼容性,此处自行实现了 libsysy
,与 nscscc/compiler2021 中提供的 sylib.h
保持 API 兼容性,但不保证 ABI 兼容性。换言之,原有的 SysY 代码需要转换为 SYsU 并重新编译。
libsysu
暴露了类似于 open()
、read()
、write()
、close()
、fork()
的系统调用,使 SYsU 具有了处理文件、使用多进程的可能。
后续会逐步支持更多 C 标准库函数与 Linux 系统函数,以用于 Yat-sen OS 或实现编译器自举。
tester
目录下提供了一系列 SYsU 格式的测试代码以及对应程序的输入输出,修改自 nscscc/compiler2021 中提供的算例。
大算例以 git submodule
的形式存放在 tester/third_party
。加载方式:
git submodule update --init --recursive --depth 1
sysu-translator
以及链接器的接口 sysu-linker
,相关部分的可选实验设计正在进行中,学有余力的同学也可以自行实现。clang
代替 ,避免学生一个实验不成功影响到后续实验的开展。.sysu.c
,指明了 SYsU 是 C 的严格子集,可以让 clang
直接编译代码,方便学生与正确实现对拍。#include
等预处理语句的支持,可以让学生更加熟悉预编译过程(即使不用实现一个预编译器),也为 SYsU 增加了实现库或调用外部库的可能(可用于实现 Yat-sen OS)。do
- while
循环,因为这是很好用的语法糖。char
、long long
和字符串,同样便于实现 OS。latest
分支下为中大课程教学中使用的代码,功能较为稳定,预期在 ubuntu:noble
环境中工作。文档可能不会及时更新,以对应 Dockerfile 中的测试语句为准。
对于中大以外的高校教学者与个人自学者,我们建议使用 releases 中最新发布的实验框架源码以及对应版本号的 docker image。它们可能在时间上略有落后,但经过了中大一学期的教学检验,不存在潜在的可能导致教学事故的错误。我们也十分欢迎来自你们的课堂反馈 与改进建议 。
版本号的命名格式为 <major>.<minor>.<patch>.<tweak>
,如 2404.0.0.20240229
。一般来说,对于使用 latest
分支代码的用户,<major>
、<minor>
、<patch>
发生变化时,我们建议尽快更新至最新版本。
<major>
指示了该版本的软件依赖为对应的 ubuntu/debian 版本<minor>
指示了该版本的功能版本,不同 <minor>
间可能不直接兼容<patch>
指示了该版本的补丁版本,不同 <patch>
间预期可以直接更新,修正前一个版本中存在的问题<tweak>
指示了当前版本代码(不含文档)的日期,可能存在微调,但不同 <tweak>
的代码应当具有完全相同的表现由于本项目并没有提供一个完整的 sysu-compiler
,而只提供了相关的开发环境,因此项目名为 SYsU-lang。完整实现的开发已在进行,暂不对外开放。