/JustAToyCCompiler

Just refactoring and extending of https://github.com/rswier/c4.

Primary LanguageCGNU General Public License v2.0GPL-2.0

能够自举的C编译器

一个能够自举的玩具C编译器,只支持其中一部分核心特性。完全就是rswier/c4的重构和扩展。

特性

编译器特性:

  • 前后端合一,无中间优化。
  • 目标代码基于自定义的虚拟机(VM),非常简单但也足够完整。
  • 单趟(One-Pass)解析过程:源代码经过解析和代码生成过程直接生成虚拟机指令,然后由虚拟机来执行。
  • 按字节读取源码,支持兼容ASCII码的编码,比如GBK/UTF-8,不支持UTF-16/UTF-32。
  • 可以使用GCC或者MSVC来编译,支持32位或者64位。

jatcc.c(仅仅是c4的重构)支持的C语言特性:

  • 基本类型:charint,指针,匿名enum
  • 控制流:if-elsewhile
  • 运算符:, = ?: || && | ^ & == != < > <= >= << >> + - * / % ++ -- [] ()
  • 函数定义

其中由于实现带来的限制:

  • 变量定义时不能初始化。
  • 函数内局部变量的定义必须集中放在函数开头。
  • void将被视为char
  • 执行类型转换但不做严格的类型检查。
  • 不支持函数的前向声明,也就不能做到相互递归。
  • 不检查函数调用参数个数与类型是否匹配。
  • 类型系统实现得非常简单,支持数组下标操作但不支持数组定义。

jatccex.c添加的扩展:

  • 控制流:完美支持 for do while break continue goto
  • 命名enum支持,简单等同于int
  • 有限地支持了unionstruct的核心特性,添加运算符. ->
    • 不支持嵌套声明、匿名结构/联合、位域声明、柔性数组、初始化器等花里胡哨的东西。
    • 不支持作为函数参数和返回值,但在任何情况都可以使用指针。
    • 不支持赋值运算符,使用memcpy拷贝内存替代。
    • 支持全局变量和局部变量声明。
    • 支持使用指针进行的一切操作。
    • 支持前向声明。
    • 按照 sizeof(int) 字节对齐。
  • 支持函数前向声明,检查返回值类型,但和函数调用一样不会检查参数列表是否匹配。
  • 同样自举

实现带来的限制:

  • 现有线性解析框架下难以实现switch语句,不做支持。

构建与测试

jatcc [-d] xxx.c [args to main]

c4的重构:

gcc jatcc.c -o jatcc
./jatcc test.c
./jatcc -d test.c
./jatcc jatcc.c test.c
./jatcc jatcc.c jatcc.c test.c

扩展版本:

gcc jatccex.c -o jatccex
./jatccex testex.c
./jatccex jatccex.c testex.c
./jatccex jatccex.c test.c
./jatccex jatcc.c test.c

实现细节

License

同c4使用GPL-2.0 License

参考

TODO

  • float & double ? 虚拟机没有实现浮点指令,需要扩展指令集,现有框架能否完整且良好地支持还不好说,暂不实现。
  • x86 JIT compiling ?
  • debugger ?

PR要求

  • jatcc.c作为基础版本不再改动。
  • 接受对jatccex.c的有意义改进,针对改进在testex.c中补充测试用例。如果是仅改进了语法检查,仅针对语法错误的情况那可以没有测试用例。
  • 确保以下测试能够顺利通过
    ./jatccex testex.c
    ./jatccex jatccex.c test.c
    ./jatccex jatccex.c testex.c

欢迎任何有意义的改进、扩展、建议与BUG反馈。