Compiler-rt cross-compile for ARMv5 fails because D99282 made it an error if DMB
is used for any pre-ARMv6 targets. More specifically, the "#error only supported
on ARMv6+" added in D99282 will cause compilation to fail when any source file
which includes assembly.h are compiled for pre-ARMv6 targets. Since the only
place where DMB is used is syn-ops.h (which is only included by
arm/sync_fetch_and_* and these files are excluded from being built for older
targets), this patch moves the definition there to avoid the issues described
above.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
I'm not sure that this is right. From the Armv5/v6 ARM ARM https://developer.arm.com/documentation/ddi0100/i/ I think DMB was introduced in Armv6 (see B2.6.1 DataMemoryBarrier (DMB) CP15 register 7) . Armv5 did have an operation called Drain Write Buffer DWB that was renamed in Armv6 to DSB (see DataSynchronizationBarrier (DSB) CP15 register 7). From B6.6.5 Register 7: cache management functions this is opcode 4 but I don't think DWB is exactly the same as DSB is on Armv6.
With some searching I found https://bugs.linaro.org/show_bug.cgi?id=355 which describes what the linux kernel uses in inline assembly, which is essentially #define dmb(x) __asm__ __volatile__ ("" : : : "memory")
Would you be able to provide us with a reference for how this MCR is expected to behave on Arm v5? It will compile, but I've no idea what will happen if executed, possible it will do nothing. If it is the case that it does nothing then it would be better to replace DMB with nothing on v5+. It may be that the old DWB is more appropriate on v5.
Would also be useful to know why you want to make the change? Is this just to make the code compile, or does the code have to be behave like a DMB would be executed on an Arm v5?
Even if this did work, the only current use is in compiler-rt/lib/builtins/arm/sync-ops.h, and those routines definitely won't work on ARMv5. (For baremetal targets, there's simply no way to provide those routines for v5. On Linux, see https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt .)
Thanks for digging out the references, @peter.smith. You are right, DMB is only available for ARMv6+ and what is available for ARMv5 is DWB. I overlooked some details.
The reason why I created the change was to resolve an error when compiler-rt was built for ARMv5. The build error I saw was due to D99282 making it always an error for any pre-ARMv6 target. Like what you have pointed out, DWB may not be exactly the same as DMB, so defining DMB as nothing and warn about this may be enough to unblock the build.
I agree, @efriedma, the routines in sync-ops.h probably won't work as expected on ARMv5 and I doubt any of our baremetal customers actually use any of these. For now, to unblock the ARMv5 build, does it make sense to define DMB as nothing for any target pre-ARMv6? Any other suggestions are welcome too.
I think I'd prefer to just hack the CMake files to exclude arm/sync_fetch_and_* from any ARM target less than v7, given the routines don't actually work.
Thanks for the suggestions, @efriedma. I checked the cmake files and the arm/sync_fetch_and_* files seem to have been properly excluded from unsupported archs. The build errors I saw are actually because the assembly.h header being included in many other assembly files too (e.g., aeabi_dcmp.S). After D99282, compiling any file which includes assembly.h for any pre-ARVv6 target will fail due to the "#error only supported on ARMv6+."
In that case, I see two options:
- Just skip defining "DMB" at all. And maybe rename it so "DMB" isn't accidentally interpreted as an instruction.
- Move the define into sync-ops.h.