使用llvm-hs开发编译器:能否直接拼接Definition列表生成Module?
关于llvm-hs中复用预定义函数的方案解答
核心结论
完全可以直接拼接Definition列表来将预定义函数加入每个新Module,这是可行的方案。
具体分析
1. 拼接Definition的可行性
你的预定义函数都是带有外部链接属性的LLVM函数实现,将它们的Definition直接追加到新Module的定义列表中,效果等同于在新Module的ModuleBuilder里直接定义这些函数。LLVM会正确识别这些函数的完整实现,生成的IR中会包含这些函数的代码,Module内的其他代码可以直接调用它们,不会出现符号问题。
2. 与链接库方案的差异
- 拼接方式:
- 优点:实现简单,不需要额外的链接流程,每个生成的Module都是独立可执行的IR文件,适合快速验证逻辑。
- 缺点:每个Module都会包含预定义函数的完整代码,会造成代码冗余,当预定义函数数量增多时,最终产物的体积会显著增大。
- 链接库方式:
- 优点:预定义函数只存在于单独的库文件中,新Module仅保留函数的外部声明,避免了代码冗余;LLVM的优化器可以跨模块进行更深度的优化(如跨模块内联、全局死代码消除),产物性能和体积更优。
- 缺点:需要额外管理库文件和链接流程,初期配置稍复杂。
3. 外部链接属性的作用
你设置的外部链接属性刚好适配这两种方案:
- 拼接时,外部链接的函数可以被Module内的代码直接引用,LLVM不会因为符号重复定义报错(但要注意如果后续修改函数实现,需确保所有拼接的地方同步更新)。
- 链接时,新Module中的外部声明可以在链接阶段找到库中的函数实现,解决符号依赖问题。
实践建议
- 如果当前预定义函数数量少,且优先追求开发效率,拼接
Definition列表的方式完全够用。 - 如果未来预定义函数会持续扩充,或者对产物的体积、性能有要求,建议尽早切换到库链接模式:可以先将预定义函数单独生成一个IR模块,后续新模块仅生成调用这些函数的代码,最后用llvm-hs的
linkModules工具将多个模块合并。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

