理解GHC汇编输出

34

使用GHC的-S选项编译Haskell源文件时,生成的汇编代码不是很清晰。汇编代码中没有明确区分哪些部分属于Haskell代码的哪些部分。与GCC不同,它会按照每个标签对应的函数进行命名。

GHC生成的这些名称是否遵循某种惯例?如何将生成的汇编代码中的某些部分与其在Haskell代码中对应的部分联系起来?

1个回答

31

对于顶层声明来说,这并不太难。但对于局部定义,由于名称会被混淆并且可能会被内联,因此很难识别。

让我们看看当我们编译这个简单模块时会发生什么。

module Example where

add :: Int -> Int -> Int
add x y = x + y
.data
    .align 8
.globl Example_add_closure
.type Example_add_closure, @object
Example_add_closure:
    .quad   Example_add_info
.text
    .align 8
    .quad   8589934604
    .quad   0
    .quad   15
.globl Example_add_info
.type Example_add_info, @object
Example_add_info:
.LckX:
    jmp base_GHCziBase_plusInt_info
.data
    .align 8
_module_registered:
    .quad   0
.text
    .align 8
.globl __stginit_Example_
.type __stginit_Example_, @object
__stginit_Example_:
.Lcl7:
    cmpq $0,_module_registered
    jne .Lcl8
.Lcl9:
    movq $1,_module_registered
    addq $-8,%rbp
    movq $__stginit_base_Prelude_,(%rbp)
.Lcl8:
    addq $8,%rbp
    jmp *-8(%rbp)
.text
    .align 8
.globl __stginit_Example
.type __stginit_Example, @object
__stginit_Example:
.Lcld:
    jmp __stginit_Example_
.section .note.GNU-stack,"",@progbits
.ident "GHC 7.0.2"
你可以看到我们的函数 Example.add 生成了 Example_add_closureExample_add_info_closure 部分与闭包有关,而 _info 部分包含函数的实际指令。在这种情况下,它只是跳转到内置函数 GHC.Base.plusInt
请注意,从 Haskell 代码生成的汇编与其他语言得到的汇编看起来非常不同。调用约定也不同,事情可能会被重排很多次。
在大多数情况下,你不需要直接跳转到汇编。通常更容易理解的是核心语言(core),它是 Haskell 的简化版本。(编译更简单,不一定易读)。要获取核心代码,请使用 -ddump-simpl 选项进行编译。
Example.add :: GHC.Types.Int -> GHC.Types.Int -> GHC.Types.Int
[GblId, Arity=2]
Example.add =
  \ (x_abt :: GHC.Types.Int) (y_abu :: GHC.Types.Int) ->
    GHC.Num.+ @ GHC.Types.Int GHC.Num.$fNumInt x_abt y_abu

关于如何阅读core的一些好资源,可以参考这个问题


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接