cmd/compile: fix bad order of evaluation for min/max builtin

For float or string, min/max builtin performs a runtime call, so we need
to save its result to temporary variable. Otherwise, the runtime call
will clobber closure's arguments currently on the stack when passing
min/max as argument to closures.

Fixes #60990

Change-Id: I1397800f815ec7853182868678d0f760b22afff2
Reviewed-on: https://go-review.googlesource.com/c/go/+/506115
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Cuong Manh Le 2023-06-26 11:30:48 +07:00 committed by Gopher Robot
parent 4f36f7e4dd
commit 4ad4128d3c
2 changed files with 34 additions and 1 deletions

View File

@ -755,7 +755,7 @@ func (o *orderState) stmt(n ir.Node) {
o.out = append(o.out, n)
o.popTemp(t)
case ir.OMAX, ir.OMIN, ir.OPRINT, ir.OPRINTN, ir.ORECOVERFP:
case ir.OPRINT, ir.OPRINTN, ir.ORECOVERFP:
n := n.(*ir.CallExpr)
t := o.markTemp()
o.call(n)
@ -1247,6 +1247,8 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node {
ir.OMAKEMAP,
ir.OMAKESLICE,
ir.OMAKESLICECOPY,
ir.OMAX,
ir.OMIN,
ir.ONEW,
ir.OREAL,
ir.ORECOVERFP,

View File

@ -0,0 +1,31 @@
// compile
// Copyright 2023 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
type T struct{ _, _ []int }
func F[_ int]() {
var f0, f1 float64
var b bool
_ = func(T, float64) bool {
b = deepEqual(0, 1)
return func() bool {
f1 = min(f0, 0)
return b
}()
}(T{nil, nil}, min(0, f1))
f0 = min(0, 1)
}
//go:noinline
func deepEqual(x, y any) bool {
return x == y
}
func init() {
F[int]()
}