example with custom import
codefromthecrypt opened this issue · comments
Users can define their own "go" module function imports by defining a func
without a body in their source and a%_wasm.s
or %_js.s
file that uses the
CallImport
instruction.
The compiler chooses a naming prefix of "main.$funcName", if defined in the
main
package, or a fully-qualified based on the module, if elsewhere.
For example, given func logString(msg string)
and the below assembly:
#include "textflag.h"
TEXT ·logString(SB), NOSPLIT, $0
CallImport
RET
If the package was main
, the WebAssembly function name would be
"main.logString". If it was util
and your go.mod
module was
"github.com/user/me", the WebAssembly function name would be
"github.com/prep/user/me/util.logString"
You may want to add an example of this, so that you can see the impact
to the various runtimes. It is the same as the other "go".
Note that you will need to put this in a separate directory so you can
compile . or ./... and get the .s file. Also, the func
has to be called, or
the compiler will skip writing it!
Here's an example which would work the same way in user-code as go's
source tree
https://github.com/golang/go/blob/master/src/syscall/js/js.go#L569
https://github.com/golang/go/blob/master/src/syscall/js/js_js.s#L63-L65
I've been playing with this for a bit and I wonder how useful this really is 🤔 You cannot really break out of the go
module so it has be to included in those imports. This takes a true waPC
implementation off the table, for example.
I did find out that you can override the package name, though. For example, you can do this:
//go:linkname exampleImport foo.exampleImport
func exampleImport() int32
and this:
#include "textflag.h"
TEXT foo·exampleImport(SB), NOSPLIT, $0
CallImport
RET
To change the import to foo.exampleImport
in the go
module.
oh.. sorry I should have elaborated. At least in wazero, I had planned to allow folks to configure custom host functions. I think translating from the go stack semantics to a normal signature is automatable also, but at least dealing with stack pointers should work.
Ex. in worst case:
wasm_exec.NewBuilder().ExportFunction("main.logString", func(ctx context.Context, api.Module, sp uint32) {...})
Ex. in best case we mechanically do the stack pointer thing given the signature we receive (via reflection)
wasm_exec.NewBuilder().ExportFunction("main.logString", func(ctx context.Context, api.Module, offset, len uint32) {...})
In any case, you are right. Unless something allows changing the host functions in the "go" package, either directly, or via ImportRenamer, it wouldn't work