1
0
mirror of https://github.com/golang/go synced 2024-10-05 16:41:21 -06:00

[dev.ssa] cmd/compile: implement OCALLMETH

This mimics the way the old backend
compiles OCALLMETH.

Change-Id: I635c8e7a48c8b5619bd837f78fa6eeba83a57b2f
Reviewed-on: https://go-review.googlesource.com/12549
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2015-07-21 07:37:47 -07:00
parent c9a38ce758
commit 15dcdfba0f

View File

@ -940,13 +940,30 @@ func (s *state) expr(n *Node) *ssa.Value {
return s.constInt(s.config.Int, n.Left.Type.Bound)
}
case OCALLFUNC:
static := n.Left.Op == ONAME && n.Left.Class == PFUNC
case OCALLFUNC, OCALLMETH:
left := n.Left
static := left.Op == ONAME && left.Class == PFUNC
if n.Op == OCALLMETH {
// Rewrite to an OCALLFUNC: (p.f)(...) becomes (f)(p, ...)
// Take care not to modify the original AST.
if left.Op != ODOTMETH {
Fatal("OCALLMETH: n.Left not an ODOTMETH: %v", left)
}
newLeft := *left.Right
newLeft.Type = left.Type
if newLeft.Op == ONAME {
newLeft.Class = PFUNC
}
left = &newLeft
static = true
}
// evaluate closure
var closure *ssa.Value
if !static {
closure = s.expr(n.Left)
closure = s.expr(left)
}
// run all argument assignments
@ -955,13 +972,13 @@ func (s *state) expr(n *Node) *ssa.Value {
bNext := s.f.NewBlock(ssa.BlockPlain)
var call *ssa.Value
if static {
call = s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, n.Left.Sym, s.mem())
call = s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, left.Sym, s.mem())
} else {
entry := s.newValue2(ssa.OpLoad, s.config.Uintptr, closure, s.mem())
call = s.newValue3(ssa.OpClosureCall, ssa.TypeMem, entry, closure, s.mem())
}
dowidth(n.Left.Type)
call.AuxInt = n.Left.Type.Argwid // call operations carry the argsize of the callee along with them
dowidth(left.Type)
call.AuxInt = left.Type.Argwid // call operations carry the argsize of the callee along with them
b := s.endBlock()
b.Kind = ssa.BlockCall
b.Control = call
@ -971,7 +988,7 @@ func (s *state) expr(n *Node) *ssa.Value {
// read result from stack at the start of the fallthrough block
s.startBlock(bNext)
var titer Iter
fp := Structfirst(&titer, Getoutarg(n.Left.Type))
fp := Structfirst(&titer, Getoutarg(left.Type))
if fp == nil {
// CALLFUNC has no return value. Continue with the next statement.
return nil