mirror of
https://github.com/golang/go
synced 2024-10-05 20:21: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:
parent
c9a38ce758
commit
15dcdfba0f
@ -940,13 +940,30 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
return s.constInt(s.config.Int, n.Left.Type.Bound)
|
return s.constInt(s.config.Int, n.Left.Type.Bound)
|
||||||
}
|
}
|
||||||
|
|
||||||
case OCALLFUNC:
|
case OCALLFUNC, OCALLMETH:
|
||||||
static := n.Left.Op == ONAME && n.Left.Class == PFUNC
|
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
|
// evaluate closure
|
||||||
var closure *ssa.Value
|
var closure *ssa.Value
|
||||||
if !static {
|
if !static {
|
||||||
closure = s.expr(n.Left)
|
closure = s.expr(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run all argument assignments
|
// run all argument assignments
|
||||||
@ -955,13 +972,13 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
bNext := s.f.NewBlock(ssa.BlockPlain)
|
bNext := s.f.NewBlock(ssa.BlockPlain)
|
||||||
var call *ssa.Value
|
var call *ssa.Value
|
||||||
if static {
|
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 {
|
} else {
|
||||||
entry := s.newValue2(ssa.OpLoad, s.config.Uintptr, closure, s.mem())
|
entry := s.newValue2(ssa.OpLoad, s.config.Uintptr, closure, s.mem())
|
||||||
call = s.newValue3(ssa.OpClosureCall, ssa.TypeMem, entry, closure, s.mem())
|
call = s.newValue3(ssa.OpClosureCall, ssa.TypeMem, entry, closure, s.mem())
|
||||||
}
|
}
|
||||||
dowidth(n.Left.Type)
|
dowidth(left.Type)
|
||||||
call.AuxInt = n.Left.Type.Argwid // call operations carry the argsize of the callee along with them
|
call.AuxInt = left.Type.Argwid // call operations carry the argsize of the callee along with them
|
||||||
b := s.endBlock()
|
b := s.endBlock()
|
||||||
b.Kind = ssa.BlockCall
|
b.Kind = ssa.BlockCall
|
||||||
b.Control = call
|
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
|
// read result from stack at the start of the fallthrough block
|
||||||
s.startBlock(bNext)
|
s.startBlock(bNext)
|
||||||
var titer Iter
|
var titer Iter
|
||||||
fp := Structfirst(&titer, Getoutarg(n.Left.Type))
|
fp := Structfirst(&titer, Getoutarg(left.Type))
|
||||||
if fp == nil {
|
if fp == nil {
|
||||||
// CALLFUNC has no return value. Continue with the next statement.
|
// CALLFUNC has no return value. Continue with the next statement.
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user