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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With