Closed hmelder closed 4 months ago
I cannot reproduce the build error from the powerpc-linux-gnu
cross builder. It seems like the GitHub Ubuntu image has some additional packages in /usr/lib32
which are incorrectly used instead.
The powerpc64le-linux-gnu
cross builder works just fine.
@rmottola do you want to try the changes out on real hardware, or perhaps have a look at the ASM?
Take a look at what we do in snmalloc for the hacks required to make PowerPC run correctly. The Debian / Ubuntu binfmt packages set it up with the wrong page size. It's very annoying.
Take a look at what we do in snmalloc for the hacks required to make PowerPC run correctly.
Alright. Thank you :)
The Debian / Ubuntu binfmt packages set it up with the wrong page size. It's very annoying.
The weird thing is that it works on a fresh 22.04 aarch64 rootfs with powerpc cross.
Take a look at what we do in snmalloc for the hacks required to make PowerPC run correctly.
It seems that snalloc only has a powerpc64le configuration in the workflow, but the problem lies with PowerPC (32-bit, Big-Endian). We can skip the integration for now, as it is a legacy architecture.
@rmottola do you want to try the changes out on real hardware, or perhaps have a look at the ASM?
Yes, I can test it on real hardware. Setting up thinks on my iBook G4 as a first test. Will report.
I can use:
Debian clang version 16.0.6 (19)
Target: powerpc-unknown-linux-gnu
Thread model: posix
processor : 0
cpu : 7447A, altivec supported
Built completes of the branch ppc-block-trampoline
.
I get a couple of warnings
/home/multix/code/libobjc2/sarray2.h:55:8: warning: variable length array folded to constant array as an extension [-Wgnu-folding-constant]
`/home/multix/code/libobjc2/objc_msgSend.S:16:2: warning: objc_msgSend() not implemented for your architecture [-W#warnings]
`
How should I run tests?
multix@iBookG4-14:~/code/libobjc2/Build$ make test
make: *** No rule to make target 'test'. Stop
Tests aren't built by default. Run ccmake and toggle the option. Then ctest
will run them.
I get a couple of warnings /home/multix/code/libobjc2/objc_msgSend.S:16:2: warning: objc_msgSend() not implemented for your architecture [-> W#warnings] #warning objc_msgSend() not implemented for your architecture
This is expected. We are still using the two-stage message dispatch mechanism, as I have not yet implemented objc_msgSend.powerpc.S
.
How should I run tests?
You need to enable them with the TESTS
flag. Building in Debug mode can be useful as well :)
cmake -DTESTS=ON -DCMAKE_BUILD_TYPE=Debug <OTHER_CMAKE_ARGS> -B build
Thank you for trying this out!
I reconfigured TESTS=ON with ccmake as David suggested.
100% tests passed, 0 tests failed out of 190
Total Test time (real) = 154.75 sec
The following tests did not run:
115 - objc_msgSend (Skipped)
116 - objc_msgSend_optimised (Skipped)
117 - objc_msgSend_legacy (Skipped)
118 - objc_msgSend_legacy_optimised (Skipped)
151 - UnexpectedException (Skipped)
152 - UnexpectedException_optimised (Skipped)
153 - UnexpectedException_legacy (Skipped)
154 - UnexpectedException_legacy_optimised (Skipped)
171 - FastPathAlloc (Skipped)
172 - FastPathAlloc_optimised (Skipped)
Thanks for testing Riccardo.
So the only thing left is to check whether the binfmt bug for ppc64el still exists.
Needing libatomic is a bit worrying. I think that should be needed on 32-bit PowerPC if we do 64-bit atomics, but we shouldn’t be. Can you see where the call is in the generated assembly?
Can you see where the call is in the generated assembly?
[389/431] Linking C executable Test/CXXExceptions FAILED: Test/CXXExceptions : && /usr/bin/clang-17 --target=powerpc-linux-gnu -O3 -DNDEBUG -L/usr/lib/llvm-17/lib/ -fuse-ld=lld-17 -Wl,--dynamic-linker=/usr/powerpc-linux-gnu/lib/ld.so.1,-rpath,/usr/powerpc-linux-gnu/lib Test/CMakeFiles/test_runtime.dir/Test.m.o Test/CMakeFiles/CXXExceptions.dir/CXXException.m.o Test/CMakeFiles/CXXExceptions.dir/CXXException.cc.o -o Test/CXXExceptions -Wl,-rpath,/Users/hugo/Source/github.com/gnustep/libobjc2/build-powerpc libobjc.so.4.6 -lstdc++ -lm && : ld.lld-17: error: undefined reference due to --no-allow-shlib-undefined: __atomic_fetch_add_8 >> referenced by libobjc.so.4.6
__atomic_fetch_add_8
is used in objc_update_dtable_for_new_superclass
:
objc_method_cache_version
is defined as an _Atomic(uint64_t)
. Can we make this architecture dependent?
Hmm, that’s needed for the safe caching, but it isn’t useful on platforms where 64-bit atomic reads are expensive. It needs to be 64-bit to avoid overflows. We can probably just not enable it on PowerPC32.
Sorry my question was malformed.
It needs to be 64-bit to avoid overflows.
This answers it.
We can probably just not enable it on PowerPC32.
I am not familiar with the performance differences of non-native atomic reads, but is it that big of a deal? What would you use instead?
I am not familiar with the performance differences of non-native atomic reads, but is it that big of a deal?
Non-native ones require acquiring a lock and then doing the read. This basically serialises them all and so will offset any potential benefit from caching.
What would you use instead?
Don't do lookup caching on PowerPC32. The compiler doesn't (yet?) do this automatically anyway.
Don't do lookup caching on PowerPC32. The compiler doesn't (yet?) do this automatically anyway.
If I understand the lookup caching implementation correctly, the caller can opt in and cache a pointer to the current slot, checking whether the slot was invalidated before using it.
When you call
objc_slot_lookup_version
, the final parameter is used to return either the current value ofobjc_method_cache_version
or 0 if the slot is uncacheable.
What about wrapping the atomic objc_method_cache_version
operations in ifdefs (not including them on ppc32), and always write 0 to *version
in objc_method_cache_version
?
What about wrapping the atomic objc_method_cache_version operations in ifdefs (not including them on ppc32), and always write 0 to *version in objc_method_cache_version?
Yup, I think the thing to do on PowerPC32 is to always write 0 to *version
and to hide the declaration of objc_method_cache_version
.
And to hide the declaration of objc_method_cache_version.
But does the declaration of an _Atomic type pull in the libatomic library?
I do not like conditionally hiding parts of the public API.
Updates to it will pull in atomic things, we should simply remove it if we’re on a platform without 64-bit atomics.
Caching is now disabled on ppc32. All tests are passing.
100% tests passed, 0 tests failed out of 190
Total Test time (real) = 201.64 sec
The following tests did not run:
115 - objc_msgSend (Skipped)
116 - objc_msgSend_optimised (Skipped)
117 - objc_msgSend_legacy (Skipped)
118 - objc_msgSend_legacy_optimised (Skipped)
151 - UnexpectedException (Skipped)
152 - UnexpectedException_optimised (Skipped)
153 - UnexpectedException_legacy (Skipped)
154 - UnexpectedException_legacy_optimised (Skipped)
171 - FastPathAlloc (Skipped)
172 - FastPathAlloc_optimised (Skipped)
root@debian:~/libobjc2/build-ppc# uname -a
Linux debian 6.6.8-powerpc-smp #1 SMP Debian 6.6.8-1 (2023-12-22) ppc GNU/Linux
LGTM, please do some squashing before you merge!
Status
Besides UnexpectedException failing (just like on AArch64), all unit tests are passing. However, I would like to incorporate a proper fix for the hard-coded page sizes (See #271) as marking the whole page RWX is not really great... (edit: This was due to mprotect failing to set PROT_EXEC on an unaligned page as ppc64el has a page size of 64k on Debian) This is why this PR is still marked as a draft.
It would also be good to have a CI workflow for PowerPC.
PowerPC 32-bit
System (QEMU):
Clang:
I needed to link objc to
libatomic
. Ideas on how to check this in CMake are welcome!Results:
POWER9 (PowerPC 64-bit Little-Endian)
System (QEMU):
Clang:
Results: