[release-branch.go1.16] cmd/compile: only update source type when processing struct/array

This is backport of CL 3651594, with the test from CL 360057.

CL 360057 fixed missing update source type in storeArgOrLoad. However,
we should only update the type when processing struct/array. If we
update the type right before calling storeArgOrLoad, we may generate a
value with invalid type, e.g, OpStructSelect with non-struct type.

Fixes #49391

Change-Id: Ib7e10f72f818880f550aae5c9f653db463ce29b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/361594
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/361597
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Cuong Manh Le 2021-11-05 20:30:38 +07:00 committed by Michael Knyszek
parent b29e772caf
commit 8a12f5d6e8
3 changed files with 82 additions and 0 deletions

View File

@ -527,6 +527,7 @@ func expandCalls(f *Func) {
// it could be a leaf type, but the "leaf" could be complex64 (for example)
return storeArgOrLoad(pos, b, base, source, mem, t, offset)
}
source.Type = t
for i := int64(0); i < t.NumElem(); i++ {
sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source)
mem = storeArgOrLoad(pos, b, base, sel, mem, elt, offset+i*elt.Width)
@ -559,6 +560,7 @@ func expandCalls(f *Func) {
return storeArgOrLoad(pos, b, base, source, mem, t, offset)
}
source.Type = t
for i := 0; i < t.NumFields(); i++ {
fld := t.Field(i)
sel := source.Block.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source)

View File

@ -0,0 +1,55 @@
// compile -l
// Copyright 2021 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 p
func f() int {
var a, b struct {
s struct {
s struct {
byte
float32
}
}
}
_ = a
return func() int {
return func() int {
a = struct {
s struct {
s struct {
byte
float32
}
}
}{b.s}
return 0
}()
}()
}
func g() int {
var a, b struct {
s [1][1]struct {
byte
float32
}
}
_ = a
return func() int {
return func() int {
a = struct {
s [1][1]struct {
byte
float32
}
}{b.s}
return 0
}()
}()
}

View File

@ -0,0 +1,25 @@
// compile
// Copyright 2021 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 p
func f(i int) {
var s1 struct {
s struct{ s struct{ i int } }
}
var s2, s3 struct {
a struct{ i int }
b int
}
func() {
i = 1 + 2*i + s3.a.i + func() int {
s2.a, s2.b = s3.a, s3.b
return 0
}() + func(*int) int {
return s1.s.s.i
}(new(int))
}()
}