wasmtime

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 21, 2022 License: Apache-2.0 Imports: 7 Imported by: 57

README

wasmtime-go

Go embedding of Wasmtime

A Bytecode Alliance project

CI status Documentation Code Coverage

Installation

go get -u github.com/bytecodealliance/wasmtime-go@v1.0.0

Be sure to check out the API documentation!

This Go library uses CGO to consume the C API of the Wasmtime project which is written in Rust. Precompiled binaries of Wasmtime are checked into this repository on tagged releases so you won't have to install Wasmtime locally, but it means that this project only works on Linux x86_64, macOS x86_64 , and Windows x86_64 currently. Building on other platforms will need to arrange to build Wasmtime and use CGO_* env vars to compile correctly.

This project has been tested with Go 1.13 or later.

If you are a bazel user, add following to your WORKSPACE file:

go_repository(
    name = "com_github_bytecodealliance_wasmtime_go",
    importpath = "github.com/bytecodealliance/wasmtime-go",
    version = "v1.0.0",
)

Usage

A "Hello, world!" example of using this package looks like:

package main

import (
    "fmt"
    "github.com/bytecodealliance/wasmtime-go"
)

func main() {
    // Almost all operations in wasmtime require a contextual `store`
    // argument to share, so create that first
    store := wasmtime.NewStore(wasmtime.NewEngine())

    // Compiling modules requires WebAssembly binary input, but the wasmtime
    // package also supports converting the WebAssembly text format to the
    // binary format.
    wasm, err := wasmtime.Wat2Wasm(`
      (module
        (import "" "hello" (func $hello))
        (func (export "run")
          (call $hello))
      )
    `)
    check(err)

    // Once we have our binary `wasm` we can compile that into a `*Module`
    // which represents compiled JIT code.
    module, err := wasmtime.NewModule(store.Engine, wasm)
    check(err)

    // Our `hello.wat` file imports one item, so we create that function
    // here.
    item := wasmtime.WrapFunc(store, func() {
        fmt.Println("Hello from Go!")
    })

    // Next up we instantiate a module which is where we link in all our
    // imports. We've got one import so we pass that in here.
    instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{item})
    check(err)

    // After we've instantiated we can lookup our `run` function and call
    // it.
    run := instance.GetFunc(store, "run")
    if run == nil {
        panic("not a function")
    }
    _, err = run.Call(store)
    check(err)
}

func check(e error) {
    if e != nil {
        panic(e)
    }
}

Contributing

So far this extension has been written by folks who are primarily Rust programmers, so it's highly likely that there's some faux pas in terms of Go idioms. Feel free to send a PR to help make things more idiomatic if you see something!

To work on this extension locally you'll first want to clone the project:

$ git clone https://github.com/bytecodealliance/wasmtime-go

Next up you'll want to have a local Wasmtime build available.

You'll need to build at least the wasmtime-c-api crate, which, at the time of this writing, would be:

$ cargo build -p wasmtime-c-api

Once you've got that you can set up the environment of this library with:

$ ./ci/local.sh /path/to/wasmtime

This will create a build directory which has the compiled libraries and header files. Next up you can run normal commands such as:

$ go test

And after that you should be good to go!

Documentation

Overview

Package wasmtime is a WebAssembly runtime for Go powered by Wasmtime.

This package provides everything necessary to compile and execute WebAssembly modules as part of a Go program. Wasmtime is a JIT compiler written in Rust, and can be found at https://github.com/bytecodealliance/wasmtime. This package is a binding to the C API provided by Wasmtime.

The API of this Go package is intended to mirror the Rust API (https://docs.rs/wasmtime) relatively closely, so if you find something is under-documented here then you may have luck consulting the Rust documentation as well. As always though feel free to file any issues at https://github.com/bytecodealliance/wasmtime-go/issues/new.

It's also worth pointing out that the authors of this package up to this point primarily work in Rust, so if you've got suggestions of how to make this package more idiomatic for Go we'd love to hear your thoughts!

Example (Gcd)

An example of a wasm module which calculates the GCD of two numbers

package main

import (
	"fmt"
	"log"

	"github.com/bytecodealliance/wasmtime-go"
)

func main() {
	store := wasmtime.NewStore(wasmtime.NewEngine())
	wasm, err := wasmtime.Wat2Wasm(`
	(module
	  (func $gcd (param i32 i32) (result i32)
	    (local i32)
	    block  ;; label = @1
	      block  ;; label = @2
	        local.get 0
	        br_if 0 (;@2;)
	        local.get 1
	        local.set 2
	        br 1 (;@1;)
	      end
	      loop  ;; label = @2
	        local.get 1
	        local.get 0
	        local.tee 2
	        i32.rem_u
	        local.set 0
	        local.get 2
	        local.set 1
	        local.get 0
	        br_if 0 (;@2;)
	      end
	    end
	    local.get 2
	  )
	  (export "gcd" (func $gcd))
	)
	`)
	if err != nil {
		log.Fatal(err)
	}
	module, err := wasmtime.NewModule(store.Engine, wasm)
	if err != nil {
		log.Fatal(err)
	}
	instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{})
	if err != nil {
		log.Fatal(err)
	}
	run := instance.GetFunc(store, "gcd")
	result, err := run.Call(store, 6, 27)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("gcd(6, 27) = %d\n", result.(int32))
}
Output:
gcd(6, 27) = 3
Example (Hello)

An example of instantiating a small wasm module which imports functionality from the host, then calling into wasm which calls back into the host.

package main

import (
	"fmt"
	"log"

	"github.com/bytecodealliance/wasmtime-go"
)

func main() {
	// Almost all operations in wasmtime require a contextual `store`
	// argument to share, so create that first
	store := wasmtime.NewStore(wasmtime.NewEngine())

	// Compiling modules requires WebAssembly binary input, but the wasmtime
	// package also supports converting the WebAssembly text format to the
	// binary format.
	wasm, err := wasmtime.Wat2Wasm(`
	(module
	  (import "" "hello" (func $hello))
	  (func (export "run")
	    (call $hello)
	  )
	)
	`)
	if err != nil {
		log.Fatal(err)
	}

	// Once we have our binary `wasm` we can compile that into a `*Module`
	// which represents compiled JIT code.
	module, err := wasmtime.NewModule(store.Engine, wasm)
	if err != nil {
		log.Fatal(err)
	}

	// Our `hello.wat` file imports one item, so we create that function
	// here.
	item := wasmtime.WrapFunc(store, func() {
		fmt.Println("Hello from Go!")
	})

	// Next up we instantiate a module which is where we link in all our
	// imports. We've got one import so we pass that in here.
	instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{item})
	if err != nil {
		log.Fatal(err)
	}

	// After we've instantiated we can lookup our `run` function and call
	// it.
	run := instance.GetFunc(store, "run")
	_, err = run.Call(store)
	if err != nil {
		log.Fatal(err)
	}
}
Output:
Hello from Go!

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ModuleValidate

func ModuleValidate(engine *Engine, wasm []byte) error

ModuleValidate validates whether `wasm` would be a valid wasm module according to the configuration in `store`

func Wat2Wasm

func Wat2Wasm(wat string) ([]byte, error)

Wat2Wasm converts the text format of WebAssembly to the binary format.

Takes the text format in-memory as input, and returns either the binary encoding of the text format or an error if parsing fails.

Types

type AsExtern

type AsExtern interface {
	AsExtern() C.wasmtime_extern_t
}

AsExtern is an interface for all types which can be imported or exported as an Extern

type AsExternType

type AsExternType interface {
	AsExternType() *ExternType
}

AsExternType is an interface for all types which can be ExternType.

type Caller

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

Caller is provided to host-defined functions when they're invoked from WebAssembly.

A `Caller` can be used for `Storelike` arguments to allow recursive execution or creation of wasm objects. Additionally `Caller` can be used to learn about the exports of the calling instance.

func (*Caller) Context added in v0.28.0

func (c *Caller) Context() *C.wasmtime_context_t

Implementation of the `Storelike` interface for `Caller`.

func (*Caller) GetExport

func (c *Caller) GetExport(name string) *Extern

GetExport gets an exported item from the caller's module.

May return `nil` if the export doesn't, if it's not a memory, if there isn't a caller, etc.

type Config

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

Config holds options used to create an Engine and customize its behavior.

Example (Fuel)

Example of limiting a WebAssembly function's runtime using "fuel consumption".

package main

import (
	"fmt"
	"log"

	"github.com/bytecodealliance/wasmtime-go"
)

func main() {
	config := wasmtime.NewConfig()
	config.SetConsumeFuel(true)
	engine := wasmtime.NewEngineWithConfig(config)
	store := wasmtime.NewStore(engine)
	err := store.AddFuel(10000)
	if err != nil {
		log.Fatal(err)
	}

	// Compile and instantiate a small example with an infinite loop.
	wasm, err := wasmtime.Wat2Wasm(`
	(module
	  (func $fibonacci (param $n i32) (result i32)
	    (if
	      (i32.lt_s (local.get $n) (i32.const 2))
	      (return (local.get $n))
	    )
	    (i32.add
	      (call $fibonacci (i32.sub (local.get $n) (i32.const 1)))
	      (call $fibonacci (i32.sub (local.get $n) (i32.const 2)))
	    )
	  )
	  (export "fibonacci" (func $fibonacci))
	)
	`)
	if err != nil {
		log.Fatal(err)
	}
	module, err := wasmtime.NewModule(store.Engine, wasm)
	if err != nil {
		log.Fatal(err)
	}
	instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{})
	if err != nil {
		log.Fatal(err)
	}

	// Invoke `fibonacci` export with higher and higher numbers until we exhaust our fuel.
	fibonacci := instance.GetFunc(store, "fibonacci")
	if fibonacci == nil {
		log.Fatal("Failed to find function export `fibonacci`")
	}
	for n := 0; ; n++ {
		fuelBefore, _ := store.FuelConsumed()
		output, err := fibonacci.Call(store, n)
		if err != nil {
			break
		}
		fuelAfter, _ := store.FuelConsumed()
		fmt.Printf("fib(%d) = %d [consumed %d fuel]\n", n, output, fuelAfter-fuelBefore)
		err = store.AddFuel(fuelAfter - fuelBefore)
		if err != nil {
			log.Fatal(err)
		}
	}
}
Output:
fib(0) = 0 [consumed 6 fuel]
fib(1) = 1 [consumed 6 fuel]
fib(2) = 1 [consumed 26 fuel]
fib(3) = 2 [consumed 46 fuel]
fib(4) = 3 [consumed 86 fuel]
fib(5) = 5 [consumed 146 fuel]
fib(6) = 8 [consumed 246 fuel]
fib(7) = 13 [consumed 406 fuel]
fib(8) = 21 [consumed 666 fuel]
fib(9) = 34 [consumed 1086 fuel]
fib(10) = 55 [consumed 1766 fuel]
fib(11) = 89 [consumed 2866 fuel]
fib(12) = 144 [consumed 4646 fuel]
fib(13) = 233 [consumed 7526 fuel]
Example (Interrupt)

Small example of how you can interrupt the execution of a wasm module to ensure that it doesn't run for too long.

package main

import (
	"errors"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/bytecodealliance/wasmtime-go"
)

func main() {
	// Enable interruptable code via `Config` and then create an interrupt
	// handle which we'll use later to interrupt running code.
	config := wasmtime.NewConfig()
	config.SetEpochInterruption(true)
	engine := wasmtime.NewEngineWithConfig(config)
	store := wasmtime.NewStore(engine)
	store.SetEpochDeadline(1)

	// Compile and instantiate a small example with an infinite loop.
	wasm, err := wasmtime.Wat2Wasm(`
	(module
	  (func (export "run")
	    (loop
	      br 0)
	  )
	)
	`)
	if err != nil {
		log.Fatal(err)
	}
	module, err := wasmtime.NewModule(store.Engine, wasm)
	if err != nil {
		log.Fatal(err)
	}
	instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{})
	if err != nil {
		log.Fatal(err)
	}
	run := instance.GetFunc(store, "run")
	if run == nil {
		log.Fatal("Failed to find function export `run`")
	}

	// Spin up a goroutine to send us an interrupt in a second
	go func() {
		time.Sleep(1 * time.Second)
		fmt.Println("Interrupting!")
		engine.IncrementEpoch()
	}()

	fmt.Println("Entering infinite loop ...")
	_, err = run.Call(store)
	var trap *wasmtime.Trap
	if !errors.As(err, &trap) {
		log.Fatal("Unexpected error")
	}

	fmt.Println("trap received...")
	if !strings.Contains(trap.Message(), "wasm trap: interrupt") {
		log.Fatalf("Unexpected trap: %s", trap.Message())
	}
}
Output:
Entering infinite loop ...
Interrupting!
trap received...
Example (Multi)

An example of enabling the multi-value feature of WebAssembly and interacting with multi-value functions.

package main

import (
	"fmt"
	"log"

	"github.com/bytecodealliance/wasmtime-go"
)

func main() {
	// Configure our `Store`, but be sure to use a `Config` that enables the
	// wasm multi-value feature since it's not stable yet.
	config := wasmtime.NewConfig()
	config.SetWasmMultiValue(true)
	store := wasmtime.NewStore(wasmtime.NewEngineWithConfig(config))

	wasm, err := wasmtime.Wat2Wasm(`
	(module
	  (func $f (import "" "f") (param i32 i64) (result i64 i32))

	  (func $g (export "g") (param i32 i64) (result i64 i32)
	    (call $f (local.get 0) (local.get 1))
	  )

	  (func $round_trip_many
	    (export "round_trip_many")
	    (param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64)
	    (result i64 i64 i64 i64 i64 i64 i64 i64 i64 i64)

	    local.get 0
	    local.get 1
	    local.get 2
	    local.get 3
	    local.get 4
	    local.get 5
	    local.get 6
	    local.get 7
	    local.get 8
	    local.get 9
	  )
	)
	`)
	if err != nil {
		log.Fatal(err)
	}
	module, err := wasmtime.NewModule(store.Engine, wasm)
	if err != nil {
		log.Fatal(err)
	}

	callback := wasmtime.WrapFunc(store, func(a int32, b int64) (int64, int32) {
		return b + 1, a + 1
	})

	instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{callback})
	if err != nil {
		log.Fatal(err)
	}

	g := instance.GetFunc(store, "g")

	results, err := g.Call(store, 1, 3)
	if err != nil {
		log.Fatal(err)
	}
	arr := results.([]wasmtime.Val)
	a := arr[0].I64()
	b := arr[1].I32()
	fmt.Printf("> %d %d\n", a, b)

	if a != 4 {
		log.Fatal("unexpected value for a")
	}
	if b != 2 {
		log.Fatal("unexpected value for b")
	}

	roundTripMany := instance.GetFunc(store, "round_trip_many")
	results, err = roundTripMany.Call(store, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
	if err != nil {
		log.Fatal(err)
	}
	arr = results.([]wasmtime.Val)

	for i := 0; i < len(arr); i++ {
		fmt.Printf(" %d", arr[i].Get())
		if arr[i].I64() != int64(i) {
			log.Fatal("unexpected value for arr[i]")
		}
	}
}
Output:
> 4 2
 0 1 2 3 4 5 6 7 8 9

func NewConfig

func NewConfig() *Config

NewConfig creates a new `Config` with all default options configured.

func (*Config) CacheConfigLoad added in v0.16.0

func (cfg *Config) CacheConfigLoad(path string) error

CacheConfigLoad enables compiled code caching for this `Config` using the settings specified in the configuration file `path`.

For more information about caching and configuration options see https://bytecodealliance.github.io/wasmtime/cli-cache.html

func (*Config) CacheConfigLoadDefault added in v0.16.0

func (cfg *Config) CacheConfigLoadDefault() error

CacheConfigLoadDefault enables compiled code caching for this `Config` using the default settings configuration can be found.

For more information about caching see https://bytecodealliance.github.io/wasmtime/cli-cache.html

func (*Config) SetConsumeFuel added in v0.34.0

func (cfg *Config) SetConsumeFuel(enabled bool)

SetConsumFuel configures whether fuel is enabled

func (*Config) SetCraneliftDebugVerifier

func (cfg *Config) SetCraneliftDebugVerifier(enabled bool)

SetCraneliftDebugVerifier configures whether the cranelift debug verifier will be active when cranelift is used to compile wasm code.

func (*Config) SetCraneliftOptLevel

func (cfg *Config) SetCraneliftOptLevel(level OptLevel)

SetCraneliftOptLevel configures the cranelift optimization level for generated code

func (*Config) SetDebugInfo

func (cfg *Config) SetDebugInfo(enabled bool)

SetDebugInfo configures whether dwarf debug information for JIT code is enabled

func (*Config) SetEpochInterruption added in v0.36.0

func (cfg *Config) SetEpochInterruption(enable bool)

SetEpochInterruption enables epoch-based instrumentation of generated code to interrupt WebAssembly execution when the current engine epoch exceeds a defined threshold.

func (*Config) SetProfiler

func (cfg *Config) SetProfiler(profiler ProfilingStrategy)

SetProfiler configures what profiler strategy to use for generated code

func (*Config) SetStrategy

func (cfg *Config) SetStrategy(strat Strategy)

SetStrategy configures what compilation strategy is used to compile wasm code

func (*Config) SetWasmBulkMemory

func (cfg *Config) SetWasmBulkMemory(enabled bool)

SetWasmBulkMemory configures whether the wasm bulk memory proposal is enabled

func (*Config) SetWasmMemory64 added in v0.30.0

func (cfg *Config) SetWasmMemory64(enabled bool)

SetWasmMemory64 configures whether the wasm memory64 proposal is enabled

func (*Config) SetWasmMultiMemory added in v0.29.0

func (cfg *Config) SetWasmMultiMemory(enabled bool)

SetWasmMultiMemory configures whether the wasm multi memory proposal is enabled

func (*Config) SetWasmMultiValue

func (cfg *Config) SetWasmMultiValue(enabled bool)

SetWasmMultiValue configures whether the wasm multi value proposal is enabled

func (*Config) SetWasmReferenceTypes

func (cfg *Config) SetWasmReferenceTypes(enabled bool)

SetWasmReferenceTypes configures whether the wasm reference types proposal is enabled

func (*Config) SetWasmSIMD

func (cfg *Config) SetWasmSIMD(enabled bool)

SetWasmSIMD configures whether the wasm SIMD proposal is enabled

func (*Config) SetWasmThreads

func (cfg *Config) SetWasmThreads(enabled bool)

SetWasmThreads configures whether the wasm threads proposal is enabled

type Engine

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

Engine is an instance of a wasmtime engine which is used to create a `Store`.

Engines are a form of global configuration for wasm compilations and modules and such.

func NewEngine

func NewEngine() *Engine

NewEngine creates a new `Engine` with default configuration.

func NewEngineWithConfig

func NewEngineWithConfig(config *Config) *Engine

NewEngineWithConfig creates a new `Engine` with the `Config` provided

Note that once a `Config` is passed to this method it cannot be used again.

func (*Engine) IncrementEpoch added in v0.36.0

func (engine *Engine) IncrementEpoch()

IncrementEpoch will increase the current epoch number by 1 within the current engine which will cause any connected stores with their epoch deadline exceeded to now be interrupted.

This method is safe to call from any goroutine.

type Error

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

func (*Error) Error

func (e *Error) Error() string

type ExportType

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

ExportType is one of the exports component. A module defines a set of exports that become accessible to the host environment once the module has been instantiated.

func NewExportType

func NewExportType(name string, ty AsExternType) *ExportType

NewExportType creates a new `ExportType` with the `name` and the type provided.

func (*ExportType) Name

func (ty *ExportType) Name() string

Name returns the name in the module this export type is exporting

func (*ExportType) Type

func (ty *ExportType) Type() *ExternType

Type returns the type of item this export type expects

type Extern

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

Extern is an external value, which is the runtime representation of an entity that can be imported or exported. It is an address denoting either a function instance, table instance, memory instance, or global instances in the shared store. Read more in [spec](https://webassembly.github.io/spec/core/exec/runtime.html#external-values)

func (*Extern) AsExtern

func (e *Extern) AsExtern() C.wasmtime_extern_t

func (*Extern) Func

func (e *Extern) Func() *Func

Func returns a Func if this export is a function or nil otherwise

func (*Extern) Global

func (e *Extern) Global() *Global

Global returns a Global if this export is a global or nil otherwise

func (*Extern) Memory

func (e *Extern) Memory() *Memory

Memory returns a Memory if this export is a memory or nil otherwise

func (*Extern) Table

func (e *Extern) Table() *Table

Table returns a Table if this export is a table or nil otherwise

func (*Extern) Type

func (e *Extern) Type(store Storelike) *ExternType

Type returns the type of this export

type ExternType

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

ExternType means one of external types which classify imports and external values with their respective types.

func (*ExternType) AsExternType

func (ty *ExternType) AsExternType() *ExternType

AsExternType returns this type itself

func (*ExternType) FuncType

func (ty *ExternType) FuncType() *FuncType

FuncType returns the underlying `FuncType` for this `ExternType` if it's a function type. Otherwise returns `nil`.

func (*ExternType) GlobalType

func (ty *ExternType) GlobalType() *GlobalType

GlobalType returns the underlying `GlobalType` for this `ExternType` if it's a *global* type. Otherwise returns `nil`.

func (*ExternType) MemoryType

func (ty *ExternType) MemoryType() *MemoryType

MemoryType returns the underlying `MemoryType` for this `ExternType` if it's a *memory* type. Otherwise returns `nil`.

func (*ExternType) TableType

func (ty *ExternType) TableType() *TableType

TableType returns the underlying `TableType` for this `ExternType` if it's a *table* type. Otherwise returns `nil`.

type Frame

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

Frame is one of activation frames which carry the return arity n of the respective function, hold the values of its locals (including arguments) in the order corresponding to their static local indices, and a reference to the function’s own module instance

func (*Frame) FuncIndex

func (f *Frame) FuncIndex() uint32

FuncIndex returns the function index in the wasm module that this frame represents

func (*Frame) FuncName

func (f *Frame) FuncName() *string

FuncName returns the name, if available, for this frame's function

func (*Frame) FuncOffset added in v0.16.0

func (f *Frame) FuncOffset() uint

FuncOffset returns offset of this frame's instruction into the original function

func (*Frame) ModuleName

func (f *Frame) ModuleName() *string

ModuleName returns the name, if available, for this frame's module

func (*Frame) ModuleOffset added in v0.16.0

func (f *Frame) ModuleOffset() uint

ModuleOffset returns offset of this frame's instruction into the original module

type Func

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

Func is a function instance, which is the runtime representation of a function. It effectively is a closure of the original function over the runtime module instance of its originating module. The module instance is used to resolve references to other definitions during execution of the function. Read more in [spec](https://webassembly.github.io/spec/core/exec/runtime.html#function-instances)

func NewFunc

func NewFunc(
	store Storelike,
	ty *FuncType,
	f func(*Caller, []Val) ([]Val, *Trap),
) *Func

NewFunc creates a new `Func` with the given `ty` which, when called, will call `f`

The `ty` given is the wasm type signature of the `Func` to create. When called the `f` callback receives two arguments. The first is a `Caller` to learn information about the calling context and the second is a list of arguments represented as a `Val`. The parameters are guaranteed to match the parameters types specified in `ty`.

The `f` callback is expected to produce one of two values. Results can be returned as an array of `[]Val`. The number and types of these results much match the `ty` given, otherwise the program will panic. The `f` callback can also produce a trap which will trigger trap unwinding in wasm, and the trap will be returned to the original caller.

If the `f` callback panics then the panic will be propagated to the caller as well.

func WrapFunc

func WrapFunc(
	store Storelike,
	f interface{},
) *Func

WrapFunc wraps a native Go function, `f`, as a wasm `Func`.

This function differs from `NewFunc` in that it will determine the type signature of the wasm function given the input value `f`. The `f` value provided must be a Go function. It may take any number of the following types as arguments:

`int32` - a wasm `i32`

`int64` - a wasm `i64`

`float32` - a wasm `f32`

`float64` - a wasm `f64`

`*Caller` - information about the caller's instance

`*Func` - a wasm `funcref`

anything else - a wasm `externref`

The Go function may return any number of values. It can return any number of primitive wasm values (integers/floats), and the last return value may optionally be `*Trap`. If a `*Trap` returned is `nil` then the other values are returned from the wasm function. Otherwise the `*Trap` is returned and it's considered as if the host function trapped.

If the function `f` panics then the panic will be propagated to the caller.

func (*Func) AsExtern

func (f *Func) AsExtern() C.wasmtime_extern_t

Implementation of the `AsExtern` interface for `Func`

func (*Func) Call

func (f *Func) Call(store Storelike, args ...interface{}) (interface{}, error)

Call invokes this function with the provided `args`.

This variadic function must be invoked with the correct number and type of `args` as specified by the type of this function. This property is checked at runtime. Each `args` may have one of the following types:

`int32` - a wasm `i32`

`int64` - a wasm `i64`

`float32` - a wasm `f32`

`float64` - a wasm `f64`

`Val` - correspond to a wasm value

`*Func` - a wasm `funcref`

anything else - a wasm `externref`

This function will have one of three results:

1. If the function returns successfully, then the `interface{}` return argument will be the result of the function. If there were 0 results then this value is `nil`. If there was one result then this is that result. Otherwise if there were multiple results then `[]Val` is returned.

2. If this function invocation traps, then the returned `interface{}` value will be `nil` and a non-`nil` `*Trap` will be returned with information about the trap that happened.

3. If a panic in Go ends up happening somewhere, then this function will panic.

func (*Func) Type

func (f *Func) Type(store Storelike) *FuncType

Type returns the type of this func

type FuncType

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

FuncType is one of function types which classify the signature of functions, mapping a vector of parameters to a vector of results. They are also used to classify the inputs and outputs of instructions.

func NewFuncType

func NewFuncType(params, results []*ValType) *FuncType

NewFuncType creates a new `FuncType` with the `kind` provided

func (*FuncType) AsExternType

func (ty *FuncType) AsExternType() *ExternType

AsExternType converts this type to an instance of `ExternType`

func (*FuncType) Params

func (ty *FuncType) Params() []*ValType

Params returns the parameter types of this function type

func (*FuncType) Results

func (ty *FuncType) Results() []*ValType

Results returns the result types of this function type

type Global

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

Global is a global instance, which is the runtime representation of a global variable. It holds an individual value and a flag indicating whether it is mutable. Read more in [spec](https://webassembly.github.io/spec/core/exec/runtime.html#global-instances)

func NewGlobal

func NewGlobal(
	store Storelike,
	ty *GlobalType,
	val Val,
) (*Global, error)

NewGlobal creates a new `Global` in the given `Store` with the specified `ty` and initial value `val`.

func (*Global) AsExtern

func (g *Global) AsExtern() C.wasmtime_extern_t

func (*Global) Get

func (g *Global) Get(store Storelike) Val

Get gets the value of this global

func (*Global) Set

func (g *Global) Set(store Storelike, val Val) error

Set sets the value of this global

func (*Global) Type

func (g *Global) Type(store Storelike) *GlobalType

Type returns the type of this global

type GlobalType

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

GlobalType is a ValType, which classify global variables and hold a value and can either be mutable or immutable.

func NewGlobalType

func NewGlobalType(content *ValType, mutable bool) *GlobalType

NewGlobalType creates a new `GlobalType` with the `kind` provided and whether it's `mutable` or not

func (*GlobalType) AsExternType

func (ty *GlobalType) AsExternType() *ExternType

AsExternType converts this type to an instance of `ExternType`

func (*GlobalType) Content

func (ty *GlobalType) Content() *ValType

Content returns the type of value stored in this global

func (*GlobalType) Mutable

func (ty *GlobalType) Mutable() bool

Mutable returns whether this global type is mutable or not

type ImportType

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

ImportType is one of the imports component A module defines a set of imports that are required for instantiation.

func NewImportType

func NewImportType(module, name string, ty AsExternType) *ImportType

NewImportType creates a new `ImportType` with the given `module` and `name` and the type provided.

func (*ImportType) Module

func (ty *ImportType) Module() string

Module returns the name in the module this import type is importing

func (*ImportType) Name

func (ty *ImportType) Name() *string

Name returns the name in the module this import type is importing.

Note that the returned string may be `nil` with the module linking proposal where this field is optional in the import type.

func (*ImportType) Type

func (ty *ImportType) Type() *ExternType

Type returns the type of item this import type expects

type Instance

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

Instance is an instantiated module instance. Once a module has been instantiated as an Instance, any exported function can be invoked externally via its function address funcaddr in the store S and an appropriate list val∗ of argument values.

func NewInstance

func NewInstance(store Storelike, module *Module, imports []AsExtern) (*Instance, error)

NewInstance instantiates a WebAssembly `module` with the `imports` provided.

This function will attempt to create a new wasm instance given the provided imports. This can fail if the wrong number of imports are specified, the imports aren't of the right type, or for other resource-related issues.

This will also run the `start` function of the instance, returning an error if it traps.

func (*Instance) Exports

func (instance *Instance) Exports(store Storelike) []*Extern

Exports returns a list of exports from this instance.

Each export is returned as a `*Extern` and lines up with the exports list of the associated `Module`.

func (*Instance) GetExport

func (i *Instance) GetExport(store Storelike, name string) *Extern

GetExport attempts to find an export on this instance by `name`

May return `nil` if this instance has no export named `name`

func (*Instance) GetFunc added in v0.26.0

func (i *Instance) GetFunc(store Storelike, name string) *Func

GetFunc attempts to find a function on this instance by `name`.

May return `nil` if this instance has no function named `name`, it is not a function, etc.

type Linker

type Linker struct {
	Engine *Engine
	// contains filtered or unexported fields
}

Linker implements a wasmtime Linking module, which can link instantiated modules together. More details you can see [examples for C](https://bytecodealliance.github.io/wasmtime/examples-c-linking.html) or [examples for Rust](https://bytecodealliance.github.io/wasmtime/examples-rust-linking.html)

Example
package main

import (
	"fmt"
	"log"

	"github.com/bytecodealliance/wasmtime-go"
)

func main() {
	store := wasmtime.NewStore(wasmtime.NewEngine())

	// Compile two wasm modules where the first references the second
	wasm1, err := wasmtime.Wat2Wasm(`
	(module
	  (import "wasm2" "double" (func $double (param i32) (result i32)))
	  (func (export "double_and_add") (param i32 i32) (result i32)
	    local.get 0
	    call $double
	    local.get 1
	    i32.add
	  )
	)
	`)
	if err != nil {
		log.Fatal(err)
	}

	wasm2, err := wasmtime.Wat2Wasm(`
	(module
	  (func (export "double") (param i32) (result i32)
	    local.get 0
	    i32.const 2
	    i32.mul
	  )
	)
	`)
	if err != nil {
		log.Fatal(err)
	}

	// Next compile both modules
	module1, err := wasmtime.NewModule(store.Engine, wasm1)
	if err != nil {
		log.Fatal(err)
	}
	module2, err := wasmtime.NewModule(store.Engine, wasm2)
	if err != nil {
		log.Fatal(err)
	}

	linker := wasmtime.NewLinker(store.Engine)

	// The second module is instantiated first since it has no imports, and
	// then we insert the instance back into the linker under the name
	// the first module expects.
	instance2, err := linker.Instantiate(store, module2)
	if err != nil {
		log.Fatal(err)
	}
	err = linker.DefineInstance(store, "wasm2", instance2)
	if err != nil {
		log.Fatal(err)
	}

	// And now we can instantiate our first module, executing the result
	// afterwards
	instance1, err := linker.Instantiate(store, module1)
	if err != nil {
		log.Fatal(err)
	}
	doubleAndAdd := instance1.GetFunc(store, "double_and_add")
	result, err := doubleAndAdd.Call(store, 2, 3)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Print(result.(int32))
}
Output:
7

func NewLinker

func NewLinker(engine *Engine) *Linker

func (*Linker) AllowShadowing

func (l *Linker) AllowShadowing(allow bool)

AllowShadowing configures whether names can be redefined after they've already been defined in this linker.

func (*Linker) Define

func (l *Linker) Define(module, name string, item AsExtern) error

Define defines a new item in this linker with the given module/name pair. Returns an error if shadowing is disallowed and the module/name is already defined.

func (*Linker) DefineFunc

func (l *Linker) DefineFunc(store Storelike, module, name string, f interface{}) error

DefineFunc acts as a convenience wrapper to calling Define and WrapFunc.

Returns an error if shadowing is disabled and the name is already defined.

func (*Linker) DefineInstance

func (l *Linker) DefineInstance(store Storelike, module string, instance *Instance) error

DefineInstance defines all exports of an instance provided under the module name provided.

Returns an error if shadowing is disabled and names are already defined.

func (*Linker) DefineModule added in v0.25.0

func (l *Linker) DefineModule(store Storelike, name string, module *Module) error

DefineModule defines automatic instantiations of the module in this linker.

The `name` of the module is the name within the linker, and the `module` is the one that's being instantiated. This function automatically handles WASI Commands and Reactors for instantiation and initialization. For more information see the Rust documentation -- https://docs.wasmtime.dev/api/wasmtime/struct.Linker.html#method.module.

func (*Linker) DefineWasi

func (l *Linker) DefineWasi() error

DefineWasi links a WASI module into this linker, ensuring that all exported functions are available for linking.

Returns an error if shadowing is disabled and names are already defined.

func (*Linker) FuncNew added in v0.29.0

func (l *Linker) FuncNew(module, name string, ty *FuncType, f func(*Caller, []Val) ([]Val, *Trap)) error

FuncNew defines a function in this linker in the same style as `NewFunc`

Note that this function does not require a `Storelike`, which is intentional. This function can be used to insert store-independent functions into this linker which allows this linker to be used for instantiating modules in multiple different stores.

Returns an error if shadowing is disabled and the name is already defined.

func (*Linker) FuncWrap added in v0.29.0

func (l *Linker) FuncWrap(module, name string, f interface{}) error

FuncWrap defines a function in this linker in the same style as `WrapFunc`

Note that this function does not require a `Storelike`, which is intentional. This function can be used to insert store-independent functions into this linker which allows this linker to be used for instantiating modules in multiple different stores.

Returns an error if shadowing is disabled and the name is already defined.

func (*Linker) Get added in v0.28.0

func (l *Linker) Get(store Storelike, module, name string) *Extern

GetOneByName loads an item by name from this linker.

If the item isn't defined then nil is returned, otherwise the item is returned.

func (*Linker) GetDefault added in v0.25.0

func (l *Linker) GetDefault(store Storelike, name string) (*Func, error)

GetDefault acquires the "default export" of the named module in this linker.

If there is no default item then an error is returned, otherwise the default function is returned.

For more information see the Rust documentation -- https://docs.wasmtime.dev/api/wasmtime/struct.Linker.html#method.get_default.

func (*Linker) Instantiate

func (l *Linker) Instantiate(store Storelike, module *Module) (*Instance, error)

Instantiate instantiates a module with all imports defined in this linker.

Returns an error if the instance's imports couldn't be satisfied, had the wrong types, or if a trap happened executing the start function.

type Memory

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

Memory instance is the runtime representation of a linear memory. It holds a vector of bytes and an optional maximum size, if one was specified at the definition site of the memory. Read more in [spec](https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances) In wasmtime-go, you can get the vector of bytes by the unsafe pointer of memory from `Memory.Data()`, or go style byte slice from `Memory.UnsafeData()`

Example

An example of working with the Memory type to read/write wasm memory.

package main

import (
	"log"
	"runtime"

	"github.com/bytecodealliance/wasmtime-go"
)

func main() {
	// Create our `Store` context and then compile a module and create an
	// instance from the compiled module all in one go.
	store := wasmtime.NewStore(wasmtime.NewEngine())
	wasm, err := wasmtime.Wat2Wasm(`
	(module
	  (memory (export "memory") 2 3)

	  (func (export "size") (result i32) (memory.size))
	  (func (export "load") (param i32) (result i32)
	    (i32.load8_s (local.get 0))
	  )
	  (func (export "store") (param i32 i32)
	    (i32.store8 (local.get 0) (local.get 1))
	  )

	  (data (i32.const 0x1000) "\01\02\03\04")
	)
	`)
	if err != nil {
		log.Fatal(err)
	}
	module, err := wasmtime.NewModule(store.Engine, wasm)
	if err != nil {
		log.Fatal(err)
	}
	instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{})
	if err != nil {
		log.Fatal(err)
	}

	// Load up our exports from the instance
	memory := instance.GetExport(store, "memory").Memory()
	sizeFn := instance.GetFunc(store, "size")
	loadFn := instance.GetFunc(store, "load")
	storeFn := instance.GetFunc(store, "store")

	// some helper functions we'll use below
	call32 := func(f *wasmtime.Func, args ...interface{}) int32 {
		ret, err := f.Call(store, args...)
		if err != nil {
			log.Fatal(err)
		}
		return ret.(int32)
	}
	call := func(f *wasmtime.Func, args ...interface{}) {
		_, err := f.Call(store, args...)
		if err != nil {
			log.Fatal(err)
		}
	}
	assertTraps := func(f *wasmtime.Func, args ...interface{}) {
		_, err := f.Call(store, args...)
		_, ok := err.(*wasmtime.Trap)
		if !ok {
			log.Fatal("expected a trap")
		}
	}
	assert := func(b bool) {
		if !b {
			log.Fatal("assertion failed")
		}
	}

	// Check the initial memory sizes/contents
	assert(memory.Size(store) == 2)
	assert(memory.DataSize(store) == 0x20000)
	buf := memory.UnsafeData(store)

	assert(buf[0] == 0)
	assert(buf[0x1000] == 1)
	assert(buf[0x1003] == 4)

	assert(call32(sizeFn) == 2)
	assert(call32(loadFn, 0) == 0)
	assert(call32(loadFn, 0x1000) == 1)
	assert(call32(loadFn, 0x1003) == 4)
	assert(call32(loadFn, 0x1ffff) == 0)
	assertTraps(loadFn, 0x20000)

	// We can mutate memory as well
	buf[0x1003] = 5
	call(storeFn, 0x1002, 6)
	assertTraps(storeFn, 0x20000, 0)

	assert(buf[0x1002] == 6)
	assert(buf[0x1003] == 5)
	assert(call32(loadFn, 0x1002) == 6)
	assert(call32(loadFn, 0x1003) == 5)

	// And like wasm instructions, we can grow memory
	_, err = memory.Grow(store, 1)
	assert(err == nil)
	assert(memory.Size(store) == 3)
	assert(memory.DataSize(store) == 0x30000)

	assert(call32(loadFn, 0x20000) == 0)
	call(storeFn, 0x20000, 0)
	assertTraps(loadFn, 0x30000)
	assertTraps(storeFn, 0x30000, 0)

	// Memory can fail to grow
	_, err = memory.Grow(store, 1)
	assert(err != nil)
	_, err = memory.Grow(store, 0)
	assert(err == nil)

	// Ensure that `memory` lives long enough to cover all our usages of
	// using its internal buffer we read from `UnsafeData()`
	runtime.KeepAlive(memory)

	// Finally we can also create standalone memories to get imported by
	// wasm modules too.
	memorytype := wasmtime.NewMemoryType(5, true, 5)
	memory2, err := wasmtime.NewMemory(store, memorytype)
	assert(err == nil)
	assert(memory2.Size(store) == 5)
	_, err = memory2.Grow(store, 1)
	assert(err != nil)
	_, err = memory2.Grow(store, 0)
	assert(err == nil)
}

func NewMemory

func NewMemory(store Storelike, ty *MemoryType) (*Memory, error)

NewMemory creates a new `Memory` in the given `Store` with the specified `ty`.

func (*Memory) AsExtern

func (mem *Memory) AsExtern() C.wasmtime_extern_t

func (*Memory) Data

func (mem *Memory) Data(store