Skip to content

Commit 13e93c8

Browse files
committed
all: wasip2 support
1 parent d33ace7 commit 13e93c8

File tree

123 files changed

+6975
-150
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+6975
-150
lines changed

.github/workflows/linux.yml

+13-11
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,19 @@ jobs:
134134
steps:
135135
- name: Checkout
136136
uses: actions/checkout@v4
137+
with:
138+
submodules: true
137139
- name: Install Go
138140
uses: actions/setup-go@v5
139141
with:
140142
go-version: '1.22'
141143
cache: true
142144
- name: Install wasmtime
143-
run: |
144-
mkdir -p $HOME/.wasmtime $HOME/.wasmtime/bin
145-
curl https://github.com/bytecodealliance/wasmtime/releases/download/v14.0.4/wasmtime-v14.0.4-x86_64-linux.tar.xz -o wasmtime-v14.0.4-x86_64-linux.tar.xz -SfL
146-
tar -C $HOME/.wasmtime/bin --wildcards -xf wasmtime-v14.0.4-x86_64-linux.tar.xz --strip-components=1 wasmtime-v14.0.4-x86_64-linux/*
147-
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
145+
uses: bytecodealliance/actions/wasmtime/setup@v1
146+
with:
147+
version: "19.0.1"
148+
- name: Install wasm-tools
149+
uses: bytecodealliance/actions/wasm-tools/setup@v1
148150
- name: Download release artifact
149151
uses: actions/download-artifact@v4
150152
with:
@@ -154,8 +156,8 @@ jobs:
154156
mkdir -p ~/lib
155157
tar -C ~/lib -xf tinygo.linux-amd64.tar.gz
156158
ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo
157-
- run: make tinygo-test-wasi-fast
158159
- run: make tinygo-test-wasip1-fast
160+
- run: make tinygo-test-wasip2-fast
159161
- run: make smoketest
160162
assert-test-linux:
161163
# Run all tests that can run on Linux, with LLVM assertions enabled to catch
@@ -187,11 +189,11 @@ jobs:
187189
with:
188190
node-version: '18'
189191
- name: Install wasmtime
190-
run: |
191-
mkdir -p $HOME/.wasmtime $HOME/.wasmtime/bin
192-
curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v14.0.4/wasmtime-v14.0.4-x86_64-linux.tar.xz -o wasmtime-v14.0.4-x86_64-linux.tar.xz -SfL
193-
tar -C $HOME/.wasmtime/bin --wildcards -xf wasmtime-v14.0.4-x86_64-linux.tar.xz --strip-components=1 wasmtime-v14.0.4-x86_64-linux/*
194-
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
192+
uses: bytecodealliance/actions/wasmtime/setup@v1
193+
with:
194+
version: "19.0.1"
195+
- name: Setup `wasm-tools`
196+
uses: bytecodealliance/actions/wasm-tools/setup@v1
195197
- name: Restore LLVM source cache
196198
uses: actions/cache/restore@v4
197199
id: cache-llvm-source

.github/workflows/windows.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -220,5 +220,5 @@ jobs:
220220
shell: bash
221221
working-directory: build
222222
run: 7z x release.zip -r
223-
- name: Test stdlib packages on wasi
224-
run: make tinygo-test-wasi-fast TINYGO=$(PWD)/build/tinygo/bin/tinygo
223+
- name: Test stdlib packages on wasip1
224+
run: make tinygo-test-wasip1-fast TINYGO=$(PWD)/build/tinygo/bin/tinygo

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
go.work
2+
go.work.sum
3+
14
docs/_build
25
src/device/avr/*.go
36
src/device/avr/*.ld
@@ -17,7 +20,7 @@ src/device/kendryte/*.go
1720
src/device/kendryte/*.s
1821
src/device/rp/*.go
1922
src/device/rp/*.s
20-
vendor
23+
./vendor
2124
llvm-build
2225
llvm-project
2326
build/*

.gitmodules

+6
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,9 @@
3939
path = src/net
4040
url = https://github.com/tinygo-org/net.git
4141
branch = dev
42+
[submodule "lib/wasi-cli"]
43+
path = lib/wasi-cli
44+
url = https://github.com/WebAssembly/wasi-cli
45+
[submodule "src/vendor/github.com/ydnar/wasm-tools-go"]
46+
path = src/vendor/github.com/ydnar/wasm-tools-go
47+
url = https://github.com/ydnar/wasm-tools-go.git

GNUmakefile

+33-5
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
268268
@if [ ! -e lib/wasi-libc/Makefile ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
269269
cd lib/wasi-libc && $(MAKE) -j4 EXTRA_CFLAGS="-O2 -g -DNDEBUG -mnontrapping-fptoint -msign-ext" MALLOC_IMPL=none CC="$(CLANG)" AR=$(LLVM_AR) NM=$(LLVM_NM)
270270

271+
# Generate WASI syscall bindings
272+
.PHONY: wasi-syscall
273+
wasi-syscall:
274+
wit-bindgen-go generate -o ./src/internal -p internal --versioned ./lib/wasi-cli/wit
275+
271276
# Check for Node.js used during WASM tests.
272277
NODEJS_VERSION := $(word 1,$(subst ., ,$(shell node -v | cut -c 2-)))
273278
MIN_NODEJS_VERSION=18
@@ -430,15 +435,36 @@ tinygo-test-wasi:
430435
$(TINYGO) test -target wasip1 $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
431436
tinygo-test-wasip1:
432437
GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
433-
tinygo-test-wasi-fast:
434-
$(TINYGO) test -target wasip1 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
435438
tinygo-test-wasip1-fast:
436-
GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
437-
tinygo-bench-wasi:
439+
$(TINYGO) test -target=wasip1 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
440+
441+
tinygo-test-wasip2-slow:
442+
$(TINYGO) test -target=wasip2 $(TEST_PACKAGES_SLOW)
443+
tinygo-test-wasip2-fast:
444+
$(TINYGO) test -target=wasip2 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
445+
446+
tinygo-test-wasip2-sum-slow:
447+
TINYGO=$(TINYGO) \
448+
TARGET=wasip2 \
449+
TESTOPTS="-x -work" \
450+
PACKAGES="$(TEST_PACKAGES_SLOW)" \
451+
gotestsum --raw-command -- ./tools/tgtestjson.sh
452+
tinygo-test-wasip2-sum-fast:
453+
TINYGO=$(TINYGO) \
454+
TARGET=wasip2 \
455+
TESTOPTS="-x -work" \
456+
PACKAGES="$(TEST_PACKAGES_FAST)" \
457+
gotestsum --raw-command -- ./tools/tgtestjson.sh
458+
tinygo-bench-wasip1:
438459
$(TINYGO) test -target wasip1 -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
439-
tinygo-bench-wasi-fast:
460+
tinygo-bench-wasip1-fast:
440461
$(TINYGO) test -target wasip1 -bench . $(TEST_PACKAGES_FAST)
441462

463+
tinygo-bench-wasip2:
464+
$(TINYGO) test -target wasip2 -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
465+
tinygo-bench-wasip2-fast:
466+
$(TINYGO) test -target wasip2 -bench . $(TEST_PACKAGES_FAST)
467+
442468
# Test external packages in a large corpus.
443469
test-corpus:
444470
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml
@@ -832,6 +858,7 @@ build/release: tinygo gen-device wasi-libc $(if $(filter 1,$(USE_SYSTEM_BINARYEN
832858
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-bottom-half/headers
833859
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
834860
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
861+
@mkdir -p build/release/tinygo/lib/wasi-cli/
835862
@mkdir -p build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0
836863
@mkdir -p build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0plus
837864
@mkdir -p build/release/tinygo/pkg/thumbv7em-unknown-unknown-eabi-cortex-m4
@@ -891,6 +918,7 @@ endif
891918
@cp -rp lib/wasi-libc/libc-top-half/musl/src/string build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
892919
@cp -rp lib/wasi-libc/libc-top-half/musl/include build/release/tinygo/lib/wasi-libc/libc-top-half/musl
893920
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
921+
@cp -rp lib/wasi-cli/wit build/release/tinygo/lib/wasi-cli/wit
894922
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
895923
@cp -rp llvm-project/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt-builtins
896924
@cp -rp src build/release/tinygo/src

builder/build.go

+59-3
Original file line numberDiff line numberDiff line change
@@ -840,11 +840,11 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
840840
"--output", result.Executable,
841841
)
842842

843+
wasmopt := goenv.Get("WASMOPT")
843844
if config.Options.PrintCommands != nil {
844-
config.Options.PrintCommands(goenv.Get("WASMOPT"), args...)
845+
config.Options.PrintCommands(wasmopt, args...)
845846
}
846-
847-
cmd := exec.Command(goenv.Get("WASMOPT"), args...)
847+
cmd := exec.Command(wasmopt, args...)
848848
cmd.Stdout = os.Stdout
849849
cmd.Stderr = os.Stderr
850850

@@ -854,6 +854,62 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
854854
}
855855
}
856856

857+
// Run wasm-tools for component-model binaries
858+
witPackage := strings.ReplaceAll(config.Target.WITPackage, "{root}", goenv.Get("TINYGOROOT"))
859+
if config.Options.WITPackage != "" {
860+
witPackage = config.Options.WITPackage
861+
}
862+
witWorld := config.Target.WITWorld
863+
if config.Options.WITWorld != "" {
864+
witWorld = config.Options.WITWorld
865+
}
866+
if witPackage != "" && witWorld != "" {
867+
868+
// wasm-tools component embed -w wasi:cli/command
869+
// $$(tinygo env TINYGOROOT)/lib/wasi-cli/wit/ main.wasm -o embedded.wasm
870+
args := []string{
871+
"component",
872+
"embed",
873+
"-w", witWorld,
874+
witPackage,
875+
result.Executable,
876+
"-o", result.Executable,
877+
}
878+
879+
wasmtools := goenv.Get("WASMTOOLS")
880+
if config.Options.PrintCommands != nil {
881+
config.Options.PrintCommands(wasmtools, args...)
882+
}
883+
cmd := exec.Command(wasmtools, args...)
884+
cmd.Stdout = os.Stdout
885+
cmd.Stderr = os.Stderr
886+
887+
err := cmd.Run()
888+
if err != nil {
889+
return fmt.Errorf("wasm-tools failed: %w", err)
890+
}
891+
892+
// wasm-tools component new embedded.wasm -o component.wasm
893+
args = []string{
894+
"component",
895+
"new",
896+
result.Executable,
897+
"-o", result.Executable,
898+
}
899+
900+
if config.Options.PrintCommands != nil {
901+
config.Options.PrintCommands(wasmtools, args...)
902+
}
903+
cmd = exec.Command(wasmtools, args...)
904+
cmd.Stdout = os.Stdout
905+
cmd.Stderr = os.Stderr
906+
907+
err = cmd.Run()
908+
if err != nil {
909+
return fmt.Errorf("wasm-tools failed: %w", err)
910+
}
911+
}
912+
857913
// Print code size if requested.
858914
if config.Options.PrintSizes == "short" || config.Options.PrintSizes == "full" {
859915
packagePathMap := make(map[string]string, len(lprogram.Packages))

builder/builder_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func TestClangAttributes(t *testing.T) {
3434
"nintendoswitch",
3535
"riscv-qemu",
3636
"wasip1",
37+
"wasip2",
3738
"wasm",
3839
"wasm-unknown",
3940
}
@@ -61,6 +62,7 @@ func TestClangAttributes(t *testing.T) {
6162
{GOOS: "windows", GOARCH: "amd64"},
6263
{GOOS: "windows", GOARCH: "arm64"},
6364
{GOOS: "wasip1", GOARCH: "wasm"},
65+
{GOOS: "wasip2", GOARCH: "wasm"},
6466
} {
6567
name := "GOOS=" + options.GOOS + ",GOARCH=" + options.GOARCH
6668
if options.GOARCH == "arm" {

compileopts/options.go

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ type Options struct {
5353
Monitor bool
5454
BaudRate int
5555
Timeout time.Duration
56+
WITPackage string // pass through to wasm-tools component embed invocation
57+
WITWorld string // pass through to wasm-tools component embed -w option
5658
}
5759

5860
// Verify performs a validation on the given options, raising an error if options are not valid.

compileopts/target.go

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ type TargetSpec struct {
6262
JLinkDevice string `json:"jlink-device,omitempty"`
6363
CodeModel string `json:"code-model,omitempty"`
6464
RelocationModel string `json:"relocation-model,omitempty"`
65+
WITPackage string `json:"wit-package,omitempty"`
66+
WITWorld string `json:"wit-world,omitempty"`
6567
}
6668

6769
// overrideProperties overrides all properties that are set in child into itself using reflection.

compiler/symbol.go

+29-8
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
346346
// The list of allowed types is based on this proposal:
347347
// https://github.com/golang/go/issues/59149
348348
func (c *compilerContext) checkWasmImport(f *ssa.Function, pragma string) {
349-
if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" {
349+
if c.pkg.Path() == "runtime" || c.pkg.Path() == "syscall/js" || c.pkg.Path() == "syscall" {
350350
// The runtime is a special case. Allow all kinds of parameters
351351
// (importantly, including pointers).
352352
return
@@ -360,7 +360,7 @@ func (c *compilerContext) checkWasmImport(f *ssa.Function, pragma string) {
360360
c.addError(f.Signature.Results().At(1).Pos(), fmt.Sprintf("%s: too many return values", pragma))
361361
} else if f.Signature.Results().Len() == 1 {
362362
result := f.Signature.Results().At(0)
363-
if !isValidWasmType(result.Type(), true) {
363+
if !isValidWasmType(result.Type(), false) {
364364
c.addError(result.Pos(), fmt.Sprintf("%s: unsupported result type %s", pragma, result.Type().String()))
365365
}
366366
}
@@ -373,21 +373,42 @@ func (c *compilerContext) checkWasmImport(f *ssa.Function, pragma string) {
373373
}
374374
}
375375

376-
// Check whether the type maps directly to a WebAssembly type, according to:
376+
// Check whether the type maps directly to a WebAssembly type.
377+
//
378+
// This reflects the relaxed type restrictions proposed here (except for structs.HostLayout):
379+
// https://github.com/golang/go/issues/66984
380+
//
381+
// This previously reflected the additional restrictions documented here:
377382
// https://github.com/golang/go/issues/59149
378-
func isValidWasmType(typ types.Type, isReturn bool) bool {
383+
func isValidWasmType(typ types.Type, isPointerOrField bool) bool {
379384
switch typ := typ.Underlying().(type) {
380385
case *types.Basic:
381386
switch typ.Kind() {
382-
case types.Int32, types.Uint32, types.Int64, types.Uint64:
387+
case types.Bool:
388+
return true
389+
case types.Int, types.Uint, types.Int8, types.Uint8, types.Int16, types.Uint16, types.Int32, types.Uint32, types.Int64, types.Uint64:
383390
return true
384391
case types.Float32, types.Float64:
385392
return true
386-
case types.UnsafePointer:
387-
if !isReturn {
388-
return true
393+
case types.Uintptr, types.UnsafePointer:
394+
return true
395+
case types.String:
396+
return isPointerOrField
397+
}
398+
case *types.Array:
399+
return isPointerOrField && isValidWasmType(typ.Elem(), true)
400+
case *types.Struct:
401+
if !isPointerOrField {
402+
return false
403+
}
404+
for i := 0; i < typ.NumFields(); i++ {
405+
if !isValidWasmType(typ.Field(i).Type(), true) {
406+
return false
389407
}
390408
}
409+
return true
410+
case *types.Pointer:
411+
return isValidWasmType(typ.Elem(), true)
391412
}
392413
return false
393414
}

compiler/testdata/errors.go

-13
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,6 @@ type Uint uint32
1616
//go:wasmimport modulename validparam
1717
func validparam(a int32, b uint64, c float64, d unsafe.Pointer, e Uint)
1818

19-
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type int
20-
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type string
21-
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type []byte
22-
// ERROR: //go:wasmimport modulename invalidparam: unsupported parameter type *int32
23-
//
24-
//go:wasmimport modulename invalidparam
25-
func invalidparam(a int, b string, c []byte, d *int32)
26-
2719
//go:wasmimport modulename validreturn
2820
func validreturn() int32
2921

@@ -36,8 +28,3 @@ func manyreturns() (int32, int32)
3628
//
3729
//go:wasmimport modulename invalidreturn
3830
func invalidreturn() int
39-
40-
// ERROR: //go:wasmimport modulename invalidUnsafePointerReturn: unsupported result type unsafe.Pointer
41-
//
42-
//go:wasmimport modulename invalidUnsafePointerReturn
43-
func invalidUnsafePointerReturn() unsafe.Pointer

goenv/goenv.go

+5
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ func Get(name string) string {
159159
}
160160

161161
return findWasmOpt()
162+
case "WASMTOOLS":
163+
if path := os.Getenv("WASMTOOLS"); path != "" {
164+
return path
165+
}
166+
return "wasm-tools"
162167
default:
163168
return ""
164169
}

lib/wasi-cli

Submodule wasi-cli added at 6ae8261

loader/goroot.go

+3
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
240240
"internal/fuzz/": false,
241241
"internal/reflectlite/": false,
242242
"internal/task/": false,
243+
"internal/wasi/": false,
243244
"machine/": false,
244245
"net/": true,
245246
"net/http/": false,
@@ -249,6 +250,8 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
249250
"runtime/": false,
250251
"sync/": true,
251252
"testing/": true,
253+
"vendor/": true,
254+
"vendor/github.com/": false,
252255
}
253256

254257
if goMinor >= 19 {

0 commit comments

Comments
 (0)