1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package wasm
16
17 import (
18 "fmt"
19
20 "cuelang.org/go/cue"
21 "cuelang.org/go/internal/pkg"
22 "github.com/tetratelabs/wazero/api"
23 )
24
25 func encBool(b bool) uint64 {
26 if b {
27 return api.EncodeU32(1)
28 }
29 return api.EncodeU32(0)
30 }
31
32
33
34 func encNumber(typ cue.Value, val cue.Value) (r uint64) {
35 ctx := val.Context()
36
37 _int32 := ctx.CompileString("int32")
38 if _int32.Subsume(typ) == nil {
39 i, _ := val.Int64()
40 return api.EncodeI32(int32(i))
41 }
42
43 _int64 := ctx.CompileString("int64")
44 if _int64.Subsume(typ) == nil {
45 i, _ := val.Int64()
46 return api.EncodeI64(i)
47 }
48
49 _uint32 := ctx.CompileString("uint32")
50 if _uint32.Subsume(typ) == nil {
51 i, _ := val.Uint64()
52 return api.EncodeU32(uint32(i))
53 }
54
55 _uint64 := ctx.CompileString("uint64")
56 if _uint64.Subsume(typ) == nil {
57 i, _ := val.Uint64()
58 return i
59 }
60
61 _float32 := ctx.CompileString("float32")
62 if _float32.Subsume(typ) == nil {
63 f, _ := val.Float64()
64 return api.EncodeF32(float32(f))
65 }
66
67 _float64 := ctx.CompileString("float64")
68 if _float64.Subsume(typ) == nil {
69 f, _ := val.Float64()
70 return api.EncodeF64(f)
71 }
72
73 panic("encNumber: unsupported argument type")
74 }
75
76 func decBool(v uint64) bool {
77 u := api.DecodeU32(v)
78 if u == 1 {
79 return true
80 }
81 return false
82 }
83
84
85
86 func decNumber(typ cue.Value, val uint64) (r any) {
87 ctx := typ.Context()
88
89 _int32 := ctx.CompileString("int32")
90 if _int32.Subsume(typ) == nil {
91 return api.DecodeI32(val)
92 }
93
94 _uint32 := ctx.CompileString("uint32")
95 if _uint32.Subsume(typ) == nil {
96 return api.DecodeU32(val)
97 }
98
99 _int64 := ctx.CompileString("int64")
100 if _int64.Subsume(typ) == nil {
101 return int64(val)
102 }
103
104 _uint64 := ctx.CompileString("uint64")
105 if _uint64.Subsume(typ) == nil {
106 return val
107 }
108
109 _float32 := ctx.CompileString("float32")
110 if _float32.Subsume(typ) == nil {
111 return api.DecodeF32(val)
112 }
113
114 _float64 := ctx.CompileString("float64")
115 if _float64.Subsume(typ) == nil {
116 return api.DecodeF64(val)
117 }
118
119 panic(fmt.Sprintf("unsupported argument type %v (kind %v)", typ, typ.IncompleteKind()))
120 }
121
122 func encBytes(i *instance, b []byte) *memory {
123 m, _ := i.Alloc(uint32(len(b)))
124 m.WriteAt(b, 0)
125 return m
126 }
127
128
129
130
131
132
133
134 func cABIFunc(i *instance, name string, sig []cue.Value) func(*pkg.CallCtxt) {
135
136
137
138 argsTyp, resTyp := splitLast(sig)
139 argLayouts := make([]*structLayout, 0, len(argsTyp))
140 var retLayout *structLayout
141 for _, typ := range argsTyp {
142 switch typ.IncompleteKind() {
143 case cue.StructKind:
144 argLayouts = append(argLayouts, structLayoutVal(typ))
145 default:
146 argLayouts = append(argLayouts, nil)
147 }
148 }
149 if resTyp.IncompleteKind() == cue.StructKind {
150 retLayout = structLayoutVal(resTyp)
151 }
152
153 fn, _ := i.load(name)
154 return func(c *pkg.CallCtxt) {
155 argsTyp, resTyp := splitLast(sig)
156 args := make([]uint64, 0, len(argsTyp))
157 for k, typ := range argsTyp {
158 switch typ.IncompleteKind() {
159 case cue.BoolKind:
160 args = append(args, encBool(c.Bool(k)))
161 case cue.IntKind, cue.FloatKind, cue.NumberKind:
162 args = append(args, encNumber(typ, c.Value(k)))
163 case cue.StructKind:
164 ms := encodeStruct(i, c.Value(k), argLayouts[k])
165 defer i.FreeAll(ms)
166
167 args = append(args, uint64(ms[0].ptr))
168 default:
169 panic(fmt.Sprintf("unsupported argument type %v (kind %v)", typ, typ.IncompleteKind()))
170 }
171 }
172
173 var retMem *memory
174 if resTyp.IncompleteKind() == cue.StructKind {
175 retMem, _ = i.Alloc(uint32(retLayout.size))
176
177 defer i.Free(retMem)
178 args = append(args, uint64(retMem.ptr))
179 }
180
181 if c.Do() {
182 res, err := fn.Call(i.ctx, args...)
183 if err != nil {
184 c.Err = err
185 return
186 }
187 switch resTyp.IncompleteKind() {
188 case cue.BoolKind:
189 c.Ret = decBool(res[0])
190 case cue.IntKind, cue.FloatKind, cue.NumberKind:
191 c.Ret = decNumber(resTyp, res[0])
192 case cue.StructKind:
193 c.Ret = decodeStruct(retMem.Bytes(), retLayout)
194 default:
195 panic(fmt.Sprintf("unsupported result type %v (kind %v)", resTyp, resTyp.IncompleteKind()))
196 }
197 }
198 }
199 }
200
View as plain text