lli:LLVM错误:无法选择:X86ISD::WrapperRIP TargetGlobalTLSA地址:i64

lli: LLVM ERROR: Cannot select: X86ISD::WrapperRIP TargetGlobalTLSAddress:i64

本文关键字:WrapperRIP TargetGlobalTLSA i64 X86ISD 地址 LLVM 错误 lli 选择      更新时间:2023-10-16

在Linux(Debian)上使用clang++ -S -emit-llvm main.cpp && lli main.ll运行以下代码

#include <future>
int main () {
return std::async([]{return 1;}).get();
}

由于以下错误,无法在lli上运行:

LLVM ERROR: Cannot select: 0xd012e0: 
i64 = X86ISD::WrapperRIP TargetGlobalTLSAddress:i64<i8** @_ZSt15__once_callable> 0 [TF=10]
0xd020c0: i64 = TargetGlobalTLSAddress<i8** @_ZSt15__once_callable> 0 [TF=10]
In function: _ZSt9call_onceIMNSt13__future_base13_State_baseV2EFvPSt8functionIFSt10unique_ptrINS0_12_Result_baseENS4_8_DeleterEEvEEPbEJPS1_S9_SA_EEvRSt9once_flagOT_DpOT0_

问题:

这是什么意思?

是否有任何编译器标志可以解决此问题?

使用CCD_ 2编译并成功运行*;libstdc++使用了哪些特定功能导致了此问题?

编辑:

这个问题背后的动机是了解libc++和libstdc++之间的差异,这导致了llvm的orcjit中出现这个特定的错误消息(在Linux上)。

在OSX上,gcc已被弃用,clang默认使用libc++。要在OSX上重现这个错误,您可能需要安装gcc&使用CCD_ 4。

这是llvm ir(不幸的是,直接嵌入这里太大了)

编辑:

该错误是由JITer中缺乏TLS支持引起的。这个答案描述了与链接和lli有关的另一个问题。


如果您查看clang++ -std=c++11 -S -emit-llvm test.cpp生成的IR,您会发现许多符号,例如_ZNSt6futureIiE3getEv,只是声明的,而从未定义。链接器从未被调用,因为-S"仅运行[S]预处理和编译步骤"(clang--help)。

lli只执行IR模块,没有"隐式"链接,它应该如何知道链接到哪些库?

有不同的解决方案,这取决于你为什么使用lli:

  • 编译并链接IR模块:llc main.cpp && clang++ -lpthread main.s(pthread是必需的。在linux下的GCC中使用std::thread的正确链接选项是什么?)
  • (未确认)在运行lli之前使用LD_PRELOAD="x.so y.so"强制加载库
  • 以编程方式JIT模块,并使用LoadLibraryPermanently(nullptr)(将程序的符号添加到搜索空间)和LoadLibraryPermanently(file, err)来获得额外的库。http://llvm.org/docs/doxygen/html/classllvm_1_1sys_1_1DynamicLibrary.html)

我只能猜测为什么libc++在我的机器上失败了,它对你有效,但可能是因为它已经加载到lli中,并且lli调用sys::DynamicLibrary::LoadLibraryPermanently(nullptr)将程序的符号添加到其JIT搜索空间中。https://github.com/llvm-mirror/llvm/blob/release_40/tools/lli/OrcLazyJIT.cpp#L110)。

LLVM开发邮件列表指出:

这是什么意思?

orcjit中的llvm后端当前不支持线程本地存储(TLS)

一个最小的例子是:

extern thread_local int tls;
int main() {
tls = 42;
return 0;
}

使用-stdlib=libc++编译并成功运行*;libstdc++使用了哪些特定功能导致了此问题?

这是因为libc++future::get实现不使用thread_local关键字。

是否有任何编译器标志可以解决此问题?

目前没有解决方案。使用lli -relocation-model=pic将此问题与重新定位失败进行权衡。