Update to go1.24.3
This commit is contained in:
@@ -27,6 +27,7 @@ func test42018(t *testing.T) {
|
||||
recurseHWND(400, hwnd, uintptr(unsafe.Pointer(&i)))
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func recurseHANDLE(n int, p C.HANDLE, v uintptr) {
|
||||
if n > 0 {
|
||||
recurseHANDLE(n-1, p, v)
|
||||
@@ -36,6 +37,7 @@ func recurseHANDLE(n int, p C.HANDLE, v uintptr) {
|
||||
}
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func recurseHWND(n int, p C.HWND, v uintptr) {
|
||||
if n > 0 {
|
||||
recurseHWND(n-1, p, v)
|
||||
|
||||
@@ -170,19 +170,8 @@ func CanInlineFuncs(funcs []*ir.Func, profile *pgoir.Profile) {
|
||||
}
|
||||
|
||||
ir.VisitFuncsBottomUp(funcs, func(funcs []*ir.Func, recursive bool) {
|
||||
numfns := numNonClosures(funcs)
|
||||
|
||||
for _, fn := range funcs {
|
||||
if !recursive || numfns > 1 {
|
||||
// We allow inlining if there is no
|
||||
// recursion, or the recursion cycle is
|
||||
// across more than one function.
|
||||
CanInline(fn, profile)
|
||||
} else {
|
||||
if base.Flag.LowerM > 1 && fn.OClosure == nil {
|
||||
fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(fn), fn.Nname)
|
||||
}
|
||||
}
|
||||
CanInline(fn, profile)
|
||||
if inlheur.Enabled() {
|
||||
analyzeFuncProps(fn, profile)
|
||||
}
|
||||
@@ -1023,68 +1012,6 @@ func canInlineCallExpr(callerfn *ir.Func, n *ir.CallExpr, callee *ir.Func, bigCa
|
||||
}
|
||||
}
|
||||
|
||||
if callee == callerfn {
|
||||
// Can't recursively inline a function into itself.
|
||||
if log && logopt.Enabled() {
|
||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to %s", ir.FuncName(callerfn)))
|
||||
}
|
||||
return false, 0, false
|
||||
}
|
||||
|
||||
isClosureParent := func(closure, parent *ir.Func) bool {
|
||||
for p := closure.ClosureParent; p != nil; p = p.ClosureParent {
|
||||
if p == parent {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if isClosureParent(callerfn, callee) {
|
||||
// Can't recursively inline a parent of the closure into itself.
|
||||
if log && logopt.Enabled() {
|
||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to closure parent: %s, %s", ir.FuncName(callerfn), ir.FuncName(callee)))
|
||||
}
|
||||
return false, 0, false
|
||||
}
|
||||
if isClosureParent(callee, callerfn) {
|
||||
// Can't recursively inline a closure if there's a call to the parent in closure body.
|
||||
if ir.Any(callee, func(node ir.Node) bool {
|
||||
if call, ok := node.(*ir.CallExpr); ok {
|
||||
if name, ok := call.Fun.(*ir.Name); ok && isClosureParent(callerfn, name.Func) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}) {
|
||||
if log && logopt.Enabled() {
|
||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to closure parent: %s, %s", ir.FuncName(callerfn), ir.FuncName(callee)))
|
||||
}
|
||||
return false, 0, false
|
||||
}
|
||||
}
|
||||
do := func(fn *ir.Func) bool {
|
||||
// Can't recursively inline a function if the function body contains
|
||||
// a call to a function f, which the function f is one of the call arguments.
|
||||
return ir.Any(fn, func(node ir.Node) bool {
|
||||
if call, ok := node.(*ir.CallExpr); ok {
|
||||
for _, arg := range call.Args {
|
||||
if call.Fun == arg {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
for _, fn := range []*ir.Func{callerfn, callee} {
|
||||
if do(fn) {
|
||||
if log && logopt.Enabled() {
|
||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to function: %s", ir.FuncName(fn)))
|
||||
}
|
||||
return false, 0, false
|
||||
}
|
||||
}
|
||||
|
||||
if base.Flag.Cfg.Instrumenting && types.IsNoInstrumentPkg(callee.Sym().Pkg) {
|
||||
// Runtime package must not be instrumented.
|
||||
// Instrument skips runtime package. However, some runtime code can be
|
||||
|
||||
@@ -2631,7 +2631,12 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
|
||||
vers := revInfo.Version
|
||||
if vers != "" {
|
||||
if st.Uncommitted {
|
||||
vers += "+dirty"
|
||||
// SemVer build metadata is dot-separated https://semver.org/#spec-item-10
|
||||
if strings.HasSuffix(vers, "+incompatible") {
|
||||
vers += ".dirty"
|
||||
} else {
|
||||
vers += "+dirty"
|
||||
}
|
||||
}
|
||||
info.Main.Version = vers
|
||||
}
|
||||
|
||||
@@ -108,6 +108,19 @@ go version -m example$GOEXE
|
||||
stdout '\s+mod\s+example\s+v1.0.3-0.20220719150703-2e239bf29c13\s+'
|
||||
rm example$GOEXE
|
||||
|
||||
# Create +incompatible module
|
||||
exec git checkout v1.0.4
|
||||
exec git rm go.mod
|
||||
exec git commit -m 'commit 6'
|
||||
exec git tag v2.0.0
|
||||
exec git checkout HEAD^ go.mod
|
||||
# And make the tree +dirty
|
||||
mv README4 README5
|
||||
go build
|
||||
go version -m example$GOEXE
|
||||
stdout '\s+mod\s+example\s+v2.0.0\+incompatible.dirty\s+'
|
||||
rm example$GOEXE
|
||||
|
||||
-- $WORK/repo/go.mod --
|
||||
module example
|
||||
|
||||
|
||||
@@ -1006,9 +1006,10 @@ func genWasmExportWrapper(s *obj.LSym, appendp func(p *obj.Prog, as obj.As, args
|
||||
// In the unwinding case, we call wasm_pc_f_loop_export to handle stack switch and rewinding,
|
||||
// until a normal return (non-unwinding) back to this function.
|
||||
p = appendp(p, AIf)
|
||||
p = appendp(p, AI32Const, retAddr)
|
||||
p = appendp(p, AI32Const, constAddr(16))
|
||||
p = appendp(p, AI32ShrU)
|
||||
p = appendp(p, AI64Const, retAddr)
|
||||
p = appendp(p, AI64Const, constAddr(16))
|
||||
p = appendp(p, AI64ShrU)
|
||||
p = appendp(p, AI32WrapI64)
|
||||
p = appendp(p, ACall, obj.Addr{Type: obj.TYPE_MEM, Name: obj.NAME_EXTERN, Sym: wasm_pc_f_loop_export})
|
||||
p = appendp(p, AEnd)
|
||||
|
||||
|
||||
@@ -432,16 +432,16 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
|
||||
return i
|
||||
}
|
||||
// symbol already exists
|
||||
// Fix for issue #47185 -- given two dupok or BSS symbols with
|
||||
// different sizes, favor symbol with larger size. See also
|
||||
// issue #46653 and #72032.
|
||||
oldsz := l.SymSize(oldi)
|
||||
sz := int64(r.Sym(li).Siz())
|
||||
if osym.Dupok() {
|
||||
if l.flags&FlagStrictDups != 0 {
|
||||
l.checkdup(name, r, li, oldi)
|
||||
}
|
||||
// Fix for issue #47185 -- given two dupok symbols with
|
||||
// different sizes, favor symbol with larger size. See
|
||||
// also issue #46653.
|
||||
szdup := l.SymSize(oldi)
|
||||
sz := int64(r.Sym(li).Siz())
|
||||
if szdup < sz {
|
||||
if oldsz < sz {
|
||||
// new symbol overwrites old symbol.
|
||||
l.objSyms[oldi] = objSym{r.objidx, li}
|
||||
}
|
||||
@@ -452,11 +452,24 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
|
||||
if oldsym.Dupok() {
|
||||
return oldi
|
||||
}
|
||||
overwrite := r.DataSize(li) != 0
|
||||
// If one is a DATA symbol (i.e. has content, DataSize != 0)
|
||||
// and the other is BSS, the one with content wins.
|
||||
// If both are BSS, the one with larger size wins.
|
||||
// Specifically, the "overwrite" variable and the final result are
|
||||
//
|
||||
// new sym old sym overwrite
|
||||
// ---------------------------------------------
|
||||
// DATA DATA true => ERROR
|
||||
// DATA lg/eq BSS sm/eq true => new wins
|
||||
// DATA small BSS large true => ERROR
|
||||
// BSS large DATA small true => ERROR
|
||||
// BSS large BSS small true => new wins
|
||||
// BSS sm/eq D/B lg/eq false => old wins
|
||||
overwrite := r.DataSize(li) != 0 || oldsz < sz
|
||||
if overwrite {
|
||||
// new symbol overwrites old symbol.
|
||||
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
|
||||
if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) {
|
||||
if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) || oldsz > sz {
|
||||
log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg)
|
||||
}
|
||||
l.objSyms[oldi] = objSym{r.objidx, li}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"testing"
|
||||
|
||||
imacho "cmd/internal/macho"
|
||||
"cmd/internal/objfile"
|
||||
"cmd/internal/sys"
|
||||
)
|
||||
|
||||
@@ -1541,3 +1542,53 @@ func TestCheckLinkname(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinknameBSS(t *testing.T) {
|
||||
// Test that the linker chooses the right one as the definition
|
||||
// for linknamed variables. See issue #72032.
|
||||
testenv.MustHaveGoBuild(t)
|
||||
t.Parallel()
|
||||
|
||||
tmpdir := t.TempDir()
|
||||
|
||||
src := filepath.Join("testdata", "linkname", "sched.go")
|
||||
exe := filepath.Join(tmpdir, "sched.exe")
|
||||
cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", exe, src)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("build failed unexpectedly: %v:\n%s", err, out)
|
||||
}
|
||||
|
||||
// Check the symbol size.
|
||||
f, err := objfile.Open(exe)
|
||||
if err != nil {
|
||||
t.Fatalf("fail to open executable: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
syms, err := f.Symbols()
|
||||
if err != nil {
|
||||
t.Fatalf("fail to get symbols: %v", err)
|
||||
}
|
||||
found := false
|
||||
for _, s := range syms {
|
||||
if s.Name == "runtime.sched" || s.Name == "_runtime.sched" {
|
||||
found = true
|
||||
if s.Size < 100 {
|
||||
// As of Go 1.25 (Mar 2025), runtime.sched has 6848 bytes on
|
||||
// darwin/arm64. It should always be larger than 100 bytes on
|
||||
// all platforms.
|
||||
t.Errorf("runtime.sched symbol size too small: want > 100, got %d", s.Size)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("runtime.sched symbol not found")
|
||||
}
|
||||
|
||||
// Executable should run.
|
||||
cmd = testenv.Command(t, exe)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Errorf("executable failed to run: %v\n%s", err, out)
|
||||
}
|
||||
}
|
||||
|
||||
19
src/cmd/link/testdata/linkname/sched.go
vendored
Normal file
19
src/cmd/link/testdata/linkname/sched.go
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2025 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 main
|
||||
|
||||
import _ "unsafe"
|
||||
|
||||
type schedt struct{}
|
||||
|
||||
//go:linkname sched runtime.sched
|
||||
var sched schedt
|
||||
|
||||
func main() {
|
||||
select {
|
||||
default:
|
||||
println("hello")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user