From: Cherry Zhang Date: Wed, 21 Sep 2016 22:53:31 +0000 (-0400) Subject: cmd/compile: ensure args are live in tail calls for LR machines X-Git-Tag: go1.8beta1~1194 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=3dfb92f254ed4f94e3c98a789c171a1cd9c2563d;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index 651ba42044..26e2ce9239 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -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