goc 专栏

goc 专栏

goc 是一个用 Go 写的 C 编译器,也带一个自研汇编器 goa。它做的事有点极端:

编译 C 代码,产物既不依赖 gcc,也不依赖 libc。

Windows 上产物是 PE32+,只导入 kernel32 / user32 / gdi32 这类系统 DLL;Linux 上产物是静态 ELF64,一条动态链接都没有,只走 syscall。两头都没有 msvcrt,也没有 glibc。

  foo.c ──[goc]──> foo.asm ──[goa]──> foo.exe    Windows PE32+,只导入 kernel32
              └─[goc -target linux]─[goa -f elf]─> foo    Linux ELF64,只用 syscall

源码在 GitHub:yafengabc/goc(MIT 许可,公开仓库,已发布 v0.1.1)。

这个专栏写什么

这个专栏分四块:

篇章内容
项目介绍goc 是什么、为什么这么做、架构怎么分的、和gcc 差在哪
上手教程从装工具链到写出第一个程序,含Windows GUI 和 Linux 双目标
体积实测同一份源码,goc / goc+LLVM 后端 / gcc 三方对比,全部自己跑出来的数字
项目状态已经能做什么、还不能做什么、正在进行什么,附一份测试失败怎么读的经验

另有一份开发笔记(content/goc/devnotes/),记录 bug 排查与修复的完整过程——不走弯路的那部分不进教程。

为什么值得写

goc 最有意思的地方不是"又写了个编译器"——那没什么新鲜的。而是它把取舍做得非常明白:

  • 不要 gcc:既然是 Go 写的编译器,那就纯到底,产物里不会出现任何 C 工具链的痕迹。
  • 不要 libc:那printf 怎么办?答案是把它当成一个真正的库函数写在 C 里,按需发射——只调用 putchar 的程序不会背上 printf的 512字节输出缓冲。
  • 不要假设 CPU 会变好:验证环节直接上QEMU(Unicorn),因为手写解释器只能证明"代码生成器和我的理解一致",证明不了程序真的对。

这三条决定了 goc 的整个形态。后面几篇会逐一展开。

现状速览

写这个专栏时的实测状态(2026-10-06):

  • 仓库 176 次提交,最新 tag v0.1.1
  • run_tests.sh 在 Windows 11 + MSYS2 下跑出 pass=253 fail=0
  • 85 个C 示例,81 份 golden
  • 默认后端回归基线 gocregress pass=475(81 example × 6 腿)
  • C99主体 + C11 类型系统 + C23 实用子集全部落地
  • _BitInt(N) 已实现,10 万位 π 二分算法 100,011 位对拍 Python 大整数通过

阅读顺序

  1. 第0 章:为什么再写一个 C 编译器 —— 项目介绍与设计取舍
  2. 第 1 章:5 分钟跑起来 —— 装工具链,编译第一个程序
  3. 第 2 章:写第一个 Windows GUI 程序 —— 用 MessageBox 弹个框
  4. 第 3 章:体积实测 —— goc / LLVM 后端 / gcc 对比
  5. 第 4 章:项目状态与 roadmap —— 能做什么,不能做什么

开发笔记

笔记内容
变参窄整型丢符号性gocl 把经变参传的 32 位整型符号性丢掉:从误诊为"有符号除法"到定位为"8 字节参数槽没填满"的完整排查过程

⚠️ 说明:本专栏所有体积、测试数字均为在作者机器(Windows 11 + MSYS2)实测所得,标注了日期。goc 迭代很快,数字会变——但结论和方法相对稳定。