github.com/ebiten/purego@v0.0.0-20220525025155-0f6873f42222/syscall.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2022 The Ebiten Authors
     3  
     4  //go:build darwin
     5  // +build darwin
     6  
     7  package purego
     8  
     9  import "unsafe"
    10  
    11  const maxArgs = 9
    12  
    13  // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
    14  // There is an internal maximum number of arguments that SyscallN can take. It panics
    15  // when the maximum is exceeded. It returns the result and the libc error code if there is one.
    16  //
    17  // NOTE: SyscallN does not properly call functions that have both integer and float parameters.
    18  // See discussion comment https://github.com/ebiten/purego/pull/1#issuecomment-1128057607
    19  // for an explanation of why that is.
    20  //
    21  // On amd64, if there are more than 8 floats the 9th and so on will be placed incorrectly on the
    22  // stack.
    23  func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
    24  	if len(args) > maxArgs {
    25  		panic("too many arguments to SyscallN")
    26  	}
    27  	// add padding so there is no out-of-bounds slicing
    28  	var tmp [maxArgs]uintptr
    29  	copy(tmp[:], args)
    30  	if len(args) <= 6 {
    31  		// use the 6 argument version because
    32  		// gl.GenFramebuffersEXT would fail with the 9 version
    33  		// See https://github.com/hajimehoshi/ebiten/issues/2102#issuecomment-1134679352
    34  		return syscall_syscall6X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5])
    35  	}
    36  	return syscall_syscall9X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8])
    37  }
    38  
    39  func callc(fn uintptr, args unsafe.Pointer) {
    40  	runtime_entersyscall()
    41  	runtime_libcCall(unsafe.Pointer(fn), args)
    42  	runtime_exitsyscall()
    43  }
    44  
    45  var syscall9XABI0 uintptr
    46  
    47  func syscall9X() // implemented in assembly
    48  
    49  func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
    50  	args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }{
    51  		fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err}
    52  	callc(syscall9XABI0, unsafe.Pointer(&args))
    53  	return args.r1, args.r2, args.err
    54  }