From 7962e89474188b87c41f358d9bc75ab99ad9c7d1 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 10 Aug 2023 22:36:35 +0200 Subject: [PATCH] wasm: add support for GOOS=wasip1 --- Makefile | 2 ++ builder/builder_test.go | 1 + compileopts/target.go | 32 ++++++++++++++++++++- main_test.go | 16 +++++++++-- src/os/dir_unix.go | 2 +- src/os/dir_wasi.go | 2 +- src/os/env_unix_test.go | 2 +- src/os/exec_posix.go | 2 +- src/os/file_other.go | 2 +- src/os/file_unix.go | 2 +- src/os/getpagesize_test.go | 2 +- src/os/is_wasi_no_test.go | 2 +- src/os/is_wasi_test.go | 2 +- src/os/os_anyos_test.go | 2 +- src/os/os_chmod_test.go | 2 +- src/os/os_symlink_test.go | 2 +- src/os/read_test.go | 2 +- src/os/removeall_noat.go | 2 +- src/os/removeall_other.go | 2 +- src/os/{stat_linux.go => stat_linuxlike.go} | 6 +++- src/os/stat_other.go | 2 +- src/os/stat_unix.go | 2 +- src/os/tempfile_test.go | 2 +- src/os/types_unix.go | 2 +- src/runtime/env.go | 2 +- src/runtime/env_unix.go | 2 +- src/runtime/os_wasip1.go | 8 ++++++ src/runtime/runtime_wasm_js.go | 2 +- src/runtime/runtime_wasm_js_scheduler.go | 2 +- src/runtime/runtime_wasm_wasi.go | 2 +- src/syscall/errno_other.go | 2 +- src/syscall/file_emulated.go | 2 +- src/syscall/file_hosted.go | 2 +- src/syscall/proc_emulated.go | 2 +- src/syscall/proc_hosted.go | 2 +- src/syscall/syscall_libc.go | 2 +- src/syscall/syscall_libc_wasi.go | 2 +- src/testing/is_wasi_no_test.go | 2 +- src/testing/is_wasi_test.go | 2 +- 39 files changed, 94 insertions(+), 37 deletions(-) rename src/os/{stat_linux.go => stat_linuxlike.go} (82%) create mode 100644 src/runtime/os_wasip1.go diff --git a/Makefile b/Makefile index 1bb84463b0..541c08b7f4 100644 --- a/Makefile +++ b/Makefile @@ -417,6 +417,8 @@ tinygo-bench-fast: # Same thing, except for wasi rather than the current platform. tinygo-test-wasi: $(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi +tinygo-test-wasip1: + GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi tinygo-test-wasi-fast: $(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) ./tests/runtime_wasi tinygo-bench-wasi: diff --git a/builder/builder_test.go b/builder/builder_test.go index f8bdd51341..03a33b9d49 100644 --- a/builder/builder_test.go +++ b/builder/builder_test.go @@ -60,6 +60,7 @@ func TestClangAttributes(t *testing.T) { {GOOS: "darwin", GOARCH: "arm64"}, {GOOS: "windows", GOARCH: "amd64"}, {GOOS: "windows", GOARCH: "arm64"}, + {GOOS: "wasip1", GOARCH: "wasm"}, } { name := "GOOS=" + options.GOOS + ",GOARCH=" + options.GOARCH if options.GOARCH == "arm" { diff --git a/compileopts/target.go b/compileopts/target.go index 3040f9022f..249f7c3eff 100644 --- a/compileopts/target.go +++ b/compileopts/target.go @@ -191,12 +191,15 @@ func LoadTarget(options *Options) (*TargetSpec, error) { default: return nil, fmt.Errorf("invalid GOARM=%s, must be 5, 6, or 7", options.GOARM) } + case "wasm": + llvmarch = "wasm32" default: llvmarch = options.GOARCH } llvmvendor := "unknown" llvmos := options.GOOS - if llvmos == "darwin" { + switch llvmos { + case "darwin": // Use macosx* instead of darwin, otherwise darwin/arm64 will refer // to iOS! llvmos = "macosx10.12.0" @@ -207,6 +210,8 @@ func LoadTarget(options *Options) (*TargetSpec, error) { llvmos = "macosx11.0.0" } llvmvendor = "apple" + case "wasip1": + llvmos = "wasi" } // Target triples (which actually have four components, but are called // triples for historical reasons) have the form: @@ -277,6 +282,15 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) { case "arm64": spec.CPU = "generic" spec.Features = "+neon" + case "wasm": + spec.CPU = "generic" + spec.Features = "+bulk-memory,+nontrapping-fptoint,+sign-ext" + spec.BuildTags = append(spec.BuildTags, "tinygo.wasm") + spec.CFlags = append(spec.CFlags, + "-mbulk-memory", + "-mnontrapping-fptoint", + "-msign-ext", + ) } if goos == "darwin" { spec.Linker = "ld.lld" @@ -320,6 +334,22 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) { "--no-insert-timestamp", "--no-dynamicbase", ) + } else if goos == "wasip1" { + spec.GC = "" // use default GC + spec.Scheduler = "asyncify" + spec.Linker = "wasm-ld" + spec.RTLib = "compiler-rt" + spec.Libc = "wasi-libc" + spec.DefaultStackSize = 1024 * 16 // 16kB + spec.LDFlags = append(spec.LDFlags, + "--stack-first", + "--no-demangle", + ) + spec.Emulator = "wasmtime --mapdir=/tmp::{tmpDir} {}" + spec.ExtraFiles = append(spec.ExtraFiles, + "src/runtime/asm_tinygowasm.S", + "src/internal/task/task_asyncify_wasm.S", + ) } else { spec.LDFlags = append(spec.LDFlags, "-no-pie", "-Wl,--gc-sections") // WARNING: clang < 5.0 requires -nopie } diff --git a/main_test.go b/main_test.go index 32d13f9103..ae7aed564d 100644 --- a/main_test.go +++ b/main_test.go @@ -34,6 +34,16 @@ var supportedLinuxArches = map[string]string{ "X86Linux": "linux/386", "ARMLinux": "linux/arm/6", "ARM64Linux": "linux/arm64", + "WASIp1": "wasip1/wasm", +} + +func init() { + major, _, _ := goenv.GetGorootVersion() + if major < 21 { + // Go 1.20 backwards compatibility. + // Should be removed once we drop support for Go 1.20. + delete(supportedLinuxArches, "WASIp1") + } } var sema = make(chan struct{}, runtime.NumCPU()) @@ -176,6 +186,8 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) { t.Fatal("failed to load target spec:", err) } + isWebAssembly := options.Target == "wasi" || options.Target == "wasm" || (options.Target == "" && options.GOARCH == "wasm") + for _, name := range tests { if options.GOOS == "linux" && (options.GOARCH == "arm" || options.GOARCH == "386") { switch name { @@ -226,7 +238,7 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) { runTest("env.go", options, t, []string{"first", "second"}, []string{"ENV1=VALUE1", "ENV2=VALUE2"}) }) } - if options.Target == "wasi" || options.Target == "wasm" { + if isWebAssembly { t.Run("alias.go-scheduler-none", func(t *testing.T) { t.Parallel() options := compileopts.Options(options) @@ -246,7 +258,7 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) { runTest("rand.go", options, t, nil, nil) }) } - if options.Target != "wasi" && options.Target != "wasm" { + if !isWebAssembly { // The recover() builtin isn't supported yet on WebAssembly and Windows. t.Run("recover.go", func(t *testing.T) { t.Parallel() diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go index f290ea38e7..baacdd68dc 100644 --- a/src/os/dir_unix.go +++ b/src/os/dir_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build linux && !baremetal && !wasi +//go:build linux && !baremetal && !wasi && !wasip1 package os diff --git a/src/os/dir_wasi.go b/src/os/dir_wasi.go index 60a941f24f..23be3950ee 100644 --- a/src/os/dir_wasi.go +++ b/src/os/dir_wasi.go @@ -6,7 +6,7 @@ // fairly similar: we use fdopendir, fdclosedir, and readdir from wasi-libc in // a similar way that the darwin code uses functions from libc. -//go:build wasi +//go:build wasi || wasip1 package os diff --git a/src/os/env_unix_test.go b/src/os/env_unix_test.go index b5f6473e14..034f481544 100644 --- a/src/os/env_unix_test.go +++ b/src/os/env_unix_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin || linux +//go:build darwin || linux || wasip1 package os_test diff --git a/src/os/exec_posix.go b/src/os/exec_posix.go index 151520cca7..3ccb6963bb 100644 --- a/src/os/exec_posix.go +++ b/src/os/exec_posix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows +//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || wasip1 || windows package os diff --git a/src/os/file_other.go b/src/os/file_other.go index 7e5833d353..d093e3d184 100644 --- a/src/os/file_other.go +++ b/src/os/file_other.go @@ -1,4 +1,4 @@ -//go:build baremetal || (wasm && !wasi) +//go:build baremetal || (wasm && !wasi && !wasip1) package os diff --git a/src/os/file_unix.go b/src/os/file_unix.go index 6314db8fae..665fb0937e 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -1,4 +1,4 @@ -//go:build darwin || (linux && !baremetal) +//go:build darwin || (linux && !baremetal) || wasip1 // target wasi sets GOOS=linux and thus the +linux build tag, // even though it doesn't show up in "tinygo info target -wasi" diff --git a/src/os/getpagesize_test.go b/src/os/getpagesize_test.go index 705cfd47d8..80475552be 100644 --- a/src/os/getpagesize_test.go +++ b/src/os/getpagesize_test.go @@ -1,4 +1,4 @@ -//go:build windows || darwin || (linux && !baremetal) +//go:build windows || darwin || (linux && !baremetal) || wasip1 package os_test diff --git a/src/os/is_wasi_no_test.go b/src/os/is_wasi_no_test.go index a8d04b674a..aa7745085b 100644 --- a/src/os/is_wasi_no_test.go +++ b/src/os/is_wasi_no_test.go @@ -1,4 +1,4 @@ -//go:build !wasi +//go:build !wasi && !wasip1 package os_test diff --git a/src/os/is_wasi_test.go b/src/os/is_wasi_test.go index 551e000752..619b1cb64f 100644 --- a/src/os/is_wasi_test.go +++ b/src/os/is_wasi_test.go @@ -1,4 +1,4 @@ -//go:build wasi +//go:build wasi || wasip1 package os_test diff --git a/src/os/os_anyos_test.go b/src/os/os_anyos_test.go index 76bf4f368a..6c482a166c 100644 --- a/src/os/os_anyos_test.go +++ b/src/os/os_anyos_test.go @@ -1,4 +1,4 @@ -//go:build windows || darwin || (linux && !baremetal) +//go:build windows || darwin || (linux && !baremetal) || wasip1 package os_test diff --git a/src/os/os_chmod_test.go b/src/os/os_chmod_test.go index af54815d84..911438d954 100644 --- a/src/os/os_chmod_test.go +++ b/src/os/os_chmod_test.go @@ -1,4 +1,4 @@ -//go:build !baremetal && !js && !wasi +//go:build !baremetal && !js && !wasi && !wasip1 // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/src/os/os_symlink_test.go b/src/os/os_symlink_test.go index f231f8d9d5..f252116f5a 100644 --- a/src/os/os_symlink_test.go +++ b/src/os/os_symlink_test.go @@ -1,4 +1,4 @@ -//go:build !windows && !baremetal && !js && !wasi +//go:build !windows && !baremetal && !js && !wasi && !wasip1 // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/src/os/read_test.go b/src/os/read_test.go index 6915dfaf91..e037b23498 100644 --- a/src/os/read_test.go +++ b/src/os/read_test.go @@ -1,4 +1,4 @@ -//go:build !baremetal && !js && !wasi +//go:build !baremetal && !js && !wasi && !wasip1 // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/src/os/removeall_noat.go b/src/os/removeall_noat.go index 03339ae3bb..ae945c2497 100644 --- a/src/os/removeall_noat.go +++ b/src/os/removeall_noat.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !baremetal && !js && !wasi +//go:build !baremetal && !js && !wasi && !wasip1 package os diff --git a/src/os/removeall_other.go b/src/os/removeall_other.go index a388a6c222..ec055a9875 100644 --- a/src/os/removeall_other.go +++ b/src/os/removeall_other.go @@ -1,4 +1,4 @@ -//go:build baremetal || js || wasi +//go:build baremetal || js || wasi || wasip1 // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/src/os/stat_linux.go b/src/os/stat_linuxlike.go similarity index 82% rename from src/os/stat_linux.go rename to src/os/stat_linuxlike.go index d407c5c7ec..f2ff8a5f61 100644 --- a/src/os/stat_linux.go +++ b/src/os/stat_linuxlike.go @@ -1,9 +1,13 @@ -//go:build linux && !baremetal +//go:build (linux && !baremetal) || wasip1 // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Note: this file is used for both Linux and WASI. +// Eventually it might be better to spit it up, and make the syscall constants +// match the typical WASI constants instead of the Linux-equivalents used here. + package os import ( diff --git a/src/os/stat_other.go b/src/os/stat_other.go index 162313b115..ff1bc37745 100644 --- a/src/os/stat_other.go +++ b/src/os/stat_other.go @@ -1,4 +1,4 @@ -//go:build baremetal || (wasm && !wasi) +//go:build baremetal || (wasm && !wasi && !wasip1) // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/src/os/stat_unix.go b/src/os/stat_unix.go index 4667d96a70..54b2bb4857 100644 --- a/src/os/stat_unix.go +++ b/src/os/stat_unix.go @@ -1,4 +1,4 @@ -//go:build darwin || (linux && !baremetal) +//go:build darwin || (linux && !baremetal) || wasip1 // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/src/os/tempfile_test.go b/src/os/tempfile_test.go index f25390d6c2..4b7416f4e0 100644 --- a/src/os/tempfile_test.go +++ b/src/os/tempfile_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !baremetal && !js && !wasi +//go:build !baremetal && !js && !wasi && !wasip1 package os_test diff --git a/src/os/types_unix.go b/src/os/types_unix.go index 68a4e628ad..943fc00f52 100644 --- a/src/os/types_unix.go +++ b/src/os/types_unix.go @@ -1,4 +1,4 @@ -//go:build darwin || (linux && !baremetal) +//go:build darwin || (linux && !baremetal) || wasip1 // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/src/runtime/env.go b/src/runtime/env.go index dceb6bd189..72232e2f58 100644 --- a/src/runtime/env.go +++ b/src/runtime/env.go @@ -1,4 +1,4 @@ -//go:build linux || darwin || windows +//go:build linux || darwin || windows || wasip1 package runtime diff --git a/src/runtime/env_unix.go b/src/runtime/env_unix.go index e205c14d6f..42dfd5158f 100644 --- a/src/runtime/env_unix.go +++ b/src/runtime/env_unix.go @@ -1,4 +1,4 @@ -//go:build linux || darwin +//go:build linux || darwin || wasip1 package runtime diff --git a/src/runtime/os_wasip1.go b/src/runtime/os_wasip1.go new file mode 100644 index 0000000000..52ee295e90 --- /dev/null +++ b/src/runtime/os_wasip1.go @@ -0,0 +1,8 @@ +package runtime + +// The actual GOOS=wasip1, as newly added in the Go 1.21 toolchain. +// Previously we supported -target=wasi, but that was essentially faked by using +// linux/arm instead because that was the closest thing that was already +// supported in the Go standard library. + +const GOOS = "wasip1" diff --git a/src/runtime/runtime_wasm_js.go b/src/runtime/runtime_wasm_js.go index 443ed9e2ea..18ca44abec 100644 --- a/src/runtime/runtime_wasm_js.go +++ b/src/runtime/runtime_wasm_js.go @@ -1,4 +1,4 @@ -//go:build wasm && !wasi +//go:build wasm && !wasi && !wasip1 package runtime diff --git a/src/runtime/runtime_wasm_js_scheduler.go b/src/runtime/runtime_wasm_js_scheduler.go index 8f8823fef2..fc599a2a82 100644 --- a/src/runtime/runtime_wasm_js_scheduler.go +++ b/src/runtime/runtime_wasm_js_scheduler.go @@ -1,4 +1,4 @@ -//go:build wasm && !wasi && !scheduler.none +//go:build wasm && !wasi && !scheduler.none && !wasip1 package runtime diff --git a/src/runtime/runtime_wasm_wasi.go b/src/runtime/runtime_wasm_wasi.go index aec27e4c81..f258039ae6 100644 --- a/src/runtime/runtime_wasm_wasi.go +++ b/src/runtime/runtime_wasm_wasi.go @@ -1,4 +1,4 @@ -//go:build tinygo.wasm && wasi +//go:build tinygo.wasm && (wasi || wasip1) package runtime diff --git a/src/syscall/errno_other.go b/src/syscall/errno_other.go index 19822a1c6c..a001096525 100644 --- a/src/syscall/errno_other.go +++ b/src/syscall/errno_other.go @@ -1,4 +1,4 @@ -//go:build !wasi && !darwin +//go:build !wasi && !wasip1 && !darwin package syscall diff --git a/src/syscall/file_emulated.go b/src/syscall/file_emulated.go index f12d74e58e..5ed57f13b4 100644 --- a/src/syscall/file_emulated.go +++ b/src/syscall/file_emulated.go @@ -1,4 +1,4 @@ -//go:build baremetal || wasm +//go:build baremetal || (wasm && !wasip1) // This file emulates some file-related functions that are only available // under a real operating system. diff --git a/src/syscall/file_hosted.go b/src/syscall/file_hosted.go index 553322f02c..d9198a779d 100644 --- a/src/syscall/file_hosted.go +++ b/src/syscall/file_hosted.go @@ -1,4 +1,4 @@ -//go:build !baremetal && !wasm +//go:build !(baremetal || (wasm && !wasip1)) // This file assumes there is a libc available that runs on a real operating // system. diff --git a/src/syscall/proc_emulated.go b/src/syscall/proc_emulated.go index 46570f5304..d8e7ff7a92 100644 --- a/src/syscall/proc_emulated.go +++ b/src/syscall/proc_emulated.go @@ -1,4 +1,4 @@ -//go:build baremetal || wasi || wasm +//go:build baremetal || tinygo.wasm // This file emulates some process-related functions that are only available // under a real operating system. diff --git a/src/syscall/proc_hosted.go b/src/syscall/proc_hosted.go index ab35762d06..05c509e6ff 100644 --- a/src/syscall/proc_hosted.go +++ b/src/syscall/proc_hosted.go @@ -1,4 +1,4 @@ -//go:build !baremetal && !wasi && !wasm +//go:build !baremetal && !tinygo.wasm // This file assumes there is a libc available that runs on a real operating // system. diff --git a/src/syscall/syscall_libc.go b/src/syscall/syscall_libc.go index ea0a000d18..7a13245b6d 100644 --- a/src/syscall/syscall_libc.go +++ b/src/syscall/syscall_libc.go @@ -1,4 +1,4 @@ -//go:build darwin || nintendoswitch || wasi +//go:build darwin || nintendoswitch || wasi || wasip1 package syscall diff --git a/src/syscall/syscall_libc_wasi.go b/src/syscall/syscall_libc_wasi.go index a3bd3a4872..5e6a231dff 100644 --- a/src/syscall/syscall_libc_wasi.go +++ b/src/syscall/syscall_libc_wasi.go @@ -1,4 +1,4 @@ -//go:build wasi +//go:build wasi || wasip1 package syscall diff --git a/src/testing/is_wasi_no_test.go b/src/testing/is_wasi_no_test.go index 86fab391eb..630467ec0b 100644 --- a/src/testing/is_wasi_no_test.go +++ b/src/testing/is_wasi_no_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // -//go:build !wasi +//go:build !wasi && !wasip1 package testing_test diff --git a/src/testing/is_wasi_test.go b/src/testing/is_wasi_test.go index e50af901b2..e20e15fc04 100644 --- a/src/testing/is_wasi_test.go +++ b/src/testing/is_wasi_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // -//go:build wasi +//go:build wasi || wasip1 package testing_test