This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: libffi on the HPPA (parisc)


Hi again,

Ok I think I've found my mistake - the rc type wasnt large enough to hold 64bit of data. ffi_arg seems to be 32bit on 32bit systems.. should have known, I fixed my code accordingly.

I also fixed my bug regarding custom struct handling, it works now on multiple arch's (i386, amd64, parisc, arm). :)

However, feel free to pass along helpful advice regarding my testing code and/or regarding porting libffi to parisc64.

Am 13.04.19 um 20:26 schrieb Georg Bege:
Hello guys,

Im recently tinkering with PARISC machines which I've left.
I've got two of them, one with HPUX 11iv1 (old, I know) and one with Linux.

According to the libffi main page, HPPA is indeed supported (not on Linux, but this is outdated?). I've written a simple test code, in order to sanity check libffi's basic functionality.

This code is working fine on i386 and amd64.. just for reference.
My main goal is getting libffi working (eg. ported) to HPUX LP64... I've began consulting the proper documents from HP and learning a bit of PARISC asm.. but Im still at the beginning.

Right now, I wanted to confirm the functionality which is obviously existing...
The first try I've given is on the C8k with Gentoo Linux:

Linux hppa 4.9.49-gentoo-r1-hppa64 #4 SMP Fri Jun 8 19:33:13 CEST 2018 parisc64 PA8900 (Shortfin) 9000/785/C8000 GNU/Linux

therion@hppa ~ $ qlist -Iv libffi
dev-libs/libffi-3.2.1
virtual/libffi-3.0.13-r1

So far so good... I've this installation now for a while...
The thing is that my test code is failing with 64bit signed integers.

Im hoping that any of you may look into it, or can lend me a hand - was this ever supposed to work? Is it actually working?
My test code is buggy? If so which part? :)

Since it's just test I'll attach my code here.

Output:
---------------snip--------------------
therion@hppa ~ $ ./test-ffi
Signed 8bit integer result:    126
Unsigned 8bit integer result:    254
Signed 16bit integer result:    32766
Unsigned 16bit integer result:    65534
Signed 32bit integer result:    2147483646
Unsigned 32bit integer result:    4294967294
Signed 64bit integer result:    0, expected: 2147483646
test-ffi: test-ffi.c:151: main: Assertion `*src == result' failed.
Aborted
---------------snip--------------------

best regards,

--
Georg Bege
Mail: georg@bege.email
XMPP: therion@ninth-art.de
IRC: megaTherion @ Freenode
/**
 * libffi C99 test code
 * - proves that libffi calls are working correctly
 * copyright (C) 2019 <georg@bege.email>
 * Created on:	12th April 2019
 * Modified on:	13th April 2019
 */
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include <ffi.h>
#include <inttypes.h>
#include <float.h>

typedef void (*ffi_callback)(void);

typedef struct {
	int _1;
	int _2;
} simple_t;

/* adder functors */
int8_t		add_signed8(int8_t a, int8_t b)			{ return a + b; }
uint8_t 	add_unsigned8(uint8_t a, uint8_t b)		{ return a + b; }
int16_t 	add_signed16(int16_t a, int16_t b)		{ return a + b; }
uint16_t	add_unsigned16(uint16_t a, uint16_t b)	{ return a + b; }
int32_t 	add_signed32(int32_t a, int32_t b)		{ return a + b; }
uint32_t 	add_unsigned32(uint32_t a, uint32_t b)	{ return a + b; }
int64_t 	add_signed64(int64_t a, int64_t b)		{ return a + b; }
uint64_t 	add_unsigned64(uint64_t a, uint64_t b)	{ return a + b; }
float		add_floatS(float a, float b)			{ return a + b; }
double		add_floatD(double a, double b)			{ return a + b; }

simple_t	add_simple(simple_t a, simple_t b) {
	simple_t ret = { a._1 + b._1, a._2 + b._2 };
	return ret;
}

/* ffi proxy function */
ffi_arg call(ffi_type **args, void **values, size_t nargs,
		ffi_type rctype, ffi_callback func)
{
	ffi_cif cif;
	ffi_arg rc;
	
	/* Iniitalize the cif */
	int ret = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, nargs, &rctype, args);
	if(ret != FFI_OK) {
		fprintf(stderr, "[%s] Cant prepare ffi context: %d\n", __func__, ret);
		exit(EXIT_FAILURE);
	}
	
	ffi_call(&cif, func, &rc, values);
	return rc;
}

void call_ext(ffi_type **args, void **values, size_t nargs,
				ffi_type rctype, void *rc, ffi_callback func)
{
	ffi_cif cif;
	
	/* Iniitalize the cif */
	int ret = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, nargs, &rctype, args);
	if(ret != FFI_OK) {
		fprintf(stderr, "[%s] Cant prepare ffi context: %d\n", __func__, ret);
		exit(EXIT_FAILURE);
	}
	
	ffi_call(&cif, func, rc, values);
}

int main(void) {
	/* 8bit signed integer test */
	{
		int8_t a = (SCHAR_MAX / 2) + 1, b = (SCHAR_MAX / 2) - 1;
		const int8_t result = a + b;
	
		ffi_type *args[] = {&ffi_type_sint8, &ffi_type_sint8};
		void *values[] = {&a, &b};
		
		int8_t rc = (int8_t)call(args, values, 2, ffi_type_sint8, (ffi_callback)add_signed8);
		printf("Signed 8bit integer result:\t%"PRIi8"\n", rc);
		assert(rc == result);
	}

	/* 8bit unsigned integer test */
	{
		uint8_t a = (UCHAR_MAX / 2) + 1, b = (UCHAR_MAX / 2) - 1;
		const uint8_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint8, &ffi_type_uint8};
		void *values[] = {&a, &b};
		
		uint8_t rc = call(args, values, 2, ffi_type_uint8, (ffi_callback)add_unsigned8);
		printf("Unsigned 8bit integer result:\t%"PRIu8"\n", rc);
		assert(rc == result);
	}

	/* 16bit signed integer test */
	{
		int16_t a = (SHRT_MAX / 2) + 1, b = (SHRT_MAX / 2) - 1;
		const int16_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint16, &ffi_type_sint16};
		void *values[] = {&a, &b};
		
		int16_t rc = call(args, values, 2, ffi_type_sint16, (ffi_callback)add_signed16);
		printf("Signed 16bit integer result:\t%"PRIi16"\n", rc);
		assert(rc == result);
	}

	/* 16bit unsigned integer test */
	{
		uint16_t a = (USHRT_MAX / 2) + 1, b = (USHRT_MAX / 2) - 1;
		const uint16_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint16, &ffi_type_uint16};
		void *values[] = {&a, &b};
		
		uint16_t rc = call(args, values, 2, ffi_type_uint16, (ffi_callback)add_unsigned16);
		printf("Unsigned 16bit integer result:\t%"PRIu16"\n", rc);
		assert(rc == result);
	}

	/* 32bit signed integer test */
	{
		int32_t a = (INT_MAX / 2) + 1, b = (INT_MAX / 2) - 1;
		const int32_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint32, &ffi_type_sint32};
		void *values[] = {&a, &b};
	
		int32_t rc = call(args, values, 2, ffi_type_sint32, (ffi_callback)add_signed32);
		printf("Signed 32bit integer result:\t%"PRIi32"\n", rc);
		assert(rc == result);
	}

	/* 32bit unsigned integer test */
	{
		uint32_t a = (UINT_MAX / 2) + 1, b = (UINT_MAX / 2) - 1;
		const uint32_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint32, &ffi_type_uint32};
		void *values[] = {&a, &b};
		
		uint32_t rc = call(args, values, 2, ffi_type_uint32, (ffi_callback)add_unsigned32);
		printf("Unsigned 32bit integer result:\t%"PRIu32"\n", rc);
		assert(rc == result);
	}

	/* 64bit signed integer test */
	{
		int64_t a = (LONG_MAX / 2) + 1, b = (LONG_MAX / 2) - 1, rc;
		const int64_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_sint64, &ffi_type_sint64};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, ffi_type_sint64, &rc, (ffi_callback)add_signed64);
		printf("Signed 64bit integer result:\t%"PRIi64"\n", rc);
		assert(rc == result);
	}

	/* 64bit unsigned integer test */
	{
		uint64_t a = (ULONG_MAX / 2) + 1, b = (ULONG_MAX / 2) - 1, rc;
		const uint64_t result = a + b;
		
		ffi_type *args[] = {&ffi_type_uint64, &ffi_type_uint64};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, ffi_type_uint64, &rc, (ffi_callback)add_unsigned64);
		printf("Unsigned 64bit integer result:\t%"PRIu64"\n", rc);
		assert(rc == result);
	}

	/* single precision float test */
	{
		float a = (FLT_MAX / 2.0F) + 0.5F, b = (FLT_MAX / 2.0F) - 0.5F, rc;
		const float result = a + b;
		
		ffi_type *args[] = {&ffi_type_float, &ffi_type_float};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, ffi_type_float, &rc, (ffi_callback)add_floatS);
		printf("Single precision float result:\t%f\n", rc);
		assert(rc == result);
	}

	/* double precision float test */
	{
		double a = (DBL_MAX / 2.0) + 0.5, b = (DBL_MAX / 2.0) - 0.5, rc;
		const double result = a + b;
		
		ffi_type *args[] = {&ffi_type_double, &ffi_type_double};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, ffi_type_double, &rc, (ffi_callback)add_floatD);
		printf("Double precision float result:\t%lf\n", rc);
		assert(rc == result);
	}

	/* struct test */
	{
		simple_t a = {(INT_MAX / 2) + 1, (INT_MAX / 2) - 1};
		simple_t b = {(INT_MAX / 2) - 1, (INT_MAX / 2) + 1}, rc;
		const simple_t result = {a._1 + b._1, a._2 + b._2};
		
		ffi_type *prim[] = {&ffi_type_sint32, &ffi_type_sint32, NULL};
		ffi_type sc = {0, 0, FFI_TYPE_STRUCT, (ffi_type**)&prim};
		ffi_type *args[] = {&sc, &sc};
		void *values[] = {&a, &b};
		
		call_ext(args, values, 2, sc, &rc, (ffi_callback)add_simple);
		printf("Simple_t result:\t%d, %d\n", rc._1, rc._2);
		assert(rc._1 == result._1 && rc._2 == result._2);
	}
	
	exit(EXIT_SUCCESS);
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]