[release-branch.go1.16] cmd/compile: avoid adding LECall to the entry block when has opendefers

The openDeferRecord always insert vardef/varlive pairs into the entry block, it may destroy the mem chain when LECall's args are writing into the same block. So create a new block before that happens.

Fixes #49412

Change-Id: Ibda6c4a45d960dd412a641f5e02276f663c80785
Reviewed-on: https://go-review.googlesource.com/c/go/+/361410
Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Alberto Donizetti <alb.donizetti@gmail.com>
Trust: Than McIntosh <thanm@google.com>
Reviewed-by: David Chase <drchase@google.com>
(cherry picked from commit 4f083c7dcf)
Reviewed-on: https://go-review.googlesource.com/c/go/+/362055
Reviewed-by: Keith Randall <khr@golang.org>
Trust: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
hanpro 2021-11-05 09:47:54 +08:00 committed by Dmitri Shuralyov
parent 831d491ad7
commit 168bc3a76e
2 changed files with 55 additions and 0 deletions

View File

@ -4709,6 +4709,17 @@ func (s *state) call(n *Node, k callKind, returnResultAddr bool) *ssa.Value {
}
}
// Split the entry block if there are open defers, because later calls to
// openDeferSave may cause a mismatch between the mem for an OpDereference
// and the call site which uses it. See #49282.
if s.curBlock.ID == s.f.Entry.ID && s.hasOpenDefers {
b := s.endBlock()
b.Kind = ssa.BlockPlain
curb := s.f.NewBlock(ssa.BlockPlain)
b.AddEdgeTo(curb)
s.startBlock(curb)
}
// Write args.
t := n.Left.Type
args := n.Rlist.Slice()

View File

@ -0,0 +1,44 @@
// 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
//go:noinline
func g(d uintptr, a, m []int, s struct {
a, b, c, d, e int
}, u uint) {
_ = a
_ = m
_ = s
func() {
for i := 0; i < 5; i++ {
_ = a
_ = m
_, _ = s, s
}
}()
}
var One float64 = 1.0
func f(d uintptr) {
var a, m []int
var s struct {
a, b, c, d, e int
}
g(d, a, m, s, uint(One)) // Uint of not-a-constant inserts a conditional, necessary to bug
defer func() uint {
return 0
}()
}
var d uintptr
func h() {
f(d)
}