Adds ExportedFunctions API on CompiledModule. (#681)

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
Takeshi Yoneda
2022-07-12 12:21:56 +09:00
committed by GitHub
parent 14d892d310
commit a0478f0c5c
4 changed files with 184 additions and 1 deletions

View File

@@ -173,7 +173,28 @@ type Closer interface {
Close(context.Context) error Close(context.Context) error
} }
// Function is a WebAssembly 1.0 (20191205) function exported from an instantiated module (wazero.Runtime InstantiateModule). // ExportedFunction is a WebAssembly function exported in a module (wazero.CompiledModule).
//
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#exports%E2%91%A0
type ExportedFunction interface {
// Name returns the name of this exported function which is unique across a module.
// Note: the empty name is allowed in the WebAssembly specification so returned "" is meaningful.
Name() string
// ParamTypes are the possibly empty sequence of value types accepted by a function with this signature.
//
// See ValueType documentation for encoding rules.
ParamTypes() []ValueType
// ResultTypes are the possibly empty sequence of value types returned by a function with this signature.
//
// When WebAssembly 1.0 (20191205), there can be at most one result: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#result-types%E2%91%A0
//
// See ValueType documentation for decoding rules.
ResultTypes() []ValueType
}
// Function is a WebAssembly function exported from an instantiated module (wazero.Runtime InstantiateModule).
// //
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#syntax-func // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#syntax-func
type Function interface { type Function interface {

View File

@@ -268,6 +268,9 @@ type CompiledModule interface {
// //
// Note: It is safe to call Close while having outstanding calls from an api.Module instantiated from this. // Note: It is safe to call Close while having outstanding calls from an api.Module instantiated from this.
Close(context.Context) error Close(context.Context) error
// ExportedFunctions returns all the exported functions (api.ExportedFunction) in this module.
ExportedFunctions() []api.ExportedFunction
} }
type compiledModule struct { type compiledModule struct {
@@ -288,6 +291,11 @@ func (c *compiledModule) Close(_ context.Context) error {
return nil return nil
} }
// ExportedFunctions implements CompiledModule.ExportedFunctions
func (c *compiledModule) ExportedFunctions() []api.ExportedFunction {
return c.module.ExportedFunctions()
}
// CompileConfig allows you to override what was decoded from wasm, prior to compilation (ModuleBuilder.Compile or // CompileConfig allows you to override what was decoded from wasm, prior to compilation (ModuleBuilder.Compile or
// Runtime.CompileModule). // Runtime.CompileModule).
// //

View File

@@ -0,0 +1,41 @@
package wasm
import "github.com/tetratelabs/wazero/api"
// ExportedFunctions returns the implementations of api.ExportedFunction.
func (m *Module) ExportedFunctions() (ret []api.ExportedFunction) {
for _, exp := range m.ExportSection {
if exp.Type == ExternTypeFunc {
tp := m.TypeOfFunction(exp.Index)
ret = append(ret, &exportedFunction{
exportedName: exp.Name,
params: tp.Params,
results: tp.Results,
})
}
}
return
}
// exportedFunction implements api.ExportedFunction
type exportedFunction struct {
// exportedName is the name of export entry of this function,
// which might differ from the one in the name custom section etc.
exportedName string
params, results []ValueType
}
// Name implements api.ExportedFunction Name.
func (e *exportedFunction) Name() string {
return e.exportedName
}
// ParamTypes implements api.ExportedFunction ParamTypes.
func (e *exportedFunction) ParamTypes() []ValueType {
return e.params
}
// ResultTypes implements api.ExportedFunction ResultTypes.
func (e *exportedFunction) ResultTypes() []ValueType {
return e.results
}

View File

@@ -0,0 +1,113 @@
package wasm
import (
"testing"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/testing/require"
)
func TestModule_ExportedFunctions(t *testing.T) {
tests := []struct {
name string
m *Module
exp []api.ExportedFunction
}{
{
name: "no exports",
m: &Module{},
},
{
name: "no functions",
m: &Module{
ExportSection: []*Export{{Type: ExternTypeGlobal, Index: 0}},
GlobalSection: []*Global{{}},
},
},
{
name: "without imports",
m: &Module{
ExportSection: []*Export{
{Name: "function_index=0", Type: ExternTypeFunc, Index: 0},
{Name: "function_index=2", Type: ExternTypeFunc, Index: 2},
{Name: "", Type: ExternTypeGlobal, Index: 0},
{Name: "function_index=1", Type: ExternTypeFunc, Index: 1},
},
GlobalSection: []*Global{{}},
FunctionSection: []Index{1, 2, 0},
TypeSection: []*FunctionType{
{Params: []ValueType{}, Results: []ValueType{}},
{Params: []ValueType{ValueTypeF64, ValueTypeI32}, Results: []ValueType{ValueTypeV128, ValueTypeI64}},
{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
},
},
exp: []api.ExportedFunction{
&exportedFunction{
exportedName: "function_index=0",
params: []ValueType{ValueTypeF64, ValueTypeI32},
results: []ValueType{ValueTypeV128, ValueTypeI64},
},
&exportedFunction{
exportedName: "function_index=2", params: []ValueType{}, results: []ValueType{},
},
&exportedFunction{
exportedName: "function_index=1",
params: []ValueType{ValueTypeF64, ValueTypeF32},
results: []ValueType{ValueTypeI64},
},
},
},
{
name: "with imports",
m: &Module{
ImportSection: []*Import{{
Type: ExternTypeFunc,
DescFunc: 2, // Index of type.
}},
ExportSection: []*Export{
{Name: "imported_function", Type: ExternTypeFunc, Index: 0},
{Name: "function_index=1", Type: ExternTypeFunc, Index: 1},
{Name: "function_index=2", Type: ExternTypeFunc, Index: 2},
},
FunctionSection: []Index{1, 0},
TypeSection: []*FunctionType{
{Params: []ValueType{}, Results: []ValueType{}},
{Params: []ValueType{ValueTypeF64, ValueTypeI32}, Results: []ValueType{ValueTypeV128, ValueTypeI64}},
{Params: []ValueType{ValueTypeF64, ValueTypeF32}, Results: []ValueType{ValueTypeI64}},
},
},
exp: []api.ExportedFunction{
&exportedFunction{
exportedName: "imported_function",
params: []ValueType{ValueTypeF64, ValueTypeF32},
results: []ValueType{ValueTypeI64},
},
&exportedFunction{
exportedName: "function_index=1",
params: []ValueType{ValueTypeF64, ValueTypeI32},
results: []ValueType{ValueTypeV128, ValueTypeI64},
},
&exportedFunction{
exportedName: "function_index=2",
params: []ValueType{},
results: []ValueType{},
},
},
},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
actual := tc.m.ExportedFunctions()
require.Equal(t, tc.exp, actual)
})
}
}
func TestExportedFunction(t *testing.T) {
f := &exportedFunction{exportedName: "abc", params: []ValueType{ValueTypeI32}, results: []ValueType{ValueTypeV128}}
require.Equal(t, "abc", f.exportedName)
require.Equal(t, []ValueType{ValueTypeI32}, f.ParamTypes())
require.Equal(t, []ValueType{ValueTypeV128}, f.ResultTypes())
}