You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
compiler-rt does not define aarch64 outline atomics #10086
I discovered this issue while attempting to cross compile Rust to aarch64-linux with zig cc. Rust enables outline atomics by default on aarch64-linux and currently prohibits disabling them.
Thanks for the report. How is the __aarch64_ldadd4_acq_rel symbol expected to be provided? It does not appear to be included in LLVM's compiler-rt. Is that a gcc extension?
Ah, I see the symbol names are constructed with string concatenation. Missed that in my grepping. Thanks! So the next step to resolve this issue is to port more of LLVM's compiler-rt into zig's.
Great, thanks. For those running into this issue with Rust, rust-lang/rust#90623 was recently merged which allows you to disable outline atomics with -C target-feature=-outline-atomics.
I tried to use zig to cross-compile my codebase easier so that I can develop on my pinephone while walking but have parts of the project pre-cross-compiled on a stronger machine.
Sadly these kind of errors still crop up for me when the code uses std::shared_ptr. Are there any workarounds for a real c++ codebase or some things that I can turn off so some simpler code is generated or anything?
I suspect that many people running into this issue are running into it because native CPU detection for aarch64 is failing to correctly identify the CPU features available in some cases. Here I have a Neoverse-N1 CPU:
andy@Debian-bullseye-latest-arm64-base:~/zig/build-release$ lscpu
Architecture: aarch64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 80
On-line CPU(s) list: 0-79
Thread(s) per core: 1
Core(s) per socket: 80
Socket(s): 1
NUMA node(s): 1
Vendor ID: ARM
Model: 1
Model name: Neoverse-N1
Stepping: r3p1
Frequency boost: disabled
CPU max MHz: 3000.0000
CPU min MHz: 1000.0000
BogoMIPS: 50.00
L1d cache: 5 MiB
L1i cache: 5 MiB
L2 cache: 80 MiB
NUMA node0 CPU(s): 0-79
Vulnerability Itlb multihit: Not affected
Vulnerability L1tf: Not affected
Vulnerability Mds: Not affected
Vulnerability Meltdown: Not affected
Vulnerability Mmio stale data: Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1: Mitigation; __user pointer sanitization
Vulnerability Spectre v2: Mitigation; CSV2, BHB
Vulnerability Srbds: Not affected
Vulnerability Tsx async abort: Not affected
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid
asimdrdm lrcpc dcpop asimddp ssbs
You can see that it is Neoverse-N1, and that it has the atomics flag which I believe corresponds to lse. Zig does have awareness of this cpu:
It is precisely because it sees the CPU as "generic" that it does not enable atomics, causing this issue.
To be clear, compiler_rt still needs to be augmented with these functions. However, there is a second, perhaps more important issue, which is that native CPU detection is not working.
Another clue here is that /proc/cpuinfo is missing the model name, even though lscpu is producing it:
processor : 76
BogoMIPS : 50.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x3
CPU part : 0xd0c
CPU revision : 1
This is perhaps an indicator that the implementation of lscpu does something different than looking at /proc/cpuinfo and we should read its source code to see what that logic is.
I'm confused why zig-bootstrap is able to produce aarch64-linux binaries without running into this issue. In this case, it targets the generic cpu, which, as noted in #10086 (comment), is missing the lse feature. I would therefore expect to see undefined symbol errors when linking.
Edit: I understand everything now, thanks to this comment:
Outline atomics were added with gcc 9.3.1 and turned on by default in gcc 10.1. Consequently most of distributions had libgcc with outline atomics already.
Besides Linux, Android will utilize them as well. Don't know about iOs and MacOs, I guess they are compiling with LSE enabled, so outline atomics should not affect them.
As for benchmarks, I rely on investigations completed during gcc outline atomics enablement work.
Choice of solution ../gcc/libgcc/config/aarch64/lse.S:
The problem that we are trying to solve is operating system deployment
of ARMv8.1-Atomics, also known as Large System Exensions (LSE).
There are a number of potential solutions for this problem which have
been proposed and rejected for various reasons. To recap:
(1) Multiple builds. The dynamic linker will examine /lib64/atomics/
if HWCAP_ATOMICS is set, allowing entire libraries to be overwritten.
However, not all Linux distributions are happy with multiple builds,
and anyway it has no effect on main applications.
(2) IFUNC. We could put these functions into libgcc_s.so, and have
a single copy of each function for all DSOs. However, ARM is concerned
that the branch-to-indirect-branch that is implied by using a PLT,
as required by IFUNC, is too much overhead for smaller cpus.
(3) Statically predicted direct branches. This is the approach that
is taken here. These functions are linked into every DSO that uses them.
All of the symbols are hidden, so that the functions are called via a
direct branch. The choice of LSE vs non-LSE is done via one byte load
followed by a well-predicted direct branch. The functions are compiled
separately to minimize code size.
Performance impact:
Various members in the Arm ecosystem have measured the performance impact of this indirection on a diverse set of systems and we were happy to find out that it was minimal compared to the benefit of using the LSE instructions for better scalability at large core counts.
Activity
andrewrk commentedon Nov 27, 2021
Thanks for the report. How is the
__aarch64_ldadd4_acq_relsymbol expected to be provided? It does not appear to be included in LLVM's compiler-rt. Is that a gcc extension?nitsky commentedon Nov 29, 2021
@andrewrk I see that outline atomics were added to compiler-rt a year ago: https://reviews.llvm.org/D91156.
andrewrk commentedon Nov 29, 2021
Ah, I see the symbol names are constructed with string concatenation. Missed that in my grepping. Thanks! So the next step to resolve this issue is to port more of LLVM's compiler-rt into zig's.
nitsky commentedon Nov 29, 2021
Great, thanks. For those running into this issue with Rust, rust-lang/rust#90623 was recently merged which allows you to disable outline atomics with
-C target-feature=-outline-atomics.irishgreencitrus commentedon Jan 4, 2022
I have this issue compiling https://github.com/mattnite/gyro on aarch64 Raspberry Pi OS, with just normal
zig buildPiotrSikora commentedon Jan 16, 2022
zig c++seems to be completely broken when cross-compiling toaarch64-linux-*, becauselibc++relies on atomics.PiotrSikora commentedon Feb 3, 2022
My issue above results in the same errors, but it's actually unrelated. I filed a new issue: #10777.
prenex commentedon May 25, 2022
I tried to use zig to cross-compile my codebase easier so that I can develop on my pinephone while walking but have parts of the project pre-cross-compiled on a stronger machine.
Sadly these kind of errors still crop up for me when the code uses std::shared_ptr. Are there any workarounds for a real c++ codebase or some things that I can turn off so some simpler code is generated or anything?
Add ziglang/zig#10086 to caveats
[-]`zig cc` does not define aarch64 outline atomics[/-][+]compiler-rt does not define aarch64 outline atomics[/+]andrewrk commentedon Nov 20, 2022
I suspect that many people running into this issue are running into it because native CPU detection for aarch64 is failing to correctly identify the CPU features available in some cases. Here I have a Neoverse-N1 CPU:
You can see that it is Neoverse-N1, and that it has the
atomicsflag which I believe corresponds tolse. Zig does have awareness of this cpu:https://github.com/ziglang/zig/blob/master/lib/std/target/aarch64.zig#L2091-L2106
However,
zig build-exe --show-builtindoes not pick it up:It is precisely because it sees the CPU as "generic" that it does not enable atomics, causing this issue.
To be clear, compiler_rt still needs to be augmented with these functions. However, there is a second, perhaps more important issue, which is that native CPU detection is not working.
Another clue here is that
/proc/cpuinfois missing the model name, even thoughlscpuis producing it:This is perhaps an indicator that the implementation of
lscpudoes something different than looking at/proc/cpuinfoand we should read its source code to see what that logic is.LemonBoy commentedon Nov 20, 2022
Add
.m64 = &A64.neoverse_n1here, checking if there are any other missing entries is left as an exercise for the reader.fix CPU model detection for neoverse_n1 on aarch64-linux
andrewrk commentedon Nov 20, 2022
I'm confused why zig-bootstrap is able to produce aarch64-linux binaries without running into this issue. In this case, it targets the generic cpu, which, as noted in #10086 (comment), is missing the
lsefeature. I would therefore expect to see undefined symbol errors when linking.Edit: I understand everything now, thanks to this comment:
fix CPU model detection for neoverse_n1 on aarch64-linux