cmd/compile: pointer-shaped types are SSAable even if lots of 0-sized fields

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 #77534

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>
This commit is contained in:
Keith Randall
2026-02-10 17:44:08 -08:00
parent 439a82ad25
commit 6435bf46c1
4 changed files with 45 additions and 5 deletions

View 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)
}
}

View 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)

View 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
}

View File

@@ -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)
}