考虑到 STG 生成自定义 ABI,Haskell 链接如何工作
How Haskell linking may work given that STG generates custom ABI
据我了解,从 STG 生成的代码使用非常自定义的 ABI,甚至具有自定义调用堆栈。
链接器是如何工作的? GHC 是否使用自定义链接器?
如果您 运行 ghc
使用 -v
标志来生成详细的日志输出,您会看到它调用 gcc
来执行最终的 link.当然,gcc
使用标准系统 ld
linker,但有一些 GHC 认为有用的额外设置。
正如@arrowd 在评论中提到的,linker 并不真正关心调用约定。在大多数情况下,它只是修复对其他目标文件中符号的未定义引用,无论这些符号引用代码还是数据。
当一个 Haskell 模块被编译为本机代码时,它主要采用一堆数据结构(“闭包”)和以元数据为前缀的代码片段(“信息块”)的形式,并且数据和代码标有全局符号,可以被其他模块引用并由 linker 解析,与 linking C 程序时可能解析对数据结构或 C 函数的引用的方式相同.
作为一个简单的例子,相当愚蠢的模块:
module Foo where
foo :: (a -> b -> c) -> d -> a -> b -> c
foo f = const f
当使用 ghc -c -O0 -fforce-recomp -ddump-asm Foo.hs
编译时,基本上会为 foo
生成以下信息块和闭包(通过删除一些额外的汇编编译指示进行简化)。
;; 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
符号Foo.foo_info
和Foo.foo_closure
被模块导出,符号Base.const_closure
被模型中的代码和数据引用,成为必须解析的未定义符号.
使用此 foo
函数的另一个调用模块通常会通过引用符号 Foo.foo_closure
来执行此操作。 linker 会在Foo
模块中解析调用模块对Foo.foo_closure
标签的引用,也会解析Foo
模块对标签GHC.Base.const_closure
在 GHC 基础包中。
据我了解,从 STG 生成的代码使用非常自定义的 ABI,甚至具有自定义调用堆栈。
链接器是如何工作的? GHC 是否使用自定义链接器?
如果您 运行 ghc
使用 -v
标志来生成详细的日志输出,您会看到它调用 gcc
来执行最终的 link.当然,gcc
使用标准系统 ld
linker,但有一些 GHC 认为有用的额外设置。
正如@arrowd 在评论中提到的,linker 并不真正关心调用约定。在大多数情况下,它只是修复对其他目标文件中符号的未定义引用,无论这些符号引用代码还是数据。
当一个 Haskell 模块被编译为本机代码时,它主要采用一堆数据结构(“闭包”)和以元数据为前缀的代码片段(“信息块”)的形式,并且数据和代码标有全局符号,可以被其他模块引用并由 linker 解析,与 linking C 程序时可能解析对数据结构或 C 函数的引用的方式相同.
作为一个简单的例子,相当愚蠢的模块:
module Foo where
foo :: (a -> b -> c) -> d -> a -> b -> c
foo f = const f
当使用 ghc -c -O0 -fforce-recomp -ddump-asm Foo.hs
编译时,基本上会为 foo
生成以下信息块和闭包(通过删除一些额外的汇编编译指示进行简化)。
;; 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
符号Foo.foo_info
和Foo.foo_closure
被模块导出,符号Base.const_closure
被模型中的代码和数据引用,成为必须解析的未定义符号.
使用此 foo
函数的另一个调用模块通常会通过引用符号 Foo.foo_closure
来执行此操作。 linker 会在Foo
模块中解析调用模块对Foo.foo_closure
标签的引用,也会解析Foo
模块对标签GHC.Base.const_closure
在 GHC 基础包中。