OCaml 编译器 - 2021 年 6 月至 9 月
我很高兴发布“OCaml 编译器开发时事通讯”的第三期。(这绝不是详尽无遗的:许多人最终没有时间撰写内容,这完全可以理解。)
当然,请随时评论或提出问题!
如果您一直在开发 OCaml 编译器,并且想说些什么,请随时在此线程中发帖!如果您希望我在下次准备时事通讯期刊时与您联系(未来的某个随机时间点),请通过电子邮件告知我(gabriel.scherer at gmail)。
以前的问题
Nicolás Ojeda Bär (@nojb)
标准库中的通道
-
#10545 在标准库中添加模块
In_channel
和Out_channel
。(已合并) -
#10538 添加
Out_channel.set_buffered
和Out_channel.is_buffered
用于控制和查询输出通道的缓冲模式。(已合并) -
#10596 添加
In_channel.input_all
、In_channel.with_open_{bin,text,gen}
和Out_channel.with_open_{bin,text,gen}
。(已合并)
编译器用户界面
-
#10654 提出一种方法,使在使用
-output-complete-exe
编译的字节码二进制文件中使用调试信息成为可能。(等待审查)这是对这项工作进行的第二次迭代,这项工作可能对自包含字节码二进制文件的使用性产生重大影响——将-output-complete-exe
提升至与-custom
相同的功能级别,并弃用后者的、更脆弱的方法。 -
#10555 改进和清理与“合并”项(例如
{x; y}
或< x; y >
)相关的存储的 AST 位置。(已合并) -
#10560 编译器现在尊重
NO_COLOR
环境变量。(已合并)
内部更改
-
#10624 应用一个修复程序,用于解决 4.08 中引入的编译时回归(此修复程序由 Leo White 建议)。(已合并)
-
#10606 清理
non-unit-statement
和ignored-partial-application
警告的实现。(已合并)
David Allsopp (@dra27)
- 可重定位编译器。我在 8 月和 9 月工作于此修补集。Windows 和 Unix 的原型都已重新构建到 4.12 和 4.13。使用这些修补程序,如果您的机器上有编译器的多个版本(即 opam!),则字节码可执行文件现在几乎不可能加载错误的 C 存根库(例如
dllunix.so
)或调用错误版本的ocamlrun
。此外,至少从编译器的角度来看,本地 opam 切换现在可以移动到新位置。这主要使克隆现有编译器以创建新的 opam 切换成为可能,而无需进行任何二进制重写。使用这些修补程序,新的本地切换在 5-10 秒内构建完成(其中很大一部分时间花费在 opam 上,opam 现在更有动力进行改进!)。 - 4.13 包含了减少构建系统中脚本语言使用量的首批工作,这提高了构建系统的稳定性和可移植性。Cygwin 发行版最近默认停止分发
iconv
命令,这破坏了所有 OCaml 的 Windows 构建(参见 [#10451](https://github.com/ocaml/ocaml/pull/10451 - [404 Not Found])。还有更多工作要做,但其余工作可能会被推迟到 OCaml 5.00 之后。由于脚本语言的使用大幅减少,因此可以使用本地 Windows 编译的 GNU make(即,没有其他依赖项的make.exe
)以及没有 Cygwin/MSYS2/WSL,能够在构建过程中走得更远。 - 4.13 包含了对 FlexDLL 引导和检测的全面检修(在我 4 月份的更新中提到);希望随机选择错误的 flexlink 或突然发现 FlexDLL 丢失的日子一去不复返了。在引导 FlexDLL 时,Windows 构建的速度也应该明显加快(这就是 opam 的源代码构建必须执行的操作)。
- 在 #10505 中,正在进行一些工作,旨在“现代化”我们对 POSIX 的使用,以删除 Unix 库中的一些较旧的兼容性代码。删除代码总是很令人高兴!
- 逐渐完成并关闭一些我较旧的 PR,通常用更简单的实现替换它们。有趣的是,重新回到 PR 经常会导致意识到更简单的方法;就像让茶浸泡一样!:tea
Xavier Leroy (@xavierleroy)
我处理了原生代码编译器处理尾递归调用时的老问题:如果调用有许多参数,并且这些参数没有全部适合用于参数传递的处理器寄存器,则剩余的参数将被放置在堆栈上,并执行常规的、非尾递归调用。自 OCaml 问世的第一天起,我们就一直存在这种限制。过去,我尝试过几次在参数通过堆栈传递时实现适当的尾递归调用,但都失败了,因为 GC 用于遍历堆栈的堆栈帧描述符存在困难。
在 #10595 中,我通过推广一个早期的针对 OCaml 的 i386 端口的特定技巧,开发了一种更简单的方法,该方法使用“域状态”结构中的内存,而不是堆栈。一旦用于传递函数参数的寄存器用完,接下来的 64 个参数将被传递到域状态的一部分的内存区域中。这种参数传递与尾递归调用兼容,因此我们至少保证了最多 70 个参数的尾递归调用。
域状态结构是在准备合并多核 OCaml 时引入的,它是一个每个执行域的内存区域,可以从寄存器中有效地寻址。因此,通过域状态传递参数对于并行性来说是安全的,并且与通过堆栈传递参数一样高效。
享受您的 70 个参数的尾递归调用吧!
构造函数拆箱(Nicolas Chataing @nchataing,Gabriel Scherer @gasche)
Nicolas Chataing 关于构造函数拆箱的实习(在 上一期 中提到)于 6 月底结束。我们一直在断断续续地以较慢的速度进行工作,以使原型达到我们可以提交 PR 的状态。第一步是提出我们的规范(与 Jeremy Yallop 的原始提议不同),该规范现在已发布 作为 RFC 评论。
对这个主题进行黑客攻击产生了一系列小的上游 PR,主要是清理和重构,这些清理和重构使我们的实现更轻松,还有一些文档 PR,用于我们必须阅读代码才能弄清楚的现有代码库的细微方面:#10500、#10512(尚未合并,产生了有趣的讨论)、#10516、#10637、#10646。
Vincent Laviron (@lthls(github)/@vlaviron(discuss))
Léo Boitel 关于检测和简化身份函数的实习于 6 月结束(在 OCamlPro 上找到相应的博客文章,并在 Discuss 上找到讨论)。目前将结果推送到上游并不是优先事项,但我计划在未来某个时间点构建在该工作基础上,并将其集成到主编译器或 Flambda 2 分支中。
除此之外,我还记录了我们在 Flambda 2 简化传递中用于近似的抽象域(您可以在 此处 找到结果),我还与 Keryan Dider (@Keryan-dev) 合作开发了 Flambda 2 的等效于 -Oclassic
模式的东西。
我还建议并审查了上游和 Flambda 2 存储库中的许多小修复,从修复模糊错误(如 此 Flambda 错误)到对代码生成进行的小改进。
Jacques Garrigue (@garrigue)
继续与 Takafumi Saikawa (@t6s) 合作,加强统一算法中使用的 datatypes。
- #10337 使类型节点抽象化,确保始终看到范式。6 月合并。
- #10474 多态变体行也是如此。9 月合并。
- #10627 多态变体字段类型也是如此。
- #10541 对象字段类型和函数交换标志也是如此。
还继续进行创建生成 Coq 代码的后端的工作 GitHub - COCTI/ocaml at ocaml_in_coq。现在可以与许多示例一起使用。