cmd/compile/internal/ppc64: fix the epilogue for non-leaf generated methods

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>
This commit is contained in:
Michael Hudson-Doyle 2015-09-25 11:26:40 +12:00
Родитель bc953b2ca2
Коммит 710b9ad617
3 изменённых файлов: 54 добавлений и 18 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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)

Просмотреть файл

@ -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)
}