]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: ensure args are live in tail calls for LR machines
authorCherry Zhang <cherryyz@google.com>
Wed, 21 Sep 2016 22:53:31 +0000 (18:53 -0400)
committerCherry Zhang <cherryyz@google.com>
Thu, 22 Sep 2016 19:15:09 +0000 (19:15 +0000)
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>
src/cmd/compile/internal/gc/plive.go

index 651ba42044ef7092c75db5b967a0952f35bc24b9..26e2ce9239c3a3b205c3186678ec6b95ac7c14e1 100644 (file)
@@ -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