Commit d25c3ead authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/compile: do not generate tail calls when dynamic linking on ppc64le

When a wrapper method calls the real implementation, it's not possible to use a
tail call when dynamic linking on ppc64le. The bad scenario is when a local
call is made to the wrapper: the wrapper will call the implementation, which
might be in a different module and so set the TOC to the appropriate value for
that module. But if it returns directly to the wrapper's caller, nothing will
reset it to the correct value for that function.

Change-Id: Icebf24c9a2a0a9a7c2bce6bd6f1358657284fb10
Reviewed-on: https://go-review.googlesource.com/23468Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 068c745e
...@@ -12,6 +12,10 @@ type Dep struct { ...@@ -12,6 +12,10 @@ type Dep struct {
X int X int
} }
func (d *Dep) Method() int {
return 10
}
func F() int { func F() int {
return V return V
} }
...@@ -3,5 +3,6 @@ package main ...@@ -3,5 +3,6 @@ package main
import "dep2" import "dep2"
func main() { func main() {
dep2.W = dep2.G() + 1 d := &dep2.Dep2{}
dep2.W = dep2.G() + 1 + d.Method()
} }
...@@ -1860,7 +1860,13 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) { ...@@ -1860,7 +1860,13 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
dot := adddot(NodSym(OXDOT, this.Left, method.Sym)) dot := adddot(NodSym(OXDOT, this.Left, method.Sym))
// generate call // generate call
if !instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !isifacemethod(method.Type) { // It's not possible to use a tail call when dynamic linking on ppc64le. The
// bad scenario is when a local call is made to the wrapper: the wrapper will
// call the implementation, which might be in a different module and so set
// the TOC to the appropriate value for that module. But if it returns
// directly to the wrapper's caller, nothing will reset it to the correct
// value for that function.
if !instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !isifacemethod(method.Type) && !(Thearch.LinkArch.Name == "ppc64le" && Ctxt.Flag_dynlink) {
// generate tail call: adjust pointer receiver and jump to embedded method. // generate tail call: adjust pointer receiver and jump to embedded method.
dot = dot.Left // skip final .M dot = dot.Left // skip final .M
// TODO(mdempsky): Remove dependency on dotlist. // TODO(mdempsky): Remove dependency on dotlist.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment