exec

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2019 License: BSD-3-Clause Imports: 12 Imported by: 24

Documentation

Overview

Package exec provides functions for executing WebAssembly bytecode.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrSignatureMismatch is the error value used while trapping the VM when
	// a signature mismatch between the table entry and the type entry is found
	// in a call_indirect operation.
	ErrSignatureMismatch = errors.New("exec: signature mismatch in call_indirect")
	// ErrUndefinedElementIndex is the error value used while trapping the VM when
	// an invalid index to the module's table space is used as an operand to
	// call_indirect
	ErrUndefinedElementIndex = errors.New("exec: undefined element index")
)
View Source
var (
	// ErrMultipleLinearMemories is returned by (*VM).NewVM when the module
	// has more then one entries in the linear memory space.
	ErrMultipleLinearMemories = errors.New("exec: more than one linear memories in module")
	// ErrInvalidArgumentCount is returned by (*VM).ExecCode when an invalid
	// number of arguments to the WebAssembly function are passed to it.
	ErrInvalidArgumentCount = errors.New("exec: invalid number of arguments to function")
)
View Source
var ErrOutOfBoundsMemoryAccess = errors.New("exec: out of bounds memory access")

ErrOutOfBoundsMemoryAccess is the error value used while trapping the VM when it detects an out of bounds access to the linear memory.

View Source
var ErrUnreachable = errors.New("exec: reached unreachable")

ErrUnreachable is the error value used while trapping the VM when an unreachable operator is reached during execution.

Functions

This section is empty.

Types

type InvalidFunctionIndexError

type InvalidFunctionIndexError int64

InvalidFunctionIndexError is returned by (*VM).ExecCode when the function index provided is invalid.

func (InvalidFunctionIndexError) Error

type InvalidReturnTypeError

type InvalidReturnTypeError int8

InvalidReturnTypeError is returned by (*VM).ExecCode when the module specifies an invalid return type value for the executed function.

func (InvalidReturnTypeError) Error

func (e InvalidReturnTypeError) Error() string

type NativeCompilationError added in v0.6.0

type NativeCompilationError struct {
	Start, End uint
	FuncIndex  int
	Err        error
}

NativeCompilationError represents a failure to compile a sequence of instructions to native code.

func (NativeCompilationError) Error added in v0.6.0

func (e NativeCompilationError) Error() string

type NativeCompileStats added in v0.6.0

type NativeCompileStats struct {
	Ops               map[byte]*OpStats
	NumCompiledBlocks int
}

NativeCompileStats encapsulates statistics about any native compilation performed on the VM.

type OpStats added in v0.6.0

type OpStats struct {
	Interpreted int
	Compiled    int
}

type Process

type Process struct {
	// contains filtered or unexported fields
}

Process is a proxy passed to host functions in order to access things such as memory and control.

func NewProcess

func NewProcess(vm *VM) *Process

NewProcess creates a VM interface object for host functions

func (*Process) MemSize added in v0.6.0

func (proc *Process) MemSize() int

MemSize returns the current allocated memory size in bytes.

func (*Process) ReadAt

func (proc *Process) ReadAt(p []byte, off int64) (int, error)

ReadAt implements the ReaderAt interface: it copies into p the content of memory at offset off.

func (*Process) Terminate

func (proc *Process) Terminate()

Terminate stops the execution of the current module.

func (*Process) WriteAt

func (proc *Process) WriteAt(p []byte, off int64) (int, error)

WriteAt implements the WriterAt interface: it writes the content of p into the VM memory at offset off.

type VM

type VM struct {

	// RecoverPanic controls whether the `ExecCode` method
	// recovers from a panic and returns it as an error
	// instead.
	// A panic can occur either when executing an invalid VM
	// or encountering an invalid instruction, e.g. `unreachable`.
	RecoverPanic bool
	// contains filtered or unexported fields
}

VM is the execution context for executing WebAssembly bytecode.

Example (Add)
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"reflect"

	"github.com/go-interpreter/wagon/exec"
	"github.com/go-interpreter/wagon/wasm"
)

func main() {
	raw, err := compileWast2Wasm("testdata/add-ex-main.wast")
	if err != nil {
		log.Fatalf("could not compile wast file: %v", err)
	}

	m, err := wasm.ReadModule(bytes.NewReader(raw), func(name string) (*wasm.Module, error) {
		// ReadModule takes as a second argument an optional "importer" function
		// that is supposed to locate and import other modules when some module is
		// requested (by name.)
		// Theoretically, a general "importer" function not unlike the Python's 'import'
		// mechanism (that tries to locate and import modules from a $PYTHONPATH)
		// could be devised.
		switch name {
		case "add":
			raw, err := compileWast2Wasm("testdata/add-ex.wast")
			if err != nil {
				return nil, fmt.Errorf("could not compile wast file hosting %q: %v", name, err)
			}

			add, err := wasm.ReadModule(bytes.NewReader(raw), nil)
			if err != nil {
				return nil, fmt.Errorf("could not read wasm %q module: %v", name, err)
			}
			return add, nil
		case "go":
			// create a whole new module, called "go", from scratch.
			// this module will contain one exported function "print",
			// implemented itself in pure Go.
			print := func(proc *exec.Process, v int32) {
				fmt.Printf("result = %v\n", v)
			}

			m := wasm.NewModule()
			m.Types = &wasm.SectionTypes{
				Entries: []wasm.FunctionSig{
					{
						Form:       0, // value for the 'func' type constructor
						ParamTypes: []wasm.ValueType{wasm.ValueTypeI32},
					},
				},
			}
			m.FunctionIndexSpace = []wasm.Function{
				{
					Sig:  &m.Types.Entries[0],
					Host: reflect.ValueOf(print),
					Body: &wasm.FunctionBody{}, // create a dummy wasm body (the actual value will be taken from Host.)
				},
			}
			m.Export = &wasm.SectionExports{
				Entries: map[string]wasm.ExportEntry{
					"print": {
						FieldStr: "print",
						Kind:     wasm.ExternalFunction,
						Index:    0,
					},
				},
			}

			return m, nil
		}
		return nil, fmt.Errorf("module %q unknown", name)
	})
	if err != nil {
		log.Fatalf("could not read module: %v", err)
	}

	vm, err := exec.NewVM(m)
	if err != nil {
		log.Fatalf("could not create wagon vm: %v", err)
	}

	const fct1 = 2 // index of function fct1
	out, err := vm.ExecCode(fct1)
	if err != nil {
		log.Fatalf("could not execute fct1(): %v", err)
	}
	fmt.Printf("fct1() -> %v\n", out)

	const fct2 = 3 // index of function fct2
	out, err = vm.ExecCode(fct2, 40, 6)
	if err != nil {
		log.Fatalf("could not execute fct2(40, 6): %v", err)
	}
	fmt.Printf("fct2() -> %v\n", out)

	const fct3 = 4 // index of function fct3
	out, err = vm.ExecCode(fct3, 42, 42)
	if err != nil {
		log.Fatalf("could not execute fct3(42, 42): %v", err)
	}
	fmt.Printf("fct3() -> %v\n", out)

}

// compileWast2Wasm fakes a compilation pass from WAST to WASM.
//
// When wagon gets a WAST parser, this function will be running an actual compilation.
// See: https://github.com/go-interpreter/wagon/issues/34
func compileWast2Wasm(fname string) ([]byte, error) {
	switch fname {
	case "testdata/add-ex.wast":
		// obtained by running:
		//  $> wat2wasm -v -o add-ex.wasm add-ex.wast
		return ioutil.ReadFile("testdata/add-ex.wasm")
	case "testdata/add-ex-main.wast":
		// obtained by running:
		//  $> wat2wasm -v -o add-ex-main.wasm add-ex-main.wast
		return ioutil.ReadFile("testdata/add-ex-main.wasm")
	}
	return nil, fmt.Errorf("unknown wast test file %q", fname)
}
Output:

fct1() -> 42
fct2() -> 46
result = 84
fct3() -> <nil>

func NewVM

func NewVM(module *wasm.Module, opts ...VMOption) (*VM, error)

NewVM creates a new VM from a given module and options. If the module defines a start function, it will be executed.

func (*VM) Close added in v0.6.0

func (vm *VM) Close() error

Close frees any resources managed by the VM.

func (*VM) CompileStats added in v0.6.0

func (vm *VM) CompileStats() NativeCompileStats

CompileStats returns statistics about native compilation performed on the VM.

func (*VM) ExecCode

func (vm *VM) ExecCode(fnIndex int64, args ...uint64) (rtrn interface{}, err error)

ExecCode calls the function with the given index and arguments. fnIndex should be a valid index into the function index space of the VM's module.

func (*VM) Memory

func (vm *VM) Memory() []byte

Memory returns the linear memory space for the VM.

func (*VM) Restart added in v0.6.0

func (vm *VM) Restart()

Restart readies the VM for another run.

type VMOption added in v0.6.0

type VMOption func(c *config)

VMOption describes a customization that can be applied to the VM.

func EnableAOT added in v0.6.0

func EnableAOT(v bool) VMOption

EnableAOT enables ahead-of-time compilation of supported opcodes into runs of native instructions, if wagon supports native compilation for the current architecture.

Directories

Path Synopsis
internal
compile
Package compile is used internally by wagon to convert standard structured WebAssembly bytecode into an unstructured form suitable for execution by it's VM.
Package compile is used internally by wagon to convert standard structured WebAssembly bytecode into an unstructured form suitable for execution by it's VM.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL