1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
package purego
import (
"reflect"
"unsafe"
)
func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []any) []any {
size := v.Type().Size()
if size == 0 {
return keepAlive
}
// TODO: ARM EABI: small structs are passed in registers or on stack
// For simplicity, pass by pointer for now
ptr := v.Addr().UnsafePointer()
keepAlive = append(keepAlive, ptr)
if *numInts < 4 {
addInt(uintptr(ptr))
*numInts++
} else {
addStack(uintptr(ptr))
*numStack++
}
return keepAlive
}
func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
outSize := outType.Size()
if outSize == 0 {
return reflect.New(outType).Elem()
}
if outSize <= 4 {
// Fits in one register
return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{syscall.a1})).Elem()
}
if outSize <= 8 {
// Fits in two registers
return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b uintptr }{syscall.a1, syscall.a2})).Elem()
}
// Larger structs returned via pointer in a1
return reflect.NewAt(outType, *(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))).Elem()
}
func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
// TODO: For ARM32, just pass the struct data directly
// This is a simplified implementation
size := v.Type().Size()
if size == 0 {
return
}
ptr := unsafe.Pointer(v.UnsafeAddr())
if size <= 4 {
addInt(*(*uintptr)(ptr))
} else if size <= 8 {
addInt(*(*uintptr)(ptr))
addInt(*(*uintptr)(unsafe.Add(ptr, 4)))
}
}
// shouldBundleStackArgs always returns false on arm
// since C-style stack argument bundling is only needed on Darwin ARM64.
func shouldBundleStackArgs(v reflect.Value, numInts, numFloats int) bool {
return false
}
// structFitsInRegisters is not used on arm.
func structFitsInRegisters(val reflect.Value, tempNumInts, tempNumFloats int) (bool, int, int) {
panic("purego: structFitsInRegisters should not be called on arm")
}
// collectStackArgs is not used on arm.
func collectStackArgs(args []reflect.Value, startIdx int, numInts, numFloats int,
keepAlive []any, addInt, addFloat, addStack func(uintptr),
pNumInts, pNumFloats, pNumStack *int) ([]reflect.Value, []any) {
panic("purego: collectStackArgs should not be called on arm")
}
// bundleStackArgs is not used on arm.
func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
panic("purego: bundleStackArgs should not be called on arm")
}
|