]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.26] cmd/compile: pointer-shaped types are SSAable even if lots...
authorKeith Randall <khr@golang.org>
Wed, 11 Feb 2026 01:44:08 +0000 (17:44 -0800)
committerDavid Chase <drchase@google.com>
Thu, 26 Feb 2026 18:36:00 +0000 (10:36 -0800)
Normally we don't SSA-ify variables with types that have more than
4 fields. But we really do want to SSA-ify them if they are pointer
shaped.

An odd case, but the compiler shouldn't barf on them.

Failure probably started with CL 714421.

Fixes #77536

Change-Id: I51ef87676cc31df1e51e164bbd58d58c0ab72436
Reviewed-on: https://go-review.googlesource.com/c/go/+/744280
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
(cherry picked from commit 6435bf46c17dccb2eb5f7bab7dd8aa4972252b21)
Reviewed-on: https://go-review.googlesource.com/c/go/+/749421
Reviewed-by: Mark Freeman <markfreeman@google.com>
src/cmd/compile/internal/ssa/decompose.go
src/cmd/compile/internal/ssa/expand_calls.go
src/cmd/compile/internal/ssa/value.go
test/fixedbugs/issue77534.go [new file with mode: 0644]

index d2f715a453059aa301781814d9e998444f41d93b..a3d0fbd4069760e8e0ac4c168fc2a27a811be000 100644 (file)
@@ -363,9 +363,9 @@ func decomposeUserPhi(v *Value) {
 func decomposeStructPhi(v *Value) {
        t := v.Type
        n := t.NumFields()
-       var fields [MaxStruct]*Value
+       fields := make([]*Value, 0, MaxStruct)
        for i := 0; i < n; i++ {
-               fields[i] = v.Block.NewValue0(v.Pos, OpPhi, t.FieldType(i))
+               fields = append(fields, v.Block.NewValue0(v.Pos, OpPhi, t.FieldType(i)))
        }
        for _, a := range v.Args {
                for i := 0; i < n; i++ {
@@ -373,10 +373,10 @@ func decomposeStructPhi(v *Value) {
                }
        }
        v.reset(OpStructMake)
-       v.AddArgs(fields[:n]...)
+       v.AddArgs(fields...)
 
        // Recursively decompose phis for each field.
-       for _, f := range fields[:n] {
+       for _, f := range fields {
                decomposeUserPhi(f)
        }
 }
index 1a2985d5af3dff3dcee572b008e70565ce57817c..ba2bedc65f8154d72f520bd5b4cc1f8a4671e371 100644 (file)
@@ -566,7 +566,7 @@ func (x *expandState) rewriteSelectOrArg(pos src.XPos, b *Block, container, a, m
                        addArg(e)
                        pos = pos.WithNotStmt()
                }
-               if at.NumFields() > 4 {
+               if at.NumFields() > MaxStruct && !types.IsDirectIface(at) {
                        panic(fmt.Errorf("Too many fields (%d, %d bytes), container=%s", at.NumFields(), at.Size(), container.LongString()))
                }
                a = makeOf(a, OpStructMake, args)
index 5f6040990104dc5fa85bb33e857cefec44ffd248..dba73de771da2946df07205766e986bbcef5f8e9 100644 (file)
@@ -635,6 +635,10 @@ func CanSSA(t *types.Type) bool {
                }
                return false
        case types.TSTRUCT:
+               if types.IsDirectIface(t) {
+                       // Note: even if t.NumFields()>MaxStruct! See issue 77534.
+                       return true
+               }
                if t.NumFields() > MaxStruct {
                        return false
                }
diff --git a/test/fixedbugs/issue77534.go b/test/fixedbugs/issue77534.go
new file mode 100644 (file)
index 0000000..ab4f922
--- /dev/null
@@ -0,0 +1,36 @@
+// compile
+
+// Copyright 2026 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.
+
+// Issue 77534: compiler crash when >4 fields, but only one nonempty pointer field.
+
+package p
+
+type T struct {
+       a, b, c, d struct{}
+       e          *byte
+}
+
+func f1(p *any, t T) {
+       *p = t
+}
+
+func f2(p *any, t *T) {
+       *p = *t
+}
+
+func f3(p, x, y *T, b bool) {
+       var z T
+       if b {
+               z = *x
+       } else {
+               z = *y
+       }
+       *p = z
+}
+
+func f4(i any) T {
+       return i.(T)
+}