Skip to content

Commit

Permalink
Merge #92
Browse files Browse the repository at this point in the history
92: feat(wasi) Support `WasiGetVersion` & other `*ForVersion` WASI API r=Hywan a=Hywan

Fix #90.
Fix #77.

⚠️ Depends on wasmerio/wasmer#1028, wasmerio/wasmer#1029, and wasmerio/wasmer#1030. They must be merged before merging this PR! Marking this PR as a draft to be sure (the shared libraries must be updated too).

This patch updates `bridge.go` and `wasmer.h` to support the new `wasmer_wasi_generate_import_object_for_version` and `wasmer_wasi_get_version` functions.

After that, this patch updates `wasi.go` to implement the new `NewDefaultWasiImportObjectForVersion`, `NewWasiImportObjectForVersion` and the `WasiGetVersion` functions. In addition to that, we create a new `WasiVersion` type.

Finally, this patch updates the tests to test this new API. And it works like a charm 👌.

Co-authored-by: Ivan Enderlin <[email protected]>
  • Loading branch information
bors[bot] and Hywan authored Jan 7, 2020
2 parents 7e05bbf + 602d931 commit c2db26b
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 17 deletions.
46 changes: 38 additions & 8 deletions wasmer/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ type cWasmerValueT C.wasmer_value_t
type cWasmerValueTag C.wasmer_value_tag
type cWasmerWasiMapDirEntryT C.wasmer_wasi_map_dir_entry_t

const cVersionLatest = C.Latest
const cVersionSnapshot0 = C.Snapshot0
const cVersionSnapshot1 = C.Snapshot1
const cVersionUnknown = C.Unknown
const cWasmF32 = C.WASM_F32
const cWasmF64 = C.WASM_F64
const cWasmFunction = C.WASM_FUNCTION
Expand Down Expand Up @@ -177,10 +181,6 @@ func cGetReturnsForImportFunc(function *cWasmerImportFuncT) []cWasmerValueTag {
return returns
}

func cNewWasmerDefaultWasiImportObject() *cWasmerImportObjectT {
return (*cWasmerImportObjectT)(C.wasmer_wasi_generate_default_import_object())
}

func cNewWasmerImportT(
moduleName string,
importName string,
Expand All @@ -199,13 +199,13 @@ func cNewWasmerImportT(

func cNewWasmerWasiImportObject(
arguments *cWasmerByteArray,
argumentsLength int,
argumentsLength uint,
environmentVariables *cWasmerByteArray,
environmentVariablesLength int,
environmentVariablesLength uint,
preopenedFiles *cWasmerByteArray,
preopenFilesLength int,
preopenFilesLength uint,
mappedDirs *cWasmerWasiMapDirEntryT,
mappedDirsLength int,
mappedDirsLength uint,
) *cWasmerImportObjectT {
return (*cWasmerImportObjectT)(C.wasmer_wasi_generate_import_object(
(*C.wasmer_byte_array)(arguments),
Expand All @@ -219,6 +219,36 @@ func cNewWasmerWasiImportObject(
))
}

func cNewWasmerWasiImportObjectForVersion(
version uint,
arguments *cWasmerByteArray,
argumentsLength uint,
environmentVariables *cWasmerByteArray,
environmentVariablesLength uint,
preopenedFiles *cWasmerByteArray,
preopenFilesLength uint,
mappedDirs *cWasmerWasiMapDirEntryT,
mappedDirsLength uint,
) *cWasmerImportObjectT {
return (*cWasmerImportObjectT)(C.wasmer_wasi_generate_import_object_for_version(
(C.uchar)(version),
(*C.wasmer_byte_array)(arguments),
(C.uint)(argumentsLength),
(*C.wasmer_byte_array)(environmentVariables),
(C.uint)(environmentVariablesLength),
(*C.wasmer_byte_array)(preopenedFiles),
(C.uint)(preopenFilesLength),
(*C.wasmer_wasi_map_dir_entry_t)(mappedDirs),
(C.uint)(mappedDirsLength),
))
}

func cWasmerWasiGetVersion(module *cWasmerModuleT) uint {
return (uint)(C.wasmer_wasi_get_version(
(*C.wasmer_module_t)(module),
))
}

func cWasmerImportObjectDestroy(importObject *cWasmerImportObjectT) {
C.wasmer_import_object_destroy((*C.wasmer_import_object_t)(importObject))
}
Expand Down
12 changes: 8 additions & 4 deletions wasmer/test/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,17 +264,21 @@ func testImportInstanceContextData(t *testing.T) {
}

func testWasiImportObject(t *testing.T) {
importObject := wasm.NewDefaultWasiImportObject()
module, err := wasm.Compile(getImportedFunctionBytes("wasi_hello_world.wasm"))
assert.NoError(t, err)

wasiVersion := wasm.WasiGetVersion(module)

assert.Equal(t, wasiVersion, wasm.Snapshot1)

importObject := wasm.NewDefaultWasiImportObjectForVersion(wasiVersion)

imports, err := wasm.NewImports().Namespace("env").Append("sum", sum, C.sum)
assert.NoError(t, err)

err = importObject.Extend(*imports)
assert.NoError(t, err)

module, err := wasm.Compile(getImportedFunctionBytes("wasi_hello_world.wasm"))
assert.NoError(t, err)

instance, err := module.InstantiateWithImportObject(importObject)
assert.NoError(t, err)

Expand Down
63 changes: 58 additions & 5 deletions wasmer/wasi.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ import (
"unsafe"
)

// WasiVersion represents the WASI version.
type WasiVersion uint

const (
// Unknown represents an unknown WASI version.
Unknown = WasiVersion(cVersionUnknown)

// Latest represents the latest WASI version.
Latest = WasiVersion(cVersionSnapshot0)

// Snapshot0 represents the `wasi_unstable` WASI version.
Snapshot0 = WasiVersion(cVersionSnapshot0)

// Snapshot1 represents the `wasi_snapshot1_preview` WASI version.
Snapshot1 = WasiVersion(cVersionSnapshot1)
)

// MapDirEntry is an entry that can be passed to `NewWasiImportObject`.
// Preopens a file for the WASI module but renames it to the given name
type MapDirEntry struct {
Expand All @@ -17,7 +34,13 @@ type MapDirEntry struct {
// To specify WASI program arguments, environment variables,
// preopened directories, and more, see `NewWasiImportObject`
func NewDefaultWasiImportObject() *ImportObject {
var inner = cNewWasmerDefaultWasiImportObject()
return NewDefaultWasiImportObjectForVersion(Latest)
}

// NewDefaultWasiImportObjectForVersion is similar to
// `NewDefaultWasiImportObject` but it specifies the WASI version.
func NewDefaultWasiImportObjectForVersion(version WasiVersion) *ImportObject {
var inner = cNewWasmerWasiImportObjectForVersion((uint)(version), nil, 0, nil, 0, nil, 0, nil, 0)

return &ImportObject{inner}
}
Expand All @@ -32,6 +55,24 @@ func NewWasiImportObject(
environmentVariables []string,
preopenedDirs []string,
mappedDirs []MapDirEntry,
) *ImportObject {
return NewWasiImportObjectForVersion(
Latest,
arguments,
environmentVariables,
preopenedDirs,
mappedDirs,
)
}

// NewWasiImportObjectForVersion is similar to `NewWasiImportObject`
// but it specifies the WASI version.
func NewWasiImportObjectForVersion(
version WasiVersion,
arguments []string,
environmentVariables []string,
preopenedDirs []string,
mappedDirs []MapDirEntry,
) *ImportObject {
var argumentsBytes = []cWasmerByteArray{}

Expand All @@ -58,11 +99,23 @@ func NewWasiImportObject(
}

var inner = cNewWasmerWasiImportObject(
(*cWasmerByteArray)(unsafe.Pointer(&argumentsBytes)), len(argumentsBytes),
(*cWasmerByteArray)(unsafe.Pointer(&environmentVariablesBytes)), len(environmentVariablesBytes),
(*cWasmerByteArray)(unsafe.Pointer(&preopenedDirsBytes)), len(preopenedDirsBytes),
(*cWasmerWasiMapDirEntryT)(unsafe.Pointer(&mappedDirsBytes)), len(mappedDirsBytes),
(*cWasmerByteArray)(unsafe.Pointer(&argumentsBytes)),
(uint)(len(argumentsBytes)),
(*cWasmerByteArray)(unsafe.Pointer(&environmentVariablesBytes)),
(uint)(len(environmentVariablesBytes)),
(*cWasmerByteArray)(unsafe.Pointer(&preopenedDirsBytes)),
(uint)(len(preopenedDirsBytes)),
(*cWasmerWasiMapDirEntryT)(unsafe.Pointer(&mappedDirsBytes)),
(uint)(len(mappedDirsBytes)),
)

return &ImportObject{inner}
}

// WasiGetVersion returns the WASI version of a module if any, other
// `Unknown` is returned.
func WasiGetVersion(module Module) WasiVersion {
return (WasiVersion)(cWasmerWasiGetVersion(
module.module,
))
}

0 comments on commit c2db26b

Please sign in to comment.