OCaml 编译器 - 2021 年 5 月前
嗨,Discuss,
我很高兴地介绍“OCaml 编译器开发新闻通讯”的第一期。我邀请了 OCaml 编译器代码库的常客贡献者撰写一篇关于他们最近工作的小文章,目的是分享更多关于人们感兴趣、关注和正在从事的工作的信息。
这绝非详尽无遗:许多人最终没有时间写东西,这也没关系。但希望这可以提供一个小窗口,展示与 OCaml 编译器相关的开发活动,其结构与编译器代码库中无休止的 Pull Request 流不同。
(这项倡议受到优秀的 Multicore 新闻通讯的启发。请不要期望它会像它一样完美或一致 :yo-yo: 。)
注意
-
当然,请随时发表评论或提出问题,但我不知道撰写小文章的人是否会关注该主题,所以不作任何承诺。
-
如果您一直在从事 OCaml 编译器的工作并想说些什么,请随时发布!如果您希望我在下次准备新闻通讯时与您联系(未来某个随机时间点),请通过电子邮件 (gabriel.scherer at gmail) 告诉我。
@dra27 (David Allsopp)
编译器重定位补丁现已存在。还有一些补丁需要编写,并且需要将其拆分为可审查的 PR,但核心功能正在运行。编译器安装可以复制到新位置并继续工作,这意味着 opam 中的本地切换理论上可以重命名,更重要的是,我们可以缓存先前构建的编译器在 opam 根目录中,以允许新切换的编译器成为副本。这可能无法及时审查以用于 4.13,尽管一旦合并,opam-repository 将向早期编译器提供回溯端口。
大量脚本带来的痛苦导致了一些可能的补丁,以减少编译器构建中脚本的使用,使其更接近于零。
FlexDLL 引导程序已完全更新,大大减少了构建时间。这将在 4.13 中实现 (#10135)
@nojb (Nicolás Ojeda Bär)
我正在处理 #10159,它可以在 -output-complete-exe
二进制文件中启用调试信息。它在类 Unix 系统下使用 incbin,在 Windows 下使用其他方法。
@gasche (Gabriel Scherer)
我致力于将更多 PR 推向决策(合并或关闭)。未决 PR 的数量从 220 左右减少到 180,感觉很好。
我还为 @Ekdohibs 的项目 camlboot 做出了贡献,这是一个“无需引导”的 OCaml 实现,能够编译 OCaml 编译器本身。它目前出于各种原因针对 OCaml 4.07。我们能够完成 OCaml 编译器的完整构建,并检查结果是否生成与上游引导程序一致的引导程序二进制文件。这让我们对 OCaml 引导程序免受“信任信任”攻击具有极强的信心。有关更多详细信息,请参阅我们的 草稿论文。
与 @Octachron (Florian Angeletti) 合作
我与 Florian Angeletti 合作弃用某些命令行警告说明符序列,以避免 (4.12 中新增) 警告名称带来的可用性问题。在 -w -partial-match
禁用警告 4 之前,但 -w -partial
被解释为序列 w -p -w a -w r -w t -w i -w a -w l
,其中大部分都被忽略,但 -w a
会使所有警告静音。现在,“无符号”说明符的多字母序列 (-p
是有符号的,a
是无符号的) 已被弃用。(我们首先弃用了所有无符号说明符,但 Leo White 测试了结果并指出 -w A
很常见,因此现在我们只对无符号说明符的多字母序列发出警告。)
我正在与 @Octachron (Florian Angeletti) 合作,在遍历模块签名时对签名项进行分组。某些项是“幽灵项”,在道德上附加在“主要项”中;代码大多忽略这一点,这在极端情况下会导致各种错误。这是 Florian 于 2019 年 9 月在 #8929 中开始的工作,以修复签名重印中的错误。我直到 2020 年 5 月至 9 月才开始审查,我们决定进行相当大的更改,他在 2021 年 1 月将其拆分为几个较小的更改,并在 2021 年 4 月合并了这些更改。现在我们正在寻找修复其代码的其他错误 (#9774,#10385)。就在本周,Florian 完成了一个不错的 PR,修复了与签名项分组相关的几个不同的问题:#10401。
@xavierleroy (Xavier Leroy)
我修复了 #10339,这是在新的配备“苹果硅”的 Mac 上发生的奇怪崩溃。这是由于 ARM(32 位和 64 位)特定数组边界检查优化导致的,后端与平台无关的部分没有考虑这一点,从而导致错误的活跃性分析和错误的寄存器分配。#10354 通过通知后端与平台无关的部分某些特定于平台的指令可能会引发异常来修复此问题。顺便说一句,它重构了类似的代码,这些代码在特定于平台的文件中复制了与平台无关的计算(哪些指令是纯指令)。
我在 Inria 的 Jenkins 持续集成系统上花费了大量时间,集成了新的 Mac Mini M1。由于未知原因,Jenkins 在 x86-64 模拟模式下运行 CI 脚本,因此我们构建并测试了 OCaml 的 x86-64 版本,而不是预期的 ARM64 版本。稍后进行一些脚本编写 (8b1bc01c3),瞧,arm64-macos 正确地作为我们 CI 的一部分进行了测试。
目前,我正在阅读 Sadiq Jaffer 提出的“安全点”提案 (#10039) 以及 Damien Doligez 在此基础上进行的更改。这是迈向 Multicore OCaml 的必要步骤,因此我们确实需要在这方面取得进展。这是一个非平凡的更改,涉及新的静态分析以及每个代码发射器中的许多调整,但事情开始看起来不错了。
@mshinwell (Mark Shinwell)
我对安全点 PR (#10039) 进行了第一轮审查,并大幅简化了提议的后端更改。我还参与了关于一个新的函数级属性的讨论,如果函数体中可能存在安全点(包括分配),则会导致错误,从而使当前假设这一点的代码更健壮。这方面很快就会有设计文档。
我修复了 RISC-V Inria CI 工作程序上发生的随机段错误 (#10349)。
在 Flambda 2 领域,我们花了两个人日的时间调试与 Infix_tag 相关的问题!我们发现,从 OCaml 4.12 开始,遍历静态数据 (“caml_globals”) 中 GC 根的代码,如果任何根是闭包,则不正确。这部分是因为新的压缩代码 (#9728) 有一个隐藏的不变式:它不得多次看到静态数据根的任何字段(即使通过 Infix_tag)。据我们所知,这些情况在现有编译器中不会出现,尽管我们可能会建议一个补丁来防止它们。它们在 Flambda 2 中出现,因为为了编译静态分配的不恒定闭包(其环境在运行时部分或全部计算),我们将闭包直接注册为全局根,以便稍后可以修补其环境。
@garrigue (Jacques Garrigue)
我一直在处理许多修复类型系统中错误的 PR,这些 PR 现在已合并
- #10277 修复了 GADT 类型推断主要性中的理论错误 (#10383 仅在 -principal 模式下适用)
- #10308 修复了模式中的局部打开与引入存在类型变量的新语法之间的交互
- #10322 是一个内部更改,在弱引用内部使用普通引用进行回溯;弱引用是在回溯很少使用时的一种优化,现在不再有用
- #10344 修复了可选参数求值延迟中的错误
- #10347 在统一算法中清理了一些代码,在加强了通用变量作用域之后
- #10362 修复了类型检查算法中遗漏的规范化
有些仍在进行中
- #10348 改进了统一期间扩展的方式,以避免某些虚假的与 GADT 相关的歧义错误
- #10364 更改了模式匹配情况主体类型,允许在某些非主要情况下发出警告;它还发现了类型检查器内部的一些与主要性相关的错误
最后,我与 Takafumi Saikawa (@t6s) 合作,使类型的表示更接近其逻辑含义,通过确保始终在 #10337 中操作规范化的视图(重大更改,评估正在进行中)。
@let-def (Frédéric Bour)
一段时间以来,我一直在研究从 Menhir 解析器生成错误消息的新方法。
我最初的目标是检测并为“let ;”情况生成精确的消息
let x = 5;
let y = 6
let z = 7
LR 在第三个“let”处检测到错误,这在技术上是正确的,尽管我们希望将用户指向“;”,这可能是错误的根本原因。该目标已经实现,但原型距离投入生产还有很远的路要走。
提高错误上下文识别能力和可维护性的主要思想是使用一种正则表达式的风格。解析器的堆栈定义了句子的前缀。我们的正则表达式与之匹配。自动机的内部细节不会泄露(没有对状态的引用),正则语言仅由语法定义。使用适当的工具,可以通过从粗略的表达式开始并对其进行细化以缩小感兴趣的情况来捕获特定情况。
我现在专注于“错误消息”开发流程中的一个特定点:提高“menhir --list-errors”的效率。此命令用于枚举涵盖所有错误情况(由 LR 语法定义)的句子。在我的电脑上以及使用 OCaml 语法时,它需要几分钟时间并且消耗相当多的 RAM。初步结果令人鼓舞,我希望很快就能为 Menhir 提交一个 PR。我们追求的性能改进是使该命令对于常用语法几乎达到实时,并通过减少内存需求来处理更大的语法。例如,在 OCaml 的情况下,运行时间从 3 分钟缩短到 2-3 秒,内存消耗从几个 GiB 降至 200 MiB。