Skip to content

Commit 5b3c6c5

Browse files
committed
add memory
1 parent 509538b commit 5b3c6c5

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed

pvm/engine/exec/memory.go

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
// Copyright 2017 The go-interpreter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package exec
6+
7+
import (
8+
"errors"
9+
"math"
10+
)
11+
12+
// ErrOutOfBoundsMemoryAccess is the error value used while trapping the VM
13+
// when it detects an out of bounds access to the linear memory.
14+
var ErrOutOfBoundsMemoryAccess = errors.New("exec: out of bounds memory access")
15+
16+
func (vm *VM) fetchBaseAddr() int {
17+
return int(vm.fetchUint32() + uint32(vm.popInt32()))
18+
}
19+
20+
// inBounds returns true when the next vm.fetchBaseAddr() + offset
21+
// indices are in bounds accesses to the linear memory.
22+
func (vm *VM) inBounds(offset int) bool {
23+
addr := endianess.Uint32(vm.ctx.code[vm.ctx.pc:]) + uint32(vm.ctx.stack[len(vm.ctx.stack)-1])
24+
return int(addr)+offset < len(vm.memory)
25+
}
26+
27+
// curMem returns a slice to the memeory segment pointed to by
28+
// the current base address on the bytecode stream.
29+
func (vm *VM) curMem() []byte {
30+
return vm.memory[vm.fetchBaseAddr():]
31+
}
32+
33+
func (vm *VM) i32Load() {
34+
if !vm.inBounds(3) {
35+
panic(ErrOutOfBoundsMemoryAccess)
36+
}
37+
vm.pushUint32(endianess.Uint32(vm.curMem()))
38+
}
39+
40+
func (vm *VM) i32Load8s() {
41+
if !vm.inBounds(0) {
42+
panic(ErrOutOfBoundsMemoryAccess)
43+
}
44+
vm.pushInt32(int32(int8(vm.memory[vm.fetchBaseAddr()])))
45+
}
46+
47+
func (vm *VM) i32Load8u() {
48+
if !vm.inBounds(0) {
49+
panic(ErrOutOfBoundsMemoryAccess)
50+
}
51+
vm.pushUint32(uint32(uint8(vm.memory[vm.fetchBaseAddr()])))
52+
}
53+
54+
func (vm *VM) i32Load16s() {
55+
if !vm.inBounds(1) {
56+
panic(ErrOutOfBoundsMemoryAccess)
57+
}
58+
vm.pushInt32(int32(int16(endianess.Uint16(vm.curMem()))))
59+
}
60+
61+
func (vm *VM) i32Load16u() {
62+
if !vm.inBounds(1) {
63+
panic(ErrOutOfBoundsMemoryAccess)
64+
}
65+
vm.pushUint32(uint32(endianess.Uint16(vm.curMem())))
66+
}
67+
68+
func (vm *VM) i64Load() {
69+
if !vm.inBounds(7) {
70+
panic(ErrOutOfBoundsMemoryAccess)
71+
}
72+
vm.pushUint64(endianess.Uint64(vm.curMem()))
73+
}
74+
75+
func (vm *VM) i64Load8s() {
76+
if !vm.inBounds(0) {
77+
panic(ErrOutOfBoundsMemoryAccess)
78+
}
79+
vm.pushInt64(int64(int8(vm.memory[vm.fetchBaseAddr()])))
80+
}
81+
82+
func (vm *VM) i64Load8u() {
83+
if !vm.inBounds(0) {
84+
panic(ErrOutOfBoundsMemoryAccess)
85+
}
86+
vm.pushUint64(uint64(uint8(vm.memory[vm.fetchBaseAddr()])))
87+
}
88+
89+
func (vm *VM) i64Load16s() {
90+
if !vm.inBounds(1) {
91+
panic(ErrOutOfBoundsMemoryAccess)
92+
}
93+
vm.pushInt64(int64(int16(endianess.Uint16(vm.curMem()))))
94+
}
95+
96+
func (vm *VM) i64Load16u() {
97+
if !vm.inBounds(1) {
98+
panic(ErrOutOfBoundsMemoryAccess)
99+
}
100+
vm.pushUint64(uint64(endianess.Uint16(vm.curMem())))
101+
}
102+
103+
func (vm *VM) i64Load32s() {
104+
if !vm.inBounds(3) {
105+
panic(ErrOutOfBoundsMemoryAccess)
106+
}
107+
vm.pushInt64(int64(int32(endianess.Uint32(vm.curMem()))))
108+
}
109+
110+
func (vm *VM) i64Load32u() {
111+
if !vm.inBounds(3) {
112+
panic(ErrOutOfBoundsMemoryAccess)
113+
}
114+
vm.pushUint64(uint64(endianess.Uint32(vm.curMem())))
115+
}
116+
117+
func (vm *VM) f32Store() {
118+
v := math.Float32bits(vm.popFloat32())
119+
if !vm.inBounds(3) {
120+
panic(ErrOutOfBoundsMemoryAccess)
121+
}
122+
endianess.PutUint32(vm.curMem(), v)
123+
}
124+
125+
func (vm *VM) f32Load() {
126+
if !vm.inBounds(3) {
127+
panic(ErrOutOfBoundsMemoryAccess)
128+
}
129+
vm.pushFloat32(math.Float32frombits(endianess.Uint32(vm.curMem())))
130+
}
131+
132+
func (vm *VM) f64Store() {
133+
v := math.Float64bits(vm.popFloat64())
134+
if !vm.inBounds(7) {
135+
panic(ErrOutOfBoundsMemoryAccess)
136+
}
137+
endianess.PutUint64(vm.curMem(), v)
138+
}
139+
140+
func (vm *VM) f64Load() {
141+
if !vm.inBounds(7) {
142+
panic(ErrOutOfBoundsMemoryAccess)
143+
}
144+
vm.pushFloat64(math.Float64frombits(endianess.Uint64(vm.curMem())))
145+
}
146+
147+
func (vm *VM) i32Store() {
148+
v := vm.popUint32()
149+
if !vm.inBounds(3) {
150+
panic(ErrOutOfBoundsMemoryAccess)
151+
}
152+
endianess.PutUint32(vm.curMem(), v)
153+
}
154+
155+
func (vm *VM) i32Store8() {
156+
v := byte(uint8(vm.popUint32()))
157+
if !vm.inBounds(0) {
158+
panic(ErrOutOfBoundsMemoryAccess)
159+
}
160+
vm.memory[vm.fetchBaseAddr()] = v
161+
}
162+
163+
func (vm *VM) i32Store16() {
164+
v := uint16(vm.popUint32())
165+
if !vm.inBounds(1) {
166+
panic(ErrOutOfBoundsMemoryAccess)
167+
}
168+
endianess.PutUint16(vm.curMem(), v)
169+
}
170+
171+
func (vm *VM) i64Store() {
172+
v := vm.popUint64()
173+
if !vm.inBounds(7) {
174+
panic(ErrOutOfBoundsMemoryAccess)
175+
}
176+
endianess.PutUint64(vm.curMem(), v)
177+
}
178+
179+
func (vm *VM) i64Store8() {
180+
v := byte(uint8(vm.popUint64()))
181+
if !vm.inBounds(0) {
182+
panic(ErrOutOfBoundsMemoryAccess)
183+
}
184+
vm.memory[vm.fetchBaseAddr()] = v
185+
}
186+
187+
func (vm *VM) i64Store16() {
188+
v := uint16(vm.popUint64())
189+
if !vm.inBounds(1) {
190+
panic(ErrOutOfBoundsMemoryAccess)
191+
}
192+
endianess.PutUint16(vm.curMem(), v)
193+
}
194+
195+
func (vm *VM) i64Store32() {
196+
v := uint32(vm.popUint64())
197+
if !vm.inBounds(3) {
198+
panic(ErrOutOfBoundsMemoryAccess)
199+
}
200+
endianess.PutUint32(vm.curMem(), v)
201+
}
202+
203+
func (vm *VM) currentMemory() {
204+
_ = vm.fetchInt8() // reserved (https://github.com/WebAssembly/design/blob/27ac254c854994103c24834a994be16f74f54186/BinaryEncoding.md#memory-related-operators-described-here)
205+
vm.pushInt32(int32(len(vm.memory) / wasmPageSize))
206+
}
207+
208+
func (vm *VM) growMemory() {
209+
_ = vm.fetchInt8() // reserved (https://github.com/WebAssembly/design/blob/27ac254c854994103c24834a994be16f74f54186/BinaryEncoding.md#memory-related-operators-described-here)
210+
curLen := len(vm.memory) / wasmPageSize
211+
n := vm.popInt32()
212+
vm.memory = append(vm.memory, make([]byte, n*wasmPageSize)...)
213+
vm.pushInt32(int32(curLen))
214+
}

0 commit comments

Comments
 (0)