Files
gasm-sdk/verify/call_loong64.go
T

55 lines
1.5 KiB
Go
Raw Permalink Normal View History

// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
//go:build loong64
package verify
import (
"encoding/binary"
"fmt"
"syscall"
"unsafe"
)
//go:nosplit
func enterJIT(fn uintptr, stack uintptr)
//go:nosplit
func leaveJIT()
// leaveRawAddr is the raw ABI0 address of leaveJIT, handed over by the
// GLOBL/DATA in abi_loong64.s (reflect would return the interposed
// ABIInternal wrapper instead: its prologue clobbers the saved-register
// window the JIT call depends on).
var leaveRawAddr uintptr
var leaveJITAddr = leaveRawAddr
const stackPad = 64
// Call invokes the assembled function at fnAddr with the given ABI0 argument block.
//
// Not safe for concurrent use: only one JIT call may be in flight at a
// time, the trampolines keep the saved registers in package globals.
func Call(fnAddr uintptr, args []byte) ([]byte, error) {
stackSize := stackPad + 8 + len(args) + 64
stackMem, err := syscall.Mmap(-1, 0, stackSize,
syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_PRIVATE|syscall.MAP_ANON)
if err != nil {
return nil, fmt.Errorf("verify: stack mmap: %w", err)
}
defer syscall.Munmap(stackMem)
retOff := stackPad
binary.LittleEndian.PutUint64(stackMem[retOff:retOff+8], uint64(leaveJITAddr))
copy(stackMem[retOff+8:], args)
stackBase := uintptr(unsafe.Pointer(&stackMem[retOff]))
enterJIT(fnAddr, stackBase)
out := make([]byte, len(args))
copy(out, stackMem[retOff+8:retOff+8+len(args)])
return out, nil
}