Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
  • Loading branch information
jwijenbergh committed Sep 14, 2023
1 parent 6319229 commit 39be9b4
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 191 deletions.
90 changes: 90 additions & 0 deletions callback_float_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 The Ebitengine Authors

//go:build darwin || (!cgo && linux)

package purego_test
import (
"testing"

"github.com/ebitengine/purego"
)

func TestNewCallbackFloat64(t *testing.T) {
// This tests the maximum number of arguments a function to NewCallback can take
const (
expectCbTotal = -3
expectedCbTotalF = float64(36)
)
var cbTotal int
var cbTotalF float64
imp := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int,
f1, f2, f3, f4, f5, f6, f7, f8 float64) {
cbTotal = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9
cbTotalF = f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8
})
var fn func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int,
f1, f2, f3, f4, f5, f6, f7, f8 float64)
purego.RegisterFunc(&fn, imp)
fn(1, 2, -3, 4, -5, 6, -7, 8, -9,
1, 2, 3, 4, 5, 6, 7, 8)

if cbTotal != expectCbTotal {
t.Errorf("cbTotal not correct got %d but wanted %d", cbTotal, expectCbTotal)
}
if cbTotalF != expectedCbTotalF {
t.Errorf("cbTotalF not correct got %f but wanted %f", cbTotalF, expectedCbTotalF)
}
}

func TestNewCallbackFloat32(t *testing.T) {
// This tests the maximum number of float32 arguments a function to NewCallback can take
const (
expectCbTotal = 6
expectedCbTotalF = float32(45)
)
var cbTotal int
var cbTotalF float32
imp := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8 int,
f1, f2, f3, f4, f5, f6, f7, f8, f9 float32) {
cbTotal = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8
cbTotalF = f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
})
var fn func(a1, a2, a3, a4, a5, a6, a7, a8 int,
f1, f2, f3, f4, f5, f6, f7, f8, f9 float32)
purego.RegisterFunc(&fn, imp)
fn(1, 2, -3, 4, -5, 6, -7, 8,
1, 2, 3, 4, 5, 6, 7, 8, 9)

if cbTotal != expectCbTotal {
t.Errorf("cbTotal not correct got %d but wanted %d", cbTotal, expectCbTotal)
}
if cbTotalF != expectedCbTotalF {
t.Errorf("cbTotalF not correct got %f but wanted %f", cbTotalF, expectedCbTotalF)
}
}

func TestNewCallbackFloat32AndFloat64(t *testing.T) {
// This tests that calling a function with a mix of float32 and float64 arguments works
const (
expectedCbTotalF32 = float32(30)
expectedCbTotalF64 = float64(15)
)
var cbTotalF32 float32
var cbTotalF64 float64
imp := purego.NewCallback(func(f1, f2, f3 float32, f4, f5, f6 float64, f7, f8, f9 float32) {
cbTotalF32 = f1 + f2 + f3 + f7 + f8 + f9
cbTotalF64 = f4 + f5 + f6

})
var fn func(f1, f2, f3 float32, f4, f5, f6 float64, f7, f8, f9 float32)
purego.RegisterFunc(&fn, imp)
fn(1, 2, 3, 4, 5, 6, 7, 8, 9)

if cbTotalF32 != expectedCbTotalF32 {
t.Errorf("cbTotalF32 not correct got %f but wanted %f", cbTotalF32, expectedCbTotalF32)
}
if cbTotalF64 != expectedCbTotalF64 {
t.Errorf("cbTotalF64 not correct got %f but wanted %f", cbTotalF64, expectedCbTotalF64)
}
}
81 changes: 1 addition & 80 deletions callback_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 The Ebitengine Authors

//go:build darwin
//go:build darwin || linux

package purego_test

Expand Down Expand Up @@ -48,82 +48,3 @@ func TestCallGoFromSharedLib(t *testing.T) {
}
}
}

func TestNewCallbackFloat64(t *testing.T) {
// This tests the maximum number of arguments a function to NewCallback can take
const (
expectCbTotal = -3
expectedCbTotalF = float64(36)
)
var cbTotal int
var cbTotalF float64
imp := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int,
f1, f2, f3, f4, f5, f6, f7, f8 float64) {
cbTotal = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9
cbTotalF = f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8
})
var fn func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int,
f1, f2, f3, f4, f5, f6, f7, f8 float64)
purego.RegisterFunc(&fn, imp)
fn(1, 2, -3, 4, -5, 6, -7, 8, -9,
1, 2, 3, 4, 5, 6, 7, 8)

if cbTotal != expectCbTotal {
t.Errorf("cbTotal not correct got %d but wanted %d", cbTotal, expectCbTotal)
}
if cbTotalF != expectedCbTotalF {
t.Errorf("cbTotalF not correct got %f but wanted %f", cbTotalF, expectedCbTotalF)
}
}

func TestNewCallbackFloat32(t *testing.T) {
// This tests the maximum number of float32 arguments a function to NewCallback can take
const (
expectCbTotal = 6
expectedCbTotalF = float32(45)
)
var cbTotal int
var cbTotalF float32
imp := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8 int,
f1, f2, f3, f4, f5, f6, f7, f8, f9 float32) {
cbTotal = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8
cbTotalF = f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
})
var fn func(a1, a2, a3, a4, a5, a6, a7, a8 int,
f1, f2, f3, f4, f5, f6, f7, f8, f9 float32)
purego.RegisterFunc(&fn, imp)
fn(1, 2, -3, 4, -5, 6, -7, 8,
1, 2, 3, 4, 5, 6, 7, 8, 9)

if cbTotal != expectCbTotal {
t.Errorf("cbTotal not correct got %d but wanted %d", cbTotal, expectCbTotal)
}
if cbTotalF != expectedCbTotalF {
t.Errorf("cbTotalF not correct got %f but wanted %f", cbTotalF, expectedCbTotalF)
}
}

func TestNewCallbackFloat32AndFloat64(t *testing.T) {
// This tests that calling a function with a mix of float32 and float64 arguments works
const (
expectedCbTotalF32 = float32(30)
expectedCbTotalF64 = float64(15)
)
var cbTotalF32 float32
var cbTotalF64 float64
imp := purego.NewCallback(func(f1, f2, f3 float32, f4, f5, f6 float64, f7, f8, f9 float32) {
cbTotalF32 = f1 + f2 + f3 + f7 + f8 + f9
cbTotalF64 = f4 + f5 + f6

})
var fn func(f1, f2, f3 float32, f4, f5, f6 float64, f7, f8, f9 float32)
purego.RegisterFunc(&fn, imp)
fn(1, 2, 3, 4, 5, 6, 7, 8, 9)

if cbTotalF32 != expectedCbTotalF32 {
t.Errorf("cbTotalF32 not correct got %f but wanted %f", cbTotalF32, expectedCbTotalF32)
}
if cbTotalF64 != expectedCbTotalF64 {
t.Errorf("cbTotalF64 not correct got %f but wanted %f", cbTotalF64, expectedCbTotalF64)
}
}
11 changes: 0 additions & 11 deletions func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@ func TestRegisterFunc(t *testing.T) {
}

func ExampleNewCallback() {
if runtime.GOOS == "linux" {
// TODO: enable once callbacks are working properly on Linux
fmt.Println("1 2 3 4 5 6 7 8 9\n45")
return
}

cb := purego.NewCallback(func(a1, a2, a3, a4, a5, a6, a7, a8, a9 int) int {
fmt.Println(a1, a2, a3, a4, a5, a6, a7, a8, a9)
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9
Expand All @@ -69,11 +63,6 @@ func ExampleNewCallback() {
}

func Test_qsort(t *testing.T) {
if runtime.GOOS == "linux" {
// TODO: enable once callbacks are working properly on Linux
t.Skip("callbacks are not supported on Linux")
}

library, err := getSystemLibrary()
if err != nil {
t.Errorf("couldn't get system library: %s", err)
Expand Down
69 changes: 0 additions & 69 deletions sys_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -72,72 +72,3 @@ TEXT syscall9X(SB), NOSPLIT|NOFRAME, $0
MOVQ BP, SP
POPQ BP
RET

TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
// remove return address from stack, we are not returning to callbackasm, but to its caller.
MOVQ 0(SP), AX
ADDQ $8, SP

MOVQ 0(SP), R10 // get the return SP so that we can align register args with stack args

// make space for first six int and 8 float arguments below the frame
ADJSP $14*8, SP
MOVSD X0, (1*8)(SP)
MOVSD X1, (2*8)(SP)
MOVSD X2, (3*8)(SP)
MOVSD X3, (4*8)(SP)
MOVSD X4, (5*8)(SP)
MOVSD X5, (6*8)(SP)
MOVSD X6, (7*8)(SP)
MOVSD X7, (8*8)(SP)
MOVQ DI, (9*8)(SP)
MOVQ SI, (10*8)(SP)
MOVQ DX, (11*8)(SP)
MOVQ CX, (12*8)(SP)
MOVQ R8, (13*8)(SP)
MOVQ R9, (14*8)(SP)
LEAQ 8(SP), R8 // R8 = address of args vector

MOVQ R10, 0(SP) // push the stack pointer below registers

// determine index into runtime·cbs table
MOVQ $callbackasm(SB), DX
SUBQ DX, AX
MOVQ $0, DX
MOVQ $5, CX // divide by 5 because each call instruction in ·callbacks is 5 bytes long
DIVL CX
SUBQ $1, AX // subtract 1 because return PC is to the next slot

// Switch from the host ABI to the Go ABI.
PUSH_REGS_HOST_TO_ABI0()

// Create a struct callbackArgs on our stack to be passed as
// the "frame" to cgocallback and on to callbackWrap.
// $24 to make enough room for the arguments to runtime.cgocallback
SUBQ $(24+callbackArgs__size), SP
MOVQ AX, (24+callbackArgs_index)(SP) // callback index
MOVQ R8, (24+callbackArgs_args)(SP) // address of args vector
MOVQ $0, (24+callbackArgs_result)(SP) // result
LEAQ 24(SP), AX // take the address of callbackArgs

// Call cgocallback, which will call callbackWrap(frame).
MOVQ ·callbackWrap_call(SB), DI // Get the ABIInternal function pointer
MOVQ (DI), DI // without <ABIInternal> by using a closure.
MOVQ AX, SI // frame (address of callbackArgs)
MOVQ $0, CX // context

CALL crosscall2(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)

// Get callback result.
MOVQ (24+callbackArgs_result)(SP), AX
ADDQ $(24+callbackArgs__size), SP // remove callbackArgs struct

POP_REGS_HOST_TO_ABI0()

MOVQ 0(SP), R10 // get the SP back

ADJSP $-14*8, SP // remove arguments

MOVQ R10, 0(SP)

RET
78 changes: 78 additions & 0 deletions sys_unix_amd64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 The Ebitengine Authors

//go:build darwin || freebsd || linux

#include "textflag.h"
#include "abi_amd64.h"
#include "go_asm.h"
#include "funcdata.h"

TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
// remove return address from stack, we are not returning to callbackasm, but to its caller.
MOVQ 0(SP), AX
ADDQ $8, SP

MOVQ 0(SP), R10 // get the return SP so that we can align register args with stack args

// make space for first six int and 8 float arguments below the frame
ADJSP $14*8, SP
MOVSD X0, (1*8)(SP)
MOVSD X1, (2*8)(SP)
MOVSD X2, (3*8)(SP)
MOVSD X3, (4*8)(SP)
MOVSD X4, (5*8)(SP)
MOVSD X5, (6*8)(SP)
MOVSD X6, (7*8)(SP)
MOVSD X7, (8*8)(SP)
MOVQ DI, (9*8)(SP)
MOVQ SI, (10*8)(SP)
MOVQ DX, (11*8)(SP)
MOVQ CX, (12*8)(SP)
MOVQ R8, (13*8)(SP)
MOVQ R9, (14*8)(SP)
LEAQ 8(SP), R8 // R8 = address of args vector

MOVQ R10, 0(SP) // push the stack pointer below registers

// determine index into runtime·cbs table
MOVQ $callbackasm(SB), DX
SUBQ DX, AX
MOVQ $0, DX
MOVQ $5, CX // divide by 5 because each call instruction in ·callbacks is 5 bytes long
DIVL CX
SUBQ $1, AX // subtract 1 because return PC is to the next slot

// Switch from the host ABI to the Go ABI.
PUSH_REGS_HOST_TO_ABI0()

// Create a struct callbackArgs on our stack to be passed as
// the "frame" to cgocallback and on to callbackWrap.
// $24 to make enough room for the arguments to runtime.cgocallback
SUBQ $(24+callbackArgs__size), SP
MOVQ AX, (24+callbackArgs_index)(SP) // callback index
MOVQ R8, (24+callbackArgs_args)(SP) // address of args vector
MOVQ $0, (24+callbackArgs_result)(SP) // result
LEAQ 24(SP), AX // take the address of callbackArgs

// Call cgocallback, which will call callbackWrap(frame).
MOVQ ·callbackWrap_call(SB), DI // Get the ABIInternal function pointer
MOVQ (DI), DI // without <ABIInternal> by using a closure.
MOVQ AX, SI // frame (address of callbackArgs)
MOVQ $0, CX // context

CALL crosscall2(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)

// Get callback result.
MOVQ (24+callbackArgs_result)(SP), AX
ADDQ $(24+callbackArgs__size), SP // remove callbackArgs struct

POP_REGS_HOST_TO_ABI0()

MOVQ 0(SP), R10 // get the SP back

ADJSP $-14*8, SP // remove arguments

MOVQ R10, 0(SP)

RET
2 changes: 1 addition & 1 deletion sys_unix_arm64.s
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 The Ebitengine Authors

//go:build darwin || freebsd || (!cgo && linux)
//go:build darwin || freebsd || linux

#include "textflag.h"
#include "go_asm.h"
Expand Down
11 changes: 0 additions & 11 deletions syscall_cgo_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,7 @@ import (

var syscall9XABI0 = uintptr(cgo.Syscall9XABI0)

// this is only here to make the assembly files happy :)
type syscall9Args struct {
fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr
f1, f2, f3, f4, f5, f6, f7, f8 uintptr
r1, r2, err uintptr
}

//go:nosplit
func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
return cgo.Syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
}

func NewCallback(_ interface{}) uintptr {
panic("purego: NewCallback not supported")
}
Loading

0 comments on commit 39be9b4

Please sign in to comment.