mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-12-05 01:52:46 +00:00
83 lines
2.4 KiB
Go
83 lines
2.4 KiB
Go
|
package wazevo
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"reflect"
|
||
|
"unsafe"
|
||
|
|
||
|
"github.com/tetratelabs/wazero/experimental"
|
||
|
"github.com/tetratelabs/wazero/internal/wasm"
|
||
|
)
|
||
|
|
||
|
func buildHostModuleOpaque(m *wasm.Module, listeners []experimental.FunctionListener) moduleContextOpaque {
|
||
|
size := len(m.CodeSection)*16 + 32
|
||
|
ret := newAlignedOpaque(size)
|
||
|
|
||
|
binary.LittleEndian.PutUint64(ret[0:], uint64(uintptr(unsafe.Pointer(m))))
|
||
|
|
||
|
if len(listeners) > 0 {
|
||
|
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&listeners))
|
||
|
binary.LittleEndian.PutUint64(ret[8:], uint64(sliceHeader.Data))
|
||
|
binary.LittleEndian.PutUint64(ret[16:], uint64(sliceHeader.Len))
|
||
|
binary.LittleEndian.PutUint64(ret[24:], uint64(sliceHeader.Cap))
|
||
|
}
|
||
|
|
||
|
offset := 32
|
||
|
for i := range m.CodeSection {
|
||
|
goFn := m.CodeSection[i].GoFunc
|
||
|
writeIface(goFn, ret[offset:])
|
||
|
offset += 16
|
||
|
}
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
func hostModuleFromOpaque(opaqueBegin uintptr) *wasm.Module {
|
||
|
var opaqueViewOverSlice []byte
|
||
|
sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverSlice))
|
||
|
sh.Data = opaqueBegin
|
||
|
sh.Len = 32
|
||
|
sh.Cap = 32
|
||
|
return *(**wasm.Module)(unsafe.Pointer(&opaqueViewOverSlice[0]))
|
||
|
}
|
||
|
|
||
|
func hostModuleListenersSliceFromOpaque(opaqueBegin uintptr) []experimental.FunctionListener {
|
||
|
var opaqueViewOverSlice []byte
|
||
|
sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverSlice))
|
||
|
sh.Data = opaqueBegin
|
||
|
sh.Len = 32
|
||
|
sh.Cap = 32
|
||
|
|
||
|
b := binary.LittleEndian.Uint64(opaqueViewOverSlice[8:])
|
||
|
l := binary.LittleEndian.Uint64(opaqueViewOverSlice[16:])
|
||
|
c := binary.LittleEndian.Uint64(opaqueViewOverSlice[24:])
|
||
|
var ret []experimental.FunctionListener
|
||
|
sh = (*reflect.SliceHeader)(unsafe.Pointer(&ret))
|
||
|
sh.Data = uintptr(b)
|
||
|
setSliceLimits(sh, uintptr(l), uintptr(c))
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
func hostModuleGoFuncFromOpaque[T any](index int, opaqueBegin uintptr) T {
|
||
|
offset := uintptr(index*16) + 32
|
||
|
ptr := opaqueBegin + offset
|
||
|
|
||
|
var opaqueViewOverFunction []byte
|
||
|
sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverFunction))
|
||
|
sh.Data = ptr
|
||
|
sh.Len = 16
|
||
|
sh.Cap = 16
|
||
|
return readIface(opaqueViewOverFunction).(T)
|
||
|
}
|
||
|
|
||
|
func writeIface(goFn interface{}, buf []byte) {
|
||
|
goFnIface := *(*[2]uint64)(unsafe.Pointer(&goFn))
|
||
|
binary.LittleEndian.PutUint64(buf, goFnIface[0])
|
||
|
binary.LittleEndian.PutUint64(buf[8:], goFnIface[1])
|
||
|
}
|
||
|
|
||
|
func readIface(buf []byte) interface{} {
|
||
|
b := binary.LittleEndian.Uint64(buf)
|
||
|
s := binary.LittleEndian.Uint64(buf[8:])
|
||
|
return *(*interface{})(unsafe.Pointer(&[2]uint64{b, s}))
|
||
|
}
|