理解 GHC 编译代码在最低层级的工作原理

6 浏览
0 Comments

理解 GHC 编译代码在最低层级的工作原理

在使用编程语言时,我发现了解代码编译过程非常有用。例如,我喜欢使用C语言,因为我可以在像GDB这样的调试器中检查反汇编代码,并快速了解我编写的C代码实际上是如何运行的。\nHaskell维基页面上有一些调试建议,但我还没有找到一种可以查看GHC生成的反汇编代码的方法。使用GDB查看它并不是很有帮助,因为我无法找到特定函数的代码,弄清楚特定变量存储的位置,设置断点或者进行其他像在C程序中那样的操作。\n我的问题是:如何以有用的方式反汇编由GHC生成的代码?有没有工具可以生成GHC生成的代码的注释清单?是否有一种编译函数的方式,可以看到生成的代码的运行过程?\n一些额外的背景和参考资料:\n我之所以想要这样做的一个原因是,我认为这种理解对于获得良好的性能非常重要(例如,C与Haskell Collatz猜想速度比较)。Haskell维基页面上关于性能的条目并没有详细介绍如何回答这个SO问题(即,C编译器对n % 2n / 2进行优化,而GHC对quot n 2rem n 2没有进行优化)。如果我能看到反汇编代码,我就能自己弄清楚。\n我发现的一些资源包括:\n

\n这些资源非常有用,但为了完全理解它们,我觉得需要看到实际编译的GHC代码的运行情况。

0
0 Comments

运行GHC编译的程序时,使用Gnu Debugger(GDB)进行调试是一种常见的方法。然而,使用GDB追踪Haskell代码的执行过程非常困难。因此,大多数人会查看各种中间编译器输出形式,以理解GHC编译的代码。接下来,我们将讨论为什么需要了解GHC编译的代码的最低级别以及相应的解决方法。

首先,我们提到了使用GDB调试Haskell程序的方法,并展示了如何设置断点、反汇编和逐行调试代码。通过反汇编代码,我们可以看到优化后的`quot2`函数代码使用了右移操作来实现将负数向零截断的效果。通过比较使用`quot`和`div`操作的代码,我们发现`div`操作生成的代码更高效。

然而,使用GDB调试Haskell代码仍然非常困难,因为Haskell的惰性求值模型以及GHC编译器生成的汇编代码都使得追踪代码执行过程变得复杂。为了更好地理解GHC编译的代码,大多数人会查看各种中间编译器输出形式。

GHC编译器提供了一系列的`-ddump-xxx`选项来输出中间编译器输出形式。这些形式包括Core、STG、CMM和汇编代码。通过查看这些输出形式,可以更好地理解代码的执行过程。在这些输出形式中,STG是最接近实际执行的形式,而汇编代码则更容易理解。

然而,需要注意的是,在使用GDB调试时,可执行文件中的符号名称与中间编译器输出形式中的名称不同。在GDB中,符号名称被修改为一种特殊的形式,以防止与用户定义的类型或函数名称冲突。

了解GHC编译的代码的最低级别是为了更好地理解代码的执行过程和性能问题。通过查看中间编译器输出形式,特别是STG和汇编代码,可以更好地理解代码的执行过程和优化方式。这对于调试和优化Haskell代码非常有帮助。

总之,通过查看中间编译器输出形式,特别是STG和汇编代码,可以更好地理解GHC编译的代码。这有助于调试和优化Haskell代码,以提高性能和理解代码的执行过程。

0