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

C++ 链接时错误折叠LLVM IR类型(C+;+;API),c++,llvm,llvm-ir,llvm-c++-api,C++,Llvm,Llvm Ir,Llvm C++ Api,直截了当地说——我试图将两个(或更多)llvm模块链接在一起,但我遇到了来自llvm的某个奇怪错误 我不想发布太多的代码,所以我将在这里使用一堆伪代码 我有3个模块,假设A、B和C。A是主要模块;我用它初始化llvm::Linker。B和C为二级模块;我调用linker.linkInModule(B和C) 除其他外,所有3个模块都定义了以下两种类型: %String = type { i8*, i64 } %Character = type { i8*, i64 } 请注意,它们具有相同的成员

直截了当地说——我试图将两个(或更多)llvm模块链接在一起,但我遇到了来自llvm的某个奇怪错误

我不想发布太多的代码,所以我将在这里使用一堆伪代码

我有3个模块,假设A、B和C。A是主要模块;我用它初始化
llvm::Linker
。B和C为二级模块;我调用
linker.linkInModule(B和C)

除其他外,所有3个模块都定义了以下两种类型:

%String = type { i8*, i64 }
%Character = type { i8*, i64 }
请注意,它们具有相同的成员类型。此外,函数
foo
定义如下(在模块B中):

这个函数是在模块A和C中声明的。现在,一切看起来都很好——这个函数是从模块A和C调用的,IR看起来很正常,如下所示:

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

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

  • 它们失去了名称,变成了
    %2
    %String
    )和
    %3
    %Character
  • 它们似乎合并在一起了
  • 奇怪的是,虽然这种转换发生在模块A和C中,但错误只发生在C中——请注意,A是所谓的“主”模块

    链接文件的函数定义现在是

    define i1 @_ZN9Character7hasDataEv(%2*)
    
    请注意
    %Character
    %3
    如何变成
    %2
    。此外,在callsite,可能是尝试取消合并类型,我得到以下结果:

    %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一起使用作为起始模块

    此外,在我的用例中,我在链接在一起的不同模块之间重用相同的llvm::Type(内存中的实际内容)。他们说这不违法,但从未测试过,所以。。。¯\_(ツ)_/“”


    因此,无论如何,这个问题是通过从一个空模块开始传递到链接器来解决的。

    您是否尝试禁用所有优化?如果使用不同的优化,是否会产生不同的效果?如果遇到奇怪的错误,我首先怀疑的是优化传递会弄乱我的代码。我禁用了所有优化传递。我确实做到了如果没有解决方案,我会把它编辑成问题。
    %10 = call i1 bitcast (i1 (%2*)* @_ZN9Character7hasDataEv to i1 (%3*)*)(%2* %2)