1// run 2 3// Copyright 2021 The Go Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file. 6 7// This testcase caused a crash when the register ABI was in effect, 8// on amd64 (problem with register allocation). 9 10package main 11 12type Op struct { 13 tag string 14 _x []string 15 _q [20]uint64 16 plist []P 17} 18 19type P struct { 20 tag string 21 _x [10]uint64 22 b bool 23} 24 25type M int 26 27//go:noinline 28func (w *M) walkP(p *P) *P { 29 np := &P{} 30 *np = *p 31 np.tag += "new" 32 return np 33} 34 35func (w *M) walkOp(op *Op) *Op { 36 if op == nil { 37 return nil 38 } 39 40 orig := op 41 cloned := false 42 clone := func() { 43 if !cloned { 44 cloned = true 45 op = &Op{} 46 *op = *orig 47 } 48 } 49 50 pCloned := false 51 for i := range op.plist { 52 if s := w.walkP(&op.plist[i]); s != &op.plist[i] { 53 if !pCloned { 54 pCloned = true 55 clone() 56 op.plist = make([]P, len(orig.plist)) 57 copy(op.plist, orig.plist) 58 } 59 op.plist[i] = *s 60 } 61 } 62 63 return op 64} 65 66func main() { 67 var ww M 68 w := &ww 69 p1 := P{tag: "a"} 70 p1._x[1] = 9 71 o := Op{tag: "old", plist: []P{p1}} 72 no := w.walkOp(&o) 73 if no.plist[0].tag != "anew" { 74 panic("bad") 75 } 76} 77