From e79edb58b210ca11c1193583a067711aeceacbe5 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 3 Jul 2026 10:10:55 -0700 Subject: [PATCH] all: clean up code with Go 1.24+ in mind (#5489) * all: clean up code with Go 1.24+ in mind * all: more old go cleanup * all: even remove rand_fastrand64 * runtime: revert rand changes * runtime: re-drop rand_fastrand64 --- cgo/cgo.go | 4 -- cgo/cgo_go122.go | 17 ----- cgo/libclang.go | 3 +- loader/loader.go | 4 +- loader/loader_go122.go | 17 ----- main_test.go | 9 --- .../cm/{hostlayout_go123.go => hostlayout.go} | 2 - src/internal/cm/hostlayout_go122.go | 11 --- src/reflect/iter.go | 2 - src/reflect/iter_test.go | 2 - src/runtime/algorithm.go | 8 --- src/runtime/env.go | 14 ---- src/runtime/runtime.go | 7 +- src/runtime/runtime_unix.go | 28 +------- src/runtime/time.go | 66 +++++++++++++++++ src/runtime/time_go122.go | 65 ----------------- src/runtime/time_go123.go | 71 ------------------- src/sync/map.go | 6 ++ src/sync/map_go123.go | 13 ---- 19 files changed, 78 insertions(+), 271 deletions(-) delete mode 100644 cgo/cgo_go122.go delete mode 100644 loader/loader_go122.go rename src/internal/cm/{hostlayout_go123.go => hostlayout.go} (90%) delete mode 100644 src/internal/cm/hostlayout_go122.go delete mode 100644 src/runtime/time_go122.go delete mode 100644 src/runtime/time_go123.go delete mode 100644 src/sync/map_go123.go diff --git a/cgo/cgo.go b/cgo/cgo.go index 16ae5c850..af24dd181 100644 --- a/cgo/cgo.go +++ b/cgo/cgo.go @@ -26,10 +26,6 @@ import ( "golang.org/x/tools/go/ast/astutil" ) -// Function that's only defined in Go 1.22. -var setASTFileFields = func(f *ast.File, start, end token.Pos) { -} - // cgoPackage holds all CGo-related information of a package. type cgoPackage struct { generated *ast.File diff --git a/cgo/cgo_go122.go b/cgo/cgo_go122.go deleted file mode 100644 index 7304aaa28..000000000 --- a/cgo/cgo_go122.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build go1.22 - -package cgo - -// Code specifically for Go 1.22. - -import ( - "go/ast" - "go/token" -) - -func init() { - setASTFileFields = func(f *ast.File, start, end token.Pos) { - f.FileStart = start - f.FileEnd = end - } -} diff --git a/cgo/libclang.go b/cgo/libclang.go index 1f8e86ba5..ea86b7d1d 100644 --- a/cgo/libclang.go +++ b/cgo/libclang.go @@ -592,7 +592,8 @@ func (p *cgoPackage) getClangLocationPosition(location C.CXSourceLocation, tu C. Package: f.Pos(0), Name: ast.NewIdent(p.packageName), } - setASTFileFields(astFile, f.Pos(0), f.Pos(int(size))) + astFile.FileStart = f.Pos(0) + astFile.FileEnd = f.Pos(int(size)) p.cgoFiles = append(p.cgoFiles, astFile) } positionFile := p.tokenFiles[filename] diff --git a/loader/loader.go b/loader/loader.go index 61433b559..b87a95416 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -27,8 +27,6 @@ import ( "github.com/tinygo-org/tinygo/goenv" ) -var initFileVersions = func(info *types.Info) {} - // Program holds all packages and some metadata about the program as a whole. type Program struct { config *compileopts.Config @@ -435,7 +433,7 @@ func (p *Package) Check() error { } checker.GoVersion = fmt.Sprintf("go%d.%d", major, minor) } - initFileVersions(&p.info) + p.info.FileVersions = make(map[*ast.File]string) // Do typechecking of the package. packageName := p.ImportPath diff --git a/loader/loader_go122.go b/loader/loader_go122.go deleted file mode 100644 index 24d060643..000000000 --- a/loader/loader_go122.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build go1.22 - -// types.Info.FileVersions was added in Go 1.22, so we can only initialize it -// when built with Go 1.22. - -package loader - -import ( - "go/ast" - "go/types" -) - -func init() { - initFileVersions = func(info *types.Info) { - info.FileVersions = make(map[*ast.File]string) - } -} diff --git a/main_test.go b/main_test.go index 0da9e5b6b..65e6b24d9 100644 --- a/main_test.go +++ b/main_test.go @@ -46,15 +46,6 @@ var supportedLinuxArches = map[string]string{ "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()) func TestBuild(t *testing.T) { diff --git a/src/internal/cm/hostlayout_go123.go b/src/internal/cm/hostlayout.go similarity index 90% rename from src/internal/cm/hostlayout_go123.go rename to src/internal/cm/hostlayout.go index 4fc3a2bdf..60a2c4a51 100644 --- a/src/internal/cm/hostlayout_go123.go +++ b/src/internal/cm/hostlayout.go @@ -1,5 +1,3 @@ -//go:build go1.23 - package cm import "structs" diff --git a/src/internal/cm/hostlayout_go122.go b/src/internal/cm/hostlayout_go122.go deleted file mode 100644 index 25c146976..000000000 --- a/src/internal/cm/hostlayout_go122.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !go1.23 - -package cm - -// HostLayout marks a struct as using host memory layout. -// See [structs.HostLayout] in Go 1.23 or later. -type HostLayout struct { - _ hostLayout // prevent accidental conversion with plain struct{} -} - -type hostLayout struct{} diff --git a/src/reflect/iter.go b/src/reflect/iter.go index 4cc2df8fd..2c6af42f0 100644 --- a/src/reflect/iter.go +++ b/src/reflect/iter.go @@ -1,5 +1,3 @@ -//go:build go1.23 - // Copyright 2024 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. diff --git a/src/reflect/iter_test.go b/src/reflect/iter_test.go index 48c62c477..fdcc83fc9 100644 --- a/src/reflect/iter_test.go +++ b/src/reflect/iter_test.go @@ -1,5 +1,3 @@ -//go:build go1.23 - // Copyright 2024 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. diff --git a/src/runtime/algorithm.go b/src/runtime/algorithm.go index d8cd1ca43..fda226c03 100644 --- a/src/runtime/algorithm.go +++ b/src/runtime/algorithm.go @@ -7,14 +7,6 @@ import ( "unsafe" ) -// This function is needed by math/rand since Go 1.20. -// See: https://github.com/golang/go/issues/54880 -// -//go:linkname rand_fastrand64 math/rand.fastrand64 -func rand_fastrand64() uint64 { - return fastrand64() -} - // This function is used by hash/maphash. // This function isn't required anymore since Go 1.22, so should be removed once // that becomes the minimum requirement. diff --git a/src/runtime/env.go b/src/runtime/env.go index f20cc0851..e6c96f241 100644 --- a/src/runtime/env.go +++ b/src/runtime/env.go @@ -37,20 +37,6 @@ func syscallClearenv(env map[string]int) { } } -// Compatibility with Go 1.19 and below. -// -//go:linkname syscall_setenv_c syscall.setenv_c -func syscall_setenv_c(key string, val string) { - syscallSetenv(key, val) -} - -// Compatibility with Go 1.19 and below. -// -//go:linkname syscall_unsetenv_c syscall.unsetenv_c -func syscall_unsetenv_c(key string) { - syscallUnsetenv(key) -} - // cstring converts a Go string to a C string. // borrowed from syscall func cstring(s string) []byte { diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go index c9b095938..26d29dbc9 100644 --- a/src/runtime/runtime.go +++ b/src/runtime/runtime.go @@ -160,12 +160,7 @@ func write(fd uintptr, p unsafe.Pointer, n int32) int32 { if fd == 2 { // stderr // Convert to a string, because we know that p won't change during the // call to printstring. - // TODO: use unsafe.String instead once we require Go 1.20. - s := _string{ - ptr: (*byte)(p), - length: uintptr(n), - } - str := *(*string)(unsafe.Pointer(&s)) + str := unsafe.String((*byte)(p), int(n)) printstring(str) return n } diff --git a/src/runtime/runtime_unix.go b/src/runtime/runtime_unix.go index 0e2654941..12a8c265c 100644 --- a/src/runtime/runtime_unix.go +++ b/src/runtime/runtime_unix.go @@ -438,19 +438,7 @@ func tinygo_signal_disable(s uint32) // //export tinygo_signal_handler func tinygo_signal_handler(s int32) { - // The following loop is equivalent to the following: - // - // receivedSignals.Or(uint32(1) << uint32(s)) - // - // TODO: use this instead of a loop once we drop support for Go 1.22. - for { - mask := uint32(1) << uint32(s) - val := receivedSignals.Load() - swapped := receivedSignals.CompareAndSwap(val, val|mask) - if swapped { - break - } - } + receivedSignals.Or(uint32(1) << uint32(s)) // Notify the main thread that there was a signal. // This will exit the call to Wait or WaitUntil early. @@ -485,19 +473,7 @@ func signal_recv() uint32 { num := uint32(bits.TrailingZeros32(val)) // Atomically clear the signal number from receivedSignals. - // TODO: use atomic.Uint32.And once we drop support for Go 1.22 instead - // of this loop, like so: - // - // receivedSignals.And(^(uint32(1) << num)) - // - for { - newVal := val &^ (1 << num) - swapped := receivedSignals.CompareAndSwap(val, newVal) - if swapped { - break - } - val = receivedSignals.Load() - } + receivedSignals.And(^(uint32(1) << num)) return num } diff --git a/src/runtime/time.go b/src/runtime/time.go index 23a9bf5e2..e0d913e3b 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -1,5 +1,71 @@ package runtime +import "unsafe" + +// This is the timer that's used internally inside the runtime. +type timer struct { + // When to call the timer, and the interval for the ticker. + when int64 + period int64 + + // Callback from the time package. + f func(arg any, seq uintptr, delta int64) + arg any +} + +func (tim *timer) callCallback(delta int64) { + tim.f(tim.arg, 0, delta) +} + +// This is the struct used internally in the runtime. The first two fields are +// the same as time.Timer and time.Ticker so it can be used as-is in the time +// package. +type timeTimer struct { + c unsafe.Pointer // <-chan time.Time + init bool + timer +} + +//go:linkname newTimer time.newTimer +func newTimer(when, period int64, f func(arg any, seq uintptr, delta int64), arg any, c unsafe.Pointer) *timeTimer { + tim := &timeTimer{ + c: c, + init: true, + timer: timer{ + when: when, + period: period, + f: f, + arg: arg, + }, + } + scheduleLog("new timer") + addTimer(&timerNode{ + timer: &tim.timer, + callback: timerCallback, + }) + return tim +} + +//go:linkname stopTimer time.stopTimer +func stopTimer(tim *timeTimer) bool { + return removeTimer(&tim.timer) != nil +} + +//go:linkname resetTimer time.resetTimer +func resetTimer(t *timeTimer, when, period int64) bool { + t.timer.when = when + t.timer.period = period + n := removeTimer(&t.timer) + removed := n != nil + if n == nil { + n = new(timerNode) + } + n.timer = &t.timer + n.callback = timerCallback + addTimer(n) + return removed +} + //go:linkname time_runtimeNano time.runtimeNano func time_runtimeNano() int64 { // Note: we're ignoring sync groups here (package testing/synctest). diff --git a/src/runtime/time_go122.go b/src/runtime/time_go122.go deleted file mode 100644 index 2693555cf..000000000 --- a/src/runtime/time_go122.go +++ /dev/null @@ -1,65 +0,0 @@ -//go:build !go1.23 - -// Portions 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. - -package runtime - -// Time functions for Go 1.22 and below. - -type puintptr uintptr - -// Package time knows the layout of this structure. -// If this struct changes, adjust ../time/sleep.go:/runtimeTimer. -type timer struct { - // If this timer is on a heap, which P's heap it is on. - // puintptr rather than *p to match uintptr in the versions - // of this struct defined in other packages. - pp puintptr - - // Timer wakes up at when, and then at when+period, ... (period > 0 only) - // each time calling f(arg, now) in the timer goroutine, so f must be - // a well-behaved function and not block. - // - // when must be positive on an active timer. - when int64 - period int64 - f func(any, uintptr) - arg any - seq uintptr - - // What to set the when field to in timerModifiedXX status. - nextwhen int64 - - // The status field holds one of the values below. - status uint32 -} - -func (tim *timer) callCallback(delta int64) { - tim.f(tim.arg, 0) -} - -// Defined in the time package, implemented here in the runtime. -// -//go:linkname startTimer time.startTimer -func startTimer(tim *timer) { - addTimer(&timerNode{ - timer: tim, - callback: timerCallback, - }) - scheduleLog("adding timer") -} - -//go:linkname stopTimer time.stopTimer -func stopTimer(tim *timer) bool { - return removeTimer(tim) != nil -} - -//go:linkname resetTimer time.resetTimer -func resetTimer(tim *timer, when int64) bool { - tim.when = when - n := removeTimer(tim) - startTimer(tim) - return n != nil -} diff --git a/src/runtime/time_go123.go b/src/runtime/time_go123.go deleted file mode 100644 index e39da7448..000000000 --- a/src/runtime/time_go123.go +++ /dev/null @@ -1,71 +0,0 @@ -//go:build go1.23 - -package runtime - -import "unsafe" - -// Time functions for Go 1.23 and above. - -// This is the timer that's used internally inside the runtime. -type timer struct { - // When to call the timer, and the interval for the ticker. - when int64 - period int64 - - // Callback from the time package. - f func(arg any, seq uintptr, delta int64) - arg any -} - -func (tim *timer) callCallback(delta int64) { - tim.f(tim.arg, 0, delta) -} - -// This is the struct used internally in the runtime. The first two fields are -// the same as time.Timer and time.Ticker so it can be used as-is in the time -// package. -type timeTimer struct { - c unsafe.Pointer // <-chan time.Time - init bool - timer -} - -//go:linkname newTimer time.newTimer -func newTimer(when, period int64, f func(arg any, seq uintptr, delta int64), arg any, c unsafe.Pointer) *timeTimer { - tim := &timeTimer{ - c: c, - init: true, - timer: timer{ - when: when, - period: period, - f: f, - arg: arg, - }, - } - scheduleLog("new timer") - addTimer(&timerNode{ - timer: &tim.timer, - callback: timerCallback, - }) - return tim -} - -//go:linkname stopTimer time.stopTimer -func stopTimer(tim *timeTimer) bool { - return removeTimer(&tim.timer) != nil -} - -//go:linkname resetTimer time.resetTimer -func resetTimer(t *timeTimer, when, period int64) bool { - t.timer.when = when - t.timer.period = period - n := removeTimer(&t.timer) - removed := n != nil - if n == nil { - n = new(timerNode) - } - n.timer = &t.timer - n.callback = timerCallback - addTimer(n) - return removed -} diff --git a/src/sync/map.go b/src/sync/map.go index 76bdd8380..b26f2dc3b 100644 --- a/src/sync/map.go +++ b/src/sync/map.go @@ -71,6 +71,12 @@ func (m *Map) Range(f func(key, value interface{}) bool) { } } +func (m *Map) Clear() { + m.lock.Lock() + defer m.lock.Unlock() + clear(m.m) +} + // Swap replaces the value for the given key, and returns the old value if any. func (m *Map) Swap(key, value any) (previous any, loaded bool) { m.lock.Lock() diff --git a/src/sync/map_go123.go b/src/sync/map_go123.go deleted file mode 100644 index b7bd61e10..000000000 --- a/src/sync/map_go123.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build go1.23 - -package sync - -// Go 1.23 added the Clear() method. The clear() function is added in Go 1.21, -// so this method can be moved to map.go once we drop support for Go 1.20 and -// below. - -func (m *Map) Clear() { - m.lock.Lock() - defer m.lock.Unlock() - clear(m.m) -}