Skip to content

Commit 998fe70

Browse files
committed
cmd/compile: fixed which-result confusion in presence of 0-width types
A function returning multiple results, some of them zero-width, will have more than one result present at an offset. Be sure that offset AND type match. Includes test. Change-Id: I3eb1f56116d989b4e73f533fefabb1bf554c901b Reviewed-on: https://go-review.googlesource.com/c/go/+/297169 Trust: David Chase <[email protected]> Run-TryBot: David Chase <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Jeremy Faller <[email protected]>
1 parent d9fd38e commit 998fe70

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

src/cmd/compile/internal/ssa/op.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,15 @@ type AuxCall struct {
8686
abiInfo *abi.ABIParamResultInfo // TODO remove fields above redundant with this information.
8787
}
8888

89-
// ResultForOffset returns the index of the result at a particular offset among the results
89+
// ResultForOffsetAndType returns the index of a t-typed result at *A* particular offset among the results.
90+
// An arbitrary number of zero-width-typed results may reside at the same offset with a single not-zero-width
91+
// typed result, but the ones with the same type are all indistinguishable so it doesn't matter "which one"
92+
// is obtained.
9093
// This does not include the mem result for the call opcode.
91-
func (a *AuxCall) ResultForOffset(offset int64) int64 {
94+
func (a *AuxCall) ResultForOffsetAndType(offset int64, t *types.Type) int64 {
9295
which := int64(-1)
9396
for i := int64(0); i < a.NResults(); i++ { // note aux NResults does not include mem result.
94-
if a.OffsetOfResult(i) == offset {
97+
if a.OffsetOfResult(i) == offset && a.TypeOfResult(i) == t {
9598
which = i
9699
break
97100
}

src/cmd/compile/internal/ssagen/ssa.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,7 +2909,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
29092909
addr := s.constOffPtrSP(types.NewPtr(n.Type()), n.Offset)
29102910
return s.rawLoad(n.Type(), addr)
29112911
}
2912-
which := s.prevCall.Aux.(*ssa.AuxCall).ResultForOffset(n.Offset)
2912+
which := s.prevCall.Aux.(*ssa.AuxCall).ResultForOffsetAndType(n.Offset, n.Type())
29132913
if which == -1 {
29142914
// Do the old thing // TODO: Panic instead.
29152915
addr := s.constOffPtrSP(types.NewPtr(n.Type()), n.Offset)
@@ -5119,7 +5119,7 @@ func (s *state) addr(n ir.Node) *ssa.Value {
51195119
if s.prevCall == nil || s.prevCall.Op != ssa.OpStaticLECall && s.prevCall.Op != ssa.OpInterLECall && s.prevCall.Op != ssa.OpClosureLECall {
51205120
return s.constOffPtrSP(t, n.Offset)
51215121
}
5122-
which := s.prevCall.Aux.(*ssa.AuxCall).ResultForOffset(n.Offset)
5122+
which := s.prevCall.Aux.(*ssa.AuxCall).ResultForOffsetAndType(n.Offset, n.Type())
51235123
if which == -1 {
51245124
// Do the old thing // TODO: Panic instead.
51255125
return s.constOffPtrSP(t, n.Offset)

test/abi/f_ret_z_not.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
package main
8+
9+
import "fmt"
10+
11+
type Z struct {
12+
}
13+
14+
type NZ struct {
15+
x, y int
16+
}
17+
18+
//go:noinline
19+
func f(x,y int) (Z,NZ,Z) {
20+
var z Z
21+
return z,NZ{x,y},z
22+
}
23+
24+
//go:noinline
25+
func g() (Z,NZ,Z) {
26+
a,b,c := f(3,4)
27+
return c,b,a
28+
}
29+
30+
func main() {
31+
_,b,_ := g()
32+
fmt.Println(b.x+b.y)
33+
}

test/abi/f_ret_z_not.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7

0 commit comments

Comments
 (0)