Подтвердить что ты не робот

Понимание сборки сборок GHC

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

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

4b9b3361

Ответ 1

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

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

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_closure и Example_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

Для некоторых хороших ресурсов о том, как читать ядро, см. этот вопрос.