1 package wasm
2 3 import (
4 "bytes"
5 "fmt"
6 "io"
7 )
8 9 const (
10 opEnd = 0x0B // end
11 opI32Const = 0x41 // i32.const
12 opI64Const = 0x42 // i64.const
13 )
14 15 // Eval tries to evaluate the (constant) expression in the buffer. It returns
16 // the evaluation stack at the end of the sequence or an error, if there was
17 // one.
18 func Eval(r *bytes.Buffer) ([]interface{}, error) {
19 // Right now, this is only meant to parse very simple expressions like the
20 // one used for the start offset of a data segment (which is an expression).
21 var stack []interface{}
22 for {
23 b, err := r.ReadByte()
24 if err == io.EOF {
25 return nil, io.ErrUnexpectedEOF
26 }
27 if b == opEnd {
28 // End of expression.
29 break
30 }
31 switch b {
32 case opI32Const:
33 var n int32
34 err := readVarInt32(r, &n)
35 if err != nil {
36 return nil, err
37 }
38 stack = append(stack, n)
39 default:
40 return nil, fmt.Errorf("unknown opcode: 0x%02X", b)
41 }
42 }
43 return stack, nil
44 }
45 46 // Read a sequence of instructions used to initialize something.
47 func readInitExpr(r io.Reader, expr *[]byte) error {
48 for {
49 // Read a single byte.
50 b, err := readByte(r)
51 if err != nil {
52 return err
53 }
54 *expr = append(*expr, b)
55 switch b {
56 case opEnd:
57 return nil // finished the expression
58 case opI32Const, opI64Const:
59 // Read a single LEB128 encoded number.
60 for {
61 b, err := readByte(r)
62 if err != nil {
63 return err
64 }
65 *expr = append(*expr, b)
66 if (b & 0x80) == 0 {
67 break
68 }
69 }
70 default:
71 return fmt.Errorf("unknown opcode in init expression: 0x%02X", b)
72 }
73 }
74 }
75