lli:LLVM错误:无法选择:X86ISD :: WrapperRIP TargetGlobalTLSAddress:i64

时间:2017-02-03 11:11:04

标签: c++ g++ clang llvm-ir lli

在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&amp;使用-stdlib=libstdc++

以下是llvm-ir(不幸的是,它直接将其嵌入此处)

2 个答案:

答案 0 :(得分:3)

编辑:

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

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

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

根据您使用lli的原因,有不同的解决方案:

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

答案 1 :(得分:1)

LLVM-dev邮件列表指出:

  

这是什么意思?

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

最小的例子是:

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

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

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

  

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

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