2011-07-24 44 views
29

Khi biên dịch tệp nguồn haskell bằng tùy chọn -S trong GHC, mã assembly được tạo không rõ ràng. Không có sự phân biệt rõ ràng giữa các phần nào của mã assembly thuộc về các phần nào của mã haskell. Không giống như GCC, mỗi nhãn được đặt tên theo hàm tương ứng với nó.Hiểu đầu ra lắp ráp GHC

Có một quy ước nào đó trong những tên này do GHC sản xuất không? Làm thế nào tôi có thể liên kết một số phần trong mã lắp ráp được tạo ra với các phần tương ứng của chúng trong mã haskell?

Trả lời

26

Đối với các khai báo cấp cao nhất, nó không quá khó. Các định nghĩa địa phương có thể khó nhận ra hơn vì tên của chúng bị xáo trộn và chúng có khả năng bị gạch chân.

Hãy xem điều gì xảy ra khi chúng tôi biên dịch mô-đun đơn giản này.

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" 

Bạn có thể thấy rằng chức năng của chúng tôi Example.add dẫn đến việc tạo ra Example_add_closureExample_add_info. Phần _closure, như tên cho thấy, phải làm với bao đóng. Phần _info chứa hướng dẫn thực tế của hàm. Trong trường hợp này, điều này chỉ đơn giản là một bước nhảy đến hàm dựng sẵn GHC.Base.plusInt.

Lưu ý rằng hội đồng được tạo từ mã Haskell trông khá khác với những gì bạn có thể nhận được từ các ngôn ngữ khác. Các quy ước gọi là khác nhau, và mọi thứ có thể được sắp xếp lại rất nhiều.

Trong hầu hết các trường hợp, bạn không muốn chuyển thẳng sang hội đồng. Thông thường, việc hiểu rõ hơn lõi, một phiên bản đơn giản của Haskell. (Đơn giản để biên dịch, không nhất thiết phải đọc). Để lấy cốt lõi, biên dịch với tùy chọn -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 

Đối với một số tài nguyên tốt về cách đọc lõi, xem this question.