Skip to content

Commit 8e7a288

Browse files
committed
wasm: use wasip1 API for parameter/env passing
Instead of hardcoding the command line parameters and the environment variables in the binary, pass them at runtime to Node.js and use the WASIp1 API to retrieve them in wasm_exec.js. The only real benefit right now is that it becomes possible to change `go.argv` and `go.env` before running a wasm binary. This also changes the syscall package for GOOS=js: it now becomes more like a libc (using wasi-libc), which means error values like `syscall.EEXIST` will actually match the one returned by the relevant libc function. Wasm binary size for packages that import the os package will be increased somewhat.
1 parent 0edeaf6 commit 8e7a288

File tree

12 files changed

+105
-57
lines changed

12 files changed

+105
-57
lines changed

main.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -770,12 +770,11 @@ func Run(pkgName string, options *compileopts.Options, cmdArgs []string) error {
770770
// for the given emulator.
771771
func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, cmdArgs, environmentVars []string, timeout time.Duration, run func(cmd *exec.Cmd, result builder.BuildResult) error) (builder.BuildResult, error) {
772772
// Determine whether we're on a system that supports environment variables
773-
// and command line parameters (operating systems, WASI) or not (baremetal,
774-
// WebAssembly in the browser). If we're on a system without an environment,
775-
// we need to pass command line arguments and environment variables through
776-
// global variables (built into the binary directly) instead of the
777-
// conventional way.
778-
needsEnvInVars := config.GOOS() == "js"
773+
// and command line parameters (operating systems, WASI) or not (baremetal).
774+
// If we're on a system without an environment, we need to pass command line
775+
// arguments and environment variables through global variables (built into
776+
// the binary directly) instead of the conventional way.
777+
needsEnvInVars := false
779778
for _, tag := range config.BuildTags() {
780779
if tag == "baremetal" {
781780
needsEnvInVars = true

src/runtime/nonhosted.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build baremetal || js || wasm_unknown
1+
//go:build baremetal || wasm_unknown
22

33
package runtime
44

src/runtime/runtime_tinygowasm.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,44 @@ func proc_exit(exitcode uint32)
2929
//export __stdio_exit
3030
func __stdio_exit()
3131

32+
var args []string
33+
34+
//go:linkname os_runtime_args os.runtime_args
35+
func os_runtime_args() []string {
36+
if args == nil {
37+
// Read the number of args (argc) and the buffer size required to store
38+
// all these args (argv).
39+
var argc, argv_buf_size uint32
40+
args_sizes_get(&argc, &argv_buf_size)
41+
if argc == 0 {
42+
return nil
43+
}
44+
45+
// Obtain the command line arguments
46+
argsSlice := make([]unsafe.Pointer, argc)
47+
buf := make([]byte, argv_buf_size)
48+
args_get(&argsSlice[0], unsafe.Pointer(&buf[0]))
49+
50+
// Convert the array of C strings to an array of Go strings.
51+
args = make([]string, argc)
52+
for i, cstr := range argsSlice {
53+
length := strlen(cstr)
54+
argString := _string{
55+
length: length,
56+
ptr: (*byte)(cstr),
57+
}
58+
args[i] = *(*string)(unsafe.Pointer(&argString))
59+
}
60+
}
61+
return args
62+
}
63+
64+
//go:wasmimport wasi_snapshot_preview1 args_get
65+
func args_get(argv *unsafe.Pointer, argv_buf unsafe.Pointer) (errno uint16)
66+
67+
//go:wasmimport wasi_snapshot_preview1 args_sizes_get
68+
func args_sizes_get(argc *uint32, argv_buf_size *uint32) (errno uint16)
69+
3270
const (
3371
putcharBufferSize = 120
3472
stdout = 1

src/runtime/runtime_wasip1.go

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22

33
package runtime
44

5-
import (
6-
"unsafe"
7-
)
8-
95
type timeUnit int64
106

117
// libc constructors
@@ -21,38 +17,6 @@ func init() {
2117
__wasm_call_ctors()
2218
}
2319

24-
var args []string
25-
26-
//go:linkname os_runtime_args os.runtime_args
27-
func os_runtime_args() []string {
28-
if args == nil {
29-
// Read the number of args (argc) and the buffer size required to store
30-
// all these args (argv).
31-
var argc, argv_buf_size uint32
32-
args_sizes_get(&argc, &argv_buf_size)
33-
if argc == 0 {
34-
return nil
35-
}
36-
37-
// Obtain the command line arguments
38-
argsSlice := make([]unsafe.Pointer, argc)
39-
buf := make([]byte, argv_buf_size)
40-
args_get(&argsSlice[0], unsafe.Pointer(&buf[0]))
41-
42-
// Convert the array of C strings to an array of Go strings.
43-
args = make([]string, argc)
44-
for i, cstr := range argsSlice {
45-
length := strlen(cstr)
46-
argString := _string{
47-
length: length,
48-
ptr: (*byte)(cstr),
49-
}
50-
args[i] = *(*string)(unsafe.Pointer(&argString))
51-
}
52-
}
53-
return args
54-
}
55-
5620
func ticksToNanoseconds(ticks timeUnit) int64 {
5721
return int64(ticks)
5822
}
@@ -97,12 +61,6 @@ func beforeExit() {
9761

9862
// Implementations of WASI APIs
9963

100-
//go:wasmimport wasi_snapshot_preview1 args_get
101-
func args_get(argv *unsafe.Pointer, argv_buf unsafe.Pointer) (errno uint16)
102-
103-
//go:wasmimport wasi_snapshot_preview1 args_sizes_get
104-
func args_sizes_get(argc *uint32, argv_buf_size *uint32) (errno uint16)
105-
10664
//go:wasmimport wasi_snapshot_preview1 clock_time_get
10765
func clock_time_get(clockid uint32, precision uint64, time *uint64) (errno uint16)
10866

src/syscall/env_libc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build nintendoswitch || wasip1
1+
//go:build js || nintendoswitch || wasip1
22

33
package syscall
44

src/syscall/errno_other.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build !wasip1 && !wasip2
1+
//go:build !js && !wasip1 && !wasip2
22

33
package syscall
44

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build wasip1
1+
//go:build js || wasip1
22

33
package syscall
44

src/syscall/syscall_libc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build nintendoswitch || wasip1 || wasip2
1+
//go:build js || nintendoswitch || wasip1 || wasip2
22

33
package syscall
44

src/syscall/syscall_libc_wasi.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build wasip1 || wasip2
1+
//go:build js || wasip1 || wasip2
22

33
package syscall
44

src/syscall/syscall_nonhosted.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build baremetal || js || wasm_unknown
1+
//go:build baremetal || wasm_unknown
22

33
package syscall
44

0 commit comments

Comments
 (0)