Понимание вывода сборки GHC - PullRequest
32 голосов
/ 24 июля 2011

При компиляции исходного файла haskell с использованием опции -S в GHC сгенерированный код сборки неясен.Нет четкого различия между частями кода сборки и частями кода haskell.В отличие от GCC, где каждая метка была названа в соответствии с функцией, которой она соответствует.

Существует ли определенное соглашение в этих именах, создаваемых GHC?Как связать определенные детали в сгенерированном коде сборки с соответствующими деталями в коде haskell?

1 Ответ

29 голосов
/ 24 июля 2011

Для объявлений верхнего уровня это не так уж сложно.Локальные определения может быть сложнее распознать, так как их имена искажены, и они могут быть встроенными.

Давайте посмотрим, что произойдет, когда мы скомпилируем этот простой модуль.

module Example where

add :: Int -> Int -> Int
add x y = x + y
<strong>.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</strong>
.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_closure и Example_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

Чтобы узнать, как читать ядро, см. этот вопрос .

...