2011-07-24 87 views
29

使用GHC中的-S選項編譯haskell源文件時,生成的彙編代碼不清晰。彙編代碼的哪些部分屬於haskell代碼的哪些部分之間沒有明確的區別。與GCC不同,每個標籤都是根據其對應的功能命名的。瞭解GHC彙編輸出

GHC生成的這些名稱是否存在某種約定?我如何將生成的彙編代碼中的某些部分與haskell代碼中的相應部分相關聯?

回答

26

對於頂級聲明,這並不難。局部定義可能更難以識別,因爲他們的名字會被破壞,並且可能會被內聯。我們來看看編譯這個簡單模塊時會發生什麼。

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代碼生成的程序集看起來與您可能從其他語言獲得的程序完全不同。調用約定是不同的,事情可以重新排序。

在大多數情況下,您不想直接跳到裝配。理解核心是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 

對於如何讀取核心的一些很好的資源,請參閱this question