mirror of
https://github.com/golang/go
synced 2024-11-18 12:04:57 -07:00
cmd/compile: ensure args are live in tail calls for LR machines
On link-register machines we uses RET (sym), instead of JMP (sym), for tail call (so the assembler knows and may rewrite it to restore link register if necessary). Add RET to the analysis. Fixes #17186. Fixes #16016 on link-register machines. Change-Id: I8690ac57dd9d49beeea76a5f291988e9a1d3afe5 Reviewed-on: https://go-review.googlesource.com/29570 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
254169d7bb
commit
3dfb92f254
@ -549,6 +549,22 @@ func progeffects(prog *obj.Prog, vars []*Node, uevar bvec, varkill bvec, avarini
|
||||
bvresetall(varkill)
|
||||
bvresetall(avarinit)
|
||||
|
||||
// A return instruction with a p.to is a tail return, which brings
|
||||
// the stack pointer back up (if it ever went down) and then jumps
|
||||
// to a new function entirely. That form of instruction must read
|
||||
// all the parameters for correctness, and similarly it must not
|
||||
// read the out arguments - they won't be set until the new
|
||||
// function runs.
|
||||
if (prog.As == obj.AJMP || prog.As == obj.ARET) && prog.To.Type == obj.TYPE_MEM && prog.To.Name == obj.NAME_EXTERN {
|
||||
// This is a tail call. Ensure the arguments are still alive.
|
||||
// See issue 16016.
|
||||
for i, node := range vars {
|
||||
if node.Class == PPARAM {
|
||||
bvset(uevar, int32(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if prog.As == obj.ARET {
|
||||
// Return instructions read all of the out arguments.
|
||||
for i, node := range vars {
|
||||
@ -569,21 +585,6 @@ func progeffects(prog *obj.Prog, vars []*Node, uevar bvec, varkill bvec, avarini
|
||||
|
||||
return
|
||||
}
|
||||
// A return instruction with a p.to is a tail return, which brings
|
||||
// the stack pointer back up (if it ever went down) and then jumps
|
||||
// to a new function entirely. That form of instruction must read
|
||||
// all the parameters for correctness, and similarly it must not
|
||||
// read the out arguments - they won't be set until the new
|
||||
// function runs.
|
||||
if prog.As == obj.AJMP && prog.To.Type == obj.TYPE_MEM && prog.To.Name == obj.NAME_EXTERN {
|
||||
// This is a tail call. Ensure the arguments are still alive.
|
||||
// See issue 16016.
|
||||
for i, node := range vars {
|
||||
if node.Class == PPARAM {
|
||||
bvset(uevar, int32(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if prog.As == obj.ATEXT {
|
||||
// A text instruction marks the entry point to a function and
|
||||
|
Loading…
Reference in New Issue
Block a user