LLVM-embedded-toolchain-for-Arm icon indicating copy to clipboard operation
LLVM-embedded-toolchain-for-Arm copied to clipboard

Missing implementations of clang-rt atomic builtins

Open celskeggs opened this issue 10 months ago • 2 comments

When compiling C++ code that uses std::atomic on a 8-byte struct with the 19.1.1 toolchain, I get the following errors:

[build] ld.lld: error: undefined symbol: __atomic_is_lock_free
[build] ld.lld: error: undefined symbol: __atomic_load
[build] ld.lld: error: undefined symbol: __atomic_compare_exchange

These symbols seem to be missing from libclang_rt.builtins.a on all targets. (I checked with the 19.1.5 toolchain, since that was the latest.)

$ nm libclang_rt.builtins.a |& grep __atomic | wc -l
0

The likely cause is that COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN is set to On by default in llvm-project/compiler-rt/lib/builtins/CMakeLists.txt, which means that atomic.c is excluded from compilation, resulting in the absence of these symbols.

The reason this option is set to On by default is to avoid misbehavior on platforms that use shared libraries, where multiple definitions of the fallback locks could result in improperly synchronized access to atomic variables.

However, since this toolchain is (as far as I know) only intended for use with static linking, it seems to me that this option could be set to Off safely when building libclang-rt. Does that sound right?

celskeggs avatar Feb 05 '25 02:02 celskeggs

Thanks very much for the report.

We are aware of the CMake option and we are planning to investigate at a future point in time. From a glance at the source code it looks like the option will work, we haven't tried it ourselves to check that it builds or tested it to check that it works on all platforms. In particular we'll need to avoid enabling it for v6-m as that does not have any load/store exclusive instructions.

By all means try it out to see if it works for you.

If you are able to use the C++ atomics header, I think that if -ffreestanding is used then code will be inlined rather than call out to libatomic

smithp35 avatar Feb 05 '25 09:02 smithp35

Thank you for your consideration! After filing this ticket, I realized that it isn't actually useful to me. I had inadvertently used std::atomic with a data type larger than the target's maximum lock-free atomic data size, which is why clang generated the references to __atomic_* builtins instead of generating the instructions inline.

I don't actually want to use fallback locks in my case, so the right answer was to change my std::atomic to use a smaller data type. However, this feature might be useful for other users, so I'll leave it up to your discretion whether to close the ticket.

celskeggs avatar Feb 06 '25 01:02 celskeggs