链接时 LLVM IR 类型被错误折叠 (C++ API)

LLVM IR types being collapsed wrongly when linking (C++ API)

开门见山——我正在尝试 link 将两个(或更多)llvm 模块组合在一起,但我遇到了来自 LLVM 的某个奇怪错误。

我不想post太多代码,所以我会在这里使用一堆伪代码。

我有3个模块,比方说A、B和C。A是主模块;我用它初始化 llvm::Linker 。 B和C是二级模块;我叫linker.linkInModule(B and C).

所有 3 个模块都定义了这两种类型:

%String = type { i8*, i64 }
%Character = type { i8*, i64 }

请注意,它们具有相同的成员类型。此外,函数 foo 是这样定义的(在模块 B 中):

define i1 @_ZN9Character7hasDataEv(%Character*) { }

此函数在模块 A 和 C 中声明。现在,一切似乎都很好 -- 从模块 A 和 C 调用此函数,并且 IR 看起来正常,如下所示:

%21 = call i1 @_ZN9Character7hasDataEv(%Character* %4)

问题来了:当所有 3 个模块 link 在一起时,这些类型发生了一些事情:

  1. 他们失去了名字,成为 %2 (%String) 和 %3 (%Character)。
  2. 它们似乎合并在一起了。

奇怪的是,虽然这种转换发生在模块 A 和 C 中,但错误只发生在 C 中——注意 A 是所谓的 "main" 模块。

linked 文件的函数定义现在是

define i1 @_ZN9Character7hasDataEv(%2*)

请注意 %Character%3 是如何变成 %2 的。此外,在调用站点,大概是在尝试取消合并类型,我得到了这个:

%10 = call i1 bitcast (i1 (%2*)* @_ZN9Character7hasDataEv to i1 (%3*)*)(%2* %2)

奇怪的是,尽管函数从 i1 (%2*) 转换为 %3 (%2*),但传递的参数 (arg. 1) 仍然是 %2 类型。怎么回事?

请注意,在模块A中,无论发生什么都正确完成,没有错误。许多功能都会发生这种情况,但仅限于模块 C。

我尝试通过将这些复制粘贴到 .ll 文件并调用 llvm-link 然后调用 llvm-dis 来重现它,但是 1. 类型没有合并,并且 2.没有这样的错误。

谢谢...?

好的,事实证明,在 llvm IRC 频道中进行了一些探索之后,llvm::Linker 应该与一个空的 llvm::Module 作为起始模块一起使用。

此外,在我的用例中,我在 link 的不同模块中重复使用相同的 llvm::Type(内存中的实际内容)。他们说这不违法,但是从来没有测试过,所以...¯\_(ツ)_/¯

所以无论如何,问题是通过从一个空模块开始传递给 linker 来解决的。