# MiniC Compiler
**Repository Path**: baichendada/mini-c-compiler
## Basic Information
- **Project Name**: MiniC Compiler
- **Description**: 基于flex/bison实现的小型C语言编译器
- **Primary Language**: C++
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 0
- **Created**: 2024-04-23
- **Last Updated**: 2025-04-22
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 计算器
## 计算机实现的主要功能
命令格式:
minic -S [-A | -D] [-a | -I] [-o output] source
minic -R [-A | -D] source
选项-S -a 借助 flex+bison 产生抽象语法树 AST
选项-S -I 借助 flex+bison 产生线性 IR
选项-o output 可把输出的抽象语法树或线性 IR 保存到文件中
选项-R 可直接运行得出计算器结果
选项-A 指定时可通过 antlr4 进行词法与语法分析
选项-D 指定时可通过递归下降分析法实现语法分析,词法分析手动实现
不指定-A 或-D 选项时默认采用 Flex/Bison 实现词法与语法分析
## 源代码构成
frontend 目录下的源代码实现编译器的前端,有三种:flex/bison、antlr4、递归下降分析法
backend 目录下的源代码实现编译器的后端,有两种:解释执行或转换成 ARM32 汇编
DragonIR 目录下的源代码描述规定的线性 IR
common 目录下的源代码描述符号表或共通的代码
utils 目录下的源代码实现个别函数的操作系统差异
tests 目录下放置了一些简单的测试用例代码
thirdparty 目录下放置了一些第三方的工具,如 antlr4.12.0
## 程序构建
请使用VSCode + WSL/Container/SSH + Ubuntu 22.04进行编译与程序构建。
在使用前请使用命令安装clang-format与clang-tidy,这样该项目可使用根文件夹下的.clang-format和.clang-tidy进行代码分析。
大家也可自行修改.clang-format和.clang-tidy的内容。
安装命令格式如下:
```shell
sudo apt install -y clang-format clang-tidy
```
方式一使用VScode的cmake插件直接先选择clang编译器后进行程序的构建。
方式二可使用如下的命令进行构建。
```shell
# cmake根据CMakeLists.txt进行配置与检查,这里使用clang编译器并且是Debug模式
cmake -B cmake-build-debug -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++
# cmake,其中--parallel说明是并行编译
cmake --build cmake-build-debug --parallel
```
## 计算器使用方法
在Ubuntu 22.04平台上运行。支持的命令如下所示:
```shell
./cmake-build-debug/minic -S -a test.txt
./cmake-build-debug/minic -S -a -A test.txt
./cmake-build-debug/minic -S -a -D test.txt
./cmake-build-debug/minic -S -a -o test.pdf test.txt
./cmake-build-debug/minic -S -a -A -o test.pdf test.txt
./cmake-build-debug/minic -S -a -D -o test.pdf test.txt
./cmake-build-debug/minic -S -I test.txt
./cmake-build-debug/minic -S -I -A test.txt
./cmake-build-debug/minic -S -I -D test.txt
./cmake-build-debug/minic -S -I -o ir.txt test.txt
./cmake-build-debug/minic -S -I -A -o ir.txt test.txt
./cmake-build-debug/minic -S -I -D -o ir.txt test.txt
./cmake-build-debug/minic -R test.txt
./cmake-build-debug/minic -R -A test.txt
./cmake-build-debug/minic -R -D test.txt
```
## 工具
计算器实验的所有工具在实验一中已经安装,这里不需要再次安装。这里主要介绍一些功能。
### Flex 与 Bison
#### Windows
主要给 Visual Studio 用
win_flex -o minic_lex.cpp --wincompat minic.l
win_bison -o minic.cpp minic.y
#### MinGW、Linux or Mac
flex -o minic_lex.cpp --header-file=minic_lex.h minic.l
bison -o minic_yacc.cpp --header=minic_yacc.h -d minic.y
请注意 bison 的--header 在某些平台上可能是--defines,要根据情况调整指定。
### Antlr 4.12.0
要确认java15 以上版本的 JDK,否则编译不会通过。默认已经安装了JDK 17的版本。
由于cmake的bug可能会导致适配不到15以上的版本,请删除旧版的JDK。
编写 g4 文件然后通过 antlr 生成 C++代码,用 Visitor 模式。
```shell
java -jar tools/antlr-4.12.0-complete.jar -Dlanguage=Cpp -no-listener -visitor -o frontend/antlr4 frontend/antlr4/minic.g4
```
C++使用 antlr 时需要使用 antlr 的头文件和库,在 msys2 下可通过如下命令安装 antlr 4.12.0 版即可。
```shell
pacman -U https://mirrors.ustc.edu.cn/msys2/mingw/mingw64/mingw-w64-x86_64-antlr4-runtime-cpp-4.12.0-1-any.pkg.tar.zst
```
### Graphviz
借助该工具提供的C语言API实现抽象语法树的绘制。
### doxygen
借助该工具分析代码中的注释,产生详细分析的文档。这要求注释要满足一定的格式。具体可参考实验文档。
### texlive
把doxygen生成的文档转换成pdf格式。
## 根据注释生成文档
请按照计算器实验的文档要求编写注释,可通过doxygen工具生成网页版的文档,借助latex可生成pdf格式的文档。
请在本实验以及后续的实验按照格式进行注释。
### 生成网页版文档
```shell
doxygen Doxygen.config
```
需要时可自行修改配置文件 Doxygen.config。
### 生成 pdf格式的文档
```shell
cd latex
make
```
## 计算器运行
tests 目录下存放了一些简单的测试用例。其中 test1.c 是 test1.txt 的 C 语言版本实现,用于运行的对比。
由于 qemu 的用户模式在 Window 系统下不支持,因此要么在真实的开发板上运行,或者用 Linux 系统下的 qemu 来运行。
后面介绍如用 Linux 系统下的 qemu 来运行。
### 计算器调试运行
由于自定的gdb或者lldb调试器对C++的STL模版库提供的类如string、map等的显示不够友好,因此请大家确保安装
vadimcn.vscode-lldb插件,也可以更新最新的代码后vscode会提示安装推荐插件后自动安装。
如安装不上请手动下载后安装,网址如下:
调试运行配置可参考.vscode/launch.json中的配置。
### 生成 ARM32 的汇编
```shell
# 通过计算器翻译 test1.txt 成 ARM32 汇编
./cmake-build-debug/minic -S -o tests/test1.s tests/test1.txt
# 把 test1-1.c 通过 arm 版的交叉编译器 gcc 翻译成汇编
arm-linux-gnueabihf-gcc -S -include tests/std.h -o tests/test1-1.s tests/test1-1.c
```
如果不指定--include tests/std.h,编译会提示函数 putint 没有声明的警告信息。
test1-1.c 是脚本型语言 test1.txt 的 C 语言表达。
### 生成可执行程序
通过 gcc 的 arm 交叉编译器对生成的汇编进行编译,生成可执行程序。
```shell
# 通过 ARM gcc 编译器把汇编程序翻译成可执行程序,目标平台 ARM32
arm-linux-gnueabihf-gcc -static -g -o tests/test1 tests/std.c tests/test1.s
# 通过 ARM gcc 编译器把汇编程序翻译成可执行程序,目标平台 ARM32
arm-linux-gnueabihf-gcc -static -g -o tests/test1-1 tests/std.c tests/test1-1.s
```
有以下几个点需要注意:
1. 这里必须用-static 进行静态编译,不依赖动态库,否则后续通过 qemu-arm-static 运行时会提示动态库找不到的错误
2. 生成的汇编中包含了 内置 putint 等函数的调用,用来进行数据的输出或输出等,因此在通过 arm-linux-gnueabihf-gcc 进行交叉编译时,需要和 std.c 一起进行编译链接才可以。
3. 可通过网址输入 C 语言源代码后查看各种目标后端的汇编。下图是选择 ARM GCC 11.4.0 的源代码与汇编对应。

4. 这些内置函数的具体实现放在了 tests/std.c 中,其原型在 tests/std.h 中,很简单,请自行查阅与理解。
### 运行可执行程序
借助用户模式的 qemu 来运行,arm 架构可使用 qemu-arm-static 命令。
```shell
qemu-arm-static tests/test1
qemu-arm-static tests/test1-1
```
这里可比较运行的结果,如果两者不一致,则计算器程序有问题。
## qemu 的用户模式
qemu 的用户模式下可直接运行交叉编译的用户态程序。这种模式只在 Linux 和 BSD 系统下支持,Windows 下不支持。
因此,为便于后端开发与调试,请用 Linux 系统进行程序的模拟运行与调试。
## qemu 用户程序调试
### 安装 gdb 调试器
该软件 gdb-multiarch 在前面工具安装时已经安装。如没有,则通过下面的命令进行安装。
```shell
sudo apt-get install -y gdb-multiarch
```
### 启动具有 gdbserver 功能的 qemu
假定通过交叉编译出的程序为 tests/test1,执行的命令如下:
```shell
# 启动 gdb server,监视的端口号为 1234
qemu-arm-static -g 1234 tests/test1
```
其中-g 指定远程调试的端口,这里指定端口号为 1234,这样 qemu 会开启 gdb 的远程调试服务。
### 启动 gdb 作为客户端远程调试
建议通过 vscode 的调试,选择 Qemu Debug 进行调试,可开启图形化调试界面。
可根据需要修改相关的配置,如 miDebuggerServerAddress、program 等选项。
也可以在命令行终端上启动 gdb 进行远程调试,需要指定远程机器的主机与端口。
注意这里的 gdb 要支持目标 CPU 的 gdb-multiarch,而不是本地的 gdb。
```shell
gdb-multiarch tests/test1
# 输入如下的命令,远程连接 qemu 的 gdb server
target remote localhost:1234
# 在 main 函数入口设置断点
b main
# 继续程序的运行
c
# 之后可使用 gdb 的其它命令进行单步运行与调试
```
在调试完毕后前面启动的 qemu-arm-static 程序会自动退出。因此,要想重新调试,请启动第一步的 qemu-arm-static 程序。