From fc0673430d7eb421d6e6f578484b0e124c57a003 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Sat, 29 Aug 2026 23:45:30 -0700 Subject: [PATCH] builder: add strlen to wasm builtins LLVM 22 can replace string-scanning loops with calls to strlen during optimization. Add the implementation to wasmbuiltins and invalidate cached archives. Add an optimized wasm-unknown smoke test that exercises the reflect name-decoding path which exposed the missing symbol. --- builder/wasmbuiltins.go | 4 ++-- compileopts/config.go | 5 +++-- make/smoketest.mk | 7 ++++--- testdata/wasm-unknown-opt/main.go | 15 +++++++++++++++ 4 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 testdata/wasm-unknown-opt/main.go diff --git a/builder/wasmbuiltins.go b/builder/wasmbuiltins.go index e08eb7fcf..976a93840 100644 --- a/builder/wasmbuiltins.go +++ b/builder/wasmbuiltins.go @@ -43,11 +43,11 @@ var libWasmBuiltins = Library{ sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc") }, librarySources: func(target string, _ bool) ([]string, error) { return []string{ - // memory builtins needed for llvm.memcpy.*, llvm.memmove.*, and - // llvm.memset.* LLVM intrinsics. + // Memory builtins needed for LLVM intrinsics and library calls. "libc-top-half/musl/src/string/memcpy.c", "libc-top-half/musl/src/string/memmove.c", "libc-top-half/musl/src/string/memset.c", + "libc-top-half/musl/src/string/strlen.c", // exp, exp2, and log are needed for LLVM math builtin functions // like llvm.exp.*. diff --git a/compileopts/config.go b/compileopts/config.go index 7786cd217..207584b5e 100644 --- a/compileopts/config.go +++ b/compileopts/config.go @@ -23,8 +23,9 @@ import ( // builder.Library struct but that's hard to do since we want to know the // library path in advance in several places). var libVersions = map[string]int{ - "musl": 3, - "bdwgc": 2, + "musl": 3, + "bdwgc": 2, + "wasmbuiltins": 1, } // Config keeps all configuration affecting the build in a single struct. diff --git a/make/smoketest.mk b/make/smoketest.mk index 12ecc2ad8..9b540da94 100644 --- a/make/smoketest.mk +++ b/make/smoketest.mk @@ -573,9 +573,10 @@ smoketest-riscv: | build/smoke smoketest-wasm: SMOKE_OUT = build/smoke/wasm smoketest-wasm: | build/smoke ifneq ($(WASM), 0) - $(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm examples/wasm/export - $(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm examples/wasm/main - $(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm-unknown examples/hello-wasm-unknown + $(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm examples/wasm/export + $(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm examples/wasm/main + $(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm-unknown examples/hello-wasm-unknown + $(TINYGO) build -size short -o $(SMOKE_OUT).wasm -target=wasm-unknown -opt=2 ./testdata/wasm-unknown-opt endif smoketest-flags: SMOKE_OUT = build/smoke/flags diff --git a/testdata/wasm-unknown-opt/main.go b/testdata/wasm-unknown-opt/main.go new file mode 100644 index 000000000..9a8cd9b90 --- /dev/null +++ b/testdata/wasm-unknown-opt/main.go @@ -0,0 +1,15 @@ +package main + +import "reflect" + +type value struct { + Field int +} + +//go:wasmexport typeNameLength +func typeNameLength() uint32 { + return uint32(len(reflect.TypeOf(value{}).String())) +} + +func main() { +}