runtime: Handle FFI promoting result types.

From-SVN: r184123
This commit is contained in:
Ian Lance Taylor 2012-02-11 07:08:13 +00:00
parent edb7412e0e
commit 83a5c149a6
1 changed files with 99 additions and 1 deletions

View File

@ -5,6 +5,7 @@
license that can be found in the LICENSE file. */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "ffi.h"
@ -326,6 +327,28 @@ go_results_size (const struct __go_func_type *func)
types = (const struct __go_type_descriptor **) func->__out.__values;
/* A single integer return value is always promoted to a full
word. */
if (count == 1)
{
switch (types[0]->__code & GO_CODE_MASK)
{
case GO_BOOL:
case GO_INT8:
case GO_INT16:
case GO_INT32:
case GO_UINT8:
case GO_UINT16:
case GO_UINT32:
case GO_INT:
case GO_UINT:
return sizeof (ffi_arg);
default:
break;
}
}
off = 0;
maxalign = 0;
for (i = 0; i < count; ++i)
@ -362,6 +385,81 @@ go_set_results (const struct __go_func_type *func, unsigned char *call_result,
types = (const struct __go_type_descriptor **) func->__out.__values;
/* A single integer return value is always promoted to a full
word. */
if (count == 1)
{
switch (types[0]->__code & GO_CODE_MASK)
{
case GO_BOOL:
case GO_INT8:
case GO_INT16:
case GO_INT32:
case GO_UINT8:
case GO_UINT16:
case GO_UINT32:
case GO_INT:
case GO_UINT:
{
union
{
unsigned char buf[sizeof (ffi_arg)];
ffi_arg v;
} u;
ffi_arg v;
__builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg));
v = u.v;
switch (types[0]->__size)
{
case 1:
{
uint8_t b;
b = (uint8_t) v;
__builtin_memcpy (results[0], &b, 1);
}
break;
case 2:
{
uint16_t s;
s = (uint16_t) v;
__builtin_memcpy (results[0], &s, 2);
}
break;
case 4:
{
uint32_t w;
w = (uint32_t) v;
__builtin_memcpy (results[0], &w, 4);
}
break;
case 8:
{
uint64_t d;
d = (uint64_t) v;
__builtin_memcpy (results[0], &d, 8);
}
break;
default:
abort ();
}
}
return;
default:
break;
}
}
off = 0;
for (i = 0; i < count; ++i)
{
@ -388,7 +486,7 @@ reflect_call (const struct __go_func_type *func_type, const void *func_addr,
ffi_cif cif;
unsigned char *call_result;
__go_assert (func_type->__common.__code == GO_FUNC);
__go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC);
go_func_to_cif (func_type, is_interface, is_method, &cif);
call_result = (unsigned char *) malloc (go_results_size (func_type));