1package wazevo
2
3import (
4 "encoding/binary"
5 "reflect"
6 "unsafe"
7
8 "github.com/tetratelabs/wazero/experimental"
9 "github.com/tetratelabs/wazero/internal/wasm"
10)
11
12func buildHostModuleOpaque(m *wasm.Module, listeners []experimental.FunctionListener) moduleContextOpaque {
13 size := len(m.CodeSection)*16 + 32
14 ret := newAlignedOpaque(size)
15
16 binary.LittleEndian.PutUint64(ret[0:], uint64(uintptr(unsafe.Pointer(m))))
17
18 if len(listeners) > 0 {
19 //nolint:staticcheck
20 sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&listeners))
21 binary.LittleEndian.PutUint64(ret[8:], uint64(sliceHeader.Data))
22 binary.LittleEndian.PutUint64(ret[16:], uint64(sliceHeader.Len))
23 binary.LittleEndian.PutUint64(ret[24:], uint64(sliceHeader.Cap))
24 }
25
26 offset := 32
27 for i := range m.CodeSection {
28 goFn := m.CodeSection[i].GoFunc
29 writeIface(goFn, ret[offset:])
30 offset += 16
31 }
32 return ret
33}
34
35func hostModuleFromOpaque(opaqueBegin uintptr) *wasm.Module {
36 var opaqueViewOverSlice []byte
37 //nolint:staticcheck
38 sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverSlice))
39 sh.Data = opaqueBegin
40 sh.Len = 32
41 sh.Cap = 32
42 return *(**wasm.Module)(unsafe.Pointer(&opaqueViewOverSlice[0]))
43}
44
45func hostModuleListenersSliceFromOpaque(opaqueBegin uintptr) []experimental.FunctionListener {
46 var opaqueViewOverSlice []byte
47 //nolint:staticcheck
48 sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverSlice))
49 sh.Data = opaqueBegin
50 sh.Len = 32
51 sh.Cap = 32
52
53 b := binary.LittleEndian.Uint64(opaqueViewOverSlice[8:])
54 l := binary.LittleEndian.Uint64(opaqueViewOverSlice[16:])
55 c := binary.LittleEndian.Uint64(opaqueViewOverSlice[24:])
56 var ret []experimental.FunctionListener
57 //nolint:staticcheck
58 sh = (*reflect.SliceHeader)(unsafe.Pointer(&ret))
59 sh.Data = uintptr(b)
60 sh.Len = int(l)
61 sh.Cap = int(c)
62 return ret
63}
64
65func hostModuleGoFuncFromOpaque[T any](index int, opaqueBegin uintptr) T {
66 offset := uintptr(index*16) + 32
67 ptr := opaqueBegin + offset
68
69 var opaqueViewOverFunction []byte
70 //nolint:staticcheck
71 sh := (*reflect.SliceHeader)(unsafe.Pointer(&opaqueViewOverFunction))
72 sh.Data = ptr
73 sh.Len = 16
74 sh.Cap = 16
75 return readIface(opaqueViewOverFunction).(T)
76}
77
78func writeIface(goFn interface{}, buf []byte) {
79 goFnIface := *(*[2]uint64)(unsafe.Pointer(&goFn))
80 binary.LittleEndian.PutUint64(buf, goFnIface[0])
81 binary.LittleEndian.PutUint64(buf[8:], goFnIface[1])
82}
83
84func readIface(buf []byte) interface{} {
85 b := binary.LittleEndian.Uint64(buf)
86 s := binary.LittleEndian.Uint64(buf[8:])
87 return *(*interface{})(unsafe.Pointer(&[2]uint64{b, s}))
88}