cmd/link, runtime: support library mode on wasip1

This CL adds support of "library", i.e. c-shared, build mode on
wasip1. When -buildmode=c-shared is set, it builds a Wasm module
that is intended to be used as a library, instead of an executable.
It does not have the _start function. Instead, it has an
_initialize function, which initializes the runtime, but not call
the main function.

This is similar to the c-shared build mode on other platforms. One
difference is that unlike cgo callbacks, where Ms are created on-
demand, on Wasm we have only one M, so we just keep the M (and the
G) for callbacks.

For #65199.

Change-Id: Ieb21da96b25c1a9f3989d945cddc964c26f9085b
Reviewed-on: https://go-review.googlesource.com/c/go/+/604316
Reviewed-by: Achille Roussel <achille.roussel@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Cherry Mui 2024-08-08 18:45:18 -04:00
parent 0253c0f4ac
commit 0b1494f5d2
14 changed files with 85 additions and 17 deletions

View file

@ -68,6 +68,7 @@ func readWasmImport(ldr *loader.Loader, s loader.Sym) obj.WasmImport {
var wasmFuncTypes = map[string]*wasmFuncType{
"_rt0_wasm_js": {Params: []byte{}}, //
"_rt0_wasm_wasip1": {Params: []byte{}}, //
"_rt0_wasm_wasip1_lib": {Params: []byte{}}, //
"wasm_export__start": {}, //
"wasm_export_run": {Params: []byte{I32, I32}}, // argc, argv
"wasm_export_resume": {Params: []byte{}}, //
@ -418,9 +419,21 @@ func writeExportSec(ctxt *ld.Link, ldr *loader.Loader, lenHostImports int) {
switch buildcfg.GOOS {
case "wasip1":
writeUleb128(ctxt.Out, uint64(2+len(ldr.WasmExports))) // number of exports
s := ldr.Lookup("_rt0_wasm_wasip1", 0)
var entry, entryExpName string
switch ctxt.BuildMode {
case ld.BuildModeExe:
entry = "_rt0_wasm_wasip1"
entryExpName = "_start"
case ld.BuildModeCShared:
entry = "_rt0_wasm_wasip1_lib"
entryExpName = "_initialize"
}
s := ldr.Lookup(entry, 0)
if s == 0 {
ld.Errorf(nil, "export symbol %s not defined", entry)
}
idx := uint32(lenHostImports) + uint32(ldr.SymValue(s)>>16) - funcValueOffset
writeName(ctxt.Out, "_start") // the wasi entrypoint
writeName(ctxt.Out, entryExpName) // the wasi entrypoint
ctxt.Out.WriteByte(0x00) // func export
writeUleb128(ctxt.Out, uint64(idx)) // funcidx
for _, s := range ldr.WasmExports {
@ -436,6 +449,9 @@ func writeExportSec(ctxt *ld.Link, ldr *loader.Loader, lenHostImports int) {
writeUleb128(ctxt.Out, 4) // number of exports
for _, name := range []string{"run", "resume", "getsp"} {
s := ldr.Lookup("wasm_export_"+name, 0)
if s == 0 {
ld.Errorf(nil, "export symbol %s not defined", "wasm_export_"+name)
}
idx := uint32(lenHostImports) + uint32(ldr.SymValue(s)>>16) - funcValueOffset
writeName(ctxt.Out, name) // inst.exports.run/resume/getsp in wasm_exec.js
ctxt.Out.WriteByte(0x00) // func export