mirror of
https://github.com/golang/go
synced 2024-11-26 11:58:07 -07:00
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:
parent
bc953b2ca2
commit
710b9ad617
@ -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) {
|
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)
|
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
|
} else if cnt <= int64(128*gc.Widthptr) {
|
||||||
// If DUFFZERO is used inside a tail call (see genwrapper) it will
|
|
||||||
// overwrite the link register.
|
|
||||||
} else if false && 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 = appendpp(p, ppc64.AADD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGRT1, 0)
|
||||||
p.Reg = ppc64.REGSP
|
p.Reg = ppc64.REGSP
|
||||||
p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
|
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
|
// The loop leaves R3 on the last zeroed dword
|
||||||
boff = 8
|
boff = 8
|
||||||
// TODO(dfc): https://golang.org/issue/12108
|
} else if q >= 4 {
|
||||||
// If DUFFZERO is used inside a tail call (see genwrapper) it will
|
|
||||||
// overwrite the link register.
|
|
||||||
} else if false && q >= 4 {
|
|
||||||
p := gins(ppc64.ASUB, nil, &dst)
|
p := gins(ppc64.ASUB, nil, &dst)
|
||||||
p.From.Type = obj.TYPE_CONST
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Offset = 8
|
p.From.Offset = 8
|
||||||
|
@ -473,18 +473,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.To.Sym != nil { // retjmp
|
retTarget := p.To.Sym
|
||||||
p.As = ABR
|
|
||||||
p.To.Type = obj.TYPE_BRANCH
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if cursym.Text.Mark&LEAF != 0 {
|
if cursym.Text.Mark&LEAF != 0 {
|
||||||
if autosize == 0 {
|
if autosize == 0 {
|
||||||
p.As = ABR
|
p.As = ABR
|
||||||
p.From = obj.Addr{}
|
p.From = obj.Addr{}
|
||||||
p.To.Type = obj.TYPE_REG
|
if retTarget == nil {
|
||||||
p.To.Reg = REG_LR
|
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
|
p.Mark |= BRANCH
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -562,14 +563,18 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
|
|||||||
q1 = ctxt.NewProg()
|
q1 = ctxt.NewProg()
|
||||||
q1.As = ABR
|
q1.As = ABR
|
||||||
q1.Lineno = p.Lineno
|
q1.Lineno = p.Lineno
|
||||||
q1.To.Type = obj.TYPE_REG
|
if retTarget == nil {
|
||||||
q1.To.Reg = REG_LR
|
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.Mark |= BRANCH
|
||||||
q1.Spadj = +autosize
|
q1.Spadj = +autosize
|
||||||
|
|
||||||
q1.Link = q.Link
|
q1.Link = q.Link
|
||||||
q.Link = q1
|
q.Link = q1
|
||||||
|
|
||||||
case AADD:
|
case AADD:
|
||||||
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
|
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
|
||||||
p.Spadj = int32(-p.From.Offset)
|
p.Spadj = int32(-p.From.Offset)
|
||||||
|
37
test/fixedbugs/issue12108.go
Normal file
37
test/fixedbugs/issue12108.go
Normal file
@ -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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user