Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Running the following code with clang++ -S -emit-llvm main.cpp && lli main.ll on Linux(Debian)

#include <future>

int main () {
  return std::async([]{return 1;}).get();
}

fails to run on lli due to the following error:

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_

Questions:

What does it mean?

Are there any compiler-flags that fix this problem?

using -stdlib=libc++ compiles and runs successfully*; what specific features is libstdc++ using that cause this issue ?

EDIT:

The motivation behind this question is to understand the differences between libc++ and libstdc++ that leads to this specific error message (on Linux) in llvm's orcjit.

On OSX gcc has been deprecated and clang uses by default libc++. To reproduce this error on OSX you probably have to install gcc & use -stdlib=libstdc++.

Here is the llvm-ir (it's unfortunately to big to embed it here directly)

like image 524
Gaetano Avatar asked Feb 03 '17 11:02

Gaetano


2 Answers

The LLVM-dev mailinglist pointed out:

What does it mean?

The llvm-backend in orcjit does currently not support thread-local storage(TLS)

a minimal example is:

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

using -stdlib=libc++ compiles and runs successfully*; what specific features is libstdc++ using that cause this issue ?

this works because libc++ future::get implementation does not use thread_local keyword.

Are there any compiler-flags that fix this problem?

currently there is no solution. Using lli -relocation-model=pic trades this problem with a relocation failure.

like image 81
Gaetano Avatar answered Oct 02 '22 23:10

Gaetano


EDIT:

The error turned out to be caused by the lack of TLS support in the JITer. This answer describes another problem concerned with linking and lli.


If you have a look at the generated IR from clang++ -std=c++11 -S -emit-llvm test.cpp, you will find that many of the symbols, e.g. _ZNSt6futureIiE3getEv, are only declared, but never defined. The linker is never called, since -S "Only run[s] preprocess and compilation steps" (clang --help).

lli only executes the IR Module and does no "implicit" linking, how is it supposed to know which libraries to link in?

There are different solutions to this, depending on why you are using lli:

  • compile and link the IR Module: llc main.cpp && clang++ -lpthread main.s (pthread is required s. What is the correct link options to use std::thread in GCC under linux?)
  • (unconfirmed) use LD_PRELOAD="x.so y.so" to force-load the libraries before running lli
  • JIT the module programmatically and use LoadLibraryPermanently(nullptr) (adds symbols of the program into the search space) and LoadLibraryPermanently(file, err) for additional libs (s. http://llvm.org/docs/doxygen/html/classllvm_1_1sys_1_1DynamicLibrary.html)

I can only guess as to why libc++ works for you since it fails on my machine, but presumably it's the case because it is loaded into lli already and lli calls sys::DynamicLibrary::LoadLibraryPermanently(nullptr) to add the program's symbols to its JIT search space (s. https://github.com/llvm-mirror/llvm/blob/release_40/tools/lli/OrcLazyJIT.cpp#L110).

like image 40
Tobias Avatar answered Oct 02 '22 22:10

Tobias