refactor: hostfunc module builder
This commit is contained in:
20
README.md
20
README.md
@@ -23,8 +23,7 @@ Full examples can be found at: https://github.com/mathetake/gasm/tree/master/exa
|
||||
func Test_fibonacci(t *testing.T) {
|
||||
buf, _ := ioutil.ReadFile("wasm/fibonacci.wasm")
|
||||
mod, _ := wasm.DecodeModule(bytes.NewBuffer(buf))
|
||||
mod.BuildIndexSpaces(wasi.Modules)
|
||||
vm, _ := wasm.NewVM(mod)
|
||||
vm, _ := wasm.NewVM(mod, wasi.Modules)
|
||||
|
||||
for _, c := range []struct {
|
||||
in, exp int32
|
||||
@@ -45,11 +44,8 @@ func Test_fibonacci(t *testing.T) {
|
||||
```golang
|
||||
|
||||
func Test_hostFunc(t *testing.T) {
|
||||
buf, err := ioutil.ReadFile("wasm/host_func.wasm")
|
||||
require.NoError(t, err)
|
||||
|
||||
mod, err := wasm.DecodeModule(bytes.NewBuffer(buf))
|
||||
require.NoError(t, err)
|
||||
buf, _ := ioutil.ReadFile("wasm/host_func.wasm")
|
||||
mod, _ := wasm.DecodeModule(bytes.NewBuffer(buf))
|
||||
|
||||
var cnt uint64 // to be incremented as hostFunc is called
|
||||
|
||||
@@ -61,13 +57,9 @@ func Test_hostFunc(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
builder := hostmodule.NewBuilderWith(wasi.Modules)
|
||||
builder.MustAddFunction("env", "host_func", hostFunc)
|
||||
err = mod.BuildIndexSpaces(builder.Done())
|
||||
require.NoError(t, err)
|
||||
|
||||
vm, err := wasm.NewVM(mod)
|
||||
require.NoError(t, err)
|
||||
builder := hostfunc.NewModuleBuilderWith(wasi.Modules)
|
||||
builder.MustSetFunction("env", "host_func", hostFunc)
|
||||
vm, _ := wasm.NewVM(mod, builder.Done())
|
||||
|
||||
for _, exp := range []uint64{5, 10, 15} {
|
||||
vm.ExecExportedFunction("call_host_func", exp)
|
||||
|
||||
@@ -17,10 +17,7 @@ func Test_fibonacci(t *testing.T) {
|
||||
mod, err := wasm.DecodeModule(bytes.NewBuffer(buf))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = mod.BuildIndexSpaces(wasi.Modules)
|
||||
require.NoError(t, err)
|
||||
|
||||
vm, err := wasm.NewVM(mod)
|
||||
vm, err := wasm.NewVM(mod, wasi.Modules)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, c := range []struct {
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/mathetake/gasm/hostmodule"
|
||||
"github.com/mathetake/gasm/hostfunc"
|
||||
"github.com/mathetake/gasm/wasi"
|
||||
"github.com/mathetake/gasm/wasm"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -26,12 +26,9 @@ func Test_hostFunc(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
builder := hostmodule.NewBuilderWith(wasi.Modules)
|
||||
builder.MustAddFunction("env", "host_func", hostFunc)
|
||||
err = mod.BuildIndexSpaces(builder.Done())
|
||||
require.NoError(t, err)
|
||||
|
||||
vm, err := wasm.NewVM(mod)
|
||||
builder := hostfunc.NewModuleBuilderWith(wasi.Modules)
|
||||
builder.MustSetFunction("env", "host_func", hostFunc)
|
||||
vm, err := wasm.NewVM(mod, builder.Done())
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, exp := range []uint64{5, 10, 15} {
|
||||
|
||||
@@ -17,10 +17,7 @@ func Test_panic(t *testing.T) {
|
||||
mod, err := wasm.DecodeModule(bytes.NewBuffer(buf))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = mod.BuildIndexSpaces(wasi.Modules)
|
||||
require.NoError(t, err)
|
||||
|
||||
vm, err := wasm.NewVM(mod)
|
||||
vm, err := wasm.NewVM(mod, wasi.Modules)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer func() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package hostmodule
|
||||
package hostfunc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -7,27 +7,25 @@ import (
|
||||
"github.com/mathetake/gasm/wasm"
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
type ModuleBuilder struct {
|
||||
modules map[string]*wasm.Module
|
||||
}
|
||||
|
||||
func NewBuilder() *Builder {
|
||||
return &Builder{modules: map[string]*wasm.Module{}}
|
||||
func NewModuleBuilder() *ModuleBuilder {
|
||||
return &ModuleBuilder{modules: map[string]*wasm.Module{}}
|
||||
}
|
||||
|
||||
func NewBuilderWith(in map[string]*wasm.Module) *Builder {
|
||||
return &Builder{modules: in}
|
||||
func NewModuleBuilderWith(in map[string]*wasm.Module) *ModuleBuilder {
|
||||
return &ModuleBuilder{modules: in}
|
||||
}
|
||||
|
||||
// TODO: support other types
|
||||
|
||||
func (m *Builder) MustAddFunction(modName, funcName string, fn func(machine *wasm.VirtualMachine) reflect.Value) {
|
||||
if err := m.AddFunction(modName, funcName, fn); err != nil {
|
||||
func (m *ModuleBuilder) MustSetFunction(modName, funcName string, fn func(machine *wasm.VirtualMachine) reflect.Value) {
|
||||
if err := m.SetFunction(modName, funcName, fn); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Builder) AddFunction(modName, funcName string, fn func(machine *wasm.VirtualMachine) reflect.Value) error {
|
||||
func (m *ModuleBuilder) SetFunction(modName, funcName string, fn func(machine *wasm.VirtualMachine) reflect.Value) error {
|
||||
|
||||
mod, ok := m.modules[modName]
|
||||
if !ok {
|
||||
@@ -89,6 +87,6 @@ func getTypeOf(kind reflect.Kind) (wasm.ValueType, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Builder) Done() map[string]*wasm.Module {
|
||||
func (m *ModuleBuilder) Done() map[string]*wasm.Module {
|
||||
return m.modules
|
||||
}
|
||||
3
hostfunc/hostfunc_test.go
Normal file
3
hostfunc/hostfunc_test.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package hostfunc
|
||||
|
||||
// fixme:
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/mathetake/gasm/hostmodule"
|
||||
"github.com/mathetake/gasm/hostfunc"
|
||||
"github.com/mathetake/gasm/wasm"
|
||||
)
|
||||
|
||||
@@ -15,8 +15,8 @@ const wasiUnstableName = "wasi_unstable"
|
||||
var Modules map[string]*wasm.Module
|
||||
|
||||
func init() {
|
||||
b := hostmodule.NewBuilder()
|
||||
b.MustAddFunction(wasiUnstableName, "fd_write", fd_write)
|
||||
b := hostfunc.NewModuleBuilder()
|
||||
b.MustSetFunction(wasiUnstableName, "fd_write", fd_write)
|
||||
Modules = b.Done()
|
||||
}
|
||||
|
||||
|
||||
@@ -79,8 +79,8 @@ func DecodeModule(r io.Reader) (*Module, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// BuildIndexSpaces build index spaces of the module with the given external modules
|
||||
func (m *Module) BuildIndexSpaces(externModules map[string]*Module) error {
|
||||
// buildIndexSpaces build index spaces of the module with the given external modules
|
||||
func (m *Module) buildIndexSpaces(externModules map[string]*Module) error {
|
||||
m.IndexSpace = new(ModuleIndexSpace)
|
||||
|
||||
// resolve imports
|
||||
|
||||
@@ -30,7 +30,11 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func NewVM(module *Module) (*VirtualMachine, error) {
|
||||
func NewVM(module *Module, externModules map[string]*Module) (*VirtualMachine, error) {
|
||||
if err := module.buildIndexSpaces(externModules); err != nil {
|
||||
return nil, fmt.Errorf("build index space: %w", err)
|
||||
}
|
||||
|
||||
vm := &VirtualMachine{
|
||||
InnerModule: module,
|
||||
OperandStack: NewVirtualMachineOperandStack(),
|
||||
|
||||
@@ -161,5 +161,9 @@ func Test_brIf(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_brAt(t *testing.T) {
|
||||
|
||||
// fixme:
|
||||
}
|
||||
|
||||
func Test_brTable(t *testing.T) {
|
||||
// fixme:
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package wasm
|
||||
|
||||
const initialStackHeight = 1024
|
||||
const (
|
||||
initialOperandStackHeight = 1024
|
||||
initialLabelStackHeight = 10
|
||||
)
|
||||
|
||||
func drop(vm *VirtualMachine) {
|
||||
vm.OperandStack.Drop()
|
||||
@@ -17,7 +20,7 @@ func selectOp(vm *VirtualMachine) {
|
||||
|
||||
func NewVirtualMachineOperandStack() *VirtualMachineOperandStack {
|
||||
return &VirtualMachineOperandStack{
|
||||
Stack: make([]uint64, initialStackHeight),
|
||||
Stack: make([]uint64, initialOperandStackHeight),
|
||||
SP: -1,
|
||||
}
|
||||
}
|
||||
@@ -71,7 +74,7 @@ type Label struct {
|
||||
|
||||
func NewVirtualMachineLabelStack() *VirtualMachineLabelStack {
|
||||
return &VirtualMachineLabelStack{
|
||||
Stack: make([]*Label, initialStackHeight),
|
||||
Stack: make([]*Label, initialLabelStackHeight),
|
||||
SP: -1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,44 +8,44 @@ import (
|
||||
|
||||
func TestVirtualMachineOperandStack(t *testing.T) {
|
||||
s := NewVirtualMachineOperandStack()
|
||||
assert.Equal(t, initialStackHeight, len(s.Stack))
|
||||
assert.Equal(t, initialOperandStackHeight, len(s.Stack))
|
||||
|
||||
var exp uint64 = 10
|
||||
s.Push(exp)
|
||||
assert.Equal(t, exp, s.Pop())
|
||||
|
||||
// verify the length grows
|
||||
for i := 0; i < initialStackHeight+1; i++ {
|
||||
for i := 0; i < initialOperandStackHeight+1; i++ {
|
||||
s.Push(uint64(i))
|
||||
}
|
||||
assert.True(t, len(s.Stack) > initialStackHeight)
|
||||
assert.True(t, len(s.Stack) > initialOperandStackHeight)
|
||||
|
||||
// verify the length is not shortened
|
||||
for i := 0; i < len(s.Stack); i++ {
|
||||
_ = s.Pop()
|
||||
}
|
||||
|
||||
assert.True(t, len(s.Stack) > initialStackHeight)
|
||||
assert.True(t, len(s.Stack) > initialOperandStackHeight)
|
||||
}
|
||||
|
||||
func TestVirtualMachineLabelStack(t *testing.T) {
|
||||
s := NewVirtualMachineLabelStack()
|
||||
assert.Equal(t, initialStackHeight, len(s.Stack))
|
||||
assert.Equal(t, initialLabelStackHeight, len(s.Stack))
|
||||
|
||||
exp := &Label{Arity: 100}
|
||||
s.Push(exp)
|
||||
assert.Equal(t, exp, s.Pop())
|
||||
|
||||
// verify the length grows
|
||||
for i := 0; i < initialStackHeight+1; i++ {
|
||||
for i := 0; i < initialLabelStackHeight+1; i++ {
|
||||
s.Push(&Label{})
|
||||
}
|
||||
assert.True(t, len(s.Stack) > initialStackHeight)
|
||||
assert.True(t, len(s.Stack) > initialLabelStackHeight)
|
||||
|
||||
// verify the length is not shortened
|
||||
for i := 0; i < len(s.Stack); i++ {
|
||||
_ = s.Pop()
|
||||
}
|
||||
|
||||
assert.True(t, len(s.Stack) > initialStackHeight)
|
||||
assert.True(t, len(s.Stack) > initialLabelStackHeight)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user