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