1 package wasm
2
3 import (
4 "bytes"
5 "errors"
6 "fmt"
7 "strconv"
8 "strings"
9
10 "github.com/tetratelabs/wazero/api"
11 "github.com/tetratelabs/wazero/internal/leb128"
12 )
13
14
15 const maximumValuesOnStack = 1 << 27
16
17
18
19
20
21
22
23
24
25
26
27
28
29 func (m *Module) validateFunction(sts *stacks, enabledFeatures api.CoreFeatures, idx Index, functions []Index,
30 globals []GlobalType, memory *Memory, tables []Table, declaredFunctionIndexes map[Index]struct{}, br *bytes.Reader,
31 ) error {
32 return m.validateFunctionWithMaxStackValues(sts, enabledFeatures, idx, functions, globals, memory, tables, maximumValuesOnStack, declaredFunctionIndexes, br)
33 }
34
35 func readMemArg(pc uint64, body []byte) (align, offset uint32, read uint64, err error) {
36 align, num, err := leb128.LoadUint32(body[pc:])
37 if err != nil {
38 err = fmt.Errorf("read memory align: %v", err)
39 return
40 }
41 read += num
42
43 offset, num, err = leb128.LoadUint32(body[pc+num:])
44 if err != nil {
45 err = fmt.Errorf("read memory offset: %v", err)
46 return
47 }
48
49 read += num
50 return align, offset, read, nil
51 }
52
53
54
55
56
57 func (m *Module) validateFunctionWithMaxStackValues(
58 sts *stacks,
59 enabledFeatures api.CoreFeatures,
60 idx Index,
61 functions []Index,
62 globals []GlobalType,
63 memory *Memory,
64 tables []Table,
65 maxStackValues int,
66 declaredFunctionIndexes map[Index]struct{},
67 br *bytes.Reader,
68 ) error {
69 functionType := &m.TypeSection[m.FunctionSection[idx]]
70 code := &m.CodeSection[idx]
71 body := code.Body
72 localTypes := code.LocalTypes
73
74 sts.reset(functionType)
75 valueTypeStack := &sts.vs
76
77 controlBlockStack := &sts.cs
78
79
80
81 for pc := uint64(0); pc < uint64(len(body)); pc++ {
82 op := body[pc]
83 if false {
84 var instName string
85 if op == OpcodeMiscPrefix {
86 instName = MiscInstructionName(body[pc+1])
87 } else if op == OpcodeVecPrefix {
88 instName = VectorInstructionName(body[pc+1])
89 } else {
90 instName = InstructionName(op)
91 }
92 fmt.Printf("handling %s, stack=%s, blocks: %v\n", instName, valueTypeStack.stack, controlBlockStack)
93 }
94
95 if OpcodeI32Load <= op && op <= OpcodeI64Store32 {
96 if memory == nil {
97 return fmt.Errorf("memory must exist for %s", InstructionName(op))
98 }
99 pc++
100 align, _, read, err := readMemArg(pc, body)
101 if err != nil {
102 return err
103 }
104 pc += read - 1
105 switch op {
106 case OpcodeI32Load:
107 if 1<<align > 32/8 {
108 return fmt.Errorf("invalid memory alignment")
109 }
110 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
111 return err
112 }
113 valueTypeStack.push(ValueTypeI32)
114 case OpcodeF32Load:
115 if 1<<align > 32/8 {
116 return fmt.Errorf("invalid memory alignment")
117 }
118 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
119 return err
120 }
121 valueTypeStack.push(ValueTypeF32)
122 case OpcodeI32Store:
123 if 1<<align > 32/8 {
124 return fmt.Errorf("invalid memory alignment")
125 }
126 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
127 return err
128 }
129 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
130 return err
131 }
132 case OpcodeF32Store:
133 if 1<<align > 32/8 {
134 return fmt.Errorf("invalid memory alignment")
135 }
136 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
137 return err
138 }
139 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
140 return err
141 }
142 case OpcodeI64Load:
143 if 1<<align > 64/8 {
144 return fmt.Errorf("invalid memory alignment")
145 }
146 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
147 return err
148 }
149 valueTypeStack.push(ValueTypeI64)
150 case OpcodeF64Load:
151 if 1<<align > 64/8 {
152 return fmt.Errorf("invalid memory alignment")
153 }
154 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
155 return err
156 }
157 valueTypeStack.push(ValueTypeF64)
158 case OpcodeI64Store:
159 if 1<<align > 64/8 {
160 return fmt.Errorf("invalid memory alignment")
161 }
162 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
163 return err
164 }
165 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
166 return err
167 }
168 case OpcodeF64Store:
169 if 1<<align > 64/8 {
170 return fmt.Errorf("invalid memory alignment")
171 }
172 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
173 return err
174 }
175 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
176 return err
177 }
178 case OpcodeI32Load8S:
179 if 1<<align > 1 {
180 return fmt.Errorf("invalid memory alignment")
181 }
182 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
183 return err
184 }
185 valueTypeStack.push(ValueTypeI32)
186 case OpcodeI32Load8U:
187 if 1<<align > 1 {
188 return fmt.Errorf("invalid memory alignment")
189 }
190 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
191 return err
192 }
193 valueTypeStack.push(ValueTypeI32)
194 case OpcodeI64Load8S, OpcodeI64Load8U:
195 if 1<<align > 1 {
196 return fmt.Errorf("invalid memory alignment")
197 }
198 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
199 return err
200 }
201 valueTypeStack.push(ValueTypeI64)
202 case OpcodeI32Store8:
203 if 1<<align > 1 {
204 return fmt.Errorf("invalid memory alignment")
205 }
206 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
207 return err
208 }
209 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
210 return err
211 }
212 case OpcodeI64Store8:
213 if 1<<align > 1 {
214 return fmt.Errorf("invalid memory alignment")
215 }
216 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
217 return err
218 }
219 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
220 return err
221 }
222 case OpcodeI32Load16S, OpcodeI32Load16U:
223 if 1<<align > 16/8 {
224 return fmt.Errorf("invalid memory alignment")
225 }
226 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
227 return err
228 }
229 valueTypeStack.push(ValueTypeI32)
230 case OpcodeI64Load16S, OpcodeI64Load16U:
231 if 1<<align > 16/8 {
232 return fmt.Errorf("invalid memory alignment")
233 }
234 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
235 return err
236 }
237 valueTypeStack.push(ValueTypeI64)
238 case OpcodeI32Store16:
239 if 1<<align > 16/8 {
240 return fmt.Errorf("invalid memory alignment")
241 }
242 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
243 return err
244 }
245 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
246 return err
247 }
248 case OpcodeI64Store16:
249 if 1<<align > 16/8 {
250 return fmt.Errorf("invalid memory alignment")
251 }
252 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
253 return err
254 }
255 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
256 return err
257 }
258 case OpcodeI64Load32S, OpcodeI64Load32U:
259 if 1<<align > 32/8 {
260 return fmt.Errorf("invalid memory alignment")
261 }
262 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
263 return err
264 }
265 valueTypeStack.push(ValueTypeI64)
266 case OpcodeI64Store32:
267 if 1<<align > 32/8 {
268 return fmt.Errorf("invalid memory alignment")
269 }
270 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
271 return err
272 }
273 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
274 return err
275 }
276 }
277 } else if OpcodeMemorySize <= op && op <= OpcodeMemoryGrow {
278 if memory == nil {
279 return fmt.Errorf("memory must exist for %s", InstructionName(op))
280 }
281 pc++
282 val, num, err := leb128.LoadUint32(body[pc:])
283 if err != nil {
284 return fmt.Errorf("read immediate: %v", err)
285 }
286 if val != 0 || num != 1 {
287 return fmt.Errorf("memory instruction reserved bytes not zero with 1 byte")
288 }
289 switch Opcode(op) {
290 case OpcodeMemoryGrow:
291 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
292 return err
293 }
294 valueTypeStack.push(ValueTypeI32)
295 case OpcodeMemorySize:
296 valueTypeStack.push(ValueTypeI32)
297 }
298 pc += num - 1
299 } else if OpcodeI32Const <= op && op <= OpcodeF64Const {
300 pc++
301 switch Opcode(op) {
302 case OpcodeI32Const:
303 _, num, err := leb128.LoadInt32(body[pc:])
304 if err != nil {
305 return fmt.Errorf("read i32 immediate: %s", err)
306 }
307 pc += num - 1
308 valueTypeStack.push(ValueTypeI32)
309 case OpcodeI64Const:
310 _, num, err := leb128.LoadInt64(body[pc:])
311 if err != nil {
312 return fmt.Errorf("read i64 immediate: %v", err)
313 }
314 valueTypeStack.push(ValueTypeI64)
315 pc += num - 1
316 case OpcodeF32Const:
317 valueTypeStack.push(ValueTypeF32)
318 pc += 3
319 case OpcodeF64Const:
320 valueTypeStack.push(ValueTypeF64)
321 pc += 7
322 }
323 } else if OpcodeLocalGet <= op && op <= OpcodeGlobalSet {
324 pc++
325 index, num, err := leb128.LoadUint32(body[pc:])
326 if err != nil {
327 return fmt.Errorf("read immediate: %v", err)
328 }
329 pc += num - 1
330 switch op {
331 case OpcodeLocalGet:
332 inputLen := uint32(len(functionType.Params))
333 if l := uint32(len(localTypes)) + inputLen; index >= l {
334 return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
335 OpcodeLocalGetName, index, l)
336 }
337 if index < inputLen {
338 valueTypeStack.push(functionType.Params[index])
339 } else {
340 valueTypeStack.push(localTypes[index-inputLen])
341 }
342 case OpcodeLocalSet:
343 inputLen := uint32(len(functionType.Params))
344 if l := uint32(len(localTypes)) + inputLen; index >= l {
345 return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
346 OpcodeLocalSetName, index, l)
347 }
348 var expType ValueType
349 if index < inputLen {
350 expType = functionType.Params[index]
351 } else {
352 expType = localTypes[index-inputLen]
353 }
354 if err := valueTypeStack.popAndVerifyType(expType); err != nil {
355 return err
356 }
357 case OpcodeLocalTee:
358 inputLen := uint32(len(functionType.Params))
359 if l := uint32(len(localTypes)) + inputLen; index >= l {
360 return fmt.Errorf("invalid local index for %s %d >= %d(=len(locals)+len(parameters))",
361 OpcodeLocalTeeName, index, l)
362 }
363 var expType ValueType
364 if index < inputLen {
365 expType = functionType.Params[index]
366 } else {
367 expType = localTypes[index-inputLen]
368 }
369 if err := valueTypeStack.popAndVerifyType(expType); err != nil {
370 return err
371 }
372 valueTypeStack.push(expType)
373 case OpcodeGlobalGet:
374 if index >= uint32(len(globals)) {
375 return fmt.Errorf("invalid index for %s", OpcodeGlobalGetName)
376 }
377 valueTypeStack.push(globals[index].ValType)
378 case OpcodeGlobalSet:
379 if index >= uint32(len(globals)) {
380 return fmt.Errorf("invalid global index")
381 } else if !globals[index].Mutable {
382 return fmt.Errorf("%s when not mutable", OpcodeGlobalSetName)
383 } else if err := valueTypeStack.popAndVerifyType(
384 globals[index].ValType); err != nil {
385 return err
386 }
387 }
388 } else if op == OpcodeBr {
389 pc++
390 index, num, err := leb128.LoadUint32(body[pc:])
391 if err != nil {
392 return fmt.Errorf("read immediate: %v", err)
393 } else if int(index) >= len(controlBlockStack.stack) {
394 return fmt.Errorf("invalid %s operation: index out of range", OpcodeBrName)
395 }
396 pc += num - 1
397
398 target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
399 var targetResultType []ValueType
400 if target.op == OpcodeLoop {
401 targetResultType = target.blockType.Params
402 } else {
403 targetResultType = target.blockType.Results
404 }
405 if err = valueTypeStack.popResults(op, targetResultType, false); err != nil {
406 return err
407 }
408
409 valueTypeStack.unreachable()
410 } else if op == OpcodeBrIf {
411 pc++
412 index, num, err := leb128.LoadUint32(body[pc:])
413 if err != nil {
414 return fmt.Errorf("read immediate: %v", err)
415 } else if int(index) >= len(controlBlockStack.stack) {
416 return fmt.Errorf(
417 "invalid ln param given for %s: index=%d with %d for the current label stack length",
418 OpcodeBrIfName, index, len(controlBlockStack.stack))
419 }
420 pc += num - 1
421 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
422 return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrIfName)
423 }
424
425 target := &controlBlockStack.stack[len(controlBlockStack.stack)-int(index)-1]
426 var targetResultType []ValueType
427 if target.op == OpcodeLoop {
428 targetResultType = target.blockType.Params
429 } else {
430 targetResultType = target.blockType.Results
431 }
432 if err := valueTypeStack.popResults(op, targetResultType, false); err != nil {
433 return err
434 }
435
436 for _, t := range targetResultType {
437 valueTypeStack.push(t)
438 }
439 } else if op == OpcodeBrTable {
440 pc++
441 br.Reset(body[pc:])
442 nl, num, err := leb128.DecodeUint32(br)
443 if err != nil {
444 return fmt.Errorf("read immediate: %w", err)
445 }
446
447 list := make([]uint32, nl)
448 for i := uint32(0); i < nl; i++ {
449 l, n, err := leb128.DecodeUint32(br)
450 if err != nil {
451 return fmt.Errorf("read immediate: %w", err)
452 }
453 num += n
454 list[i] = l
455 }
456 ln, n, err := leb128.DecodeUint32(br)
457 if err != nil {
458 return fmt.Errorf("read immediate: %w", err)
459 } else if int(ln) >= len(controlBlockStack.stack) {
460 return fmt.Errorf(
461 "invalid ln param given for %s: ln=%d with %d for the current label stack length",
462 OpcodeBrTableName, ln, len(controlBlockStack.stack))
463 }
464 pc += n + num - 1
465
466 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
467 return fmt.Errorf("cannot pop the required operand for %s", OpcodeBrTableName)
468 }
469 lnLabel := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(ln)]
470 var defaultLabelType []ValueType
471
472
473
474
475 if lnLabel.op != OpcodeLoop {
476 defaultLabelType = make([]ValueType, len(lnLabel.blockType.Results))
477 copy(defaultLabelType, lnLabel.blockType.Results)
478 } else {
479 defaultLabelType = make([]ValueType, len(lnLabel.blockType.Params))
480 copy(defaultLabelType, lnLabel.blockType.Params)
481 }
482
483 if enabledFeatures.IsEnabled(api.CoreFeatureReferenceTypes) {
484
485
486
487 for i := range defaultLabelType {
488 index := len(defaultLabelType) - 1 - i
489 exp := defaultLabelType[index]
490 actual, err := valueTypeStack.pop()
491 if err != nil {
492 return err
493 }
494 if actual == valueTypeUnknown {
495
496 defaultLabelType[index] = valueTypeUnknown
497 } else if actual != exp {
498 return typeMismatchError(true, OpcodeBrTableName, actual, exp, i)
499 }
500 }
501 } else {
502 if err = valueTypeStack.popResults(op, defaultLabelType, false); err != nil {
503 return err
504 }
505 }
506
507 for _, l := range list {
508 if int(l) >= len(controlBlockStack.stack) {
509 return fmt.Errorf("invalid l param given for %s", OpcodeBrTableName)
510 }
511 label := &controlBlockStack.stack[len(controlBlockStack.stack)-1-int(l)]
512 var tableLabelType []ValueType
513 if label.op != OpcodeLoop {
514 tableLabelType = label.blockType.Results
515 } else {
516 tableLabelType = label.blockType.Params
517 }
518 if len(defaultLabelType) != len(tableLabelType) {
519 return fmt.Errorf("inconsistent block type length for %s at %d; %v (ln=%d) != %v (l=%d)", OpcodeBrTableName, l, defaultLabelType, ln, tableLabelType, l)
520 }
521 for i := range defaultLabelType {
522 if defaultLabelType[i] != valueTypeUnknown && defaultLabelType[i] != tableLabelType[i] {
523 return fmt.Errorf("incosistent block type for %s at %d", OpcodeBrTableName, l)
524 }
525 }
526 }
527
528
529 valueTypeStack.unreachable()
530 } else if op == OpcodeCall {
531 pc++
532 index, num, err := leb128.LoadUint32(body[pc:])
533 if err != nil {
534 return fmt.Errorf("read immediate: %v", err)
535 }
536 pc += num - 1
537 if int(index) >= len(functions) {
538 return fmt.Errorf("invalid function index")
539 }
540 funcType := &m.TypeSection[functions[index]]
541 for i := 0; i < len(funcType.Params); i++ {
542 if err := valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil {
543 return fmt.Errorf("type mismatch on %s operation param type: %v", OpcodeCallName, err)
544 }
545 }
546 for _, exp := range funcType.Results {
547 valueTypeStack.push(exp)
548 }
549 } else if op == OpcodeCallIndirect {
550 pc++
551 typeIndex, num, err := leb128.LoadUint32(body[pc:])
552 if err != nil {
553 return fmt.Errorf("read immediate: %v", err)
554 }
555 pc += num
556
557 if int(typeIndex) >= len(m.TypeSection) {
558 return fmt.Errorf("invalid type index at %s: %d", OpcodeCallIndirectName, typeIndex)
559 }
560
561 tableIndex, num, err := leb128.LoadUint32(body[pc:])
562 if err != nil {
563 return fmt.Errorf("read table index: %v", err)
564 }
565 pc += num - 1
566 if tableIndex != 0 {
567 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
568 return fmt.Errorf("table index must be zero but was %d: %w", tableIndex, err)
569 }
570 }
571
572 if tableIndex >= uint32(len(tables)) {
573 return fmt.Errorf("unknown table index: %d", tableIndex)
574 }
575
576 table := tables[tableIndex]
577 if table.Type != RefTypeFuncref {
578 return fmt.Errorf("table is not funcref type but was %s for %s", RefTypeName(table.Type), OpcodeCallIndirectName)
579 }
580
581 if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
582 return fmt.Errorf("cannot pop the offset in table for %s", OpcodeCallIndirectName)
583 }
584 funcType := &m.TypeSection[typeIndex]
585 for i := 0; i < len(funcType.Params); i++ {
586 if err = valueTypeStack.popAndVerifyType(funcType.Params[len(funcType.Params)-1-i]); err != nil {
587 return fmt.Errorf("type mismatch on %s operation input type", OpcodeCallIndirectName)
588 }
589 }
590 for _, exp := range funcType.Results {
591 valueTypeStack.push(exp)
592 }
593 } else if OpcodeI32Eqz <= op && op <= OpcodeI64Extend32S {
594 switch op {
595 case OpcodeI32Eqz:
596 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
597 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32EqzName, err)
598 }
599 valueTypeStack.push(ValueTypeI32)
600 case OpcodeI32Eq, OpcodeI32Ne, OpcodeI32LtS,
601 OpcodeI32LtU, OpcodeI32GtS, OpcodeI32GtU, OpcodeI32LeS,
602 OpcodeI32LeU, OpcodeI32GeS, OpcodeI32GeU:
603 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
604 return fmt.Errorf("cannot pop the 1st i32 operand for %s: %v", InstructionName(op), err)
605 }
606 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
607 return fmt.Errorf("cannot pop the 2nd i32 operand for %s: %v", InstructionName(op), err)
608 }
609 valueTypeStack.push(ValueTypeI32)
610 case OpcodeI64Eqz:
611 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
612 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64EqzName, err)
613 }
614 valueTypeStack.push(ValueTypeI32)
615 case OpcodeI64Eq, OpcodeI64Ne, OpcodeI64LtS,
616 OpcodeI64LtU, OpcodeI64GtS, OpcodeI64GtU,
617 OpcodeI64LeS, OpcodeI64LeU, OpcodeI64GeS, OpcodeI64GeU:
618 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
619 return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err)
620 }
621 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
622 return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err)
623 }
624 valueTypeStack.push(ValueTypeI32)
625 case OpcodeF32Eq, OpcodeF32Ne, OpcodeF32Lt, OpcodeF32Gt, OpcodeF32Le, OpcodeF32Ge:
626 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
627 return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
628 }
629 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
630 return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err)
631 }
632 valueTypeStack.push(ValueTypeI32)
633 case OpcodeF64Eq, OpcodeF64Ne, OpcodeF64Lt, OpcodeF64Gt, OpcodeF64Le, OpcodeF64Ge:
634 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
635 return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
636 }
637 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
638 return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err)
639 }
640 valueTypeStack.push(ValueTypeI32)
641 case OpcodeI32Clz, OpcodeI32Ctz, OpcodeI32Popcnt:
642 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
643 return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
644 }
645 valueTypeStack.push(ValueTypeI32)
646 case OpcodeI32Add, OpcodeI32Sub, OpcodeI32Mul, OpcodeI32DivS,
647 OpcodeI32DivU, OpcodeI32RemS, OpcodeI32RemU, OpcodeI32And,
648 OpcodeI32Or, OpcodeI32Xor, OpcodeI32Shl, OpcodeI32ShrS,
649 OpcodeI32ShrU, OpcodeI32Rotl, OpcodeI32Rotr:
650 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
651 return fmt.Errorf("cannot pop the 1st operand for %s: %v", InstructionName(op), err)
652 }
653 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
654 return fmt.Errorf("cannot pop the 2nd operand for %s: %v", InstructionName(op), err)
655 }
656 valueTypeStack.push(ValueTypeI32)
657 case OpcodeI64Clz, OpcodeI64Ctz, OpcodeI64Popcnt:
658 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
659 return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
660 }
661 valueTypeStack.push(ValueTypeI64)
662 case OpcodeI64Add, OpcodeI64Sub, OpcodeI64Mul, OpcodeI64DivS,
663 OpcodeI64DivU, OpcodeI64RemS, OpcodeI64RemU, OpcodeI64And,
664 OpcodeI64Or, OpcodeI64Xor, OpcodeI64Shl, OpcodeI64ShrS,
665 OpcodeI64ShrU, OpcodeI64Rotl, OpcodeI64Rotr:
666 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
667 return fmt.Errorf("cannot pop the 1st i64 operand for %s: %v", InstructionName(op), err)
668 }
669 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
670 return fmt.Errorf("cannot pop the 2nd i64 operand for %s: %v", InstructionName(op), err)
671 }
672 valueTypeStack.push(ValueTypeI64)
673 case OpcodeF32Abs, OpcodeF32Neg, OpcodeF32Ceil,
674 OpcodeF32Floor, OpcodeF32Trunc, OpcodeF32Nearest,
675 OpcodeF32Sqrt:
676 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
677 return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
678 }
679 valueTypeStack.push(ValueTypeF32)
680 case OpcodeF32Add, OpcodeF32Sub, OpcodeF32Mul,
681 OpcodeF32Div, OpcodeF32Min, OpcodeF32Max,
682 OpcodeF32Copysign:
683 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
684 return fmt.Errorf("cannot pop the 1st f32 operand for %s: %v", InstructionName(op), err)
685 }
686 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
687 return fmt.Errorf("cannot pop the 2nd f32 operand for %s: %v", InstructionName(op), err)
688 }
689 valueTypeStack.push(ValueTypeF32)
690 case OpcodeF64Abs, OpcodeF64Neg, OpcodeF64Ceil,
691 OpcodeF64Floor, OpcodeF64Trunc, OpcodeF64Nearest,
692 OpcodeF64Sqrt:
693 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
694 return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
695 }
696 valueTypeStack.push(ValueTypeF64)
697 case OpcodeF64Add, OpcodeF64Sub, OpcodeF64Mul,
698 OpcodeF64Div, OpcodeF64Min, OpcodeF64Max,
699 OpcodeF64Copysign:
700 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
701 return fmt.Errorf("cannot pop the 1st f64 operand for %s: %v", InstructionName(op), err)
702 }
703 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
704 return fmt.Errorf("cannot pop the 2nd f64 operand for %s: %v", InstructionName(op), err)
705 }
706 valueTypeStack.push(ValueTypeF64)
707 case OpcodeI32WrapI64:
708 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
709 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32WrapI64Name, err)
710 }
711 valueTypeStack.push(ValueTypeI32)
712 case OpcodeI32TruncF32S, OpcodeI32TruncF32U:
713 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
714 return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err)
715 }
716 valueTypeStack.push(ValueTypeI32)
717 case OpcodeI32TruncF64S, OpcodeI32TruncF64U:
718 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
719 return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err)
720 }
721 valueTypeStack.push(ValueTypeI32)
722 case OpcodeI64ExtendI32S, OpcodeI64ExtendI32U:
723 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
724 return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
725 }
726 valueTypeStack.push(ValueTypeI64)
727 case OpcodeI64TruncF32S, OpcodeI64TruncF32U:
728 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
729 return fmt.Errorf("cannot pop the f32 operand for %s: %v", InstructionName(op), err)
730 }
731 valueTypeStack.push(ValueTypeI64)
732 case OpcodeI64TruncF64S, OpcodeI64TruncF64U:
733 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
734 return fmt.Errorf("cannot pop the f64 operand for %s: %v", InstructionName(op), err)
735 }
736 valueTypeStack.push(ValueTypeI64)
737 case OpcodeF32ConvertI32S, OpcodeF32ConvertI32U:
738 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
739 return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
740 }
741 valueTypeStack.push(ValueTypeF32)
742 case OpcodeF32ConvertI64S, OpcodeF32ConvertI64U:
743 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
744 return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
745 }
746 valueTypeStack.push(ValueTypeF32)
747 case OpcodeF32DemoteF64:
748 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
749 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32DemoteF64Name, err)
750 }
751 valueTypeStack.push(ValueTypeF32)
752 case OpcodeF64ConvertI32S, OpcodeF64ConvertI32U:
753 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
754 return fmt.Errorf("cannot pop the i32 operand for %s: %v", InstructionName(op), err)
755 }
756 valueTypeStack.push(ValueTypeF64)
757 case OpcodeF64ConvertI64S, OpcodeF64ConvertI64U:
758 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
759 return fmt.Errorf("cannot pop the i64 operand for %s: %v", InstructionName(op), err)
760 }
761 valueTypeStack.push(ValueTypeF64)
762 case OpcodeF64PromoteF32:
763 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
764 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64PromoteF32Name, err)
765 }
766 valueTypeStack.push(ValueTypeF64)
767 case OpcodeI32ReinterpretF32:
768 if err := valueTypeStack.popAndVerifyType(ValueTypeF32); err != nil {
769 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI32ReinterpretF32Name, err)
770 }
771 valueTypeStack.push(ValueTypeI32)
772 case OpcodeI64ReinterpretF64:
773 if err := valueTypeStack.popAndVerifyType(ValueTypeF64); err != nil {
774 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeI64ReinterpretF64Name, err)
775 }
776 valueTypeStack.push(ValueTypeI64)
777 case OpcodeF32ReinterpretI32:
778 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
779 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF32ReinterpretI32Name, err)
780 }
781 valueTypeStack.push(ValueTypeF32)
782 case OpcodeF64ReinterpretI64:
783 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
784 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeF64ReinterpretI64Name, err)
785 }
786 valueTypeStack.push(ValueTypeF64)
787 case OpcodeI32Extend8S, OpcodeI32Extend16S:
788 if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil {
789 return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
790 }
791 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
792 return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err)
793 }
794 valueTypeStack.push(ValueTypeI32)
795 case OpcodeI64Extend8S, OpcodeI64Extend16S, OpcodeI64Extend32S:
796 if err := enabledFeatures.RequireEnabled(api.CoreFeatureSignExtensionOps); err != nil {
797 return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
798 }
799 if err := valueTypeStack.popAndVerifyType(ValueTypeI64); err != nil {
800 return fmt.Errorf("cannot pop the operand for %s: %v", instructionNames[op], err)
801 }
802 valueTypeStack.push(ValueTypeI64)
803 default:
804 return fmt.Errorf("invalid numeric instruction 0x%x", op)
805 }
806 } else if op >= OpcodeRefNull && op <= OpcodeRefFunc {
807 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
808 return fmt.Errorf("%s invalid as %v", instructionNames[op], err)
809 }
810 switch op {
811 case OpcodeRefNull:
812 pc++
813 switch reftype := body[pc]; reftype {
814 case ValueTypeExternref:
815 valueTypeStack.push(ValueTypeExternref)
816 case ValueTypeFuncref:
817 valueTypeStack.push(ValueTypeFuncref)
818 default:
819 return fmt.Errorf("unknown type for ref.null: 0x%x", reftype)
820 }
821 case OpcodeRefIsNull:
822 tp, err := valueTypeStack.pop()
823 if err != nil {
824 return fmt.Errorf("cannot pop the operand for ref.is_null: %v", err)
825 } else if !isReferenceValueType(tp) && tp != valueTypeUnknown {
826 return fmt.Errorf("type mismatch: expected reference type but was %s", ValueTypeName(tp))
827 }
828 valueTypeStack.push(ValueTypeI32)
829 case OpcodeRefFunc:
830 pc++
831 index, num, err := leb128.LoadUint32(body[pc:])
832 if err != nil {
833 return fmt.Errorf("failed to read function index for ref.func: %v", err)
834 }
835 if _, ok := declaredFunctionIndexes[index]; !ok {
836 return fmt.Errorf("undeclared function index %d for ref.func", index)
837 }
838 pc += num - 1
839 valueTypeStack.push(ValueTypeFuncref)
840 }
841 } else if op == OpcodeTableGet || op == OpcodeTableSet {
842 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
843 return fmt.Errorf("%s is invalid as %v", InstructionName(op), err)
844 }
845 pc++
846 tableIndex, num, err := leb128.LoadUint32(body[pc:])
847 if err != nil {
848 return fmt.Errorf("read immediate: %v", err)
849 }
850 if tableIndex >= uint32(len(tables)) {
851 return fmt.Errorf("table of index %d not found", tableIndex)
852 }
853
854 refType := tables[tableIndex].Type
855 if op == OpcodeTableGet {
856 if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil {
857 return fmt.Errorf("cannot pop the operand for table.get: %v", err)
858 }
859 valueTypeStack.push(refType)
860 } else {
861 if err := valueTypeStack.popAndVerifyType(refType); err != nil {
862 return fmt.Errorf("cannot pop the operand for table.set: %v", err)
863 }
864 if err := valueTypeStack.popAndVerifyType(api.ValueTypeI32); err != nil {
865 return fmt.Errorf("cannot pop the operand for table.set: %v", err)
866 }
867 }
868 pc += num - 1
869 } else if op == OpcodeMiscPrefix {
870 pc++
871
872 miscOp32, num, err := leb128.LoadUint32(body[pc:])
873 if err != nil {
874 return fmt.Errorf("failed to read misc opcode: %v", err)
875 }
876 pc += num - 1
877 miscOpcode := byte(miscOp32)
878
879
880
881 if uint32(byte(miscOp32)) != miscOp32 {
882 return fmt.Errorf("invalid misc opcode: %#x", miscOp32)
883 }
884 if miscOpcode >= OpcodeMiscI32TruncSatF32S && miscOpcode <= OpcodeMiscI64TruncSatF64U {
885 if err := enabledFeatures.RequireEnabled(api.CoreFeatureNonTrappingFloatToIntConversion); err != nil {
886 return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
887 }
888 var inType, outType ValueType
889 switch miscOpcode {
890 case OpcodeMiscI32TruncSatF32S, OpcodeMiscI32TruncSatF32U:
891 inType, outType = ValueTypeF32, ValueTypeI32
892 case OpcodeMiscI32TruncSatF64S, OpcodeMiscI32TruncSatF64U:
893 inType, outType = ValueTypeF64, ValueTypeI32
894 case OpcodeMiscI64TruncSatF32S, OpcodeMiscI64TruncSatF32U:
895 inType, outType = ValueTypeF32, ValueTypeI64
896 case OpcodeMiscI64TruncSatF64S, OpcodeMiscI64TruncSatF64U:
897 inType, outType = ValueTypeF64, ValueTypeI64
898 }
899 if err := valueTypeStack.popAndVerifyType(inType); err != nil {
900 return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
901 }
902 valueTypeStack.push(outType)
903 } else if miscOpcode >= OpcodeMiscMemoryInit && miscOpcode <= OpcodeMiscTableCopy {
904 if err := enabledFeatures.RequireEnabled(api.CoreFeatureBulkMemoryOperations); err != nil {
905 return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
906 }
907 var params []ValueType
908
909 switch miscOpcode {
910 case OpcodeMiscDataDrop:
911 if m.DataCountSection == nil {
912 return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
913 }
914
915
916 pc++
917 index, num, err := leb128.LoadUint32(body[pc:])
918 if err != nil {
919 return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
920 }
921 if int(index) >= len(m.DataSection) {
922 return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
923 }
924 pc += num - 1
925 case OpcodeMiscMemoryInit, OpcodeMiscMemoryCopy, OpcodeMiscMemoryFill:
926 if memory == nil {
927 return fmt.Errorf("memory must exist for %s", MiscInstructionName(miscOpcode))
928 }
929 params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
930
931 if miscOpcode == OpcodeMiscMemoryInit {
932 if m.DataCountSection == nil {
933 return fmt.Errorf("%s requires data count section", MiscInstructionName(miscOpcode))
934 }
935
936
937 pc++
938 index, num, err := leb128.LoadUint32(body[pc:])
939 if err != nil {
940 return fmt.Errorf("failed to read data segment index for %s: %v", MiscInstructionName(miscOpcode), err)
941 }
942 if int(index) >= len(m.DataSection) {
943 return fmt.Errorf("index %d out of range of data section(len=%d)", index, len(m.DataSection))
944 }
945 pc += num - 1
946 }
947
948 pc++
949 val, num, err := leb128.LoadUint32(body[pc:])
950 if err != nil {
951 return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err)
952 }
953 if val != 0 || num != 1 {
954 return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode))
955 }
956 if miscOpcode == OpcodeMiscMemoryCopy {
957 pc++
958
959 val, num, err := leb128.LoadUint32(body[pc:])
960 if err != nil {
961 return fmt.Errorf("failed to read memory index for %s: %v", MiscInstructionName(miscOpcode), err)
962 }
963 if val != 0 || num != 1 {
964 return fmt.Errorf("%s reserved byte must be zero encoded with 1 byte", MiscInstructionName(miscOpcode))
965 }
966 }
967
968 case OpcodeMiscTableInit:
969 params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
970 pc++
971 elementIndex, num, err := leb128.LoadUint32(body[pc:])
972 if err != nil {
973 return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
974 }
975 if int(elementIndex) >= len(m.ElementSection) {
976 return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
977 }
978 pc += num
979
980 tableIndex, num, err := leb128.LoadUint32(body[pc:])
981 if err != nil {
982 return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
983 }
984 if tableIndex != 0 {
985 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
986 return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
987 }
988 }
989 if tableIndex >= uint32(len(tables)) {
990 return fmt.Errorf("table of index %d not found", tableIndex)
991 }
992
993 if m.ElementSection[elementIndex].Type != tables[tableIndex].Type {
994 return fmt.Errorf("type mismatch for table.init: element type %s does not match table type %s",
995 RefTypeName(m.ElementSection[elementIndex].Type),
996 RefTypeName(tables[tableIndex].Type),
997 )
998 }
999 pc += num - 1
1000 case OpcodeMiscElemDrop:
1001 pc++
1002 elementIndex, num, err := leb128.LoadUint32(body[pc:])
1003 if err != nil {
1004 return fmt.Errorf("failed to read element segment index for %s: %v", MiscInstructionName(miscOpcode), err)
1005 } else if int(elementIndex) >= len(m.ElementSection) {
1006 return fmt.Errorf("index %d out of range of element section(len=%d)", elementIndex, len(m.ElementSection))
1007 }
1008 pc += num - 1
1009 case OpcodeMiscTableCopy:
1010 params = []ValueType{ValueTypeI32, ValueTypeI32, ValueTypeI32}
1011 pc++
1012
1013 dstTableIndex, num, err := leb128.LoadUint32(body[pc:])
1014 if err != nil {
1015 return fmt.Errorf("failed to read destination table index for %s: %v", MiscInstructionName(miscOpcode), err)
1016 }
1017 if dstTableIndex != 0 {
1018 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1019 return fmt.Errorf("destination table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
1020 }
1021 }
1022 if dstTableIndex >= uint32(len(tables)) {
1023 return fmt.Errorf("table of index %d not found", dstTableIndex)
1024 }
1025 pc += num
1026
1027 srcTableIndex, num, err := leb128.LoadUint32(body[pc:])
1028 if err != nil {
1029 return fmt.Errorf("failed to read source table index for %s: %v", MiscInstructionName(miscOpcode), err)
1030 }
1031 if srcTableIndex != 0 {
1032 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1033 return fmt.Errorf("source table index must be zero for %s as %v", MiscInstructionName(miscOpcode), err)
1034 }
1035 }
1036 if srcTableIndex >= uint32(len(tables)) {
1037 return fmt.Errorf("table of index %d not found", srcTableIndex)
1038 }
1039
1040 if tables[srcTableIndex].Type != tables[dstTableIndex].Type {
1041 return fmt.Errorf("table type mismatch for table.copy: %s (src) != %s (dst)",
1042 RefTypeName(tables[srcTableIndex].Type), RefTypeName(tables[dstTableIndex].Type))
1043 }
1044
1045 pc += num - 1
1046 }
1047 for _, p := range params {
1048 if err := valueTypeStack.popAndVerifyType(p); err != nil {
1049 return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
1050 }
1051 }
1052 } else if miscOpcode >= OpcodeMiscTableGrow && miscOpcode <= OpcodeMiscTableFill {
1053 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1054 return fmt.Errorf("%s invalid as %v", miscInstructionNames[miscOpcode], err)
1055 }
1056
1057 pc++
1058 tableIndex, num, err := leb128.LoadUint32(body[pc:])
1059 if err != nil {
1060 return fmt.Errorf("failed to read table index for %s: %v", MiscInstructionName(miscOpcode), err)
1061 }
1062 if tableIndex >= uint32(len(tables)) {
1063 return fmt.Errorf("table of index %d not found", tableIndex)
1064 }
1065 pc += num - 1
1066
1067 var params, results []ValueType
1068 reftype := tables[tableIndex].Type
1069 if miscOpcode == OpcodeMiscTableGrow {
1070 params = []ValueType{ValueTypeI32, reftype}
1071 results = []ValueType{ValueTypeI32}
1072 } else if miscOpcode == OpcodeMiscTableSize {
1073 results = []ValueType{ValueTypeI32}
1074 } else if miscOpcode == OpcodeMiscTableFill {
1075 params = []ValueType{ValueTypeI32, reftype, ValueTypeI32}
1076 }
1077
1078 for _, p := range params {
1079 if err := valueTypeStack.popAndVerifyType(p); err != nil {
1080 return fmt.Errorf("cannot pop the operand for %s: %v", miscInstructionNames[miscOpcode], err)
1081 }
1082 }
1083 for _, r := range results {
1084 valueTypeStack.push(r)
1085 }
1086 }
1087 } else if op == OpcodeVecPrefix {
1088 pc++
1089
1090
1091 vecOpcode := body[pc]
1092 if err := enabledFeatures.RequireEnabled(api.CoreFeatureSIMD); err != nil {
1093 return fmt.Errorf("%s invalid as %v", vectorInstructionName[vecOpcode], err)
1094 }
1095
1096 switch vecOpcode {
1097 case OpcodeVecV128Const:
1098
1099 if int(pc+16) >= len(body) {
1100 return fmt.Errorf("cannot read constant vector value for %s", vectorInstructionName[vecOpcode])
1101 }
1102 pc += 16
1103 valueTypeStack.push(ValueTypeV128)
1104 case OpcodeVecV128AnyTrue, OpcodeVecI8x16AllTrue, OpcodeVecI16x8AllTrue, OpcodeVecI32x4AllTrue, OpcodeVecI64x2AllTrue,
1105 OpcodeVecI8x16BitMask, OpcodeVecI16x8BitMask, OpcodeVecI32x4BitMask, OpcodeVecI64x2BitMask:
1106 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1107 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1108 }
1109 valueTypeStack.push(ValueTypeI32)
1110 case OpcodeVecV128Load, OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
1111 OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u, OpcodeVecV128Load8Splat, OpcodeVecV128Load16Splat,
1112 OpcodeVecV128Load32Splat, OpcodeVecV128Load64Splat,
1113 OpcodeVecV128Load32zero, OpcodeVecV128Load64zero:
1114 if memory == nil {
1115 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1116 }
1117 pc++
1118 align, _, read, err := readMemArg(pc, body)
1119 if err != nil {
1120 return err
1121 }
1122 pc += read - 1
1123 var maxAlign uint32
1124 switch vecOpcode {
1125 case OpcodeVecV128Load:
1126 maxAlign = 128 / 8
1127 case OpcodeVecV128Load8x8s, OpcodeVecV128Load8x8u, OpcodeVecV128Load16x4s, OpcodeVecV128Load16x4u,
1128 OpcodeVecV128Load32x2s, OpcodeVecV128Load32x2u:
1129 maxAlign = 64 / 8
1130 case OpcodeVecV128Load8Splat:
1131 maxAlign = 1
1132 case OpcodeVecV128Load16Splat:
1133 maxAlign = 16 / 8
1134 case OpcodeVecV128Load32Splat:
1135 maxAlign = 32 / 8
1136 case OpcodeVecV128Load64Splat:
1137 maxAlign = 64 / 8
1138 case OpcodeVecV128Load32zero:
1139 maxAlign = 32 / 8
1140 case OpcodeVecV128Load64zero:
1141 maxAlign = 64 / 8
1142 }
1143
1144 if 1<<align > maxAlign {
1145 return fmt.Errorf("invalid memory alignment %d for %s", align, VectorInstructionName(vecOpcode))
1146 }
1147 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1148 return fmt.Errorf("cannot pop the operand for %s: %v", VectorInstructionName(vecOpcode), err)
1149 }
1150 valueTypeStack.push(ValueTypeV128)
1151 case OpcodeVecV128Store:
1152 if memory == nil {
1153 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1154 }
1155 pc++
1156 align, _, read, err := readMemArg(pc, body)
1157 if err != nil {
1158 return err
1159 }
1160 pc += read - 1
1161 if 1<<align > 128/8 {
1162 return fmt.Errorf("invalid memory alignment %d for %s", align, OpcodeVecV128StoreName)
1163 }
1164 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1165 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
1166 }
1167 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1168 return fmt.Errorf("cannot pop the operand for %s: %v", OpcodeVecV128StoreName, err)
1169 }
1170 case OpcodeVecV128Load8Lane, OpcodeVecV128Load16Lane, OpcodeVecV128Load32Lane, OpcodeVecV128Load64Lane:
1171 if memory == nil {
1172 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1173 }
1174 attr := vecLoadLanes[vecOpcode]
1175 pc++
1176 align, _, read, err := readMemArg(pc, body)
1177 if err != nil {
1178 return err
1179 }
1180 if 1<<align > attr.alignMax {
1181 return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
1182 }
1183 pc += read
1184 if pc >= uint64(len(body)) {
1185 return fmt.Errorf("lane for %s not found", OpcodeVecV128Load64LaneName)
1186 }
1187 lane := body[pc]
1188 if lane >= attr.laneCeil {
1189 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1190 }
1191 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1192 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1193 }
1194 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1195 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1196 }
1197 valueTypeStack.push(ValueTypeV128)
1198 case OpcodeVecV128Store8Lane, OpcodeVecV128Store16Lane, OpcodeVecV128Store32Lane, OpcodeVecV128Store64Lane:
1199 if memory == nil {
1200 return fmt.Errorf("memory must exist for %s", VectorInstructionName(vecOpcode))
1201 }
1202 attr := vecStoreLanes[vecOpcode]
1203 pc++
1204 align, _, read, err := readMemArg(pc, body)
1205 if err != nil {
1206 return err
1207 }
1208 if 1<<align > attr.alignMax {
1209 return fmt.Errorf("invalid memory alignment %d for %s", align, vectorInstructionName[vecOpcode])
1210 }
1211 pc += read
1212 if pc >= uint64(len(body)) {
1213 return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
1214 }
1215 lane := body[pc]
1216 if lane >= attr.laneCeil {
1217 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1218 }
1219 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1220 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1221 }
1222 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1223 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1224 }
1225 case OpcodeVecI8x16ExtractLaneS,
1226 OpcodeVecI8x16ExtractLaneU,
1227 OpcodeVecI16x8ExtractLaneS,
1228 OpcodeVecI16x8ExtractLaneU,
1229 OpcodeVecI32x4ExtractLane,
1230 OpcodeVecI64x2ExtractLane,
1231 OpcodeVecF32x4ExtractLane,
1232 OpcodeVecF64x2ExtractLane:
1233 pc++
1234 if pc >= uint64(len(body)) {
1235 return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
1236 }
1237 attr := vecExtractLanes[vecOpcode]
1238 lane := body[pc]
1239 if lane >= attr.laneCeil {
1240 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1241 }
1242 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1243 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1244 }
1245 valueTypeStack.push(attr.resultType)
1246 case OpcodeVecI8x16ReplaceLane, OpcodeVecI16x8ReplaceLane, OpcodeVecI32x4ReplaceLane,
1247 OpcodeVecI64x2ReplaceLane, OpcodeVecF32x4ReplaceLane, OpcodeVecF64x2ReplaceLane:
1248 pc++
1249 if pc >= uint64(len(body)) {
1250 return fmt.Errorf("lane for %s not found", vectorInstructionName[vecOpcode])
1251 }
1252 attr := vecReplaceLanes[vecOpcode]
1253 lane := body[pc]
1254 if lane >= attr.laneCeil {
1255 return fmt.Errorf("invalid lane index %d >= %d for %s", lane, attr.laneCeil, vectorInstructionName[vecOpcode])
1256 }
1257 if err := valueTypeStack.popAndVerifyType(attr.paramType); err != nil {
1258 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1259 }
1260 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1261 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1262 }
1263 valueTypeStack.push(ValueTypeV128)
1264 case OpcodeVecI8x16Splat, OpcodeVecI16x8Splat, OpcodeVecI32x4Splat,
1265 OpcodeVecI64x2Splat, OpcodeVecF32x4Splat, OpcodeVecF64x2Splat:
1266 tp := vecSplatValueTypes[vecOpcode]
1267 if err := valueTypeStack.popAndVerifyType(tp); err != nil {
1268 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1269 }
1270 valueTypeStack.push(ValueTypeV128)
1271 case OpcodeVecI8x16Swizzle, OpcodeVecV128And, OpcodeVecV128Or, OpcodeVecV128Xor, OpcodeVecV128AndNot:
1272 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1273 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1274 }
1275 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1276 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1277 }
1278 valueTypeStack.push(ValueTypeV128)
1279 case OpcodeVecV128Bitselect:
1280 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1281 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1282 }
1283 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1284 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1285 }
1286 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1287 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1288 }
1289 valueTypeStack.push(ValueTypeV128)
1290 case OpcodeVecV128Not:
1291 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1292 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1293 }
1294 valueTypeStack.push(ValueTypeV128)
1295 case OpcodeVecV128i8x16Shuffle:
1296 pc++
1297 if pc+15 >= uint64(len(body)) {
1298 return fmt.Errorf("16 lane indexes for %s not found", vectorInstructionName[vecOpcode])
1299 }
1300 lanes := body[pc : pc+16]
1301 for i, l := range lanes {
1302 if l >= 32 {
1303 return fmt.Errorf("invalid lane index[%d] %d >= %d for %s", i, l, 32, vectorInstructionName[vecOpcode])
1304 }
1305 }
1306 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1307 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1308 }
1309 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1310 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1311 }
1312 valueTypeStack.push(ValueTypeV128)
1313 pc += 15
1314 case OpcodeVecI8x16Shl, OpcodeVecI8x16ShrS, OpcodeVecI8x16ShrU,
1315 OpcodeVecI16x8Shl, OpcodeVecI16x8ShrS, OpcodeVecI16x8ShrU,
1316 OpcodeVecI32x4Shl, OpcodeVecI32x4ShrS, OpcodeVecI32x4ShrU,
1317 OpcodeVecI64x2Shl, OpcodeVecI64x2ShrS, OpcodeVecI64x2ShrU:
1318 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1319 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1320 }
1321 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1322 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1323 }
1324 valueTypeStack.push(ValueTypeV128)
1325 case OpcodeVecI8x16Eq, OpcodeVecI8x16Ne, OpcodeVecI8x16LtS, OpcodeVecI8x16LtU, OpcodeVecI8x16GtS,
1326 OpcodeVecI8x16GtU, OpcodeVecI8x16LeS, OpcodeVecI8x16LeU, OpcodeVecI8x16GeS, OpcodeVecI8x16GeU,
1327 OpcodeVecI16x8Eq, OpcodeVecI16x8Ne, OpcodeVecI16x8LtS, OpcodeVecI16x8LtU, OpcodeVecI16x8GtS,
1328 OpcodeVecI16x8GtU, OpcodeVecI16x8LeS, OpcodeVecI16x8LeU, OpcodeVecI16x8GeS, OpcodeVecI16x8GeU,
1329 OpcodeVecI32x4Eq, OpcodeVecI32x4Ne, OpcodeVecI32x4LtS, OpcodeVecI32x4LtU, OpcodeVecI32x4GtS,
1330 OpcodeVecI32x4GtU, OpcodeVecI32x4LeS, OpcodeVecI32x4LeU, OpcodeVecI32x4GeS, OpcodeVecI32x4GeU,
1331 OpcodeVecI64x2Eq, OpcodeVecI64x2Ne, OpcodeVecI64x2LtS, OpcodeVecI64x2GtS, OpcodeVecI64x2LeS,
1332 OpcodeVecI64x2GeS, OpcodeVecF32x4Eq, OpcodeVecF32x4Ne, OpcodeVecF32x4Lt, OpcodeVecF32x4Gt,
1333 OpcodeVecF32x4Le, OpcodeVecF32x4Ge, OpcodeVecF64x2Eq, OpcodeVecF64x2Ne, OpcodeVecF64x2Lt,
1334 OpcodeVecF64x2Gt, OpcodeVecF64x2Le, OpcodeVecF64x2Ge,
1335 OpcodeVecI32x4DotI16x8S,
1336 OpcodeVecI8x16NarrowI16x8S, OpcodeVecI8x16NarrowI16x8U, OpcodeVecI16x8NarrowI32x4S, OpcodeVecI16x8NarrowI32x4U:
1337 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1338 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1339 }
1340 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1341 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1342 }
1343 valueTypeStack.push(ValueTypeV128)
1344 case OpcodeVecI8x16Neg, OpcodeVecI16x8Neg, OpcodeVecI32x4Neg, OpcodeVecI64x2Neg, OpcodeVecF32x4Neg, OpcodeVecF64x2Neg,
1345 OpcodeVecF32x4Sqrt, OpcodeVecF64x2Sqrt,
1346 OpcodeVecI8x16Abs, OpcodeVecI8x16Popcnt, OpcodeVecI16x8Abs, OpcodeVecI32x4Abs, OpcodeVecI64x2Abs,
1347 OpcodeVecF32x4Abs, OpcodeVecF64x2Abs,
1348 OpcodeVecF32x4Ceil, OpcodeVecF32x4Floor, OpcodeVecF32x4Trunc, OpcodeVecF32x4Nearest,
1349 OpcodeVecF64x2Ceil, OpcodeVecF64x2Floor, OpcodeVecF64x2Trunc, OpcodeVecF64x2Nearest,
1350 OpcodeVecI16x8ExtendLowI8x16S, OpcodeVecI16x8ExtendHighI8x16S, OpcodeVecI16x8ExtendLowI8x16U, OpcodeVecI16x8ExtendHighI8x16U,
1351 OpcodeVecI32x4ExtendLowI16x8S, OpcodeVecI32x4ExtendHighI16x8S, OpcodeVecI32x4ExtendLowI16x8U, OpcodeVecI32x4ExtendHighI16x8U,
1352 OpcodeVecI64x2ExtendLowI32x4S, OpcodeVecI64x2ExtendHighI32x4S, OpcodeVecI64x2ExtendLowI32x4U, OpcodeVecI64x2ExtendHighI32x4U,
1353 OpcodeVecI16x8ExtaddPairwiseI8x16S, OpcodeVecI16x8ExtaddPairwiseI8x16U,
1354 OpcodeVecI32x4ExtaddPairwiseI16x8S, OpcodeVecI32x4ExtaddPairwiseI16x8U,
1355 OpcodeVecF64x2PromoteLowF32x4Zero, OpcodeVecF32x4DemoteF64x2Zero,
1356 OpcodeVecF32x4ConvertI32x4S, OpcodeVecF32x4ConvertI32x4U,
1357 OpcodeVecF64x2ConvertLowI32x4S, OpcodeVecF64x2ConvertLowI32x4U,
1358 OpcodeVecI32x4TruncSatF32x4S, OpcodeVecI32x4TruncSatF32x4U, OpcodeVecI32x4TruncSatF64x2SZero, OpcodeVecI32x4TruncSatF64x2UZero:
1359 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1360 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1361 }
1362 valueTypeStack.push(ValueTypeV128)
1363
1364 case OpcodeVecI8x16Add, OpcodeVecI8x16AddSatS, OpcodeVecI8x16AddSatU, OpcodeVecI8x16Sub, OpcodeVecI8x16SubSatS, OpcodeVecI8x16SubSatU,
1365 OpcodeVecI16x8Add, OpcodeVecI16x8AddSatS, OpcodeVecI16x8AddSatU, OpcodeVecI16x8Sub, OpcodeVecI16x8SubSatS, OpcodeVecI16x8SubSatU, OpcodeVecI16x8Mul,
1366 OpcodeVecI32x4Add, OpcodeVecI32x4Sub, OpcodeVecI32x4Mul,
1367 OpcodeVecI64x2Add, OpcodeVecI64x2Sub, OpcodeVecI64x2Mul,
1368 OpcodeVecF32x4Add, OpcodeVecF32x4Sub, OpcodeVecF32x4Mul, OpcodeVecF32x4Div,
1369 OpcodeVecF64x2Add, OpcodeVecF64x2Sub, OpcodeVecF64x2Mul, OpcodeVecF64x2Div,
1370 OpcodeVecI8x16MinS, OpcodeVecI8x16MinU, OpcodeVecI8x16MaxS, OpcodeVecI8x16MaxU,
1371 OpcodeVecI8x16AvgrU,
1372 OpcodeVecI16x8MinS, OpcodeVecI16x8MinU, OpcodeVecI16x8MaxS, OpcodeVecI16x8MaxU,
1373 OpcodeVecI16x8AvgrU,
1374 OpcodeVecI32x4MinS, OpcodeVecI32x4MinU, OpcodeVecI32x4MaxS, OpcodeVecI32x4MaxU,
1375 OpcodeVecF32x4Min, OpcodeVecF32x4Max, OpcodeVecF64x2Min, OpcodeVecF64x2Max,
1376 OpcodeVecF32x4Pmin, OpcodeVecF32x4Pmax, OpcodeVecF64x2Pmin, OpcodeVecF64x2Pmax,
1377 OpcodeVecI16x8Q15mulrSatS,
1378 OpcodeVecI16x8ExtMulLowI8x16S, OpcodeVecI16x8ExtMulHighI8x16S, OpcodeVecI16x8ExtMulLowI8x16U, OpcodeVecI16x8ExtMulHighI8x16U,
1379 OpcodeVecI32x4ExtMulLowI16x8S, OpcodeVecI32x4ExtMulHighI16x8S, OpcodeVecI32x4ExtMulLowI16x8U, OpcodeVecI32x4ExtMulHighI16x8U,
1380 OpcodeVecI64x2ExtMulLowI32x4S, OpcodeVecI64x2ExtMulHighI32x4S, OpcodeVecI64x2ExtMulLowI32x4U, OpcodeVecI64x2ExtMulHighI32x4U:
1381 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1382 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1383 }
1384 if err := valueTypeStack.popAndVerifyType(ValueTypeV128); err != nil {
1385 return fmt.Errorf("cannot pop the operand for %s: %v", vectorInstructionName[vecOpcode], err)
1386 }
1387 valueTypeStack.push(ValueTypeV128)
1388 default:
1389 return fmt.Errorf("TODO: SIMD instruction %s will be implemented in #506", vectorInstructionName[vecOpcode])
1390 }
1391 } else if op == OpcodeBlock {
1392 br.Reset(body[pc+1:])
1393 bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
1394 if err != nil {
1395 return fmt.Errorf("read block: %w", err)
1396 }
1397 controlBlockStack.push(pc, 0, 0, bt, num, 0)
1398 if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
1399 return err
1400 }
1401
1402 for _, p := range bt.Params {
1403 valueTypeStack.push(p)
1404 }
1405 valueTypeStack.pushStackLimit(len(bt.Params))
1406 pc += num
1407 } else if op == OpcodeLoop {
1408 br.Reset(body[pc+1:])
1409 bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
1410 if err != nil {
1411 return fmt.Errorf("read block: %w", err)
1412 }
1413 controlBlockStack.push(pc, 0, 0, bt, num, op)
1414 if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
1415 return err
1416 }
1417
1418 for _, p := range bt.Params {
1419 valueTypeStack.push(p)
1420 }
1421 valueTypeStack.pushStackLimit(len(bt.Params))
1422 pc += num
1423 } else if op == OpcodeIf {
1424 br.Reset(body[pc+1:])
1425 bt, num, err := DecodeBlockType(m.TypeSection, br, enabledFeatures)
1426 if err != nil {
1427 return fmt.Errorf("read block: %w", err)
1428 }
1429 controlBlockStack.push(pc, 0, 0, bt, num, op)
1430 if err = valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1431 return fmt.Errorf("cannot pop the operand for 'if': %v", err)
1432 }
1433 if err = valueTypeStack.popParams(op, bt.Params, false); err != nil {
1434 return err
1435 }
1436
1437 for _, p := range bt.Params {
1438 valueTypeStack.push(p)
1439 }
1440 valueTypeStack.pushStackLimit(len(bt.Params))
1441 pc += num
1442 } else if op == OpcodeElse {
1443 if len(controlBlockStack.stack) == 0 {
1444 return fmt.Errorf("redundant Else instruction at %#x", pc)
1445 }
1446 bl := &controlBlockStack.stack[len(controlBlockStack.stack)-1]
1447 bl.elseAt = pc
1448
1449 if err := valueTypeStack.popResults(OpcodeIf, bl.blockType.Results, true); err != nil {
1450 return err
1451 }
1452
1453 valueTypeStack.resetAtStackLimit()
1454
1455 for _, p := range bl.blockType.Params {
1456 valueTypeStack.push(p)
1457 }
1458 } else if op == OpcodeEnd {
1459 if len(controlBlockStack.stack) == 0 {
1460 return fmt.Errorf("redundant End instruction at %#x", pc)
1461 }
1462 bl := controlBlockStack.pop()
1463 bl.endAt = pc
1464
1465
1466
1467 ifMissingElse := bl.op == OpcodeIf && bl.elseAt <= bl.startAt
1468 if ifMissingElse {
1469
1470
1471 if !bytes.Equal(bl.blockType.Results, bl.blockType.Params) {
1472 return typeCountError(false, OpcodeElseName, bl.blockType.Params, bl.blockType.Results)
1473 }
1474
1475 bl.elseAt = bl.endAt - 1
1476 }
1477
1478
1479 ctx := ""
1480 if bl.op == OpcodeIf && !ifMissingElse && bl.elseAt > 0 {
1481 ctx = OpcodeElseName
1482 } else if bl.op != 0 {
1483 ctx = InstructionName(bl.op)
1484 }
1485
1486
1487 if err := valueTypeStack.requireStackValues(false, ctx, bl.blockType.Results, true); err != nil {
1488 return err
1489 }
1490
1491
1492
1493 valueTypeStack.resetAtStackLimit()
1494 for _, exp := range bl.blockType.Results {
1495 valueTypeStack.push(exp)
1496 }
1497
1498
1499 valueTypeStack.popStackLimit()
1500 } else if op == OpcodeReturn {
1501
1502 if err := valueTypeStack.requireStackValues(false, "", functionType.Results, false); err != nil {
1503 return err
1504 }
1505
1506 valueTypeStack.unreachable()
1507 } else if op == OpcodeDrop {
1508 _, err := valueTypeStack.pop()
1509 if err != nil {
1510 return fmt.Errorf("invalid drop: %v", err)
1511 }
1512 } else if op == OpcodeSelect || op == OpcodeTypedSelect {
1513 if err := valueTypeStack.popAndVerifyType(ValueTypeI32); err != nil {
1514 return fmt.Errorf("type mismatch on 3rd select operand: %v", err)
1515 }
1516 v1, err := valueTypeStack.pop()
1517 if err != nil {
1518 return fmt.Errorf("invalid select: %v", err)
1519 }
1520 v2, err := valueTypeStack.pop()
1521 if err != nil {
1522 return fmt.Errorf("invalid select: %v", err)
1523 }
1524
1525 if op == OpcodeTypedSelect {
1526 if err := enabledFeatures.RequireEnabled(api.CoreFeatureReferenceTypes); err != nil {
1527 return fmt.Errorf("%s is invalid as %w", InstructionName(op), err)
1528 }
1529 pc++
1530 if numTypeImmeidates := body[pc]; numTypeImmeidates != 1 {
1531 return fmt.Errorf("too many type immediates for %s", InstructionName(op))
1532 }
1533 pc++
1534 tp := body[pc]
1535 if tp != ValueTypeI32 && tp != ValueTypeI64 && tp != ValueTypeF32 && tp != ValueTypeF64 &&
1536 tp != api.ValueTypeExternref && tp != ValueTypeFuncref && tp != ValueTypeV128 {
1537 return fmt.Errorf("invalid type %s for %s", ValueTypeName(tp), OpcodeTypedSelectName)
1538 }
1539 } else if isReferenceValueType(v1) || isReferenceValueType(v2) {
1540 return fmt.Errorf("reference types cannot be used for non typed select instruction")
1541 }
1542
1543 if v1 != v2 && v1 != valueTypeUnknown && v2 != valueTypeUnknown {
1544 return fmt.Errorf("type mismatch on 1st and 2nd select operands")
1545 }
1546 if v1 == valueTypeUnknown {
1547 valueTypeStack.push(v2)
1548 } else {
1549 valueTypeStack.push(v1)
1550 }
1551 } else if op == OpcodeUnreachable {
1552
1553 valueTypeStack.unreachable()
1554 } else if op == OpcodeNop {
1555 } else {
1556 return fmt.Errorf("invalid instruction 0x%x", op)
1557 }
1558 }
1559
1560 if len(controlBlockStack.stack) > 0 {
1561 return fmt.Errorf("ill-nested block exists")
1562 }
1563 if valueTypeStack.maximumStackPointer > maxStackValues {
1564 return fmt.Errorf("function may have %d stack values, which exceeds limit %d", valueTypeStack.maximumStackPointer, maxStackValues)
1565 }
1566 return nil
1567 }
1568
1569 var vecExtractLanes = [...]struct {
1570 laneCeil byte
1571 resultType ValueType
1572 }{
1573 OpcodeVecI8x16ExtractLaneS: {laneCeil: 16, resultType: ValueTypeI32},
1574 OpcodeVecI8x16ExtractLaneU: {laneCeil: 16, resultType: ValueTypeI32},
1575 OpcodeVecI16x8ExtractLaneS: {laneCeil: 8, resultType: ValueTypeI32},
1576 OpcodeVecI16x8ExtractLaneU: {laneCeil: 8, resultType: ValueTypeI32},
1577 OpcodeVecI32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeI32},
1578 OpcodeVecI64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeI64},
1579 OpcodeVecF32x4ExtractLane: {laneCeil: 4, resultType: ValueTypeF32},
1580 OpcodeVecF64x2ExtractLane: {laneCeil: 2, resultType: ValueTypeF64},
1581 }
1582
1583 var vecReplaceLanes = [...]struct {
1584 laneCeil byte
1585 paramType ValueType
1586 }{
1587 OpcodeVecI8x16ReplaceLane: {laneCeil: 16, paramType: ValueTypeI32},
1588 OpcodeVecI16x8ReplaceLane: {laneCeil: 8, paramType: ValueTypeI32},
1589 OpcodeVecI32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeI32},
1590 OpcodeVecI64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeI64},
1591 OpcodeVecF32x4ReplaceLane: {laneCeil: 4, paramType: ValueTypeF32},
1592 OpcodeVecF64x2ReplaceLane: {laneCeil: 2, paramType: ValueTypeF64},
1593 }
1594
1595 var vecStoreLanes = [...]struct {
1596 alignMax uint32
1597 laneCeil byte
1598 }{
1599 OpcodeVecV128Store64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
1600 OpcodeVecV128Store32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
1601 OpcodeVecV128Store16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
1602 OpcodeVecV128Store8Lane: {alignMax: 1, laneCeil: 128 / 8},
1603 }
1604
1605 var vecLoadLanes = [...]struct {
1606 alignMax uint32
1607 laneCeil byte
1608 }{
1609 OpcodeVecV128Load64Lane: {alignMax: 64 / 8, laneCeil: 128 / 64},
1610 OpcodeVecV128Load32Lane: {alignMax: 32 / 8, laneCeil: 128 / 32},
1611 OpcodeVecV128Load16Lane: {alignMax: 16 / 8, laneCeil: 128 / 16},
1612 OpcodeVecV128Load8Lane: {alignMax: 1, laneCeil: 128 / 8},
1613 }
1614
1615 var vecSplatValueTypes = [...]ValueType{
1616 OpcodeVecI8x16Splat: ValueTypeI32,
1617 OpcodeVecI16x8Splat: ValueTypeI32,
1618 OpcodeVecI32x4Splat: ValueTypeI32,
1619 OpcodeVecI64x2Splat: ValueTypeI64,
1620 OpcodeVecF32x4Splat: ValueTypeF32,
1621 OpcodeVecF64x2Splat: ValueTypeF64,
1622 }
1623
1624 type stacks struct {
1625 vs valueTypeStack
1626 cs controlBlockStack
1627 }
1628
1629 func (sts *stacks) reset(functionType *FunctionType) {
1630
1631 sts.vs.stack = sts.vs.stack[:0]
1632 sts.vs.stackLimits = sts.vs.stackLimits[:0]
1633 sts.vs.maximumStackPointer = 0
1634 sts.cs.stack = sts.cs.stack[:0]
1635 sts.cs.stack = append(sts.cs.stack, controlBlock{blockType: functionType})
1636 }
1637
1638 type controlBlockStack struct {
1639 stack []controlBlock
1640 }
1641
1642 func (s *controlBlockStack) pop() *controlBlock {
1643 tail := len(s.stack) - 1
1644 ret := &s.stack[tail]
1645 s.stack = s.stack[:tail]
1646 return ret
1647 }
1648
1649 func (s *controlBlockStack) push(startAt, elseAt, endAt uint64, blockType *FunctionType, blockTypeBytes uint64, op Opcode) {
1650 s.stack = append(s.stack, controlBlock{
1651 startAt: startAt,
1652 elseAt: elseAt,
1653 endAt: endAt,
1654 blockType: blockType,
1655 blockTypeBytes: blockTypeBytes,
1656 op: op,
1657 })
1658 }
1659
1660 type valueTypeStack struct {
1661 stack []ValueType
1662 stackLimits []int
1663 maximumStackPointer int
1664
1665 requireStackValuesTmp []ValueType
1666 }
1667
1668
1669 const valueTypeUnknown = ValueType(0xFF)
1670
1671 func (s *valueTypeStack) tryPop() (vt ValueType, limit int, ok bool) {
1672 if len(s.stackLimits) > 0 {
1673 limit = s.stackLimits[len(s.stackLimits)-1]
1674 }
1675 stackLen := len(s.stack)
1676 if stackLen <= limit {
1677 return
1678 } else if stackLen == limit+1 && s.stack[limit] == valueTypeUnknown {
1679 vt = valueTypeUnknown
1680 ok = true
1681 return
1682 } else {
1683 vt = s.stack[stackLen-1]
1684 s.stack = s.stack[:stackLen-1]
1685 ok = true
1686 return
1687 }
1688 }
1689
1690 func (s *valueTypeStack) pop() (ValueType, error) {
1691 if vt, limit, ok := s.tryPop(); ok {
1692 return vt, nil
1693 } else {
1694 return 0, fmt.Errorf("invalid operation: trying to pop at %d with limit %d", len(s.stack), limit)
1695 }
1696 }
1697
1698
1699 func (s *valueTypeStack) popAndVerifyType(expected ValueType) error {
1700 have, _, ok := s.tryPop()
1701 if !ok {
1702 return fmt.Errorf("%s missing", ValueTypeName(expected))
1703 }
1704 if have != expected && have != valueTypeUnknown && expected != valueTypeUnknown {
1705 return fmt.Errorf("type mismatch: expected %s, but was %s", ValueTypeName(expected), ValueTypeName(have))
1706 }
1707 return nil
1708 }
1709
1710 func (s *valueTypeStack) push(v ValueType) {
1711 s.stack = append(s.stack, v)
1712 if sp := len(s.stack); sp > s.maximumStackPointer {
1713 s.maximumStackPointer = sp
1714 }
1715 }
1716
1717 func (s *valueTypeStack) unreachable() {
1718 s.resetAtStackLimit()
1719 s.stack = append(s.stack, valueTypeUnknown)
1720 }
1721
1722 func (s *valueTypeStack) resetAtStackLimit() {
1723 if len(s.stackLimits) != 0 {
1724 s.stack = s.stack[:s.stackLimits[len(s.stackLimits)-1]]
1725 } else {
1726 s.stack = s.stack[:0]
1727 }
1728 }
1729
1730 func (s *valueTypeStack) popStackLimit() {
1731 if len(s.stackLimits) != 0 {
1732 s.stackLimits = s.stackLimits[:len(s.stackLimits)-1]
1733 }
1734 }
1735
1736
1737 func (s *valueTypeStack) pushStackLimit(params int) {
1738 limit := len(s.stack) - params
1739 s.stackLimits = append(s.stackLimits, limit)
1740 }
1741
1742 func (s *valueTypeStack) popParams(oc Opcode, want []ValueType, checkAboveLimit bool) error {
1743 return s.requireStackValues(true, InstructionName(oc), want, checkAboveLimit)
1744 }
1745
1746 func (s *valueTypeStack) popResults(oc Opcode, want []ValueType, checkAboveLimit bool) error {
1747 return s.requireStackValues(false, InstructionName(oc), want, checkAboveLimit)
1748 }
1749
1750 func (s *valueTypeStack) requireStackValues(
1751 isParam bool,
1752 context string,
1753 want []ValueType,
1754 checkAboveLimit bool,
1755 ) error {
1756 limit := 0
1757 if len(s.stackLimits) > 0 {
1758 limit = s.stackLimits[len(s.stackLimits)-1]
1759 }
1760
1761 countWanted := len(want)
1762
1763
1764 s.requireStackValuesTmp = s.requireStackValuesTmp[:0]
1765 for i := countWanted - 1; i >= 0; i-- {
1766 popped, _, ok := s.tryPop()
1767 if !ok {
1768 if len(s.requireStackValuesTmp) > len(want) {
1769 return typeCountError(isParam, context, s.requireStackValuesTmp, want)
1770 }
1771 return typeCountError(isParam, context, s.requireStackValuesTmp, want)
1772 }
1773 s.requireStackValuesTmp = append(s.requireStackValuesTmp, popped)
1774 }
1775
1776
1777 if checkAboveLimit {
1778 if !(limit == len(s.stack) || (limit+1 == len(s.stack) && s.stack[limit] == valueTypeUnknown)) {
1779 return typeCountError(isParam, context, append(s.stack, want...), want)
1780 }
1781 }
1782
1783
1784 for i, v := range s.requireStackValuesTmp {
1785 nextWant := want[countWanted-i-1]
1786 if v != nextWant && v != valueTypeUnknown && nextWant != valueTypeUnknown {
1787 return typeMismatchError(isParam, context, v, nextWant, i)
1788 }
1789 }
1790 return nil
1791 }
1792
1793
1794 func typeMismatchError(isParam bool, context string, have ValueType, want ValueType, i int) error {
1795 var ret strings.Builder
1796 ret.WriteString("cannot use ")
1797 ret.WriteString(ValueTypeName(have))
1798 if context != "" {
1799 ret.WriteString(" in ")
1800 ret.WriteString(context)
1801 ret.WriteString(" block")
1802 }
1803 if isParam {
1804 ret.WriteString(" as param")
1805 } else {
1806 ret.WriteString(" as result")
1807 }
1808 ret.WriteString("[")
1809 ret.WriteString(strconv.Itoa(i))
1810 ret.WriteString("] type ")
1811 ret.WriteString(ValueTypeName(want))
1812 return errors.New(ret.String())
1813 }
1814
1815
1816 func typeCountError(isParam bool, context string, have []ValueType, want []ValueType) error {
1817 var ret strings.Builder
1818 if len(have) > len(want) {
1819 ret.WriteString("too many ")
1820 } else {
1821 ret.WriteString("not enough ")
1822 }
1823 if isParam {
1824 ret.WriteString("params")
1825 } else {
1826 ret.WriteString("results")
1827 }
1828 if context != "" {
1829 if isParam {
1830 ret.WriteString(" for ")
1831 } else {
1832 ret.WriteString(" in ")
1833 }
1834 ret.WriteString(context)
1835 ret.WriteString(" block")
1836 }
1837 ret.WriteString("\n\thave (")
1838 writeValueTypes(have, &ret)
1839 ret.WriteString(")\n\twant (")
1840 writeValueTypes(want, &ret)
1841 ret.WriteByte(')')
1842 return errors.New(ret.String())
1843 }
1844
1845 func writeValueTypes(vts []ValueType, ret *strings.Builder) {
1846 switch len(vts) {
1847 case 0:
1848 case 1:
1849 ret.WriteString(ValueTypeName(vts[0]))
1850 default:
1851 ret.WriteString(ValueTypeName(vts[0]))
1852 for _, vt := range vts[1:] {
1853 ret.WriteString(", ")
1854 ret.WriteString(ValueTypeName(vt))
1855 }
1856 }
1857 }
1858
1859 func (s *valueTypeStack) String() string {
1860 var typeStrs, limits []string
1861 for _, v := range s.stack {
1862 var str string
1863 if v == valueTypeUnknown {
1864 str = "unknown"
1865 } else {
1866 str = ValueTypeName(v)
1867 }
1868 typeStrs = append(typeStrs, str)
1869 }
1870 for _, d := range s.stackLimits {
1871 limits = append(limits, fmt.Sprintf("%d", d))
1872 }
1873 return fmt.Sprintf("{stack: [%s], limits: [%s]}",
1874 strings.Join(typeStrs, ", "), strings.Join(limits, ","))
1875 }
1876
1877 type controlBlock struct {
1878 startAt, elseAt, endAt uint64
1879 blockType *FunctionType
1880 blockTypeBytes uint64
1881
1882 op Opcode
1883 }
1884
1885
1886
1887
1888
1889
1890
1891 func DecodeBlockType(types []FunctionType, r *bytes.Reader, enabledFeatures api.CoreFeatures) (*FunctionType, uint64, error) {
1892 raw, num, err := leb128.DecodeInt33AsInt64(r)
1893 if err != nil {
1894 return nil, 0, fmt.Errorf("decode int33: %w", err)
1895 }
1896
1897 var ret *FunctionType
1898 switch raw {
1899 case -64:
1900 ret = blockType_v_v
1901 case -1:
1902 ret = blockType_v_i32
1903 case -2:
1904 ret = blockType_v_i64
1905 case -3:
1906 ret = blockType_v_f32
1907 case -4:
1908 ret = blockType_v_f64
1909 case -5:
1910 ret = blockType_v_v128
1911 case -16:
1912 ret = blockType_v_funcref
1913 case -17:
1914 ret = blockType_v_externref
1915 default:
1916 if err = enabledFeatures.RequireEnabled(api.CoreFeatureMultiValue); err != nil {
1917 return nil, num, fmt.Errorf("block with function type return invalid as %v", err)
1918 }
1919 if raw < 0 || (raw >= int64(len(types))) {
1920 return nil, 0, fmt.Errorf("type index out of range: %d", raw)
1921 }
1922 ret = &types[raw]
1923 }
1924 return ret, num, err
1925 }
1926
1927
1928 var (
1929 blockType_v_v = &FunctionType{}
1930 blockType_v_i32 = &FunctionType{Results: []ValueType{ValueTypeI32}, ResultNumInUint64: 1}
1931 blockType_v_i64 = &FunctionType{Results: []ValueType{ValueTypeI64}, ResultNumInUint64: 1}
1932 blockType_v_f32 = &FunctionType{Results: []ValueType{ValueTypeF32}, ResultNumInUint64: 1}
1933 blockType_v_f64 = &FunctionType{Results: []ValueType{ValueTypeF64}, ResultNumInUint64: 1}
1934 blockType_v_v128 = &FunctionType{Results: []ValueType{ValueTypeV128}, ResultNumInUint64: 2}
1935 blockType_v_funcref = &FunctionType{Results: []ValueType{ValueTypeFuncref}, ResultNumInUint64: 1}
1936 blockType_v_externref = &FunctionType{Results: []ValueType{ValueTypeExternref}, ResultNumInUint64: 1}
1937 )
1938
1939
1940
1941 func SplitCallStack(ft *FunctionType, stack []uint64) (params []uint64, results []uint64, err error) {
1942 stackLen := len(stack)
1943 if n := ft.ParamNumInUint64; n > stackLen {
1944 return nil, nil, fmt.Errorf("need %d params, but stack size is %d", n, stackLen)
1945 } else if n > 0 {
1946 params = stack[:n]
1947 }
1948 if n := ft.ResultNumInUint64; n > stackLen {
1949 return nil, nil, fmt.Errorf("need %d results, but stack size is %d", n, stackLen)
1950 } else if n > 0 {
1951 results = stack[:n]
1952 }
1953 return
1954 }
1955
View as plain text