]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/ppc64: fix the epilogue for non-leaf generated methods
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Thu, 24 Sep 2015 23:26:40 +0000 (11:26 +1200)
committerMichael Hudson-Doyle <michael.hudson@canonical.com>
Tue, 6 Oct 2015 03:34:13 +0000 (03:34 +0000)
This lets us re-enable duffzero.

Fixes #12108

Change-Id: Iefd24d26eaa56067caa2c29ff99cd20a42d8714a
Reviewed-on: https://go-review.googlesource.com/14937
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/ppc64/ggen.go
src/cmd/internal/obj/ppc64/obj9.go
test/fixedbugs/issue12108.go [new file with mode: 0644]

index 173e2f0c6c2f3304ffe2bc4d49460d6db0be31b5..195f2b0f66b0cc4fd30c3746198d380de8fb860b 100644 (file)
@@ -71,10 +71,7 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
                for i := int64(0); i < cnt; i += int64(gc.Widthptr) {
                        p = appendpp(p, ppc64.AMOVD, obj.TYPE_REG, ppc64.REGZERO, 0, obj.TYPE_MEM, ppc64.REGSP, 8+frame+lo+i)
                }
-               // TODO(dfc): https://golang.org/issue/12108
-               // If DUFFZERO is used inside a tail call (see genwrapper) it will
-               // overwrite the link register.
-       } else if false && cnt <= int64(128*gc.Widthptr) {
+       } else if cnt <= int64(128*gc.Widthptr) {
                p = appendpp(p, ppc64.AADD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGRT1, 0)
                p.Reg = ppc64.REGSP
                p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
@@ -443,10 +440,7 @@ func clearfat(nl *gc.Node) {
 
                // The loop leaves R3 on the last zeroed dword
                boff = 8
-               // TODO(dfc): https://golang.org/issue/12108
-               // If DUFFZERO is used inside a tail call (see genwrapper) it will
-               // overwrite the link register.
-       } else if false && q >= 4 {
+       } else if q >= 4 {
                p := gins(ppc64.ASUB, nil, &dst)
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = 8
index 1eddc6fc6cba97e77b0de2279ce1c902d2b6668f..d609f98502aa19228f8a51b03d7702a6d7a5778f 100644 (file)
@@ -473,18 +473,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                                break
                        }
 
-                       if p.To.Sym != nil { // retjmp
-                               p.As = ABR
-                               p.To.Type = obj.TYPE_BRANCH
-                               break
-                       }
+                       retTarget := p.To.Sym
 
                        if cursym.Text.Mark&LEAF != 0 {
                                if autosize == 0 {
                                        p.As = ABR
                                        p.From = obj.Addr{}
-                                       p.To.Type = obj.TYPE_REG
-                                       p.To.Reg = REG_LR
+                                       if retTarget == nil {
+                                               p.To.Type = obj.TYPE_REG
+                                               p.To.Reg = REG_LR
+                                       } else {
+                                               p.To.Type = obj.TYPE_BRANCH
+                                               p.To.Sym = retTarget
+                                       }
                                        p.Mark |= BRANCH
                                        break
                                }
@@ -562,14 +563,18 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
                        q1 = ctxt.NewProg()
                        q1.As = ABR
                        q1.Lineno = p.Lineno
-                       q1.To.Type = obj.TYPE_REG
-                       q1.To.Reg = REG_LR
+                       if retTarget == nil {
+                               q1.To.Type = obj.TYPE_REG
+                               q1.To.Reg = REG_LR
+                       } else {
+                               q1.To.Type = obj.TYPE_BRANCH
+                               q1.To.Sym = retTarget
+                       }
                        q1.Mark |= BRANCH
                        q1.Spadj = +autosize
 
                        q1.Link = q.Link
                        q.Link = q1
-
                case AADD:
                        if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
                                p.Spadj = int32(-p.From.Offset)
diff --git a/test/fixedbugs/issue12108.go b/test/fixedbugs/issue12108.go
new file mode 100644 (file)
index 0000000..c7a7425
--- /dev/null
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2015 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.
+
+// A generated method with a return value large enough to be
+// initialized by duffzero is not a leaf method, which violated
+// assumptions made by cmd/internal/obj/ppc64.
+
+package main
+
+const N = 9 // values > 8 cause (Super).Method to use duffzero
+
+type Base struct {
+}
+
+func (b *Base) Method() (x [N]uintptr) {
+       return
+}
+
+type Super struct {
+       Base
+}
+
+type T interface {
+       Method() [N]uintptr
+}
+
+func f(q T) {
+       q.Method()
+}
+
+func main() {
+       var s Super
+       f(&s)
+}