aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/ssa/decompose.go8
-rw-r--r--src/cmd/compile/internal/ssa/expand_calls.go2
-rw-r--r--src/cmd/compile/internal/ssa/value.go4
-rw-r--r--test/fixedbugs/issue77534.go36
4 files changed, 45 insertions, 5 deletions
diff --git a/src/cmd/compile/internal/ssa/decompose.go b/src/cmd/compile/internal/ssa/decompose.go
index d2f715a453..a3d0fbd406 100644
--- a/src/cmd/compile/internal/ssa/decompose.go
+++ b/src/cmd/compile/internal/ssa/decompose.go
@@ -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)
}
}
diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go
index 1a2985d5af..ba2bedc65f 100644
--- a/src/cmd/compile/internal/ssa/expand_calls.go
+++ b/src/cmd/compile/internal/ssa/expand_calls.go
@@ -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)
diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go
index 5f60409901..dba73de771 100644
--- a/src/cmd/compile/internal/ssa/value.go
+++ b/src/cmd/compile/internal/ssa/value.go
@@ -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
index 0000000000..ab4f922308
--- /dev/null
+++ b/test/fixedbugs/issue77534.go
@@ -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)
+}