1
0
mirror of https://github.com/golang/go synced 2024-11-26 11:58:07 -07:00

cmd/compile: fix buglet in walk convert phase relating to convT64

The function runtime.convT64 accepts a single uint64 argument, but the
compiler's rules in the walk phase for determining whether is it ok to
pass a value of type T to a call to runtime.convT64 were slightly off.
In particular the test was allowing a type T with size less than eight
bytes but with more than one internal element (e.g. a struct). This
patch tightens up the rules somewhat to prevent this from happening.

Updates #40724.

Change-Id: I3b909267534db59429b0aa73a3d73333e1bd6432
Reviewed-on: https://go-review.googlesource.com/c/go/+/308069
Trust: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Than McIntosh 2021-04-07 12:56:43 -04:00
parent d474b6c824
commit ca8540affd
3 changed files with 36 additions and 1 deletions

View File

@ -14,6 +14,7 @@ import (
"cmd/compile/internal/ssagen" "cmd/compile/internal/ssagen"
"cmd/compile/internal/typecheck" "cmd/compile/internal/typecheck"
"cmd/compile/internal/types" "cmd/compile/internal/types"
"cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
) )
@ -316,6 +317,14 @@ func convFuncName(from, to *types.Type) (fnname string, needsaddr bool) {
return false return false
} }
// Helper to determine whether a given type (when passed to a
// function) will fit into a single integer register, assuming
// that the reg abi is in effect. This is somewhat ad-hoc, there
// may be a cleaner way to do this.
fitsInSingleIntReg := func(t *types.Type) bool {
return from.IsScalar() || types.IsDirectIface(from)
}
tkind := to.Tie() tkind := to.Tie()
switch from.Tie() { switch from.Tie() {
case 'I': case 'I':
@ -332,7 +341,7 @@ func convFuncName(from, to *types.Type) (fnname string, needsaddr bool) {
return "convT32", false return "convT32", false
case from.Size() == 8 && isFloatLike(from): case from.Size() == 8 && isFloatLike(from):
return "convT64F", false return "convT64F", false
case from.Size() == 8 && from.Align == types.Types[types.TUINT64].Align && !from.HasPointers(): case from.Size() == 8 && from.Align == types.Types[types.TUINT64].Align && !from.HasPointers() && (!objabi.Experiment.RegabiArgs || fitsInSingleIntReg(from)):
return "convT64", false return "convT64", false
} }
if sc := from.SoleComponent(); sc != nil { if sc := from.SoleComponent(); sc != nil {

View File

@ -0,0 +1,25 @@
// run
// 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 main
import (
"fmt"
)
type MyStruct struct {
F0 [0]float64
F1 byte
F2 int16
_ struct {
F0 uint32
}
}
func main() {
p0 := MyStruct{F0: [0]float64{}, F1: byte(27), F2: int16(9887)}
fmt.Println(p0)
}

View File

@ -0,0 +1 @@
{[] 27 9887 {0}}