At the moment i'm preparing dual neko packages for the "Big" Python 2.7.16 build and one of the dependencies is libffi.
Libffi is a library which is an interface between function objects and the operating system's calling convention. For programs who want to call a function but do not know the function arguments at runtime and /or the return type, they can use the libffi API to infer the number and types of arguments and return types before a call to that function. It is used in many code generating programs, like the gcc compiler and pseudocode interpreters like Python, but also Glib has a libffi dependency.
While revisiting my work on libffi since 2009 (see the Changelog and holy crap, that's ten years ago) i noticed that it still builds fine with MIPSPro and absolves most unittests, except for a few double/float/ulong tests and four unwind cc exception handling test:
Code:
Running ../../testsuite/libffi.call/call.exp ...
XPASS: libffi.call/cls_double_va.c output pattern test
FAIL: libffi.call/cls_ulong_va.c output pattern test
FAIL: libffi.call/float.c execution test
FAIL: libffi.call/huge_struct.c output pattern test
FAIL: libffi.call/unwindtest.cc (test for excess errors)
FAIL: libffi.call/unwindtest.cc execution test
FAIL: libffi.call/unwindtest_ffi_call.cc (test for excess errors)
FAIL: libffi.call/unwindtest_ffi_call.cc execution test
=== libffi Summary ===
# of expected passes 363
# of unexpected failures 7
# of unexpected successes 1
# of expected failures 1
So i went in fixing stuff again and then i found this patch from Anthony Green in Feb 9 2011:
Code:
@@ -278,6 +278,9 @@ typedef struct {
} ffi_closure __attribute__((aligned (8)));
#else
} ffi_closure;
+# ifdef __sgi
+# pragma pack 0
+# endif
#endif
void *ffi_closure_alloc (size_t size, void **code);
@@ -296,6 +299,9 @@ ffi_prep_closure_loc (ffi_closure*,
void *user_data,
void*codeloc);
+#ifdef __sgi
+# pragma pack 8
+#endif
typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE];
This looks to be another alignment patch, except that it is backwards: #pragma pack (n) always precedes and never follows #pagma pack (0), since the scope of the pragma ends with the #pragma pack (0) statement.
Fixing that file with some more pragma packs and a missing LONGLONG_MAX plus a fix to cls_ulong_va.c i now get this:
Code:
Running ../../testsuite/libffi.call/call.exp ...
XPASS: libffi.call/cls_double_va.c output pattern test
XPASS: libffi.call/cls_longdouble_va.c output pattern test
FAIL: libffi.call/unwindtest_ffi_call.cc execution test
=== libffi Summary ===
# of expected passes 370
# of unexpected failures 1
# of unexpected successes 2
So my patch actually fixes one extra test result which was flagged as an expected failure on mips-sgi-irix6* , very cool.
This leaves us with only one test to fix, and that is a unittest in which the ffi function causes a 'throw' in C++ which is 'caught' in the main test-program.
To fix this test requires an exception handling frame in the n32.S machinecode. It is present for GAS as .eh_frame but there is nothing for the MIPSPro's AS so this test should for now fail only on MIPSPro compile, until i know enough assembly to add an .eh_handle equivalent for MIPSPro assembler (which should be _MIPS_eh_region BTW).
Practically this means that the libffi-3.2.1 + my patch can be used with MIPSPro C and C++ provided that you compile C++ programs with -LANG:exceptions=OFF or that you do not use exceptions in C++ code which uses ffi_call's.
I'll leave you with the libffi-3.2.1 IRIX patch and my environment settings for now so you can try it for your Python and GCC compiles and see if it fixes unittests for you.
Code:
setenv CC 'c99 -woff 1185,1552,3968,3970'
setenv CFLAGS '-O2 -mips3 -n32 -diag_error 1035'
setenv CXX 'CC -woff 3970'
setenv CXXFLAGS '-O2 -mips3 -n32 -diag_error 1035'
setenv CPPFLAGS -I/usr/nekoware/include
setenv LDFLAGS -L/usr/nekoware/lib
libffi-3.2.1_irix.patch:
--- ./testsuite/libffi.call/ffitest.h Sun Jul 14 03:03:59 2019
+++ ./testsuite/libffi.call/ffitest.h Sun Jul 14 23:01:21 2019
@@ -6,7 +6,9 @@
#include "fficonfig.h"
#if defined HAVE_STDINT_H
-#include <stdint.h>
+# if !(defined(__cplusplus) && defined(__sgi) && !defined(__GNUC__) )
+# include <stdint.h>
+# endif
#endif
#if defined HAVE_INTTYPES_H
@@ -109,6 +111,7 @@
#endif
/* This doesn't match <inttypes.h>, which has "u" here, but the arguments
are uintptr_t, which is always unsigned long. */
+#undef PRIuPTR
#define PRIuPTR "lu"
#endif
--- ./testsuite/libffi.call/cls_ulong_va.c Thu Jul 18 01:54:09 2019
+++ ./testsuite/libffi.call/cls_ulong_va.c Thu Jul 18 01:56:15 2019
@@ -13,9 +13,9 @@
static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
void* userdata __UNUSED__)
{
- *(T *)resp = *(T *)args[0];
+ *(ffi_arg *)resp = *(T *)args[0];
- printf("%ld: %ld %ld\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
+ printf("%ld: %ld %ld\n", (long)*(ffi_arg *)resp, *(T *)args[0], *(T *)args[1]);
}
typedef T (*cls_ret_T)(T, ...);
--- include/ffi.h.in.orig Sat Nov 8 13:47:24 2014
+++ include/ffi.h.in Sat Jul 20 23:18:59 2019
@@ -103,6 +103,11 @@
# undef FFI_64_BIT_MAX
# define FFI_64_BIT_MAX 9223372036854775807LL
# endif
+# ifdef __sgi /* IRIX has LONGLONG_MAX */
+# define FFI_LONG_LONG_MAX LONGLONG_MAX
+# undef FFI_64_BIT_MAX
+# define FFI_64_BIT_MAX 9223372036854775807LL
+# endif
# endif
#endif
@@ -311,6 +316,9 @@
#ifdef _MSC_VER
__declspec(align(8))
#endif
+# ifdef __sgi
+# pragma pack (8)
+# endif
typedef struct {
#if @FFI_EXEC_TRAMPOLINE_TABLE@
void *trampoline_table;
@@ -326,7 +334,7 @@
#else
} ffi_closure;
# ifdef __sgi
-# pragma pack 0
+# pragma pack (0)
# endif
#endif
@@ -347,7 +355,7 @@
void*codeloc);
#ifdef __sgi
-# pragma pack 8
+# pragma pack (8)
#endif
typedef struct {
#if @FFI_EXEC_TRAMPOLINE_TABLE@
@@ -373,6 +381,9 @@
void *user_data;
} ffi_raw_closure;
+# ifdef __sgi
+# pragma pack (0)
+# endif
typedef struct {
#if @FFI_EXEC_TRAMPOLINE_TABLE@