From c06dcc6c826af751a9cf26534ba5a2d815a295ed Mon Sep 17 00:00:00 2001 From: deadprogram Date: Thu, 25 Jun 2026 22:26:01 +0200 Subject: [PATCH 01/12] all: build/test using Go 1.27-rc1 Signed-off-by: deadprogram --- .github/workflows/build-macos.yml | 6 +++--- .github/workflows/linux.yml | 20 ++++++++++---------- .github/workflows/windows.yml | 8 ++++---- Dockerfile | 4 ++-- src/runtime/os_darwin_go126.go | 2 +- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index f457cc687c..846b18a9a3 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -40,7 +40,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Restore LLVM source cache uses: actions/cache/restore@v5 @@ -71,7 +71,7 @@ jobs: uses: actions/cache/restore@v5 id: cache-llvm-build with: - key: llvm-build-20-${{ matrix.os }}-v2 + key: llvm-build-20-${{ matrix.os }}-v3 path: llvm-build - name: Build LLVM if: steps.cache-llvm-build.outputs.cache-hit != 'true' @@ -131,7 +131,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Build TinyGo (LLVM ${{ matrix.version }}) run: go install -tags=llvm${{ matrix.version }} diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index fc519c07dd..74c9dc0bd3 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -23,7 +23,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Run go mod tidy run: go mod tidy @@ -36,7 +36,7 @@ jobs: # statically linked binary. runs-on: ubuntu-latest container: - image: golang:1.26-alpine + image: golang:1.27rc1-alpine outputs: version: ${{ steps.version.outputs.version }} steps: @@ -91,7 +91,7 @@ jobs: uses: actions/cache/restore@v5 id: cache-llvm-build with: - key: llvm-build-20-linux-alpine-v2 + key: llvm-build-20-linux-alpine-v3 path: llvm-build - name: Build LLVM if: steps.cache-llvm-build.outputs.cache-hit != 'true' @@ -115,7 +115,7 @@ jobs: uses: actions/cache@v5 id: cache-binaryen with: - key: binaryen-linux-alpine-v2 + key: binaryen-linux-alpine-v3 path: build/wasm-opt - name: Build Binaryen if: steps.cache-binaryen.outputs.cache-hit != 'true' @@ -160,7 +160,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Install wasmtime uses: bytecodealliance/actions/wasmtime/setup@v1 @@ -204,7 +204,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Install Node.js uses: actions/setup-node@v6 @@ -245,7 +245,7 @@ jobs: uses: actions/cache/restore@v5 id: cache-llvm-build with: - key: llvm-build-20-linux-asserts-v1 + key: llvm-build-20-linux-asserts-v2 path: llvm-build - name: Build LLVM if: steps.cache-llvm-build.outputs.cache-hit != 'true' @@ -323,7 +323,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Restore LLVM source cache uses: actions/cache/restore@v5 @@ -354,7 +354,7 @@ jobs: uses: actions/cache/restore@v5 id: cache-llvm-build with: - key: llvm-build-20-linux-${{ matrix.goarch }}-v1 + key: llvm-build-20-linux-${{ matrix.goarch }}-v2 path: llvm-build - name: Build LLVM if: steps.cache-llvm-build.outputs.cache-hit != 'true' @@ -378,7 +378,7 @@ jobs: uses: actions/cache@v5 id: cache-binaryen with: - key: binaryen-linux-${{ matrix.goarch }}-v4 + key: binaryen-linux-${{ matrix.goarch }}-v5 path: build/wasm-opt - name: Build Binaryen if: steps.cache-binaryen.outputs.cache-hit != 'true' diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 5e76e207d2..a8285e046c 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -34,7 +34,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Restore cached LLVM source uses: actions/cache/restore@v5 @@ -129,7 +129,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Download TinyGo build uses: actions/download-artifact@v8 @@ -150,7 +150,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Download TinyGo build uses: actions/download-artifact@v8 @@ -176,7 +176,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.26.4' + go-version: '1.27.0-rc.1' cache: true - name: Download TinyGo build uses: actions/download-artifact@v8 diff --git a/Dockerfile b/Dockerfile index 1fe6d2d74e..23ab6ed182 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # tinygo-llvm stage obtains the llvm source for TinyGo -FROM golang:1.26 AS tinygo-llvm +FROM golang:1.27rc1 AS tinygo-llvm RUN apt-get update && \ apt-get install -y apt-utils make cmake clang-17 ninja-build && \ @@ -33,7 +33,7 @@ RUN cd /tinygo/ && \ # tinygo-compiler copies the compiler build over to a base Go container (without # all the build tools etc). -FROM golang:1.26 AS tinygo-compiler +FROM golang:1.27rc1 AS tinygo-compiler # Copy tinygo build. COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo diff --git a/src/runtime/os_darwin_go126.go b/src/runtime/os_darwin_go126.go index d676482ca8..c013f02a87 100644 --- a/src/runtime/os_darwin_go126.go +++ b/src/runtime/os_darwin_go126.go @@ -1,4 +1,4 @@ -//go:build darwin && go1.26 +//go:build darwin && (go1.26 || go1.27) package runtime From 6853e187084043ba36c96a9a26c09ad9a661b02b Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 30 Jun 2026 20:39:18 +0200 Subject: [PATCH 02/12] compiler: support //go:linknamestd pragma Go 1.27 introduced the //go:linknamestd directive, a standard-library variant of //go:linkname that does not require importing "unsafe". The iter package switched to it for referencing runtime.newcoro and runtime.coroswitch, which caused "linker could not find symbol iter.newcoro / iter.coroswitch" errors when building with Go 1.27. Handle //go:linknamestd the same as //go:linkname, bypassing the unsafe import requirement, and add test coverage in the pragma compiler test. Signed-off-by: deadprogram --- compiler/symbol.go | 2 +- compiler/testdata/pragma.go | 6 ++++++ compiler/testdata/pragma.ll | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/symbol.go b/compiler/symbol.go index d6f680c3fa..b13b619a6c 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -470,7 +470,7 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) { info.inline = inlineHint case "//go:noinline": info.inline = inlineNone - case "//go:linkname": + case "//go:linkname", "//go:linknamestd": if len(parts) != 3 || parts[1] != f.Name() { continue } diff --git a/compiler/testdata/pragma.go b/compiler/testdata/pragma.go index ebb3a2a67b..1445937df0 100644 --- a/compiler/testdata/pragma.go +++ b/compiler/testdata/pragma.go @@ -35,6 +35,12 @@ func withLinkageName1() { //go:linkname withLinkageName2 somepkg.someFunction2 func withLinkageName2() +// Import a function from a different package using go:linknamestd (the standard +// library variant of go:linkname introduced in Go 1.27). +// +//go:linknamestd withLinkageNameStd somepkg.someFunctionStd +func withLinkageNameStd() + // Function has an 'inline hint', similar to the inline keyword in C. // //go:inline diff --git a/compiler/testdata/pragma.ll b/compiler/testdata/pragma.ll index c2c06b3d49..6722e56f82 100644 --- a/compiler/testdata/pragma.ll +++ b/compiler/testdata/pragma.ll @@ -33,6 +33,8 @@ entry: declare void @somepkg.someFunction2(ptr) #0 +declare void @somepkg.someFunctionStd(ptr) #0 + ; Function Attrs: inlinehint nounwind define hidden void @main.inlineFunc(ptr %context) unnamed_addr #3 { entry: From 7a2a7939e0d012dd380be6392c749ab2da5b13a3 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 30 Jun 2026 21:04:28 +0200 Subject: [PATCH 03/12] builder: update max supported Go version to 1.27 Signed-off-by: deadprogram --- builder/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/config.go b/builder/config.go index afada914c9..e773ecbf10 100644 --- a/builder/config.go +++ b/builder/config.go @@ -26,7 +26,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) { // Version range supported by TinyGo. const minorMin = 24 // when updating the min version, also update .github/workflows/compat.yml - const minorMax = 26 + const minorMax = 27 // Check that we support this Go toolchain version. gorootMajor, gorootMinor, err := goenv.GetGorootVersion() From 53a9324c5bff21feb14aa06d9e577895dd2f5a22 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 1 Jul 2026 10:18:40 +0200 Subject: [PATCH 04/12] compiler: support Go 1.27 generic methods via x/tools upgrade Go 1.27 adds generic methods (golang/go#77273). golang.org/x/tools go/ssa v0.42.0 does not instantiate them: objectMethod only applies receiverTypeArgs and ignores method-level type parameters, so a call such as (*math/rand/v2.Rand).N resolves to the abstract generic method and its body reaches createConst with a type-parameter-typed zero constant, triggering "panic: expected nil interface constant". Upgrade golang.org/x/tools to v0.47.0, whose go/ssa returns nil from MethodValue for generic methods and instantiates method-level type parameters. No compiler changes are required. Since x/tools v0.47.0 requires Go 1.25, raise the minimum supported Go version from 1.24 to 1.25. Signed-off-by: deadprogram --- .github/workflows/compat.yml | 2 +- builder/config.go | 2 +- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/compat.yml b/.github/workflows/compat.yml index 7ba585dc78..42f6826507 100644 --- a/.github/workflows/compat.yml +++ b/.github/workflows/compat.yml @@ -20,7 +20,7 @@ jobs: env: # Oldest versions currently supported by TinyGo LLVM: "15" - Go: "1.24" # when updating this, also update minorMin in builder/config.go + Go: "1.25" # when updating this, also update minorMin in builder/config.go steps: - name: Checkout uses: actions/checkout@v6 diff --git a/builder/config.go b/builder/config.go index e773ecbf10..4dcc2786e8 100644 --- a/builder/config.go +++ b/builder/config.go @@ -25,7 +25,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) { } // Version range supported by TinyGo. - const minorMin = 24 // when updating the min version, also update .github/workflows/compat.yml + const minorMin = 25 // when updating the min version, also update .github/workflows/compat.yml const minorMax = 27 // Check that we support this Go toolchain version. diff --git a/go.mod b/go.mod index a33d3dd7cb..4a6ee01fd0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/tinygo-org/tinygo -go 1.24.0 +go 1.25.0 require ( github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139 @@ -18,9 +18,9 @@ require ( go.bug.st/serial v1.6.4 go.bytecodealliance.org v0.6.2 go.bytecodealliance.org/cm v0.2.2 - golang.org/x/net v0.50.0 - golang.org/x/sys v0.41.0 - golang.org/x/tools v0.42.0 + golang.org/x/net v0.56.0 + golang.org/x/sys v0.46.0 + golang.org/x/tools v0.47.0 gopkg.in/yaml.v2 v2.4.0 tinygo.org/x/espflasher v0.6.1 tinygo.org/x/go-llvm v0.0.0-20260422095634-06c6725fe5e6 @@ -48,6 +48,6 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/ulikunitz/xz v0.5.12 // indirect github.com/urfave/cli/v3 v3.0.0-beta1 // indirect - golang.org/x/mod v0.33.0 // indirect - golang.org/x/text v0.34.0 // indirect + golang.org/x/mod v0.37.0 // indirect + golang.org/x/text v0.38.0 // indirect ) diff --git a/go.sum b/go.sum index 0b179750d5..1f5c9b3ccf 100644 --- a/go.sum +++ b/go.sum @@ -95,24 +95,24 @@ go.bytecodealliance.org v0.6.2 h1:Jy4u5DVmSkXgsnwojBhJ+AD/YsJsR3VzVnxF0xRCqTQ= go.bytecodealliance.org v0.6.2/go.mod h1:gqjTJm0y9NSksG4py/lSjIQ/SNuIlOQ+hCIEPQwtJgA= go.bytecodealliance.org/cm v0.2.2 h1:M9iHS6qs884mbQbIjtLX1OifgyPG9DuMs2iwz8G4WQA= go.bytecodealliance.org/cm v0.2.2/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= +golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= +golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= +golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= +golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= +golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= From 5cb825e018268629d8a6600d0fb575d9db1cb229 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Wed, 8 Jul 2026 09:14:34 +0200 Subject: [PATCH 05/12] all: update builds to use Go 1.27rc2 Signed-off-by: deadprogram --- .github/workflows/build-macos.yml | 4 ++-- .github/workflows/linux.yml | 10 +++++----- .github/workflows/windows.yml | 10 +++++----- Dockerfile | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index 846b18a9a3..09ca5d69ee 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -40,7 +40,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Restore LLVM source cache uses: actions/cache/restore@v5 @@ -131,7 +131,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Build TinyGo (LLVM ${{ matrix.version }}) run: go install -tags=llvm${{ matrix.version }} diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 74c9dc0bd3..d4721ee4c8 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -23,7 +23,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Run go mod tidy run: go mod tidy @@ -36,7 +36,7 @@ jobs: # statically linked binary. runs-on: ubuntu-latest container: - image: golang:1.27rc1-alpine + image: golang:1.27rc2-alpine outputs: version: ${{ steps.version.outputs.version }} steps: @@ -160,7 +160,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Install wasmtime uses: bytecodealliance/actions/wasmtime/setup@v1 @@ -204,7 +204,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Install Node.js uses: actions/setup-node@v6 @@ -323,7 +323,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Restore LLVM source cache uses: actions/cache/restore@v5 diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index a8285e046c..77aa5d8d6c 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -34,7 +34,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Restore cached LLVM source uses: actions/cache/restore@v5 @@ -65,7 +65,7 @@ jobs: uses: actions/cache/restore@v5 id: cache-llvm-build with: - key: llvm-build-20-windows-v5 + key: llvm-build-20-windows-v6 path: llvm-build - name: Build LLVM if: steps.cache-llvm-build.outputs.cache-hit != 'true' @@ -129,7 +129,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Download TinyGo build uses: actions/download-artifact@v8 @@ -150,7 +150,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Download TinyGo build uses: actions/download-artifact@v8 @@ -176,7 +176,7 @@ jobs: - name: Install Go uses: actions/setup-go@v6 with: - go-version: '1.27.0-rc.1' + go-version: '1.27.0-rc.2' cache: true - name: Download TinyGo build uses: actions/download-artifact@v8 diff --git a/Dockerfile b/Dockerfile index 23ab6ed182..4103d00770 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # tinygo-llvm stage obtains the llvm source for TinyGo -FROM golang:1.27rc1 AS tinygo-llvm +FROM golang:1.27rc2 AS tinygo-llvm RUN apt-get update && \ apt-get install -y apt-utils make cmake clang-17 ninja-build && \ @@ -33,7 +33,7 @@ RUN cd /tinygo/ && \ # tinygo-compiler copies the compiler build over to a base Go container (without # all the build tools etc). -FROM golang:1.27rc1 AS tinygo-compiler +FROM golang:1.27rc2 AS tinygo-compiler # Copy tinygo build. COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo From ec86c4b0f253d4307555708aed4fe554998a1c3d Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 8 Jul 2026 10:05:34 -0700 Subject: [PATCH 06/12] builder: link stack probes on Windows amd64 and arm64 Go 1.27 packages can emit stack probes on Windows amd64 and arm64. Link the compiler-rt stack probe builtins and use compiler-rt for those targets so these packages build. --- builder/builtins.go | 29 +++++++++++++++++++++++++++-- compileopts/target.go | 2 ++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/builder/builtins.go b/builder/builtins.go index f135c83dd1..1feeb5d5a3 100644 --- a/builder/builtins.go +++ b/builder/builtins.go @@ -207,6 +207,16 @@ var windowsI386Builtins = []string{ "i386/chkstk.S", // also _alloca } +// Builtins needed specifically for windows/amd64. +var windowsAMD64Builtins = []string{ + "x86_64/chkstk.S", +} + +// Builtins needed specifically for windows/arm64. +var windowsARM64Builtins = []string{ + "aarch64/chkstk.S", +} + // libCompilerRT is a library with symbols required by programs compiled with // LLVM. These symbols are for operations that cannot be emitted with a single // instruction or a short sequence of instructions for that target. @@ -233,13 +243,28 @@ var libCompilerRT = Library{ builtins = append(builtins, aeabiBuiltins...) case "avr": builtins = append(builtins, avrBuiltins...) - case "x86_64", "aarch64", "riscv64": // any 64-bit arch + case "x86_64": + builtins = append(builtins, genericBuiltins128...) + if isWindowsTriple(target) { + builtins = append(builtins, windowsAMD64Builtins...) + } + case "aarch64": + builtins = append(builtins, genericBuiltins128...) + if isWindowsTriple(target) { + builtins = append(builtins, windowsARM64Builtins...) + } + case "riscv64": builtins = append(builtins, genericBuiltins128...) case "i386": - if strings.Split(target, "-")[2] == "windows" { + if isWindowsTriple(target) { builtins = append(builtins, windowsI386Builtins...) } } return builtins, nil }, } + +func isWindowsTriple(target string) bool { + parts := strings.Split(target, "-") + return len(parts) > 2 && parts[2] == "windows" +} diff --git a/compileopts/target.go b/compileopts/target.go index 42e3734870..92b011b830 100644 --- a/compileopts/target.go +++ b/compileopts/target.go @@ -475,10 +475,12 @@ func defaultTarget(options *Options) (*TargetSpec, error) { "-m", "i386pep", "--image-base", "0x400000", ) + spec.RTLib = "compiler-rt" case "arm64": spec.LDFlags = append(spec.LDFlags, "-m", "arm64pe", ) + spec.RTLib = "compiler-rt" } spec.LDFlags = append(spec.LDFlags, "-Bdynamic", From 01066df229ea0d01928953be5cee6bff5e099d59 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 8 Jul 2026 10:05:34 -0700 Subject: [PATCH 07/12] main_test: skip json on Cortex-M QEMU with Go 1.27 Go 1.27 jsonv2 pushes testdata/json.go beyond the LM3S6965 flash budget. Keep coverage on larger emulated targets while skipping only the too-small Cortex-M QEMU configuration. --- main_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/main_test.go b/main_test.go index b7dfa6b0f5..4316c2daee 100644 --- a/main_test.go +++ b/main_test.go @@ -273,6 +273,10 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) { isWASI := strings.HasPrefix(options.Target, "wasi") isWebAssembly := isWASI || strings.HasPrefix(options.Target, "wasm") || (options.Target == "" && strings.HasPrefix(options.GOARCH, "wasm")) isBaremetal := options.Target == "simavr" || options.Target == "cortex-m-qemu" || options.Target == "riscv-qemu" + _, goMinor, err := goenv.GetGorootVersion() + if err != nil { + t.Fatal("could not get version:", goMinor) + } for _, name := range tests { if options.GOOS == "linux" && (options.GOARCH == "arm" || options.GOARCH == "386") { @@ -296,6 +300,11 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) { continue } } + if options.Target == "cortex-m-qemu" && goMinor >= 27 && name == "json.go" { + // Go 1.27 jsonv2 exceeds the LM3S6965's 256KiB flash. json.go + // is still covered by larger targets such as riscv-qemu. + continue + } if options.Target == "simavr" { // Not all tests are currently supported on AVR. // Skip the ones that aren't. From 47f445f823172e903e50f2c7890ddf273dbb0f3e Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 11 Jul 2026 14:50:44 +0200 Subject: [PATCH 08/12] test: skip compress/flate for now due to Go 1.27 changes Signed-off-by: deadprogram --- GNUmakefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index ec4c6a1a5c..42f87b6f7f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -387,7 +387,9 @@ TEST_PACKAGES_FAST = \ # archive/zip requires os.ReadAt, which is not yet supported on windows # bytes requires mmap -# compress/flate appears to hang on wasi +# compress/flate appears to hang on wasi; on all targets Go 1.27's new +# compress/flate.indexTokens returns a ~262KB struct by value which crashes +# LLVM's X86 instruction selector during LTO codegen # crypto/aes needs reflect.Type.Method(), not yet implemented # crypto/des fails on wasi, needs panic()/recover() # crypto/hmac fails on wasi, it exits with a "slice out of range" panic @@ -409,7 +411,6 @@ TEST_PACKAGES_FAST = \ # Additional standard library packages that pass tests on individual platforms TEST_PACKAGES_LINUX := \ archive/zip \ - compress/flate \ context \ crypto/aes \ crypto/des \ @@ -437,7 +438,6 @@ TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX) # os/user requires t.Skip() support TEST_PACKAGES_WINDOWS := \ - compress/flate \ crypto/des \ crypto/hmac \ image \ From 348b1b439e507f27e2b120237c50d4d3c4f803c0 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 11 Jul 2026 15:36:17 +0200 Subject: [PATCH 09/12] builder: adjust sizes test for tiny difference Signed-off-by: deadprogram --- builder/sizes_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/sizes_test.go b/builder/sizes_test.go index c73d653c0e..ee769ee9d9 100644 --- a/builder/sizes_test.go +++ b/builder/sizes_test.go @@ -42,8 +42,8 @@ func TestBinarySize(t *testing.T) { // This is a small number of very diverse targets that we want to test. tests := []sizeTest{ // microcontrollers - {"hifive1b", "examples/echo", 3771, 309, 0, 2260}, - {"microbit", "examples/serial", 2832, 368, 8, 2256}, + {"hifive1b", "examples/echo", 3769, 307, 0, 2260}, + {"microbit", "examples/serial", 2828, 368, 8, 2256}, {"wioterminal", "examples/pininterrupt", 8053, 1663, 132, 7488}, // TODO: also check wasm. Right now this is difficult, because From 062a57d8c4b7bcc75eec1838da3aaa4cbfd71382 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 11 Jul 2026 18:05:55 +0200 Subject: [PATCH 10/12] builds: update wasmtime used for CI to v36.0.11 Signed-off-by: deadprogram --- .github/workflows/linux.yml | 4 ++-- .github/workflows/windows.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index d4721ee4c8..4711909cd7 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -165,7 +165,7 @@ jobs: - name: Install wasmtime uses: bytecodealliance/actions/wasmtime/setup@v1 with: - version: "29.0.1" + version: "36.0.11" - name: Install wasm-tools uses: bytecodealliance/actions/wasm-tools/setup@v1 - name: Download release artifact @@ -213,7 +213,7 @@ jobs: - name: Install wasmtime uses: bytecodealliance/actions/wasmtime/setup@v1 with: - version: "29.0.1" + version: "36.0.11" - name: Setup `wasm-tools` uses: bytecodealliance/actions/wasm-tools/setup@v1 - name: Restore LLVM source cache diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 77aa5d8d6c..a0d07902bf 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -94,7 +94,7 @@ jobs: - name: Install wasmtime run: | scoop config use_external_7zip true - scoop install wasmtime@29.0.1 + scoop install wasmtime@36.0.11 - name: make gen-device run: make -j3 gen-device - name: Test TinyGo @@ -170,7 +170,7 @@ jobs: shell: bash run: | scoop config use_external_7zip true - scoop install binaryen wasmtime@29.0.1 + scoop install binaryen wasmtime@36.0.11 - name: Checkout uses: actions/checkout@v6 - name: Install Go From dc7e117331c1b28666ed90b83320a7b52bc31160 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 11 Jul 2026 18:28:03 +0200 Subject: [PATCH 11/12] compiler: disambiguate generic instances with function-local type aliases x/tools go/ssa names instantiations using the type argument's String(). Function-local aliases like `type F = float64` therefore collide when two callers use distinct aliases named F (Go 1.27's internal/strconv.ftoa32 and ftoa64 do exactly this). Extend localTypeArgsSuffix to detect local aliases and include their declaration position, so the float32 and float64 instantiations get distinct LLVM symbols. Fixes wrong float formatting in strconv/math on Go 1.27, and adds a regression test to testdata/localtypes.go. Signed-off-by: deadprogram --- compiler/symbol.go | 17 +++++++++++++++++ testdata/localtypes.go | 32 +++++++++++++++++++++++++++++++- testdata/localtypes.txt | 2 ++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/compiler/symbol.go b/compiler/symbol.go index b13b619a6c..3a3591a241 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -8,6 +8,7 @@ import ( "go/ast" "go/token" "go/types" + "path/filepath" "slices" "strconv" "strings" @@ -365,6 +366,22 @@ func (c *compilerContext) localTypeArgsSuffix(f *ssa.Function) string { if isLocal { hasLocal = true } + // A function-local type alias (e.g. `type F = float64` inside a + // function body) is invisible to getTypeCodeName because it calls + // types.Unalias first. Two callers that use distinct aliases with + // the same name (e.g. Go 1.27's internal/strconv.ftoa32 and ftoa64 + // both declare a local `type F = ...`) then produce identical + // RelStrings for their shortFloat[F] instantiations and collide on + // mod.NamedFunction. Treat these aliases as local so the suffix + // disambiguates them. + if alias, ok := ta.(*types.Alias); ok { + if obj := alias.Obj(); obj.Pkg() != nil && obj.Parent() != obj.Pkg().Scope() { + hasLocal = true + pos := c.program.Fset.PositionFor(obj.Pos(), false) + parts[i] = fmt.Sprintf("%s$alias:%s:%d:%d", name, filepath.Base(pos.Filename), pos.Line, pos.Column) + continue + } + } parts[i] = name } if !hasLocal { diff --git a/testdata/localtypes.go b/testdata/localtypes.go index f9081d00b6..945ccebffe 100644 --- a/testdata/localtypes.go +++ b/testdata/localtypes.go @@ -1,6 +1,9 @@ package main -import "reflect" +import ( + "reflect" + "unsafe" +) type checker = func(any) bool @@ -216,6 +219,28 @@ func issue5180CopyIgnoreNilMembers() (ok bool) { return ok } +// aliasSize is the pattern used by Go 1.27's internal/strconv.ftoa32 and +// ftoa64 (and by shortFloat in internal/strconv/uscale.go): a generic +// function parameterized on F={float32|float64} that switches on +// unsafe.Sizeof(F(0)). Callers pass F via a function-local `type F = ...` +// alias. If the two instantiations share an SSA function name (because +// x/tools' go/ssa targstr uses the alias's declared name), TinyGo's +// getFunction reuses the first LLVM function for the second call and the +// second instantiation returns the first's result. +func aliasSize[F float32 | float64]() int { + return 8 * int(unsafe.Sizeof(F(0))) +} + +func aliasSizeCaller32() int { + type F = float32 + return aliasSize[F]() +} + +func aliasSizeCaller64() int { + type F = float64 + return aliasSize[F]() +} + func main() { expect("issue5180 TestCopy1", issue5180Copy1()) expect("issue5180 TestCopyIgnoreNilMembers", issue5180CopyIgnoreNilMembers()) @@ -300,4 +325,9 @@ func main() { println("issue4931PairB labels:", issue4931PairB()) println("issue4931MethodA labels:", issue4931MethodA()) println("issue4931MethodB labels:", issue4931MethodB()) + + // Generic instances distinguished only by function-local type aliases + // must not share bodies either (the Go 1.27 strconv shortFloat pattern). + expect("aliasSize[float32]==32", aliasSizeCaller32() == 32) + expect("aliasSize[float64]==64", aliasSizeCaller64() == 64) } diff --git a/testdata/localtypes.txt b/testdata/localtypes.txt index dd5d72ddd6..9f3d778ec0 100644 --- a/testdata/localtypes.txt +++ b/testdata/localtypes.txt @@ -47,3 +47,5 @@ issue4931PairA labels: 0 issue4931PairB labels: 0 issue4931MethodA labels: 0 issue4931MethodB labels: 0 +ok: aliasSize[float32]==32 +ok: aliasSize[float64]==64 From b840c5fdfeb71a142d4d235a895d625fa3a29f09 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 11 Jul 2026 19:40:55 +0200 Subject: [PATCH 12/12] tests: skip crypto/ecdsa on wasi for now, since it never finishes Signed-off-by: deadprogram --- GNUmakefile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 42f87b6f7f..2985069220 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -479,6 +479,11 @@ TEST_PACKAGES_NONBAREMETAL = \ math \ $(nil) +TEST_PACKAGES_FAST_WASI = $(filter-out $(TEST_PACKAGES_NOWASI), $(TEST_PACKAGES_FAST)) +TEST_PACKAGES_NOWASI = \ + crypto/ecdsa \ + $(nil) + # Report platforms on which each standard library package is known to pass tests report-stdlib-tests-pass: $(eval jointmp := $(shell echo /tmp/join.$$$$)) @@ -539,12 +544,12 @@ tinygo-test-wasi: tinygo-test-wasip1: GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi tinygo-test-wasip1-fast: - $(TINYGO) test -target=wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) ./tests/runtime_wasi + $(TINYGO) test -target=wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST_WASI) ./tests/runtime_wasi tinygo-test-wasip2-slow: $(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_SLOW) tinygo-test-wasip2-fast: - $(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) ./tests/runtime_wasi + $(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST_WASI) ./tests/runtime_wasi tinygo-test-wasip2-sum-slow: TINYGO=$(TINYGO) \