-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstr_memory.go
213 lines (179 loc) · 5.58 KB
/
instr_memory.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
package wasm_go
// https://webassembly.github.io/spec/core/exec/instructions.html#exec-storen
type opStore struct {
offset int32
align int32
storeFn func(m *memInst, addr, align int32, v Value)
}
func (o *opStore) exec(frameStack *stack[frame], valueStack *stack[Value], store *store) error {
frame, _ := frameStack.Top()
mem := store.mems[frame.mod.defaultMemAddr()]
value, _ := valueStack.Pop()
addr := value.I32() + o.offset
o.storeFn(&mem, addr, o.align, value)
frame.NextStep()
return nil
}
func i32store(m *memInst, addr, align int32, v Value) {
m.store32(addr, align, uint32(v.I32()))
}
func i64store(m *memInst, addr, align int32, v Value) {
m.store64(addr, align, uint64(v.I64()))
}
func f32store(m *memInst, addr, align int32, v Value) {
m.store32(addr, align, uint32(v.F32()))
}
func f64store(m *memInst, addr, align int32, v Value) {
m.store64(addr, align, uint64(v.F64()))
}
func i32store8(m *memInst, addr, align int32, v Value) {
m.store8(addr, align, uint8(v.I32()))
}
func i32store16(m *memInst, addr, align int32, v Value) {
m.store16(addr, align, uint16(v.I32()))
}
func i64store8(m *memInst, addr, align int32, v Value) {
m.store8(addr, align, uint8(v.I64()))
}
func i64store16(m *memInst, addr, align int32, v Value) {
m.store16(addr, align, uint16(v.I64()))
}
func i64store32(m *memInst, addr, align int32, v Value) {
m.store32(addr, align, uint32(v.I64()))
}
// https://webassembly.github.io/spec/core/exec/instructions.html#exec-loadn
type opLoad struct {
align int32
offset int32
loadFn func(m *memInst, addr, align int32) (Value, error)
}
func (o *opLoad) exec(frameStack *stack[frame], valueStack *stack[Value], store *store) error {
frame, _ := frameStack.Top()
mem := store.mems[frame.mod.defaultMemAddr()]
baseAddr, _ := valueStack.Pop()
baseAddrI32 := baseAddr.I32()
if baseAddrI32 < 0 || o.offset < 0 {
return errOutOfBounds
}
addr := baseAddrI32 + o.offset
value, err := o.loadFn(&mem, addr, o.align)
if err != nil {
return err
}
valueStack.Push(value)
frame.NextStep()
return nil
}
func i32load(m *memInst, addr, align int32) (Value, error) {
v, err := m.load32(addr, align)
return ValueFromI32(int32(v)), err
}
func i64load(m *memInst, addr, align int32) (Value, error) {
v, err := m.load64(addr, align)
return ValueFromI64(int64(v)), err
}
func f32load(m *memInst, addr, align int32) (Value, error) {
v, err := m.load32(addr, align)
return ValueFrom(v, F32), err
}
func f64load(m *memInst, addr, align int32) (Value, error) {
v, err := m.load64(addr, align)
return ValueFrom(v, F64), err
}
func i32load8S(m *memInst, addr, align int32) (Value, error) {
v, err := m.load8(addr, align)
return ValueFromI32(extendS8_32(int32(v))), err
}
func i32load8U(m *memInst, addr, align int32) (Value, error) {
v, err := m.load8(addr, align)
return ValueFromI32(int32(v)), err
}
func i32load16S(m *memInst, addr, align int32) (Value, error) {
v, err := m.load16(addr, align)
return ValueFromI32(extendS16_32(int32(v))), err
}
func i32load16U(m *memInst, addr, align int32) (Value, error) {
v, err := m.load16(addr, align)
return ValueFromI32(int32(v)), err
}
func i64Load8S(m *memInst, addr, align int32) (Value, error) {
v, err := m.load8(addr, align)
return ValueFromI64(extendS8_64(int64(v))), err
}
func i64Load8U(m *memInst, addr, align int32) (Value, error) {
v, err := m.load8(addr, align)
return ValueFromI64(int64(v)), err
}
func i64load16S(m *memInst, addr, align int32) (Value, error) {
v, err := m.load16(addr, align)
return ValueFromI64(extendS16_64(int64(v))), err
}
func i64load16U(m *memInst, addr, align int32) (Value, error) {
v, err := m.load16(addr, align)
return ValueFromI64(int64(v)), err
}
func i64load32S(m *memInst, addr, align int32) (Value, error) {
v, err := m.load32(addr, align)
return ValueFromI64(extendS32_64(int64(v))), err
}
func i64load32U(m *memInst, addr, align int32) (Value, error) {
v, err := m.load32(addr, align)
return ValueFromI64(int64(v)), err
}
type opMemorySize struct{}
func (o *opMemorySize) exec(frameStack *stack[frame], valueStack *stack[Value], store *store) error {
frame, _ := frameStack.Top()
mem := store.mems[frame.mod.defaultMemAddr()]
valueStack.Push(ValueFrom(int32(mem.size()), I32))
frame.NextStep()
return nil
}
type opMemoryGrow struct{}
func (o *opMemoryGrow) exec(frameStack *stack[frame], valueStack *stack[Value], store *store) error {
frame, _ := frameStack.Top()
mem := store.mems[frame.mod.defaultMemAddr()]
v, _ := valueStack.Pop()
currentPages := mem.pages()
pagesWant := int(v.I32())
err := mem.grow(pagesWant)
if err != nil {
valueStack.Push(ValueFrom(-1, I32))
} else {
valueStack.Push(ValueFrom(currentPages, I32))
}
frame.NextStep()
return nil
}
type opMemoryCopy struct {
}
func (o *opMemoryCopy) exec(frameStack *stack[frame], valueStack *stack[Value], store *store) error {
len, _ := valueStack.Pop()
src, _ := valueStack.Pop()
dst, _ := valueStack.Pop()
frame, _ := frameStack.Top()
mem := store.mems[frame.mod.defaultMemAddr()]
copy(mem.data[dst.I32():], mem.data[src.I32():src.I32()+len.I32()])
frame.NextStep()
return nil
}
// https://webassembly.github.io/spec/core/bikeshed/#-hrefsyntax-instr-memorymathsfmemoryfill%E2%91%A0
type opMemoryFill struct {
}
func (o *opMemoryFill) exec(frameStack *stack[frame], valueStack *stack[Value], store *store) error {
return nil
}
func extendS8_32(v int32) int32 {
return v << 24 >> 24
}
func extendS8_64(v int64) int64 {
return v << 56 >> 56
}
func extendS16_32(v int32) int32 {
return v << 16 >> 16
}
func extendS16_64(v int64) int64 {
return v << 48 >> 48
}
func extendS32_64(v int64) int64 {
return v << 32 >> 32
}