Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Haskell linking may work given that STG generates custom ABI

Tags:

haskell

ghc

As far as I understand,code generated from STG uses very custom ABI, which even has custom call stack.

How linker does work then? Does GHC use custom linker?

like image 814
uhbif19 Avatar asked Jan 20 '26 17:01

uhbif19


1 Answers

If you run ghc with the -v flag to generate verbose logging output, you'll see that it invokes gcc to perform the final link. Of course, gcc uses the standard system ld linker, but with some additional setup that GHC finds useful.

As mentioned by @arrowd in the comments, the linker doesn't really care much about calling conventions. For the most part, it just fixes up undefined references to symbols in other object files, whether those symbols reference code or data.

When a Haskell module is compiled to native code, it mostly takes the form of a bunch of data structures ("closures") and code snippets prefixed with metadata ("info blocks"), and that data and code is labelled with global symbols, which can be referenced by other modules and resolved by the linker, the same way references to data structures or C functions might be resolved when linking a C program.

As a simple example, the rather silly module:

module Foo where

foo :: (a -> b -> c) -> d -> a -> b -> c
foo f = const f

when compiled with ghc -c -O0 -fforce-recomp -ddump-asm Foo.hs generates basically the following info block and closure for foo (simplified by removing some extra assembly pragmas).

;; info block, proceeded by a few quad words of metadata
.section .text
    .quad   4294967301
    .quad   0
    .long   14
    .long   GHC.Base.const_closure-(Foo.foo_info)+0
Foo.foo_info:
    movl $GHC.Base.const_closure,%ebx
    jmp stg_ap_p_fast
    .size Foo.foo_info, .-Foo.foo_info

;; closure    
.section .data
Foo.foo_closure:
    .quad   Foo.foo_info
    .quad   0

The symbols Foo.foo_info and Foo.foo_closure are exported by the module, and the symbol Base.const_closure is referenced by code and data in the model, becoming an undefined symbol that must be resolved.

Another calling module using this foo function will typically do so via a reference to the symbol Foo.foo_closure. The linker will resolve the reference from the calling module to the Foo.foo_closure label in the Foo module, and also resolve the reference from the Foo module to the label GHC.Base.const_closure in the GHC base package.

like image 164
K. A. Buhr Avatar answered Jan 22 '26 07:01

K. A. Buhr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!