1
0
mirror of https://github.com/golang/go synced 2024-11-11 19:31:37 -07:00

[release-branch.go1.17] 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 #49413

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/+/362054
Reviewed-by: Keith Randall <khr@golang.org>
Trust: Matthew Dempsky <mdempsky@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 0aa7f8fd4d
commit ebd1b4d97d
2 changed files with 56 additions and 0 deletions

View File

@ -5118,6 +5118,18 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
for _, p := range params.InParams() { // includes receiver for interface calls
ACArgs = append(ACArgs, p.Type)
}
// 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)
}
for i, n := range args {
callArgs = append(callArgs, s.putArg(n, t.Params().Field(i).Type))
}

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)
}