主要观点:作者一直在断断续续地开发一个玩具编译器,受 Turbo Pascal 项目编译速度快的启发,检查自己的玩具编译器后发现其速度慢,于是研究了 2021 年的“copy-and-patch”论文,尝试用其技术来提高编译器速度,并给出了一个独立的示例说明该技术的应用及细节。
关键信息:
- 玩具编译器开发过程及想法转变,从给 C 编译器添加额外语言特征到决定写新语言。
- 对比过去和现在的计算机性能,现代计算机速度至少是过去的 100 倍且核心更多,但编译 C++/Rust 等仍需等待。
- “copy-and-patch”技术的核心思想,通过
clang -O3
生成代码片段(“stencils”),利用extern uintptr_t
和特殊调用约定来填充和处理值,以提高代码生成效率。 - 示例中用 Python 生成 C 代码,包括生成代码片段的
clang_rip.py
脚本,以及使用代码片段进行复制和补丁编译的过程,如对a = (b + c + f * g) * (d + 3)
表达式的处理。 - 生成代码的反汇编结果,展示了高效利用寄存器且无不必要分支和间接性的代码。同时提到可以有更大的模板节点来处理更复杂的解析树部分。
重要细节:
- 用
extern uintptr_t K0
和extern uintptr_t K1
代替直接获取值,在解析对象文件时用实际值替换重定位记录。 - 将调用约定改为 GHC 约定,使函数无被调用者保存寄存器,通过尾调用继续传递结果。
- 在生成代码片段时要注意
clang
的假设,可使用-mcmodel=medium
或-mcmodel=large
避免地址范围问题,在 C 代码中用__vectorcall
调用约定,在.ll 文件中用[[musttail]]
属性。 - 解析树的后序遍历及代码中对各节点的处理方式,如通过后缀
_0
、_1
等指定传递的寄存器数量。 - 对
ghccc
调用约定的一些疑问,如提到只支持 10 个整数参数及虚拟栈上的活动值限制等,需进一步了解。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。