如何在编译器中实现源映射?

sin*_*ity 3 compiler-construction haskell source-maps

我正在 Haskell 中实现一个编译器,将源语言编译为目标语言(类似汇编)。

出于调试目的,需要源映射将目标语言汇编指令映射到其相应的源位置(行和列)。

我已经广泛搜索了编译器实现,但没有一个包含源映射。

谁能指出我如何生成源地图的正确方向?

代码示例、书籍等。Haskell 优先,其他语言也欢迎。

SK-*_*gic 5

详细信息取决于您所应用的编译技术。

如果您通过中间语言的一系列转换来完成此操作,就像当今大多数理智的编译器所做的那样,您的选择如下:

  • 使用源位置信息注释所有中间表示(IR) 节点。引入特殊节点来保留变量名称(它们都会在您执行 SSA 转换之后进行,因此您需要单独跟踪它们的起源)
  • 注入大量的内部函数调用(看看它在 LLVM IR 中是如何完成的),而不是注释每个节点
  • 将以上内容混合起来

第一个选项甚至可以几乎自动完成 - 如果每个转换在它创建的所有节点中保留原始节点的源位置,您只需手动更改一些重要的注释。

此外,您还必须记住,某些优化可能会使您的源位置信息完全毫无意义。例如,值编号会将多个相似的表达式折叠为一个,可能会保留一个随机来源的源位置信息。重新物化也是如此。

对于 Haskell,第一种方法会导致 ADT 定义和模式匹配中出现大量样板文件,即使您用诸如废弃您的样板文件 (SYB) 之类的东西来糖衣它,所以我建议使用第二种方法,该方法已被广泛记录并在 LLVM IR 中得到了很好的演示。