Gae*_*ano 10 c++ g++ clang llvm-ir lli
clang++ -S -emit-llvm main.cpp && lli main.ll
在Linux上运行以下代码(Debian)
#include <future>
int main () {
return std::async([]{return 1;}).get();
}
Run Code Online (Sandbox Code Playgroud)
由于以下错误,无法在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_
Run Code Online (Sandbox Code Playgroud)
问题:
这是什么意思?
是否有任何编译器标志可以解决此问题?
使用-stdlib=libc++
编译并成功运行*; libstdc ++使用哪些特定功能会导致此问题?
编辑:
这个问题背后的动机是理解libc ++和libstdc ++之间的差异,这些差异导致llvm的orcjit中的这个特定错误消息(在Linux上).
在OSX上,gcc已被弃用,默认情况下使用clang libc++
.要在OSX上重现此错误,您可能需要安装gcc和use -stdlib=libstdc++
.
这是llvm-ir(遗憾的是直接将它嵌入到这里)
编辑:
事实证明,该错误是由于 JITer 中缺乏 TLS 支持造成的。这个答案描述了与链接 和 相关的另一个问题lli
。
如果您查看 生成的 IR clang++ -std=c++11 -S -emit-llvm test.cpp
,您会发现许多符号,例如_ZNSt6futureIiE3getEv
,仅被声明,但从未定义。链接器永远不会被调用,因为 -S “仅运行[s]预处理和编译步骤”(clang --help)。
lli
只执行 IR 模块并且不进行“隐式”链接,它如何知道要链接到哪些库?
对此有不同的解决方案,具体取决于您使用 lli 的原因:
llc main.cpp && clang++ -lpthread main.s
需要 pthread。在 linux 下的 GCC 中使用 std::thread 的正确链接选项是什么?)LD_PRELOAD="x.so y.so"
在运行前强制加载库lli
LoadLibraryPermanently(nullptr)
(将程序的符号添加到搜索空间中)和LoadLibraryPermanently(file, err)
其他库(s. http://llvm.org/docs/doxygen/html/classllvm_1_1sys_1_1DynamicLibrary.html)我只能猜测为什么 libc++ 对你有用,因为它在我的机器上失败了,但大概是这样,因为它已经加载到 lli 中,并且 lli 调用将sys::DynamicLibrary::LoadLibraryPermanently(nullptr)
程序的符号添加到其 JIT 搜索空间(s. https:// github.com/llvm-mirror/llvm/blob/release_40/tools/lli/OrcLazyJIT.cpp#L110)。