diff --git a/struct_amd64.go b/struct_amd64.go index 06a82dd8..f3514c98 100644 --- a/struct_amd64.go +++ b/struct_amd64.go @@ -111,7 +111,7 @@ func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFl return keepAlive } -func postMerger(t reflect.Type) bool { +func postMerger(t reflect.Type) (passInMemory bool) { // (c) If the size of the aggregate exceeds two eightbytes and the first eight- byte isn’t SSE or any other // eightbyte isn’t SSEUP, the whole argument is passed in memory. if t.Kind() != reflect.Struct { @@ -120,19 +120,7 @@ func postMerger(t reflect.Type) bool { if t.Size() <= 2*8 { return false } - first := getFirst(t).Kind() - if first != reflect.Float32 && first != reflect.Float64 { - return false - } - return true -} - -func getFirst(t reflect.Type) reflect.Type { - first := t.Field(0).Type - if first.Kind() == reflect.Struct { - return getFirst(first) - } - return first + return true // Go does not have an SSE/SEEUP type so this is always true } func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) (ok bool) { @@ -196,7 +184,7 @@ func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintp val |= uint64(f.Int()&0xFFFF_FFFF) << shift shift += 32 class |= _INTEGER - case reflect.Int64: + case reflect.Int64, reflect.Int: val = uint64(f.Int()) shift = 64 class = _INTEGER @@ -212,7 +200,7 @@ func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintp val |= f.Uint() << shift shift += 32 class |= _INTEGER - case reflect.Uint64: + case reflect.Uint64, reflect.Uint: val = f.Uint() shift = 64 class = _INTEGER diff --git a/struct_test.go b/struct_test.go index 0d612a0a..2eb1c988 100644 --- a/struct_test.go +++ b/struct_test.go @@ -6,6 +6,7 @@ package purego_test import ( + "math" "os" "path/filepath" "runtime" @@ -440,6 +441,28 @@ func TestRegisterFunc_structArgs(t *testing.T) { t.Fatalf("InitWithContentRect returned %d wanted %#x", ret, expectedUnsigned) } } + { + type GoInt4 struct { + A, B, C, D int + } + var GoInt4Fn func(GoInt4) int + purego.RegisterLibFunc(&GoInt4Fn, lib, "GoInt4") + const expected = math.MaxInt - 52 - 3 + 4 + if ret := GoInt4Fn(GoInt4{math.MaxInt, -52, 3, 4}); ret != expected { + t.Fatalf("GoInt4Fn returned %d wanted %#x", ret, expected) + } + } + { + type GoUint4 struct { + A, B, C, D uint + } + var GoUint4Fn func(GoUint4) uint + purego.RegisterLibFunc(&GoUint4Fn, lib, "GoUint4") + const expected = 1_000_000 + 53 + 71 + 8 + if ret := GoUint4Fn(GoUint4{1_000_000, 53, 71, 8}); ret != expected { + t.Fatalf("GoUint4Fn returned %d wanted %#x", ret, expected) + } + } } func TestRegisterFunc_structReturns(t *testing.T) { diff --git a/testdata/structtest/struct_test.c b/testdata/structtest/struct_test.c index 3faaacc8..939d146d 100644 --- a/testdata/structtest/struct_test.c +++ b/testdata/structtest/struct_test.c @@ -1,6 +1,13 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2024 The Ebitengine Authors +#include "stdint.h" + +#if defined(__x86_64__) || defined(__aarch64__) +typedef int64_t GoInt; +typedef uint64_t GoUint; +#endif + // Empty is empty struct Empty {}; @@ -325,3 +332,19 @@ unsigned long InitWithContentRect(int *win, struct Content c, int style, int bac return 0xF1A6; // FLAG return (unsigned long)(c.point.x + c.point.y + c.size.width + c.size.height) / (style - backing); } + +struct GoInt4 { + GoInt a, b, c, d; +}; + +GoInt GoInt4(struct GoInt4 g) { + return g.a + g.b - g.c + g.d; +} + +struct GoUint4 { + GoUint a, b, c, d; +}; + +GoUint GoUint4(struct GoUint4 g) { + return g.a + g.b + g.c + g.d; +}