在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_

问题:

这是什么意思?

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

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

编辑:

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

在OSX上,不建议使用gcc,默认情况下clang使用libc++
要在OSX上重现此错误,您可能必须安装gcc并使用-stdlib=libstdc++

这是llvm-ir(很遗憾,直接将其嵌入此处非常大)

最佳答案

编辑:

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

如果您查看从clang++ -std=c++11 -S -emit-llvm test.cpp生成的IR,您会发现很多符号,例如_ZNSt6futureIiE3getEv仅被声明,但未定义。从不会调用链接程序,因为-S“仅运行预处理和编译步骤”(clang --help)。
lli仅执行IR模块,不执行“隐式”链接,应该如何知道要链接的库?

有多种解决方案,具体取决于您使用lli的原因:

  • 编译并链接IR模块:llc main.cpp && clang++ -lpthread main.s(pthread是必需的s。What is the correct link options to use std::thread in GCC under linux?)
  • (未确认)在运行LD_PRELOAD="x.so y.so"之前使用lli强制加载库
  • 以编程方式JIT该模块,并使用LoadLibraryPermanently(nullptr)(将程序的符号添加到搜索空间中)和LoadLibraryPermanently(file, err)以获得其他库(s。http://llvm.org/docs/doxygen/html/classllvm_1_1sys_1_1DynamicLibrary.html)

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

    关于c++ - lli:LLVM错误:无法选择:X86ISD::WrapperRIP TargetGlobalTLSAddress:i64,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42022864/

    10-13 08:16