10

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

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

问题:

这是什么意思?

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

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

编辑:

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

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

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

4

2 回答 2

3

编辑:

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


如果您查看从 生成的 IR clang++ -std=c++11 -S -emit-llvm test.cpp,您会发现许多符号,例如_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)。

于 2017-02-05T18:14:50.860 回答
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交易这个问题与重定位失败。

于 2017-02-07T16:43:42.180 回答