summaryrefslogtreecommitdiff
path: root/dev-libs/libffi
diff options
context:
space:
mode:
authorV3n3RiX <venerix@koprulu.sector>2023-04-03 11:20:10 +0100
committerV3n3RiX <venerix@koprulu.sector>2023-04-03 11:20:10 +0100
commit7837a76c344b64e925519dd5e26233bb3b648beb (patch)
tree6851e50315ad02bb7a8a172f318905eca39313ec /dev-libs/libffi
parent155cc74ccaea367efa88c8acfadcf25cb7dfe89c (diff)
gentoo auto-resync : 03:04:2023 - 11:20:10
Diffstat (limited to 'dev-libs/libffi')
-rw-r--r--dev-libs/libffi/Manifest4
-rw-r--r--dev-libs/libffi/files/libffi-3.4.4-hppa-closure-function-ptrs.patch170
-rw-r--r--dev-libs/libffi/files/libffi-3.4.4-hppa-jump-table.patch289
-rw-r--r--dev-libs/libffi/files/libffi-3.4.4-hppa-large-struct.patch36
-rw-r--r--dev-libs/libffi/libffi-3.4.4-r1.ebuild76
5 files changed, 575 insertions, 0 deletions
diff --git a/dev-libs/libffi/Manifest b/dev-libs/libffi/Manifest
index 6e0888a1eb09..30931e58a155 100644
--- a/dev-libs/libffi/Manifest
+++ b/dev-libs/libffi/Manifest
@@ -1,3 +1,7 @@
+AUX libffi-3.4.4-hppa-closure-function-ptrs.patch 5971 BLAKE2B ee754ca2d142022191cae572811082baed8321bc43a13efa4123bb455a721f0b88a8458a0337f3fe9572da9bc1251a1927ba7b2ceda926be0e25744cbe00875c SHA512 3384e316bdaf35022b0138f5ca4d51afab13c098278fa4d9780dc8400c524e4b49e51955e0c41a1bc7e7d2b959b1a808f91ffd2c5bd10009db38150d770dfa4a
+AUX libffi-3.4.4-hppa-jump-table.patch 7872 BLAKE2B c78216a9912e26e74733870d1a0f8825d426ef2e72eeed1541695bdfa058f0e029844639018579f61f03bd1b8b399e4b70f3c3760646a569425414b3630dbe89 SHA512 5e72ceede9902a7e236204f930f16b387164f7bff8762b881f1eecb2b8431684e061ab086ec0b1e9d73e23affb1b618ef5dc051f47d3029c45f41eef328e42ff
+AUX libffi-3.4.4-hppa-large-struct.patch 1129 BLAKE2B 3b172af9af01c629ce567309893e1b342b039a53a4992529b8395a426ed74a1741d6dceb660cb2b1d8c2ba1057e91bd08a52c54192ec1d429710322d2fe61ff9 SHA512 77eb9ca86651f550c4c9ae7b508cc0651bea7e17feac6f2a35963b1838c70aeeb2166606fe39f70e9e058a41a53979f2c599c1869a4714a420f2bb006d14107a
DIST libffi-3.4.4.tar.gz 1362394 BLAKE2B 189fe1ffe9507f204581b0ab09995dc7e7b761bb4eac7e338e9f5ff81431aebcef6c182c1839c9f9acb2706697a260c67e6d1351cf7e2aed7c4eb5d694f6f8fd SHA512 88680aeb0fa0dc0319e5cd2ba45b4b5a340bc9b4bcf20b1e0613b39cd898f177a3863aa94034d8e23a7f6f44d858a53dcd36d1bb8dee13b751ef814224061889
+EBUILD libffi-3.4.4-r1.ebuild 2438 BLAKE2B a2d4152bb31cebc15dd11a8d3d144f158880744159e6907a938619508d3aadea6d4ae94726cc0a067d4c8fd75052880143c87bbb1e746e15570053301452d5d3 SHA512 18d85620a58aff0ec83ada6656f8e9bec034095a5b851c05298595f0cefc8b1535e598f8f2b11f030860b5d9e0a63ab8b326aada021ff732aa089f66f050969f
EBUILD libffi-3.4.4.ebuild 2278 BLAKE2B 2f3b2d8c5311bb8e2ecdc6b05920cc6c81e50f4aecf7915d9d5343902ec04844990916ff6e6a90ee73908001806cc9e1711f6cb18f960558250629525aa9b19f SHA512 4eb143326ed514c0d5747b75b0775f653435e55a55df6c96c178b5d2187ac17660c0ed64371bb218834bfbe8c01dabc6e74591152fc331b8635e084d10c6ef6d
MISC metadata.xml 2110 BLAKE2B 2653be2cf09c047e45e489d7265d00165ddab2f94744988e4e8bca449bd1e40eeab74cb0b8d7d47a2d8b73563869460fcccb06e1fbccad697a9f213be362cb03 SHA512 e1a280792b929d38451fea1eb360053ed3a452592094f3e327ce4a4ff7eb8e0119435e8ee98f215585d8d98440512b5b68f92d1cd472a3bfd12e2f382e1981a1
diff --git a/dev-libs/libffi/files/libffi-3.4.4-hppa-closure-function-ptrs.patch b/dev-libs/libffi/files/libffi-3.4.4-hppa-closure-function-ptrs.patch
new file mode 100644
index 000000000000..065f35e7c4c2
--- /dev/null
+++ b/dev-libs/libffi/files/libffi-3.4.4-hppa-closure-function-ptrs.patch
@@ -0,0 +1,170 @@
+https://github.com/libffi/libffi/commit/e58e22b22386ed0e0a95e97eb8eed016e3f01b02
+
+From e58e22b22386ed0e0a95e97eb8eed016e3f01b02 Mon Sep 17 00:00:00 2001
+From: Anthony Green <green@moxielogic.com>
+Date: Thu, 2 Feb 2023 07:02:53 -0500
+Subject: [PATCH] From Dave Anglin:
+
+A couple of years ago the 32-bit hppa targets were converted from using a trampoline executed on the stack to the function descriptor technique used by ia64. This is more efficient and avoids having to have an executable stack. However, function pointers on 32-bit need the PLABEL bit set in the pointer. It distinguishes between pointers that point directly to the executable code and pointer that point to a function descriptor. We need the later for libffi. But as a result, it is not possible to convert using casts data pointers to function pointers.
+
+The solution at the time was to set the PLABEL bit in hppa closure pointers using FFI_CLOSURE_PTR. However, I realized recently that this was a bad choice. Packages like python-cffi allocate their own closure pointers, so this isn't going to work well there.
+
+A better solution is to leave closure pointers unchanged and only set the PLABEL bit in pointers used to point to executable code.
+
+The attached patch drops the FFI_CLOSURE_PTR and FFI_RESTORE_PTR defines. This allows some cleanup in the hppa closure routines. The FFI_FN define is now used to set the PLABEL bit on hppa. ffi_closure_alloc is modified to set the PLABEL bit in the value set in *code.
+
+I also added a FFI_CL define to convert a function pointer to a closure pointer. It is only used in one test case.
+--- a/include/ffi.h.in
++++ b/include/ffi.h.in
+@@ -361,14 +361,6 @@ typedef struct {
+ FFI_API void *ffi_closure_alloc (size_t size, void **code);
+ FFI_API void ffi_closure_free (void *);
+
+-#if defined(PA_LINUX) || defined(PA_HPUX)
+-#define FFI_CLOSURE_PTR(X) ((void *)((unsigned int)(X) | 2))
+-#define FFI_RESTORE_PTR(X) ((void *)((unsigned int)(X) & ~3))
+-#else
+-#define FFI_CLOSURE_PTR(X) (X)
+-#define FFI_RESTORE_PTR(X) (X)
+-#endif
+-
+ FFI_API ffi_status
+ ffi_prep_closure (ffi_closure*,
+ ffi_cif *,
+@@ -515,8 +507,14 @@ FFI_API
+ ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
+ size_t *offsets);
+
+-/* Useful for eliminating compiler warnings. */
++/* Convert between closure and function pointers. */
++#if defined(PA_LINUX) || defined(PA_HPUX)
++#define FFI_FN(f) ((void (*)(void))((unsigned int)(f) | 2))
++#define FFI_CL(f) ((void *)((unsigned int)(f) & ~3))
++#else
+ #define FFI_FN(f) ((void (*)(void))f)
++#define FFI_CL(f) ((void *)(f))
++#endif
+
+ /* ---- Definitions shared with assembly code ---------------------------- */
+
+--- a/src/closures.c
++++ b/src/closures.c
+@@ -993,23 +993,23 @@ ffi_closure_alloc (size_t size, void **code)
+ if (!code)
+ return NULL;
+
+- ptr = FFI_CLOSURE_PTR (dlmalloc (size));
++ ptr = dlmalloc (size);
+
+ if (ptr)
+ {
+ msegmentptr seg = segment_holding (gm, ptr);
+
+- *code = add_segment_exec_offset (ptr, seg);
++ *code = FFI_FN (add_segment_exec_offset (ptr, seg));
+ if (!ffi_tramp_is_supported ())
+ return ptr;
+
+ ftramp = ffi_tramp_alloc (0);
+ if (ftramp == NULL)
+ {
+- dlfree (FFI_RESTORE_PTR (ptr));
++ dlfree (ptr);
+ return NULL;
+ }
+- *code = ffi_tramp_get_addr (ftramp);
++ *code = FFI_FN (ffi_tramp_get_addr (ftramp));
+ ((ffi_closure *) ptr)->ftramp = ftramp;
+ }
+
+@@ -1050,7 +1050,7 @@ ffi_closure_free (void *ptr)
+ if (ffi_tramp_is_supported ())
+ ffi_tramp_free (((ffi_closure *) ptr)->ftramp);
+
+- dlfree (FFI_RESTORE_PTR (ptr));
++ dlfree (ptr);
+ }
+
+ int
+@@ -1070,16 +1070,20 @@ ffi_tramp_is_present (void *ptr)
+ void *
+ ffi_closure_alloc (size_t size, void **code)
+ {
++ void *c;
++
+ if (!code)
+ return NULL;
+
+- return *code = FFI_CLOSURE_PTR (malloc (size));
++ c = malloc (size);
++ *code = FFI_FN (c);
++ return c;
+ }
+
+ void
+ ffi_closure_free (void *ptr)
+ {
+- free (FFI_RESTORE_PTR (ptr));
++ free (ptr);
+ }
+
+ void *
+--- a/src/pa/ffi.c
++++ b/src/pa/ffi.c
+@@ -445,7 +445,6 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
+ int i, avn;
+ unsigned int slot = FIRST_ARG_SLOT;
+ register UINT32 r28 asm("r28");
+- ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure);
+
+ cif = closure->cif;
+
+@@ -548,7 +547,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
+ }
+
+ /* Invoke the closure. */
+- (c->fun) (cif, rvalue, avalue, c->user_data);
++ (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+ debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", u.ret[0],
+ u.ret[1]);
+@@ -649,8 +648,6 @@ ffi_prep_closure_loc (ffi_closure* closure,
+ void *user_data,
+ void *codeloc)
+ {
+- ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure);
+-
+ /* The layout of a function descriptor. A function pointer with the PLABEL
+ bit set points to a function descriptor. */
+ struct pa32_fd
+@@ -676,14 +673,14 @@ ffi_prep_closure_loc (ffi_closure* closure,
+ fd = (struct pa32_fd *)((UINT32)ffi_closure_pa32 & ~3);
+
+ /* Setup trampoline. */
+- tramp = (struct ffi_pa32_trampoline_struct *)c->tramp;
++ tramp = (struct ffi_pa32_trampoline_struct *)closure->tramp;
+ tramp->code_pointer = fd->code_pointer;
+ tramp->fake_gp = (UINT32)codeloc & ~3;
+ tramp->real_gp = fd->gp;
+
+- c->cif = cif;
+- c->user_data = user_data;
+- c->fun = fun;
++ closure->cif = cif;
++ closure->user_data = user_data;
++ closure->fun = fun;
+
+ return FFI_OK;
+ }
+--- a/testsuite/libffi.closures/closure_loc_fn0.c
++++ b/testsuite/libffi.closures/closure_loc_fn0.c
+@@ -85,7 +85,7 @@ int main (void)
+
+ #ifndef FFI_EXEC_STATIC_TRAMP
+ /* With static trampolines, the codeloc does not point to closure */
+- CHECK(memcmp(pcl, codeloc, sizeof(*pcl)) == 0);
++ CHECK(memcmp(pcl, FFI_CL(codeloc), sizeof(*pcl)) == 0);
+ #endif
+
+ res = (*((closure_loc_test_type0)codeloc))
+
diff --git a/dev-libs/libffi/files/libffi-3.4.4-hppa-jump-table.patch b/dev-libs/libffi/files/libffi-3.4.4-hppa-jump-table.patch
new file mode 100644
index 000000000000..822a7eb893ec
--- /dev/null
+++ b/dev-libs/libffi/files/libffi-3.4.4-hppa-jump-table.patch
@@ -0,0 +1,289 @@
+https://github.com/libffi/libffi/commit/222abd0c65babe2174b21753217145f5031a8b91
+
+From 222abd0c65babe2174b21753217145f5031a8b91 Mon Sep 17 00:00:00 2001
+From: Anthony Green <green@moxielogic.com>
+Date: Thu, 2 Feb 2023 07:04:55 -0500
+Subject: [PATCH] From Dave Anglin:
+
+This patch is derived from the work done in implementing libffi for 64-bit hppa64-hpux target. Currently, the 32-bit hppa targets do a linear search for the return type of an ffi_call. This is slow and inefficient. A jump table can used to jump directly to the code used to process the return value. In most common cases, the return value can be processed in the jump table itself.
+
+The patch also fixes return handling for FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16 and FFI_TYPE_SINT16.
+--- a/src/pa/ffi.c
++++ b/src/pa/ffi.c
+@@ -56,27 +56,12 @@ static inline int ffi_struct_type(ffi_type *t)
+ size_t sz = t->size;
+
+ /* Small structure results are passed in registers,
+- larger ones are passed by pointer. Note that
+- small structures of size 2, 4 and 8 differ from
+- the corresponding integer types in that they have
+- different alignment requirements. */
+-
+- if (sz <= 1)
+- return FFI_TYPE_UINT8;
+- else if (sz == 2)
+- return FFI_TYPE_SMALL_STRUCT2;
+- else if (sz == 3)
+- return FFI_TYPE_SMALL_STRUCT3;
+- else if (sz == 4)
+- return FFI_TYPE_SMALL_STRUCT4;
+- else if (sz == 5)
+- return FFI_TYPE_SMALL_STRUCT5;
+- else if (sz == 6)
+- return FFI_TYPE_SMALL_STRUCT6;
+- else if (sz == 7)
+- return FFI_TYPE_SMALL_STRUCT7;
+- else if (sz <= 8)
+- return FFI_TYPE_SMALL_STRUCT8;
++ larger ones are passed by pointer. Note that small
++ structures differ from the corresponding integer
++ types in that they have different alignment requirements. */
++
++ if (sz <= 8)
++ return -sz;
+ else
+ return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
+ }
+@@ -556,16 +541,16 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
+ switch (cif->flags)
+ {
+ case FFI_TYPE_UINT8:
+- *(stack - FIRST_ARG_SLOT) = (UINT8)(u.ret[0] >> 24);
++ *(stack - FIRST_ARG_SLOT) = (UINT8)u.ret[0];
+ break;
+ case FFI_TYPE_SINT8:
+- *(stack - FIRST_ARG_SLOT) = (SINT8)(u.ret[0] >> 24);
++ *(stack - FIRST_ARG_SLOT) = (SINT8)u.ret[0];
+ break;
+ case FFI_TYPE_UINT16:
+- *(stack - FIRST_ARG_SLOT) = (UINT16)(u.ret[0] >> 16);
++ *(stack - FIRST_ARG_SLOT) = (UINT16)u.ret[0];
+ break;
+ case FFI_TYPE_SINT16:
+- *(stack - FIRST_ARG_SLOT) = (SINT16)(u.ret[0] >> 16);
++ *(stack - FIRST_ARG_SLOT) = (SINT16)u.ret[0];
+ break;
+ case FFI_TYPE_INT:
+ case FFI_TYPE_SINT32:
+@@ -590,6 +575,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
+ /* Don't need a return value, done by caller. */
+ break;
+
++ case FFI_TYPE_SMALL_STRUCT1:
+ case FFI_TYPE_SMALL_STRUCT2:
+ case FFI_TYPE_SMALL_STRUCT3:
+ case FFI_TYPE_SMALL_STRUCT4:
+--- a/src/pa/ffitarget.h
++++ b/src/pa/ffitarget.h
+@@ -73,11 +73,22 @@ typedef enum ffi_abi {
+ #define FFI_TRAMPOLINE_SIZE 12
+ #endif
+
+-#define FFI_TYPE_SMALL_STRUCT2 -1
+-#define FFI_TYPE_SMALL_STRUCT3 -2
+-#define FFI_TYPE_SMALL_STRUCT4 -3
+-#define FFI_TYPE_SMALL_STRUCT5 -4
+-#define FFI_TYPE_SMALL_STRUCT6 -5
+-#define FFI_TYPE_SMALL_STRUCT7 -6
+-#define FFI_TYPE_SMALL_STRUCT8 -7
++#define FFI_TYPE_SMALL_STRUCT1 -1
++#define FFI_TYPE_SMALL_STRUCT2 -2
++#define FFI_TYPE_SMALL_STRUCT3 -3
++#define FFI_TYPE_SMALL_STRUCT4 -4
++#define FFI_TYPE_SMALL_STRUCT5 -5
++#define FFI_TYPE_SMALL_STRUCT6 -6
++#define FFI_TYPE_SMALL_STRUCT7 -7
++#define FFI_TYPE_SMALL_STRUCT8 -8
++
++/* linux.S and hpux32.S expect FFI_TYPE_COMPLEX is the last generic type. */
++#define FFI_PA_TYPE_LAST FFI_TYPE_COMPLEX
++
++/* If new generic types are added, the jump tables in linux.S and hpux32.S
++ likely need updating. */
++#if FFI_TYPE_LAST != FFI_PA_TYPE_LAST
++# error "You likely have broken jump tables"
++#endif
++
+ #endif
+
+--- a/src/pa/linux.S
++++ b/src/pa/linux.S
+@@ -103,51 +103,103 @@ ffi_call_pa32:
+
+ /* Prepare to store the result; we need to recover flags and rvalue. */
+ ldw -48(%r3), %r21 /* r21 <- flags */
+- ldw -52(%r3), %r20 /* r20 <- rvalue */
+
+- /* Store the result according to the return type. */
++ /* Adjust flags range from [-8, 15] to [0, 23]. */
++ addi 8, %r21, %r21
+
+-.Lcheckint:
+- comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
+- b .Ldone
+- stw %ret0, 0(%r20)
++ blr %r21, %r0
++ ldw -52(%r3), %r20 /* r20 <- rvalue */
+
+-.Lcheckint8:
+- comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
++ /* Giant jump table */
++ /* 8-byte small struct */
++ b,n .Lsmst8
++ nop
++ /* 7-byte small struct */
++ b,n .Lsmst7
++ nop
++ /* 6-byte small struct */
++ b,n .Lsmst6
++ nop
++ /* 5-byte small struct */
++ b,n .Lsmst5
++ nop
++ /* 4-byte small struct */
++ b,n .Lsmst4
++ nop
++ /* 3-byte small struct */
++ b,n .Lsmst3
++ nop
++ /* 2-byte small struct */
++ b,n .Lsmst2
++ nop
++ /* 1-byte small struct */
+ b .Ldone
+ stb %ret0, 0(%r20)
+-
+-.Lcheckint16:
+- comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
++ /* void */
++ b,n .Ldone
++ nop
++ /* int */
+ b .Ldone
+- sth %ret0, 0(%r20)
+-
+-.Lcheckdbl:
+- comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
++ stw %ret0, 0(%r20)
++ /* float */
++ b .Ldone
++ fstw %fr4L,0(%r20)
++ /* double */
+ b .Ldone
+ fstd %fr4,0(%r20)
+-
+-.Lcheckfloat:
+- comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
++ /* long double */
+ b .Ldone
+- fstw %fr4L,0(%r20)
++ fstd %fr4,0(%r20)
++ /* unsigned int8 */
++ b .Ldone
++ stw %ret0, 0(%r20)
++ /* sint8 */
++ b .Ldone
++ stw %ret0, 0(%r20)
++ /* unsigned int16 */
++ b .Ldone
++ stw %ret0, 0(%r20)
++ /* sint16 */
++ b .Ldone
++ stw %ret0, 0(%r20)
++ /* unsigned int32 */
++ b .Ldone
++ stw %ret0, 0(%r20)
++ /* sint32 */
++ b .Ldone
++ stw %ret0, 0(%r20)
++ /* unsigned int64 */
++ b,n .Luint64
++ nop
++ /* signed int64 */
++ b,n .Lsint64
++ nop
++ /* large struct */
++ b,n .Ldone
++ nop
++ /* pointer */
++ b .Ldone
++ stw %ret0, 0(%r20)
++ /* complex */
++ b,n .Ldone
++ nop
++
++ /* Store the result according to the return type. */
+
+-.Lcheckll:
+- comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
++.Luint64:
++.Lsint64:
+ stw %ret0, 0(%r20)
+ b .Ldone
+ stw %ret1, 4(%r20)
+
+-.Lchecksmst2:
+- comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
++.Lsmst2:
+ /* 2-byte structs are returned in ret0 as ????xxyy. */
+ extru %ret0, 23, 8, %r22
+ stbs,ma %r22, 1(%r20)
+ b .Ldone
+ stb %ret0, 0(%r20)
+
+-.Lchecksmst3:
+- comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
++.Lsmst3:
+ /* 3-byte structs are returned in ret0 as ??xxyyzz. */
+ extru %ret0, 15, 8, %r22
+ stbs,ma %r22, 1(%r20)
+@@ -156,8 +208,7 @@ ffi_call_pa32:
+ b .Ldone
+ stb %ret0, 0(%r20)
+
+-.Lchecksmst4:
+- comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
++.Lsmst4:
+ /* 4-byte structs are returned in ret0 as wwxxyyzz. */
+ extru %ret0, 7, 8, %r22
+ stbs,ma %r22, 1(%r20)
+@@ -168,8 +219,7 @@ ffi_call_pa32:
+ b .Ldone
+ stb %ret0, 0(%r20)
+
+-.Lchecksmst5:
+- comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
++.Lsmst5:
+ /* 5 byte values are returned right justified:
+ ret0 ret1
+ 5: ??????aa bbccddee */
+@@ -183,8 +233,7 @@ ffi_call_pa32:
+ b .Ldone
+ stb %ret1, 0(%r20)
+
+-.Lchecksmst6:
+- comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
++.Lsmst6:
+ /* 6 byte values are returned right justified:
+ ret0 ret1
+ 6: ????aabb ccddeeff */
+@@ -200,8 +249,7 @@ ffi_call_pa32:
+ b .Ldone
+ stb %ret1, 0(%r20)
+
+-.Lchecksmst7:
+- comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
++.Lsmst7:
+ /* 7 byte values are returned right justified:
+ ret0 ret1
+ 7: ??aabbcc ddeeffgg */
+@@ -219,8 +267,7 @@ ffi_call_pa32:
+ b .Ldone
+ stb %ret1, 0(%r20)
+
+-.Lchecksmst8:
+- comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
++.Lsmst8:
+ /* 8 byte values are returned right justified:
+ ret0 ret1
+ 8: aabbccdd eeffgghh */
diff --git a/dev-libs/libffi/files/libffi-3.4.4-hppa-large-struct.patch b/dev-libs/libffi/files/libffi-3.4.4-hppa-large-struct.patch
new file mode 100644
index 000000000000..aaf4af368432
--- /dev/null
+++ b/dev-libs/libffi/files/libffi-3.4.4-hppa-large-struct.patch
@@ -0,0 +1,36 @@
+https://github.com/libffi/libffi/commit/c50c16d0bcb58952840184aa83e62c6d912bf779
+
+From c50c16d0bcb58952840184aa83e62c6d912bf779 Mon Sep 17 00:00:00 2001
+From: Anthony Green <green@moxielogic.com>
+Date: Sun, 20 Nov 2022 12:20:40 -0500
+Subject: [PATCH] Fix large struct passing on PA-RISC
+
+--- a/src/pa/ffi.c
++++ b/src/pa/ffi.c
+@@ -376,10 +376,26 @@ extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
+ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
+ {
+ extended_cif ecif;
++ size_t i, nargs = cif->nargs;
++ ffi_type **arg_types = cif->arg_types;
+
+ ecif.cif = cif;
+ ecif.avalue = avalue;
+
++ /* If we have any large structure arguments, make a copy so we are passing
++ by value. */
++ for (i = 0; i < nargs; i++)
++ {
++ ffi_type *at = arg_types[i];
++ int size = at->size;
++ if (at->type == FFI_TYPE_STRUCT && size > 8)
++ {
++ char *argcopy = alloca (size);
++ memcpy (argcopy, avalue[i], size);
++ avalue[i] = argcopy;
++ }
++ }
++
+ /* If the return value is a struct and we don't have a return
+ value address then we need to make one. */
+
diff --git a/dev-libs/libffi/libffi-3.4.4-r1.ebuild b/dev-libs/libffi/libffi-3.4.4-r1.ebuild
new file mode 100644
index 000000000000..8d8ab583df15
--- /dev/null
+++ b/dev-libs/libffi/libffi-3.4.4-r1.ebuild
@@ -0,0 +1,76 @@
+# Copyright 1999-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+
+inherit multilib-minimal preserve-libs
+
+MY_PV=${PV/_rc/-rc}
+MY_P=${PN}-${MY_PV}
+
+DESCRIPTION="a portable, high level programming interface to various calling conventions"
+HOMEPAGE="https://sourceware.org/libffi/"
+SRC_URI="https://github.com/libffi/libffi/releases/download/v${MY_PV}/${MY_P}.tar.gz"
+S="${WORKDIR}"/${MY_P}
+
+LICENSE="MIT"
+# This is a core package which is depended on by e.g. Python
+# Please use preserve-libs.eclass in pkg_{pre,post}inst to cover users
+# with FEATURES="-preserved-libs" or another package manager if SONAME
+# changes.
+SLOT="0/8" # SONAME=libffi.so.8
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~x64-cygwin ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris"
+IUSE="debug exec-static-trampoline pax-kernel static-libs test"
+
+RESTRICT="!test? ( test )"
+BDEPEND="test? ( dev-util/dejagnu )"
+
+PATCHES=(
+ "${FILESDIR}"/${P}-hppa-large-struct.patch
+ "${FILESDIR}"/${P}-hppa-closure-function-ptrs.patch
+ "${FILESDIR}"/${P}-hppa-jump-table.patch
+)
+
+src_prepare() {
+ default
+
+ if [[ ${CHOST} == arm64-*-darwin* ]] ; then
+ # ensure we use aarch64 asm, not x86 on arm64
+ sed -i -e 's/aarch64\*-\*-\*/arm64*-*-*|&/' \
+ configure configure.host || die
+ fi
+}
+
+multilib_src_configure() {
+ # --includedir= path maintains a few properties:
+ # 1. have stable name across libffi versions: some packages like
+ # dev-lang/ghc or kde-frameworks/networkmanager-qt embed
+ # ${includedir} at build-time. Don't require those to be
+ # rebuilt unless SONAME changes. bug #695788
+ #
+ # We use /usr/.../${PN} (instead of former /usr/.../${P}).
+ #
+ # 2. have ${ABI}-specific location as ffi.h is target-dependent.
+ #
+ # We use /usr/$(get_libdir)/... to have ABI identifier.
+ ECONF_SOURCE="${S}" econf \
+ --includedir="${EPREFIX}"/usr/$(get_libdir)/${PN}/include \
+ --disable-multi-os-directory \
+ $(use_enable static-libs static) \
+ $(use_enable exec-static-trampoline exec-static-tramp) \
+ $(use_enable pax-kernel pax_emutramp) \
+ $(use_enable debug)
+}
+
+multilib_src_install_all() {
+ einstalldocs
+ find "${ED}" -name "*.la" -delete || die
+}
+
+pkg_preinst() {
+ preserve_old_lib /usr/$(get_libdir)/libffi.so.7
+}
+
+pkg_postinst() {
+ preserve_old_lib_notify /usr/$(get_libdir)/libffi.so.7
+}