lli: LLVM ERROR: Cannot select: X86ISD::WrapperRIP TargetGlobalTLSAddress:i64 - c++

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)

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).

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.

Related

Use compiled LLVM/clang without gcc

I have been trying to compile LLVM/clang from source, both by myself and using this script. I am compiling clang using gcc 11.2, which itself was also built from source, and hence resides in a non-default location on my system (/scratch/opt/gcc-ml-11.2). Note that it only works with a gcc that was compiled with multilib enabled.
The problem is that I can use the compiled clang and clang++ binaries only if I supply the gcc location as follows: --gcc-toolchain=/scratch/opt/gcc-ml-11.2.0. Without that flag, I run into linker errors:
clang test.c -o test
/usr/bin/ld: cannot find crtbeginS.o: No such file or directory
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: cannot find -lgcc_s
I do not understand why a clang compiled binary needs to link against some kind of gcc library and why clang does not supply the crtbeginS.O file.
I have also tried using the LLVM linker as well as the LLVM standard library for C++ test applications, i.e., "-fuse-ld=lld -stdlib=libc++. This did not help either.
While I could just export CXXFLAGS=--gcc-toolchain=/scratch/opt/gcc-ml-11.2.0, I am not sure whether this is the right approach. Shouldn't clang/LLVM be able to function without a gcc installation?
I have also tried using my clang installation with the --gcc-toolchain=/scratch/opt/gcc-ml-11.2.0 flag to compile clang again, but the new binary also requires the gcc-toolchain flag.
Should I just globally export the path to my gcc toolchain? Why is this necessary? Isn't clang a standalone compiler that - if supplied with the option to use its own standard library - does not require gcc?
Thank you very much for your help!
Best,
Maxbit

Asan dynamic runtime is missing on Ubuntu 18+

If I compile a simple program (sample.cpp):
#include <cstdio>
int main() {
printf("Hello, World");
return 0;
}
with a shared sanitizer library, i.e.
clang++-12 -fsanitize=address -shared-libsan sample.cpp -o sample
I am getting the following error when running ./sample:
./sample: error while loading shared libraries: libclang_rt.asan-x86_64.so: cannot open shared object file: No such file or directory
I am getting this error for the sample code on my local machine (Ubuntu 20.04 and clang-12), as well as our build runner (Ubuntu 18.04 and clang-10).
Am I missing something, or shall I submit a bug and to whom? (The options I see are Ubuntu or LLVM/Clang teams)
Please note that this question is distinct from the one that was suggested as duplicate in close votes (this was confirmed by the linked question author in comments).
This is a deficiency of the clang front-end -- when given -shared-libsan flag, it should automatically add -Wl,-rpath=/usr/lib/llvm-NN/lib/clang/MM.M.M/lib/linux to the link line, but it doesn't.
You could do that yourself by using e.g.
CXX=clang++-12
$CXX -fsanitize=address -shared-libsan sample.cpp -o sample \
-Wl,-rpath=$(dirname $($CXX --print-file-name libclang_rt.asan-x86_64.so))

Clang compiler couldn't find C/C++ standard libraries when I gave a specific target although it works without giving target

I am currently using clang11 on ubuntu to compile any c/c++ code and it works fine but when I tried to compile any code (including any standard library) to assembly code for any specific target like x86_64 (even I have x86_64) riscv with giving a flag that --target=x86_64 or --target=riscv32 I got errors for any standard library that I included in my code. A simple example:
// ex.cpp
#include<iostream>
int main(){
int a = 5;
int b = 3;
std::cout << a - b;
}
Without giving flag for a spesific target works fine:
clang++-11 -S ex.cpp -o ex.s
With --target=riscv32 flag:
clang++-11 --target=riscv32 -S ex.cpp -o ex.s
gives this error:
ex.cpp:1:9: fatal error: 'iostream' file not found
also without standard libraries gives no error even I give a spesific target.
I am searching for a solution for days but I couldn't find any proper solution for this problem, most of them says try to include gnu libraries and subfolders like -I/usr/include/x86_64-linux-gnu/c++/ but it doesn't work for me.
Please don't say use g++ compiler, for adding an optimization I need clang.
Actually I am trying to compile my codes for riscv target, linking with g++ and running with spike (doesn't differ --target=... or -target ...):
clang++-11 -target riscv32-unknown-elf -march=rv32gc -fno-addrsig -S ex.cpp -o ex.s
~/riscv/bin/riscv32-unknown-elf-g++ ex.s -o ex
~/riscv/riscv-isa-sim/build/spike --isa=RV32GC ~/riscv/riscv-pk/build/pk ex
And it works fine without include a standard library.
Now, I want to ask that
Can I solve this problem simply?
or
Can I use clang directly from riscv bin utils like ~/riscv/bin/riscv32-unknown-elf-clang++ (I saw something like this on the net but couldn't find) adding and building a submodule to my riscv directory?
Edit: As #NateEldredge said, for x86_64 target triple should --target=x86_64-linux-gnu but for riscv as a target triple riscv32-unknown-elf I still have the same errors. Is there a proper target flag for riscv any other than --target=riscv32-unknown-elf? Maybe I am missing that point.
I solved my problem by linking compilations with riscv-gnu-toolchain built and also answered a similar question here in detailed: Using Clang to compile for RISC-V
Simply we need cross-compilation.
Further information you can also look here: https://github.com/lowRISC/riscv-llvm#how-can-i-build-upstream-llvmclang-and-use-it-to-cross-compile-for-a-riscv32-target

Cannot find -lubsan on using -fsanitize=undefined (mingw-w64)

I'm using mingw-w64 (gcc 7.3.0) and when I compile any C++ program using the following command:
g++ file.cpp -fsanitize=undefined
I get the following error:
...mingw32/bin/ld.exe: cannot find -lubsan
I'm able to successfully compile and run my programs if I remove the -fsanitize=undefined flag, though. After some research I found out that this means the library ubsan (Undefined Behavior Sanitizer) is missing, but I couldn't find anything about the library. How do I fix this?
This is well known issue with mingw see for instance this msys github issue. No proper solution known but there are several WAs.
Install WSL, ubuntu over WSL and you will have ubsan inside it
Build GCC under Windows from source enabling sanitizers build. They are present in GCC sources they are just not here in mingw.
Use -fsanitize=undefined -fsanitize-undefined-trap-on-error to just not use libubsan rich logging capabilities but get it trap on undefined instruction.
Hope one of this helps.

What library do I need to link to use std::list in clang++?

I am trying to use the std::list class in C++, and I need to use clang++ to compile the program. g++ compiles the following program just fine, but I can't figure out how to compile/link it with clang++:
#include <iostream>
#include <list>
int main(){
std::list<int> L;
L.push_back(10);
std::cout << L.back() << std::endl;
return 0;
}
I've tried clang++ -lstdc++ listTest.cpp but still get the following error:
/tmp/listTest-3175a9.o: In function `std::list<int, std::allocator<int> >::_M_insert(std::_List_iterator<int>, int const&)':
listTest.cpp:(.text._ZNSt4listIiSaIiEE9_M_insertESt14_List_iteratorIiERKi[_ZNSt4listIiSaIiEE9_M_insertESt14_List_iteratorIiERKi]+0x31): undefined reference to `std::__detail::_List_node_base::_M_hook(std::__detail::_List_node_base*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Clang version:
clang version 3.4 (tags/RELEASE_34/final)
linux version:
LSB_VERSION=base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
Red Hat Enterprise Linux Server release 6.5 (Santiago)
You should provide library arguments after the translation unit that uses them:
clang++ listTest.cpp -lstdc++
I should note that I couldn't reproduce your issue, but that could easily be down to differences in version/configuration (particularly w.r.t. a stdlib implementation selected for use by default).
I solved it on mine (redhat, clang 3.4, gcc 4.7.2).
By default this project was linking against /usr/lib/libstdc++. I have a build of gcc 4.7.2 installed in a separate location; when I add lines analogous to the following to the link step it works fine
-L${GCC_PATH}/lib -Wl,-R${GCC_PATH}/lib
... provided they appear in the link step before analogous statements for /usr/lib.
edit
You can use strace to help diagnose this problem; I did something like the following:
// copy the link step into a temp shell script
strace -f ./temp.sh |& grep -P 'lib(std)?c\+\+'
... which is when I realized I probably needed a different build of the C++ runtime because I saw it was finding and linking against the one in /usr/lib.