diff options
-rw-r--r-- | libgo/runtime/go-reflect-call.c | 100 |
1 files changed, 99 insertions, 1 deletions
diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c index 27177e2..a818dba 100644 --- a/libgo/runtime/go-reflect-call.c +++ b/libgo/runtime/go-reflect-call.c @@ -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)); |