runtime: deduplicate syscall assembly for darwin

The darwin port provides different syscall functions that only
differ on how they handle the errors, and they are all written
in assembly.

This duplication can be removed by factoring out the error handling
logic to arch-agnostic Go code and leaving the assembly functions
with the only reponsibility of making the syscall and mapping
parameters between ABIs.

Updates #51087

Cq-Include-Trybots: luci.golang.try:gotip-darwin-arm64-longtest,gotip-darwin-amd64-longtest
Change-Id: I9524377f3ef9c9a638412c7e87c8f46a33ee3453
Reviewed-on: https://go-review.googlesource.com/c/go/+/699135
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
qmuntal 2025-08-26 11:47:51 +02:00 committed by Quim Muntal
parent 080882a928
commit 8320fe8f0e
3 changed files with 131 additions and 369 deletions

View file

@ -10,12 +10,27 @@ import (
"unsafe"
)
//go:nosplit
func libcError() uintptr {
errPtr, _ := syscall(abi.FuncPCABI0(libc_error_trampoline), 0, 0, 0)
return errPtr
}
func libc_error_trampoline()
// The X versions of syscall expect the libc call to return a 64-bit result.
// Otherwise (the non-X version) expects a 32-bit result.
// This distinction is required because an error is indicated by returning -1,
// and we need to know whether to check 32 or 64 bits of the result.
// (Some libc functions that return 32 bits put junk in the upper 32 bits of AX.)
//go:nosplit
func syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2 uintptr }{fn, a1, a2, a3, r1, r2}
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_trampoline)), unsafe.Pointer(&args))
return args.r1, args.r2
}
func syscall_trampoline()
// golang.org/x/sys linknames syscall_syscall
// (in addition to standard package syscall).
// Do not remove or change the type signature.
@ -23,24 +38,28 @@ import (
//go:linkname syscall_syscall syscall.syscall
//go:nosplit
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
r1, r2, err = syscall_rawSyscall(fn, a1, a2, a3)
exitsyscall()
return args.r1, args.r2, args.err
return r1, r2, err
}
func syscall()
//go:linkname syscall_syscallX syscall.syscallX
//go:nosplit
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&args))
r1, r2, err = syscall_rawSyscallX(fn, a1, a2, a3)
exitsyscall()
return args.r1, args.r2, args.err
return r1, r2, err
}
func syscallX()
//go:nosplit
func syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2 uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2}
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6_trampoline)), unsafe.Pointer(&args))
return args.r1, args.r2
}
func syscall6_trampoline()
// golang.org/x/sys linknames syscall.syscall6
// (in addition to standard package syscall).
@ -56,13 +75,28 @@ func syscallX()
//go:linkname syscall_syscall6 syscall.syscall6
//go:nosplit
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
r1, r2, err = syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6)
exitsyscall()
return args.r1, args.r2, args.err
return r1, r2, err
}
func syscall6()
//go:linkname syscall_syscall6X syscall.syscall6X
//go:nosplit
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
entersyscall()
r1, r2, err = syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6)
exitsyscall()
return r1, r2, err
}
//go:nosplit
func syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2 uintptr }{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2}
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall9_trampoline)), unsafe.Pointer(&args))
return args.r1, args.r2
}
func syscall9_trampoline()
// golang.org/x/sys linknames syscall.syscall9
// (in addition to standard package syscall).
@ -71,24 +105,11 @@ func syscall6()
//go:linkname syscall_syscall9 syscall.syscall9
//go:nosplit
func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall9)), unsafe.Pointer(&args))
r1, r2, err = syscall_rawSyscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
exitsyscall()
return args.r1, args.r2, args.err
return r1, r2, err
}
func syscall9()
//go:linkname syscall_syscall6X syscall.syscall6X
//go:nosplit
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&args))
exitsyscall()
return args.r1, args.r2, args.err
}
func syscall6X()
// golang.org/x/sys linknames syscall.syscallPtr
// (in addition to standard package syscall).
@ -97,13 +118,11 @@ func syscall6X()
//go:linkname syscall_syscallPtr syscall.syscallPtr
//go:nosplit
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
entersyscall()
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&args))
r1, r2, err = syscall_rawSyscallPtr(fn, a1, a2, a3)
exitsyscall()
return args.r1, args.r2, args.err
return r1, r2, err
}
func syscallPtr()
// golang.org/x/sys linknames syscall_rawSyscall
// (in addition to standard package syscall).
@ -112,9 +131,30 @@ func syscallPtr()
//go:linkname syscall_rawSyscall syscall.rawSyscall
//go:nosplit
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err}
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args))
return args.r1, args.r2, args.err
r1, r2 = syscall(fn, a1, a2, a3)
// Check if r1 low 32 bits is -1, indicating an error.
if int32(r1) == -1 {
err = libcError()
}
return r1, r2, err
}
//go:nosplit
func syscall_rawSyscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
r1, r2 = syscall(fn, a1, a2, a3)
if r1 == ^uintptr(0) {
err = libcError()
}
return r1, r2, err
}
//go:nosplit
func syscall_rawSyscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
r1, r2 = syscall(fn, a1, a2, a3)
if r1 == 0 {
err = libcError()
}
return r1, r2, err
}
// golang.org/x/sys linknames syscall_rawSyscall6
@ -124,9 +164,31 @@ func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:nosplit
func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err}
libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args))
return args.r1, args.r2, args.err
r1, r2 = syscall6(fn, a1, a2, a3, a4, a5, a6)
// Check if r1 low 32 bits is -1, indicating an error.
if int32(r1) == -1 {
err = libcError()
}
return r1, r2, err
}
//go:nosplit
func syscall_rawSyscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
r1, r2 = syscall6(fn, a1, a2, a3, a4, a5, a6)
if r1 == ^uintptr(0) {
err = libcError()
}
return r1, r2, err
}
//go:nosplit
func syscall_rawSyscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
r1, r2 = syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
// Check if r1 low 32 bits is -1, indicating an error.
if int32(r1) == -1 {
err = libcError()
}
return r1, r2, err
}
// crypto_x509_syscall is used in crypto/x509/internal/macos to call into Security.framework and CF.

View file

@ -506,8 +506,8 @@ TEXT runtime·arc4random_buf_trampoline(SB),NOSPLIT,$0
CALL libc_arc4random_buf(SB)
RET
// syscall calls a function in libc on behalf of the syscall package.
// syscall takes a pointer to a struct like:
// syscall_trampoline calls a function in libc on behalf of the syscall package.
// syscall_trampoline takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
@ -515,14 +515,10 @@ TEXT runtime·arc4random_buf_trampoline(SB),NOSPLIT,$0
// a3 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall must be called on the g0 stack with the
// syscall_trampoline must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscall expects a 32-bit result and tests for 32-bit -1
// to decide there was an error.
TEXT runtime·syscall(SB),NOSPLIT,$16
TEXT runtime·syscall_trampoline(SB),NOSPLIT,$16
MOVQ (0*8)(DI), CX // fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
@ -536,99 +532,11 @@ TEXT runtime·syscall(SB),NOSPLIT,$16
MOVQ AX, (4*8)(DI) // r1
MOVQ DX, (5*8)(DI) // r2
// Standard libc functions return -1 on error
// and set errno.
CMPL AX, $-1 // Note: high 32 bits are junk
JNE ok
// Get error code from libc.
CALL libc_error(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (6*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
RET
// syscallX calls a function in libc on behalf of the syscall package.
// syscallX takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscallX must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscallX is like syscall but expects a 64-bit result
// and tests for 64-bit -1 to decide there was an error.
TEXT runtime·syscallX(SB),NOSPLIT,$16
MOVQ (0*8)(DI), CX // fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
CALL CX
MOVQ (SP), DI
MOVQ AX, (4*8)(DI) // r1
MOVQ DX, (5*8)(DI) // r2
// Standard libc functions return -1 on error
// and set errno.
CMPQ AX, $-1
JNE ok
// Get error code from libc.
CALL libc_error(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (6*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
RET
// syscallPtr is like syscallX except that the libc function reports an
// error by returning NULL and setting errno.
TEXT runtime·syscallPtr(SB),NOSPLIT,$16
MOVQ (0*8)(DI), CX // fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
CALL CX
MOVQ (SP), DI
MOVQ AX, (4*8)(DI) // r1
MOVQ DX, (5*8)(DI) // r2
// syscallPtr libc functions return NULL on error
// and set errno.
TESTQ AX, AX
JNE ok
// Get error code from libc.
CALL libc_error(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (6*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
RET
// syscall6 calls a function in libc on behalf of the syscall package.
// syscall6 takes a pointer to a struct like:
// syscall6_trampoline calls a function in libc on behalf of the syscall package.
// syscall6_trampoline takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
@ -639,14 +547,10 @@ ok:
// a6 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall6 must be called on the g0 stack with the
// syscall6_trampoline must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscall6 expects a 32-bit result and tests for 32-bit -1
// to decide there was an error.
TEXT runtime·syscall6(SB),NOSPLIT,$16
TEXT runtime·syscall6_trampoline(SB),NOSPLIT,$16
MOVQ (0*8)(DI), R11// fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
@ -663,68 +567,11 @@ TEXT runtime·syscall6(SB),NOSPLIT,$16
MOVQ AX, (7*8)(DI) // r1
MOVQ DX, (8*8)(DI) // r2
CMPL AX, $-1
JNE ok
CALL libc_error(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (9*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
RET
// syscall6X calls a function in libc on behalf of the syscall package.
// syscall6X takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// a4 uintptr
// a5 uintptr
// a6 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall6X must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscall6X is like syscall6 but expects a 64-bit result
// and tests for 64-bit -1 to decide there was an error.
TEXT runtime·syscall6X(SB),NOSPLIT,$16
MOVQ (0*8)(DI), R11// fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
MOVQ (4*8)(DI), CX // a4
MOVQ (5*8)(DI), R8 // a5
MOVQ (6*8)(DI), R9 // a6
MOVQ DI, (SP)
MOVQ (1*8)(DI), DI // a1
XORL AX, AX // vararg: say "no float args"
CALL R11
MOVQ (SP), DI
MOVQ AX, (7*8)(DI) // r1
MOVQ DX, (8*8)(DI) // r2
CMPQ AX, $-1
JNE ok
CALL libc_error(SB)
MOVLQSX (AX), AX
MOVQ (SP), DI
MOVQ AX, (9*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
RET
// syscall9 calls a function in libc on behalf of the syscall package.
// syscall9 takes a pointer to a struct like:
// syscall9_trampoline calls a function in libc on behalf of the syscall package.
// syscall9_trampoline takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
@ -740,12 +587,9 @@ ok:
// r2 uintptr
// err uintptr
// }
// syscall9 must be called on the g0 stack with the
// syscall9_trampoline must be called on the g0 stack with the
// C calling convention (use libcCall).
//
// syscall9 expects a 32-bit result and tests for 32-bit -1
// to decide there was an error.
TEXT runtime·syscall9(SB),NOSPLIT,$32
TEXT runtime·syscall9_trampoline(SB),NOSPLIT,$32
MOVQ (0*8)(DI), R13// fn
MOVQ (2*8)(DI), SI // a2
MOVQ (3*8)(DI), DX // a3
@ -768,16 +612,12 @@ TEXT runtime·syscall9(SB),NOSPLIT,$32
MOVQ AX, (10*8)(DI) // r1
MOVQ DX, (11*8)(DI) // r2
CMPL AX, $-1
JNE ok
XORL AX, AX // no error (it's ignored anyway)
RET
TEXT runtime·libc_error_trampoline(SB),NOSPLIT,$0
CALL libc_error(SB)
MOVLQSX (AX), AX
MOVQ 24(SP), DI
MOVQ AX, (12*8)(DI) // err
ok:
XORL AX, AX // no error (it's ignored anyway)
RET
// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,

View file

@ -481,8 +481,8 @@ TEXT runtime·arc4random_buf_trampoline(SB),NOSPLIT,$0
BL libc_arc4random_buf(SB)
RET
// syscall calls a function in libc on behalf of the syscall package.
// syscall takes a pointer to a struct like:
// syscall_trampoline calls a function in libc on behalf of the syscall package.
// syscall_trampoline takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
@ -490,12 +490,11 @@ TEXT runtime·arc4random_buf_trampoline(SB),NOSPLIT,$0
// a3 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall must be called on the g0 stack with the
// syscall_trampoline must be called on the g0 stack with the
// C calling convention (use libcCall).
TEXT runtime·syscall(SB),NOSPLIT,$0
SUB $16, RSP // push structure pointer
TEXT runtime·syscall_trampoline(SB),NOSPLIT,$0
SUB $16, RSP // push structure pointer
MOVD R0, 8(RSP)
MOVD 0(R0), R12 // fn
@ -517,87 +516,10 @@ TEXT runtime·syscall(SB),NOSPLIT,$0
ADD $16, RSP
MOVD R0, 32(R2) // save r1
MOVD R1, 40(R2) // save r2
CMPW $-1, R0
BNE ok
SUB $16, RSP // push structure pointer
MOVD R2, 8(RSP)
BL libc_error(SB)
MOVW (R0), R0
MOVD 8(RSP), R2 // pop structure pointer
ADD $16, RSP
MOVD R0, 48(R2) // save err
ok:
RET
// syscallX calls a function in libc on behalf of the syscall package.
// syscallX takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscallX must be called on the g0 stack with the
// C calling convention (use libcCall).
TEXT runtime·syscallX(SB),NOSPLIT,$0
SUB $16, RSP // push structure pointer
MOVD R0, (RSP)
MOVD 0(R0), R12 // fn
MOVD 16(R0), R1 // a2
MOVD 24(R0), R2 // a3
MOVD 8(R0), R0 // a1
BL (R12)
MOVD (RSP), R2 // pop structure pointer
ADD $16, RSP
MOVD R0, 32(R2) // save r1
MOVD R1, 40(R2) // save r2
CMP $-1, R0
BNE ok
SUB $16, RSP // push structure pointer
MOVD R2, (RSP)
BL libc_error(SB)
MOVW (R0), R0
MOVD (RSP), R2 // pop structure pointer
ADD $16, RSP
MOVD R0, 48(R2) // save err
ok:
RET
// syscallPtr is like syscallX except that the libc function reports an
// error by returning NULL and setting errno.
TEXT runtime·syscallPtr(SB),NOSPLIT,$0
SUB $16, RSP // push structure pointer
MOVD R0, (RSP)
MOVD 0(R0), R12 // fn
MOVD 16(R0), R1 // a2
MOVD 24(R0), R2 // a3
MOVD 8(R0), R0 // a1
BL (R12)
MOVD (RSP), R2 // pop structure pointer
ADD $16, RSP
MOVD R0, 32(R2) // save r1
MOVD R1, 40(R2) // save r2
CMP $0, R0
BNE ok
SUB $16, RSP // push structure pointer
MOVD R2, (RSP)
BL libc_error(SB)
MOVW (R0), R0
MOVD (RSP), R2 // pop structure pointer
ADD $16, RSP
MOVD R0, 48(R2) // save err
ok:
RET
// syscall6 calls a function in libc on behalf of the syscall package.
// syscall6 takes a pointer to a struct like:
// syscall6_trampoline calls a function in libc on behalf of the syscall package.
// syscall6_trampoline takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
@ -608,11 +530,10 @@ ok:
// a6 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall6 must be called on the g0 stack with the
// syscall6_trampoline must be called on the g0 stack with the
// C calling convention (use libcCall).
TEXT runtime·syscall6(SB),NOSPLIT,$0
TEXT runtime·syscall6_trampoline(SB),NOSPLIT,$0
SUB $16, RSP // push structure pointer
MOVD R0, 8(RSP)
@ -625,7 +546,7 @@ TEXT runtime·syscall6(SB),NOSPLIT,$0
MOVD 8(R0), R0 // a1
// If fn is declared as vararg, we have to pass the vararg arguments on the stack.
// See syscall above. The only function this applies to is openat, for which the 4th
// See syscall_trampoline above. The only function this applies to is openat, for which the 4th
// arg must be on the stack.
MOVD R3, (RSP)
@ -635,65 +556,10 @@ TEXT runtime·syscall6(SB),NOSPLIT,$0
ADD $16, RSP
MOVD R0, 56(R2) // save r1
MOVD R1, 64(R2) // save r2
CMPW $-1, R0
BNE ok
SUB $16, RSP // push structure pointer
MOVD R2, 8(RSP)
BL libc_error(SB)
MOVW (R0), R0
MOVD 8(RSP), R2 // pop structure pointer
ADD $16, RSP
MOVD R0, 72(R2) // save err
ok:
RET
// syscall6X calls a function in libc on behalf of the syscall package.
// syscall6X takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
// a2 uintptr
// a3 uintptr
// a4 uintptr
// a5 uintptr
// a6 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall6X must be called on the g0 stack with the
// C calling convention (use libcCall).
TEXT runtime·syscall6X(SB),NOSPLIT,$0
SUB $16, RSP // push structure pointer
MOVD R0, (RSP)
MOVD 0(R0), R12 // fn
MOVD 16(R0), R1 // a2
MOVD 24(R0), R2 // a3
MOVD 32(R0), R3 // a4
MOVD 40(R0), R4 // a5
MOVD 48(R0), R5 // a6
MOVD 8(R0), R0 // a1
BL (R12)
MOVD (RSP), R2 // pop structure pointer
ADD $16, RSP
MOVD R0, 56(R2) // save r1
MOVD R1, 64(R2) // save r2
CMP $-1, R0
BNE ok
SUB $16, RSP // push structure pointer
MOVD R2, (RSP)
BL libc_error(SB)
MOVW (R0), R0
MOVD (RSP), R2 // pop structure pointer
ADD $16, RSP
MOVD R0, 72(R2) // save err
ok:
RET
// syscall9 calls a function in libc on behalf of the syscall package.
// syscall9 takes a pointer to a struct like:
// syscall9_trampoline calls a function in libc on behalf of the syscall package.
// syscall9_trampoline takes a pointer to a struct like:
// struct {
// fn uintptr
// a1 uintptr
@ -707,11 +573,10 @@ ok:
// a9 uintptr
// r1 uintptr
// r2 uintptr
// err uintptr
// }
// syscall9 must be called on the g0 stack with the
// syscall9_trampoline must be called on the g0 stack with the
// C calling convention (use libcCall).
TEXT runtime·syscall9(SB),NOSPLIT,$0
TEXT runtime·syscall9_trampoline(SB),NOSPLIT,$0
SUB $16, RSP // push structure pointer
MOVD R0, 8(RSP)
@ -733,16 +598,11 @@ TEXT runtime·syscall9(SB),NOSPLIT,$0
ADD $16, RSP
MOVD R0, 80(R2) // save r1
MOVD R1, 88(R2) // save r2
CMPW $-1, R0
BNE ok
SUB $16, RSP // push structure pointer
MOVD R2, 8(RSP)
RET
TEXT runtime·libc_error_trampoline(SB),NOSPLIT,$0
BL libc_error(SB)
MOVW (R0), R0
MOVD 8(RSP), R2 // pop structure pointer
ADD $16, RSP
MOVD R0, 96(R2) // save err
ok:
RET
// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors,