Project Icon

shecc

开源自编译C语言优化编译器

shecc是一个开源的自编译C语言优化编译器,支持32位Arm和RISC-V架构。它能生成Linux ELF可执行文件,提供基本C标准库,采用两遍编译过程。该项目实现了静态单赋值(SSA)中间表示、寄存器分配和基本优化策略,展示了编译器的核心概念和实现方法,适合学习和教育用途。

shecc : 自托管教育型C语言优化编译器

logo image

简介

shecc是从零开始构建的,针对32位Arm和RISC-V架构,作为C语言子集的自编译编译器。尽管设计简单,但它作为独立的优化编译器能够执行基本的优化策略。

特性

  • 为ARMv7-A和RV32IM生成可执行的Linux ELF二进制文件。
  • 提供最小的C标准库,用于GNU/Linux上的基本I/O操作。
  • 交叉编译器使用ANSI C编写,与大多数平台兼容。
  • 包含一个自包含的C前端,集成了机器代码生成器;无需外部汇编器或链接器。
  • 采用两遍编译过程:第一遍检查语法并将复杂语句分解为基本操作,第二遍将这些操作转换为Arm/RISC-V机器代码。
  • 开发了一个适用于RISC风格架构的寄存器分配系统。
  • 实现了一个与架构无关的、基于静态单赋值 (SSA)的中间端,以增强优化。

兼容性

shecc能够编译使用以下语法编写的C源文件:

  • 数据类型:char、int、struct和指针
  • 条件语句:if、while、for、switch、case、break、return和一般表达式
  • 复合赋值:+=-=*=
  • 支持的数据类型的全局/局部变量初始化
    • 例如 int i = [expr]
  • 对预处理器指令的有限支持:#define#ifdef#elif#endif#undef#error
  • 带有__VA_ARGS__标识符的非嵌套可变参数宏

后端针对带有Linux ABI的armv7hf,在树莓派3上验证,并且还支持RISC-V 32位架构,通过QEMU验证。

自举

验证shecc自举的步骤:

  1. stage0shecc源代码最初使用普通编译器编译,生成本机可执行文件。生成的编译器可用作交叉编译器。
  2. stage1:构建的二进制文件读取自身的源代码作为输入,并生成ARMv7-A/RV32IM二进制文件。
  3. stage2:生成的ARMv7-A/RV32IM二进制文件(通过QEMU或在Arm和RISC-V设备上运行)以自身源代码为输入,生成另一个ARMv7-A/RV32IM二进制文件。
  4. bootstrap:构建stage1stage2编译器,并验证它们是否逐字节相同。如果相同,则shecc可以编译自身的源代码并生成该程序的新版本。

先决条件

shecc中的代码生成器不依赖外部工具。你只需要普通的C编译器,如gccclang。然而,shecc会自举,因此需要Arm/RISC-V ISA模拟。在GNU/Linux上安装QEMU以进行Arm/RISC-V用户模拟:

$ sudo apt-get install qemu-user

在macOS或Microsoft Windows上构建shecc仍然可行。但由于缺少qemu-arm,第二阶段自举将失败。

要执行快照测试,请安装以下软件包:

$ sudo apt-get install graphviz jq

构建和验证

配置你想要的后端,shecc支持ARMv7-A和RV32IM后端:

$ make config ARCH=arm
# 目标机器代码切换到Arm

$ make config ARCH=riscv
# 目标机器代码切换到RISC-V

运行make,你应该看到这样的输出:

  CC+LD	out/inliner
  GEN	out/libc.inc
  CC	out/src/main.o
  LD	out/shecc
  SHECC	out/shecc-stage1.elf
  SHECC	out/shecc-stage2.elf

文件out/shecc是第一阶段编译器。其用法:

$ shecc [-o output] [+m] [--no-libc] [--dump-ir] <infile.c>

编译器选项:

  • -o : 指定输出文件名(默认:out.elf
  • +m : 使用硬件乘除法指令(默认:禁用)
  • --no-libc : 排除嵌入式C库(默认:嵌入)
  • --dump-ir : 转储中间表示(IR)

示例:

$ out/shecc -o fib tests/fib.c
$ chmod +x fib
$ qemu-arm fib

通过在调用make时指定check-snapshots目标来验证发出的IR是否与快照相同:

$ make check-snapshots

shecc附带单元测试。要运行测试,给出check作为参数:

$ make check

参考输出:

...
int main(int argc, int argv) { exit(sizeof(char)); } => 1
int main(int argc, int argv) { int a; a = 0; switch (3) { case 0: return 2; case 3: a = 10; break; case 1: return 0; } exit(a); } => 10
int main(int argc, int argv) { int a; a = 0; switch (3) { case 0: return 2; default: a = 10; break; } exit(a); } => 10
OK

要清理生成的编译器文件,执行命令 make clean。 要重置架构配置,使用命令 make distclean

中间表示

当向 shecc 传递 --dump-ir 选项时,将生成中间表示(IR)。以文件 tests/fib.c 为例。它包含一个递归的斐波那契数列函数。

int fib(int n)
{
    if (n == 0)
        return 0;
    else if (n == 1)
        return 1;
    return fib(n - 1) + fib(n - 2);
}

执行以下命令生成IR:

$ out/shecc --dump-ir -o fib tests/fib.c

C源代码和IR的逐行解释:

 C源代码               IR                                         解释
------------------+---------------------------------------+----------------------------------------------------------------------------------

int fib(int n)      def int @fib(int %n)                    表示函数定义
{                   {
  if (n == 0)         const %.t1001, $0                     将常量0加载到临时变量".t1001"中
                      %.t1002 = eq %n, %.t1001              测试"n"是否等于".t1001",并将结果写入临时变量".t1002"
                      br %.t1002, .label.1177, .label.1178  如果".t1002"等于零,跳转到假标签".label.1178",否则
                                                            跳转到真标签".label.1177"
                    .label.1177
    return 0;         const %.t1003, $0                     将常量0加载到临时变量".t1003"中
                      ret %.t1003                           返回".t1003"
                      j .label.1184                         跳转到endif标签".label.1184"
                    .label.1178
  else if (n == 1)    const %.t1004, $1                     将常量1加载到临时变量".t1004"中
                      %.t1005 = eq %n, %.t1004              测试"n"是否等于".t1004",并将结果写入临时变量".t1005"
                      br %.t1005, .label.1183, .label.1184  如果".t1005"等于零,跳转到假标签".label.1184"。否则,
                                                            跳转到真标签".label.1183"
                    .label.1183
    return 1;         const %.t1006, $1                     将常量1加载到临时变量".t1006"中
                      ret %.t1006                           返回".t1006"
                    .label.1184
  return
    fib(n - 1)        const %.t1007, $1                     将常量1加载到临时变量".t1007"中
                      %.t1008 = sub %n, %.t1007             从"n"中减去".t1007",并将结果存储在临时变量".t1008"中
                      push %.t1008                          为函数调用准备参数
                      call @fib, 1                          调用函数"fib",带一个参数
    +                 retval %.t1009                        将返回值存储在临时变量".t1009"中
    fib(n - 2);       const %.t1010, $2                     将常量2加载到临时变量".t1010"中
                      %.t1011 = sub %n, %.t1010             从"n"中减去".t1010",并将结果存储在临时变量".t1011"中
                      push %.t1011                          为函数调用准备参数
                      call @fib, 1                          调用函数"fib",带一个参数
                      retval %.t1012                        将返回值存储在临时变量".t1012"中
                      %.t1013 = add %.t1009, %.t1012        将".t1009"和".t1012"相加,并将结果存储在临时变量".t1013"中
                      ret %.t1013                           返回".t1013"
}                   }

已知问题

  1. 生成的ELF缺少.bss和.rodata段
  2. 对变参函数的支持不完整。无法使用<stdarg.h>。 或者,可以查看源文件lib/c.cprintf的实现,了解var_arg的使用。
  3. C前端有些混乱,因为没有有效的AST。

许可证

shecc 可在BSD 2条款许可证下自由重新分发。 本源代码的使用受BSD风格许可证的约束,可以在LICENSE文件中找到。

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号