public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
From: Georg Bege <georg@bege.email>
To: libffi-discuss@sourceware.org
Subject: Re: libffi on the HPPA (parisc)
Date: Sat, 13 Apr 2019 21:34:00 -0000	[thread overview]
Message-ID: <66d2f3c2-a40e-5968-b6c5-9f4d8bed246f@bege.email> (raw)
In-Reply-To: <77683e46-59c5-ba8b-4f4c-1274d29b5555@bege.email>

[-- Attachment #1: Type: text/plain, Size: 2552 bytes --]

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

[-- Attachment #2: test-ffi.c --]
[-- Type: text/x-csrc, Size: 6496 bytes --]

/**
 * 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);
}

      reply	other threads:[~2019-04-13 21:34 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-13 18:26 Georg Bege
2019-04-13 21:34 ` Georg Bege [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=66d2f3c2-a40e-5968-b6c5-9f4d8bed246f@bege.email \
    --to=georg@bege.email \
    --cc=libffi-discuss@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).